diff --git a/.classpath b/.classpath new file mode 100755 index 0000000..a662f00 --- /dev/null +++ b/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.project b/.project new file mode 100755 index 0000000..8b0d49b --- /dev/null +++ b/.project @@ -0,0 +1,33 @@ + + + ds4droid + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/AndroidManifest.xml b/AndroidManifest.xml new file mode 100755 index 0000000..96b92b5 --- /dev/null +++ b/AndroidManifest.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dscontrols.psd b/dscontrols.psd new file mode 100755 index 0000000..f1ab195 Binary files /dev/null and b/dscontrols.psd differ diff --git a/icon.fw.png b/icon.fw.png new file mode 100755 index 0000000..c36af69 Binary files /dev/null and b/icon.fw.png differ diff --git a/jni/Android.mk b/jni/Android.mk new file mode 100755 index 0000000..772cf1b --- /dev/null +++ b/jni/Android.mk @@ -0,0 +1,9 @@ +# Android ndk makefile for ds4droid + +LOCAL_BUILD_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +include $(LOCAL_BUILD_PATH)/cpudetect/cpudetect.mk +include $(LOCAL_BUILD_PATH)/desmume_neon.mk +include $(LOCAL_BUILD_PATH)/desmume_compat.mk diff --git a/jni/Application.mk b/jni/Application.mk new file mode 100755 index 0000000..06b1701 --- /dev/null +++ b/jni/Application.mk @@ -0,0 +1,6 @@ +# Android ndk makefile for ds4droid + +APP_STL := gnustl_static +APP_ABI := armeabi-v7a +APP_CFLAGS := -O3 -ffast-math -funroll-loops -fno-strict-aliasing -Wno-psabi +APP_PLATFORM := android-9 \ No newline at end of file diff --git a/jni/cpudetect/cpu.cpp b/jni/cpudetect/cpu.cpp new file mode 100755 index 0000000..4d48ef5 --- /dev/null +++ b/jni/cpudetect/cpu.cpp @@ -0,0 +1,39 @@ +/* + Copyright (C) 2012 Jeffrey Quesnelle + + This file 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 file 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 the this software. If not, see . +*/ + +#include +#include + +#define JNI_NOARGS(X) Java_com_opendoorstudios_ds4droid_DeSmuME_##X(JNIEnv* env, jclass* clazz) + +extern "C" +{ + +jboolean JNI_NOARGS(useNeon) +{ + if (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM && + (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0) + { + return JNI_TRUE; + } + else + { + return JNI_FALSE; + } +} + +} \ No newline at end of file diff --git a/jni/cpudetect/cpudetect.mk b/jni/cpudetect/cpudetect.mk new file mode 100755 index 0000000..472925f --- /dev/null +++ b/jni/cpudetect/cpudetect.mk @@ -0,0 +1,19 @@ +# Android ndk makefile for cpudetect + +LOCAL_PATH := $(call my-dir) + +MY_LOCAL_PATH := $(LOCAL_PATH) + +include $(CLEAR_VARS) + + +LOCAL_MODULE := libcpudetect +LOCAL_SRC_FILES := cpu.cpp +LOCAL_ARM_MODE := thumb +LOCAL_ARM_NEON := false +LOCAL_CFLAGS := -fexceptions +LOCAL_STATIC_LIBRARIES := cpufeatures + +include $(BUILD_SHARED_LIBRARY) + +$(call import-module,cpufeatures) \ No newline at end of file diff --git a/jni/desmume/AUTHORS b/jni/desmume/AUTHORS new file mode 100755 index 0000000..4699773 --- /dev/null +++ b/jni/desmume/AUTHORS @@ -0,0 +1,48 @@ +Original author +--------------- +yopyop + +Current team +------------ +Guillaume Duhamel +Normmatt +Bernat Muņoz (shash) +Riccardo Magliocchetti +Max Tabachenko (CrazyMax) +zeromus +rogerman +Luigi__ + +Contributors +------------ +Allustar +amponzi +Anthony Molinaro +ape +Damien Nozay (damdoum) +delfare +Romain Vallet +snkmad +Theo Berkau +thoduv +Tim Seidel (Mighty Max) +Pascal Giard (evilynux) +Ben Jaques (masscat) +Jeff Bland +Bernat Muņoz (shash) +matusz +nitsuja +gocha +pa__ +adelikat +hi-coder +WinterMute +pengvado +dormito +ldesnogue + +Thanks to our super testers for this release +------------ +nash679 +pokefan999 +dottorleo diff --git a/jni/desmume/COPYING b/jni/desmume/COPYING new file mode 100755 index 0000000..d60c31a --- /dev/null +++ b/jni/desmume/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 + + 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. + + + Copyright (C) + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 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/jni/desmume/ChangeLog b/jni/desmume/ChangeLog new file mode 100755 index 0000000..44b8345 --- /dev/null +++ b/jni/desmume/ChangeLog @@ -0,0 +1,720 @@ +0.9.7 -> 0.9.8 (r3812-r4228) + +Yes, it's been a while since the last release, but we haven't been completely idle. There's a brand new top shelf Cocoa frontend to make life far more pleasant for OSX users, and a host of compatibility fixes. + +General/Core: + bug: fix more IPC FIFO errors + bug: import more save files correctly + bug: don't autopatch already-patched roms + bug: fix bugs in piano and guitar grip + bug: fix ARM7's VRAMSTAT register + bug: fix memory leaks on compact flash emulation + bug: fix reading of rom from low header area + bug: spu: fix some poppy interpolation audio quality issues + bug: improve timing of dma operations by running through normal mem cycle accounting; fixes an annoying number of games and graphical glitches + bug: fix opcode MRC and fake bios CRC16 + enh: jitter some related register and irq events to simulate pipeline effects and stimulate some race conditions to other outcomes + enh: fake (deterministic) some tiny jitter from human's hand holding stylus; some games were accidentally depending on this + enh: support nocash-stylep rints from arm + enh: add lua apis for accessing vram + enh: platforms other than windows receive threading optimizations + enh: provide diagnostics when system powers off (useful for homebrewers returning from main()) + enh: clarify handling of different console types within the family (ds,dslite,debug) + enh: vfat support for slot-1 devices + enh: emulate temperature register + enh: add paddle emulation + +Graphics: + bug: fix occasional crash from uninitialized blending table + bug: fix some 2d alpha blending cases resulting in white screens + bug: fix VRAM_I B_OBJ mirroring and fix sprites rendering across the end of vram + bug: fix rotoscaled sprites wrapping around screen + bug: dont fix rotscaled bitmap sprites with alpha==0 + bug: opengl: fix degradation of toon rendering during loadstate + bug: opengl: alpha blending fixes + bug: many refinements to opengl renderer + bug: opengl: support rear-plane/ClearImage emulation (fixes many graphics) + bug: rasterizer: fix some rare alpha blending cases + bug: fix bug in environment mapping introduced after 0.9.6 + bug: fix totally glitched out 3d graphics with several improvements involving matrix stack + bug: fix memory overflows in epx filter + bug: prevent backdrop from blending with ??? + enh: opengl: better depth buffering emulation + enh: better support for line segment "polys" by detection and special rendering logic + enh: opengl: support quad primitives directly + enh: add hq4x filter + +Windows: + bug: fix a long-standing loadstate crash + bug: fix lag frame accounting + bug: fix glitches in cheat entry menu + bug: stop compact flash emulation from accidentally scanning c:\ sometimes + enh: add support for game database for improved save type detection + enh: hotkey for limit framerate toggle + enh: remove stop and reset toolbar buttons which were accidentally getting used + enh: additional complexification to desmume's behaviour run from a console prompt. whether it's better is uncertain. + enh: add support for cheats databases + enh: improvements to ram search tool + enh: preliminary support for varying stylus pressure + enh: add [Display] Show Console=1 to ini file + enh: more graceful cheat parsing and add some hotkeys + enh: add 5x window size + enh: add big endian and 20.12 toggle to memview and ramwatch + enh: improve FPS throttle feedback and granularity + enh: add lua menu API + enh: hud font switching + enh: add optional file association for .nds to path config dialog + +Cocoa: + enh: Big update to cocoa frontend. Pretty much entirely new. (rogerman) + +Linux: + bug: gtk: glitches in rom and recent rom loading + bug: glade: normalize savestate slot to hotkey mapping + enh: support soundtouch for use by metaspu + enh: gtk: add SPU mode selection (Tobias Jakobi) + enh: cli: better fps limiting (Thomas Jones) + +Wx: + bug: some small fixes here and there (Jan Bücken) + enh: lot of code cleanup (Jan Bücken) + +0.9.6 -> 0.9.7 (r3493-r3812) + +General/Core: + bug: fix a ton of old, broken cpu opcodes and CP15 logic + bug: return Z1 and Z2 from TSC (fixes some touch logic) + bug: gba slot save type detection improved + bug: handle unusual rom headers more correctly + bug: dont confuse motion pack commands with save memory commands + bug: make cheat system a little less flaky and add AR 1.54 support + bug: fix nondeterministic backup memory behaviour while rerecording + bug: correct emulation of register accesses of wrong size and during powerdown + bug: rewrite --cflash-path emulation + bug: rewrite IPC/GX FIFO, IRQ flag generation, and wait-for-IRQ logics + bug: rewrite RTC calendar handling; now supports years > 2038 + enh: auto-DLDI patching for homebrew + enh: --gbaslot-rom=self mounts self.nds in slot2 + enh: more realistic exception handling + enh: piano controller emulation + enh: modular slot-1 system for exact emulation of homebrew cards + +Graphics: + bug: edge marking colors were wrong + bug: handle some "invalid" vram configurations correctly + bug: convert half of geometry engine to fixed point + bug: fix sprite blend+fadein/fadeout + bug: improve rasterizer shadows + bug: fix main memory display DMA + bug: fix some raster fx timing bugs + enh: add a hack for improving some non-stencil shadows + +Windows: + bug: misc fixes and improvements to gpu viewer tools + bug: sub screen layer display toggling fixed + bug: fixes and improvements to ram watch, ram search, cheats list + bug: fix start-paused commandline + bug: fix memory leaks when sound disabled + bug: improve load average calculators and add arm7 load average + enh: background input support + enh: add vsync option + enh: support more knobs on joysticks + enh: import cheats from R4 database + enh: add xinput rumble for 360 pads + +Linux/OSX: + bug: crash less in recent roms list + enh: Add horizontal screen layout and swap screen ability to gtk frontend (noodlebox) + enh: Big improvement to joystick support, support complex configurations and multiple devices (noodlebox) + + +0.9.5 -> 0.9.6 (r3075-r3493) + +Users of gtk, cli and gtk-glade frontends please note that now we +have a common directory in ~/.config/desmume for config file, +saves and savestates. The old .desmume.ini will be moved +automatically with the name config but you have to move your saves +manually. + +Some save files may be invalidated due to use of broken crc logic. +Back up your DSV files before using this version of the emulator or else +the game might wipe it. + +General/Core: + bug: emulate keypad interrupt + bug: spu overhaul, add capture support + bug: fix dma address reloading + bug: fix rom close memory corruption + bug: fix div and sqrt busy flag bug + bug: fix vectest + bug: fix lid savestate desync + bug: fix texcache memory GB explosion when games use tons of tiny 3d sprites + bug: fix huge rerecording movie file handle leak + bug: fix EXXXXXXX cheat codes and some add/edit/save/load bugs + bug: add 8MBit - 512MBit flash emulation + bug: fix firmware booted-from-card flag + bug: fix some failures to wake + bug: fix some rtc calendar logic + bug: op_bkpt emulation + bug: correctly emulate POWCNT1 and POWCNT2 and SPI power device + bug: corrections to bootup stack configuration + bug: protect bios from being overwritten + bug: initialize save data to 0xFF instead of 0x00 + bug: handle relocated irq vectors + bug: support patched firmwares + bug: handle 8bit auxspidata, 32bit BLDY, 32bit div regs + bug: fix some divide by zero cases + bug: don't print \n in ideas debug message + bug: don't let games read off end of cart and crash emulator + bug: fix SWI 0x0E crc16 ; some save files using wrong crc may be invalidated + bug: fix many big endian bugs + bug: fix CPSR.I idle wakeup + bug: fix loadstate crashes, mostly when sound is enabled + enh: support devkitpro argv + enh: add gbaslot-rom commandline + enh: add no$gba debug message + enh: add rtc start to dsm header + +Graphics: + bug: fix a mistakenly rendered OBJ window and 3d blend effects + bug: fixes to matrix stacks, fixing lots of garbled geometry + bug: fix fog density registers + bug: fix hblank dma to run also on scanline 262 + bug: fix w/z depth flags for broken GUIs in dual screen 3d games + bug: fixes to poly sorting + bug: block 8bit vram writes + enh: improve accuracy of opengl shaders + +Windows: + bug: fix 16bpp display + bug: more fixes to multi-gamepads + bug: cheat windows robustification + bug: fix that sticky pause state when resetting and loading roms + bug: dont crash when no sound device is available + bug: change F10 to be save slot 0 + bug: fix --start-paused + enh: try not to screensave while using gamepad + enh: add EPX and EPX1.5X resize filters + enh: add a japanese translation which will soon be stale like the others + enh: add fancy ctrl+printscreen with emulator info on it + enh: add "lockdown" window mode to keep window safe from fast stylus action + enh: add alt+enter fullscreen command + enh: add card eject command + enh: add ddraw software mode forcer + enh: improve oam viewer + enh: default 3d to rasterizer so we dont have to suggest it 1000 times a day + enh: add dump-all-memory tool + enh: add reload rom menu/hotkey + +Linux/OSX: + bug: fix building for nosse2 systems + bug: fix --num-cores + bug: fix occasional touchscreen failures + bug: fix crash starting dsm record + enh: add --nojoy=1 to fix laptops with accelerometers + enh: add simple auto frameskip mode in the gtk frontend + enh: add gui for configuring joystick in the gtk frontend + enh: make the cli frontend read the ini config file too + enh: additional OpenAL microphone backend (ncalexan) + enh: common place for config and saves (Jan Steffens) + enh: libagg is now optional if you don't need the hud + +0.9.4 -> 0.9.5 (r2437-r3075) + +0.9.5 introduces an entirely rewritten main emulation loop +This totally changes the timing, and totally breaks old savestates. +The OSX build is now based on the GTK port which is more up-to-date. + +Assorted Highlights: + * synchronous SPU mode to fix streaming sounds + * win32: lua engine, path configuration, 7z dearchiving support + +General/Core: + bug: rewrite main emulation loop and cycle accounting, fixes a lot of timings + bug: add more detailed timing emulation, removes much bogus lag + bug: rewrite DMA,gxfifo,gxstat; fix many games and no more alternate flush mode + bug: fix cflash directory support for non-windows and sector-writing + bug: fix freeze in cart irq + bug: correctly emulate dma to/from tcm + bug: fix in thumb LSR carryflag + bug: fix thumb BX PC switch to arm state + bug: fix adpcm looping, remove adpcm caching (no longer necessary) + bug: fixes to swi 3,4,5,8,0x10 + bug: fixes to exmemstat and ipc sync registers + bug: support new backup commands + bug: improve bootup bios/firmware emulation steps + enh: gbaslot: add guitar grip, gbagame flash support, expansion memory pak + enh: add more powerful antigrain-based drawing library and rewrite OSD system + enh: ideas-style debugging prints + enh: most optimizations now SSE instead of SSE2 + enh: more improvements to frameskipping and frame advance/speed controls + +Graphics: + bug: fix backdrop blending with garbage + bug: fix 256B granularity sprite addressing for sub gpu + bug: fix obj blending, bmp obj rendering, and some obj window cases + bug: fix 128-wide captures + bug: fix 16color BG line buffer overflow + bug: fix color overflow in capture blending + bug: fix disp fifo capture + bug: fix simultaneous vram display and capture via same bank + bug: fix 3d overflow acknowledge registers + bug: fix 32bit toon table writes + bug: change 3d cores to use 18bit color + bug: fix boxtest (addition overflow!), move clipper to main graphics engine + bug: fix failure in some cases of polygon clipping + bug: fix disp3dcnt emulations + bug: fixes to poly sorting + bug: fix ogl renderer wireframe support + bug: swrast: fix backface culling of nonconvex polys + bug: swrast: add clear image and scroll emulation + bug: swrast: add fog emulation + bug: swrast: fixes to shadow rendering + bug: swrast: preliminary edge marking, works decent + enh: swrast: multicore optimization for a few fps speedup + +Windows: + bug: fix support for multiple gamepads and gamepad hotkeys + bug: fix mic noise code and load wav instead of raw; effective in more cases + bug: fix for several sticky and broken hotkeys, and f10 hotkeys + bug: fixes in ram search, add DTCM and ITCM searching, ... + bug: fix sound settings vol slider + bug: recover from missing window -32000 problem + bug: don't turn on mic unless mic input is enabled + enh: x64 build type now supported + enh: side-by-side and single screen view modes, many fixes to window resizing + enh: choose any gap size by dragging bottom window edge (must be enabled) + enh: choose a gap color + enh: import/export no$GBA savefiles directly + enh: multicore optimization for filters, rotation, OSD + enh: soundview can now mute channels + enh: new ioregview + enh: common commandline system, many arguments shared with linux + enh: improve map view tool to support more modes + enh: add "FORCE AS CURRENT" recovery tool for mis-sized savefiles + enh: add some kind of very small savestate rewinding buffer + enh: autoframeskip works better + enh: add Italian translation + enh: added 2x resizing filters (hq2x, hq2xs, lq2x, lq2xs, 2xsai, supereagle) + (scanlines, nearest2x, bilinear) + +Linux: + enh: alsa microphone support + enh: hud and osd notification for gtk and cli frontends + enh: add support for the SSE optimizations + +0.9.2 -> 0.9.4 (r1844->r2352->r2437) + +0.9.3 was skipped due to emu news sites sneaking it out of our staging area and +releasing it prematurely while it still had bugs. I was going to curse them +individually, but then I decided that they would just like the publicity. + +Highlights: + * New save autodetection and save file format + * Full rerecording support + +General/Core: + bug: fix many 64 bit and endian issues + bug: fix mic input, which was nearly useless before + bug: fix failures of large dmas + bug: fix in ipc sync which broke devkitpro touch + bug: screenshots now exclude hud and rotation + bug: rewritten vram mapping (fixes corrupted or missing BG) + enh: add universal commandline system (same commandline options on every port) + enh: cheats: added Action Replay code parser + enh: more reliable and useful frameskipping + enh: SPU: speedup: add adpcm caching + enh: SPU: speedup: interpolation is now optional + enh: print svn build number so we can identify people's svn builds from screenshots + +Graphics: + bug: add polygon y-sorting (fixes 3d guis) + bug: fix texcoordgen mode 3; fixes some ortho sprites and some entirely broken games + bug: display capture fixes + bug: fix a number of OBJ modes + bug: fixes to affine BG modes + bug: better emulate some translucent OBJ + bug: more correct handling of color effect windows and backdrop colors + bug: fix matrix stack overrun which crashed emulator + bug: swrast: add clear depth image emulation and other fixes to depth buffering + bug: swrast: fix some toon and highlight cases + bug: fix bug in matrix stack, fixes some broken models + enh: add alternate flush mode HACK 3d config toggle, fixes some entirely broken 3d games + +Windows: + bug: more robust cheats engine and dialog + enh: more solid avi and wav recording + enh: improved tools: memory viewer + enh: added tools: spu viewer, ram watch, ram search + enh: change build configuration system + enh: speedup: add gpu core disabling to hide useless screens + enh: add background pause feature (for when emulator loses focus) + enh: add missing autohold for L and R + enh: add chinese translation + +Gtk frontend: + enh: switch all of menu/toolbar system to GtkAction + GtkUIManager + enh: remove the gtglext 3d code + enh: improve/speedup screen resize and final presentation logic in gtk frontend + enh: minimal rerecording hookups + +Cli frontend: + enh: hooked the frameskip (szigor) + enh: misc usability improvements: auto pause switch for pausing when focus is lost and exit on escape pressing (szigor) + enh: hook the fake noise mic; use m to toggle + +0.9.1 -> 0.9.2 +General/Core: + bug: fix error in SBCS/RSCS flags; fixes many odd behaviors and crashes [zeromus] + bug: add support for sleep mode and power registers [luigi__] + bug: important fixes to RTC so correct time is actually told [luigi__] + bug: fix card reads below 0x8000; fixes some game freezes [normatt] + bug: fix 4 mbit save type; fix non-autodetect savefile dumping [zeromus, matusz] + enh: add sram to GBA game addon emulation for importing savefiles [zeromus] + enh: many improvements and feature hookups in linux ports [matusz, luigi__] + +Graphics: + bug: fix specular texture mapping mode [luigi__] + bug: repairs to some capture modes and vram mapping [zeromus, CrazyMax] + bug: viewports finally correctly handled [zeromus] + enh: add software rasterizer. quirky, but on par with opengl [zeromus] + +Windows: + bug: mitigate bad frameskipper; default to old frameskipping mode [zeromus] + bug: fixes with recent roms and zipfile loading [zeromus] + bug: fix window position memory [zeromus] + enh: bios and firmware may now be used and booted [luigi__] + enh: many display, OSD, and input enhancements [luigi__] + enh: brand new hotkey and controls binding system [zeromus] + enh: configurable screen separation [luigi__] + enh: fast forward key [pa__] + enh: improvements to mic [luigi__] + enh: faster updates in debug tools, up to once per frame [pa__] + +Mac OS X Port: + enh: added Italian translation thanks to Paolo Bernini [jeff] + enh: resurrection of GDB stub [sigmaris] + +0.9 -> 0.9.1 +General/Core: + enh: GBA slot emulation [CrazyMax] + - Rumble support (windows only) + - GBA game + enh: Mic support (windows only?) [luigi__] + enh: Preliminary cheats system [CrazyMax] + enh: Savestates invalidated, as more variables have been added. + bug: Added PSG white noise [luigi__] + bug: fix arm/thumb ROR [zeromus] + bug: [ 2550645 ] Super Princess Peach: crash when starting a puzzle [zeromus] + bug: win32: fix spu wav file writer (regression from 0.8) [zeromus,luigi__] + bug: Much work on FIFOs, still not finished [CrazyMax] + bug: Many fixes to dma [zeromus, CrazyMax] + bug: bios WaitForVblank and WaitForInterrupt fixed [luigi__] + +Graphics: + bug: Added sprite blending [luigi__] + bug: more correct mosaic effects, still imperfect [zeromus] + bug: Many fixes to tile rendering; all graphics tests now pass [luigi__] + bug: fix crashes in some affine BG [zeromus] + bug: Implement some pos test function [luigi__] + bug: fix texture mapping across texture and palette banks and to unmapped banks [zeromus] + bug: fix texture handling for texels with MSB set (fixes some texture corruption) [zeromus] + bug: fix texture coordinate generation, including environment mapping [zeromus] + bug: texture cache invalidates when palettes change, prevents some texture corruption [zeromus] + bug: fix display capturing from 2d+3d source when display mode is display-vram [zeromus] + bug: [ 2488334 ].1 fixes to layer compositing [luigi__] + bug: [ 2488334 ].3 fix bug in support for hdma affine bg parameters [zeromus] + bug: Improvements to 3d h-scrolling [luigi__] + bug: Fix some errors in rendering 512 tall BG [zeromus,CrazyMax] (still not fully resolved) + bug: Add optional fragment shading pipeline (more precision) [luigi__] + bug: Fix bug where some sprites got cut of on x=255 [zeromus] + bug: Implement GXSTAT register [CrazyMax] + +Windows: + bug: resizing and rotating work in vista [luigi__] + enh: 0 frameskip now lets emulator run at excess speed [zeromus] + +Mac OS X Port: + bug: left key setting no longer gets confused with the right key [jeff] + enh: more keys can be mapped + +0.8 -> 0.9 + There have been so many changes that this list can hardly be considered complete. + For this release, we have formatted the list into a high level overview of big changes and bad bugs relative to the previous release. Hopefully what you're interested in. + This list does not include items which are solely performance boosts, for let us just say that virtually every system has been speeded up. + + * The savestate system is totally changed and incompatible with old savestates. + * The 3d system should be considered rewritten. + +General/Core: + enh: Convert to c++ + enh: Add functions for a lid open/close. Holding key (default "Backspace" in Windows port) while game is freeze/non freeze. [CrazyMax] + enh: Add secure area decryption from ndstool [zeromus] + enh: Change savestate code to support loosely bound chunks and more easily other parts of the emu (GE, GPU). + The savestate format is changed, but from now on it is in principle more resilient + (though it will continue to break as we tinker with the internals) [zeromus] + enh: Added SSE2 optimizations for matrices. Since we now make an SSE2 build, more optimizations can be made. [CrazyMax] + enh: Add a preliminary GUI hud system [CrazyMax,zeromus] + +CPU/MMU: + bug: Many fixes in IPC and GE FIFOs. Fixes freezes in NSMB, dsracing, and others. [CrazyMax,luigi__,shash] + bug: Fix ARM instructions SBC and RSC (likewise SBC in thumb) [normatt] + bug: Fixed Thumb LDMIA (fixes ingame Dead'n'Furious) [shash] + bug: Fix repeating DMA (fixes NSMB parallax BG) [zeromus] + bug: Proper handling for unaligned CPU accesses [luigi__] + bug: Proper handling for undefined instruction exceptions [Salva Peirķ] + bug: correctly return vram control register values (fixes homebrew 3d games) [zeromus] + enh: Remove 16MB of WRAM at 0x01****** from arm9. Mapped to unused instead. Nobody knows what this was. [zeromus] + enh: Changed instruction execution to 16 at a time blocks (tested and stable) [shash] + +Hardware: + bug: Newer and better sqrt and div emulation; makes SM64DS playable [luigi__,shash,zeromus] + bug: Add preliminary RTC implementations [CrazyMax] + enh: Add cosine interpolation in the SPU (conditionally compiled) [zeromus,luigi__] + enh: Experimental: always one silent non-mixing SPU core at 44.1khz synched with emu, for more precision. + The audible core runs with the host, causing music to slow down but not tear or pitch bend. [zeromus] + +Graphics: + - Overhaul 3d: + . Move entire GE to core emu. + . Move OpenGL renderer to emu core for optional use by platforms, removing ogl_collector. Now every platform shares the same 3d code. + . Reorganize 3d code to defer rendering to after 3d vblank. Eliminates tearing, and texturing artifacts. [zeromus] + . Add optional fragment shading pipeline (more precision) [luigi__] + . Move lighting model to software instead of using opengl's fixed function model [zeromus] + . Render shadow volumes; toon shading and highlight table [zeromus, luigi__] + . Added texture caching! big speed up. [CrazyMax] + + bug: Many assorted tweaks and improvements to 3d and 2d precision [zeromus,CrazyMax,luigi__] + bug: Fixes to GE: command unpacking, projection and pos-vector mode matrix handling, mult and load commands [zeromus] + bug: Fix a bug in texture transformation mode 1 [zeromus] + bug: Fixed GPU rendering bugs in sprites and BG [CrazyMax] + bug: Fixes to texture conversion [CrazyMax,zeromus] + bug: Fixes in capture display (no blinking in many games with dual 3D) [CrazyMax] + bug: Fixes in master brightness (this fixes some games with black screens) [CrazyMax] + bug: Fixes in screen, backdrop, and sprite blending [luigi__] + bug: Changed clear depths and how depth initial values are calculated (fixes SM64DS skybox, Castlevania) [shash,lugi__] + bug: Add 3d layer h-scrolling [zeromus] + bug: Added transparency and fixed material alpha support and alpha testing on the 3D core [shash] + bug: Rewrite VRAM mapping control and rendering (more accurate) [CrazyMax,luigi__] + + bug: convert colors to opengl better to prevent alpha=31 polys from being ever so slightly transparent [zeromus] + enh: Add MMU->GPU signal for when vram mappings change to function as a texture cache invalidate signal [zeromus] + enh: Make matrix 4x4 multiply routines use W-coordinate; carry w coord through pipeline [zeromus] + +Mac OS X port: + bug: Fixed: Filenames and paths with unicode characters now work. [Jeff] + bug: Fixed: Load state from file button works again. [Jeff] + enh: Save State panel now pauses emulation while the file selection box is open. [Jeff] + bug: Fixed: Frozen video output (and/or messed 3d emulation) after loading a state. [Jeff] + bug: Added option to load the most recent file upon launching the program. [Jeff] + enh: Added French translation (thanks to Pierre Rudloff). [Jeff] + enh: Added basic key mapping configuration to application preferences (thanks to Julio GorgŽ). [Jeff] + enh: Added keyboard shortcuts for Execute, Pause and Reset command (thanks to Julio GorgŽ). [Jeff] + enh: Default key mappings are no longer case sensitive. [Jeff] + enh: Added ability to limit speed. [Jeff] + enh: Fixed: Video output should work on software-only 3D renderers. [Jeff] + +Windows port: + bug: Fix a race condition in NDS_3D_Reset and NDS_glInit [zeromus] + bug: Fix the buggy auto frameskip logic which made the emu slow to a crawl. Now it runs fast! [zeromus] + bug: Fix resizing, rotate & aspect ration of main window. [CrazyMax,_zeromus] + bug: Remove multithreading from user interface after finding several synchronization issues [zeromus] + enh: recent roms menu [luigi_] + enh: Changed graphics render core to DirectDraw (work faster) [CrazyMax] + enh: Add an arm9 cpu load average calculator similar to no$. but I dont think it works right. [zeromus] + enh: Rewrite all debug tools (autoupdate works now) [CrazyMax] + enh: Rewrite input core & replace config input dialog [CrazyMax] + enh: Add AVI output [zeromus] + enh: Add pause toggle and frame advance hotkeys [adelikat] + enh: Add frame counter display and hud messages framework [adelikat] + enh: Main window remembers position, size, and a few other emu preferences [adelikat] + enh: Removed directx sdk dependency for easier building. [zeromus] + enh: Savestate doesnt unpause emu if it is already paused [adelikat] + +0.7.3 -> 0.8 + Cocoa: + - Save State As function now works. [Jeff B] + - Recent Items menu now works. [Jeff B] + - Opening NDS files from Finder now works. [Jeff B] + - Added screenshot feature. [Jeff B] + - Added preferences. [Jeff B] + - Many more strings are translatable now. [Jeff B] + - Default screen color is black (better represents being "off" and easier on eyes at night). [Jeff B] + - Added sound. [Jeff B] + - Now is a universal binary. [Jeff B] + - Leopard resolution icon added. [Jeff B] + - Added a Japanese translation. [Jeff B] + - Added an optional status bar (resize handle no longer overlaps screen). [Jeff B] + - New ROM Info and About DeSmuME windows have been added. [Jeff B] + - Fixed several bugs in window resizing. [Jeff B] + - Added FAT image support for homebrew games (thanks to TypeError). [Jeff B] + - Key config can be changed on the command line. Save/load hotkeys changed (so expose doesn't override). [Jeff B] + - Key bindings may work better on non-US keyboards now (needs testing). [Jeff B] + general: + - Encapsulate GDB debug stub to avoid certain problems [shash] + - Fixed CPU LD*/ST* bugs [shash] + - Fixed New SMB mini-games freeze [shash] + - Fixed possible segfault in ROMReader on ia64 and amd64. [evilynux] + - Fixed a crash bug with 2D background corrupting memory [shash] + - Flag check optimization [carlo_bramini] + - Applied some endian fixes in GPU (thanks to Phazz) [Jeff B] + gtk-glade: + - Added DeSmuME version in about dialog. [evilynux] + - Updated website url in about dialog. [evilynux] + - Added Brazilian Portuguese translation by Dreampeppers99. [evilynux] + - Better desktop menu entry following FreeDesktop specifications. [evilynux] + gtk: + - Updated website url in about dialog. [evilynux] + - Better desktop menu entry following FreeDesktop specifications. [evilynux] + windows port: + - Added an "about" box [shash] + - DirectInput control interface with joystick support [CrazyMax] + - Matrix and Light viewer [Acid Burn] + +0.7.2 -> 0.7.3 + gtk-glade: + - Full localization using intltool/gettext. [evilynux] + general: + - Added a README.TRANSLATION documenting the localization process. [evilynux] + MacOS X: + - Initial version of the Mac interface added. [Jeff B] + +0.7.1 -> 0.7.2 + spu: + - big endian fixes. [cyberwarriorx] + gpu: + - big endian fixes. [marcus_c] + gtk-glade: + - opengl improvements. [masscat] + general: + - Added support for setting NDS firmware language value. [masscat] + - Function added for setting firmware language. [masscat] + - Mac/msys compilation fixes. [cyberwarriorx] + - Fix compilation when pkg-config macros are not available [evilynux] + +0.7.0 -> 0.7.1 + general: + - Added GDB debugger stub [masscat] + - Added new/different GBAMP CFlash image reader/writer [masscat] + gpu: + - Major speedup to the 2D core [shash] + gtk-glade: + - Added command line options. [masscat] + - Added FPS limiter [masscat] + cli: + - Added command line options. [masscat] + - Added FPS limiter [masscat] + - Added option to use OpenGl to render window (allows resizing). [masscat] + windows port: + - Added command line options. [masscat] + - Added multiple language support [cyberwarriorx] + - Added Danish language translation [thomas-2007] + +0.6.0 -> 0.7.0 + general: + - Added support for *.duc files [cyberwarriorx] + gpu: + - Added support for sprite rotation/scaling [shash] + - Added support for the 3D core (openGL and null plugins) [shash] + windows port: + - A bunch of fixes [Dmitry Krutskih] + - Fixed a bug in sound that was causing it to still not work for some + people [cyberwarriorx] + gtk: + - Added 3D emulation + - Added command line options. + - Added option to use OpenGL to render window (allows resizing). + gtk-glade: + - Added 3D emulation + +0.5.0 -> 0.6.0 + general: + - Added zipped (based on zziplib) and gzipped (based on zlib) rom support. + arm: + - Added relocation interrupt vector. + - Added region access right checks. + - Enabled LDC/STC instructions. + - Fixed powersave (cp15) IRQ wait. + - Fixed MOV instructions + gpu: + - Added special color effects. + - Added windowing feature. + - Fixed transparent direct color backgrounds. + - Fixed disabled sprites showing. + - Fixed 8/32 bit access to gpu registers. + - Fixed missing backgrounds + - Support for master brightness + wifi: + - Added RF chip interface. + - Added BB chip interface. + windows port: + - Fixed address calculation in disassembler. + - Added Force Maintain Ratio option for window stretching + linux port (cli, gtk and gtk-glade): + all: + - Added joystick support. + - Fixed X and Y buttons. + gtk-glade: + - Added joystick configuration. + - Improved I/O registers viewer tool. + - Added save and load states support. + +0.3.3 -> 0.5.0 + arm: + - Fixed MSR with immediate value opcode. + - Fixed LSR_0 thumb opcode (C flag is correctly set now). + - Fixed LDR*/STR* opcodes. + - Fixed unaligned memory access on THUMB Core. + - Added relocating SWI routines. + bios: + - Added decompression functions. + - Added GetPitchTable function. + - Added GetVolumeTable function. + - Added GetCRC16 function. + - Added experimental SoundBias function. + - Added GetSineTable function. + cart: + - Added CompactFlash/FAT emulation. + - Added Get ROM chip ID Cartridge command. + gpu: + - Added framebuffer emulation. + - Fixed a bug in GPU (xfin could be greater than LG causing a segfault). + - Added support for Display Mode 0(Display Off). + - Added the basic framework for Display Mode 3(Display from Main RAM). + spu: + - Added sound emulation. + - Added sound core system. + - Added WAV write core. + - Added dummy core. + - Added Direct Sound core. + linux port: + - Added GTK+ GUI. + - Added command line interface. + - Added stylus and arm9 keypad support in CLI version. + - Added FPS display. + - Added basic frameskip. + windows port: + - Fixed a bug when displaying a ROM's information. + - Added key configuration. + - Removed the debug key. + - Added new experimental auto frameskip/frame limit code. + - Added sound settings dialog. + - Added a few menu options for accessing the website, forums, and for + submitting bugs. + general: + - Rewrote code in C. + - Fixed warnings. + - Used defines and typedef's to make things more portable and easier to + read. + - Added autotools stuff. + - Changes to logging system. + - Added screenshot function. + - Translated most french to english. + - Added savestate support. + - Added firmware reading support(needs work). + - Added Backup Memory support with autodetection. + - Fixed some endianess issues. + - Fixed things so Visual C++ can compile code. + - Added bsd support. + - Reworked ROM loading so you can load a different rom without any problems. + - Finished NDS_Reset. Now the emulation can be reset even while running. diff --git a/jni/desmume/INSTALL b/jni/desmume/INSTALL new file mode 100755 index 0000000..a1e89e1 --- /dev/null +++ b/jni/desmume/INSTALL @@ -0,0 +1,370 @@ +Installation Instructions +************************* + +Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation, +Inc. + + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. + +Basic Installation +================== + + Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. Some packages provide this +`INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. + + The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. + + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package, generally using the just-built uninstalled binaries. + + 4. Type `make install' to install the programs and any data files and + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the `make install' phase executed with root + privileges. + + 5. Optionally, type `make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior `make install' required + root privileges, verifies that the installation completed + correctly. + + 6. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + + 7. Often, you can also type `make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide `make + distcheck', which can by used by developers to test that all other + targets like `make install' and `make uninstall' work correctly. + This target is generally not run by end users. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. This +is known as a "VPATH" build. + + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple `-arch' options to the +compiler but only a single `-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the `lipo' tool if you have problems. + +Installation Names +================== + + By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX', where PREFIX must be an +absolute file name. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. In general, the +default for these options is expressed in terms of `${prefix}', so that +specifying just `--prefix' will affect all of the other directory +specifications that were not explicitly provided. + + The most portable way to affect installation locations is to pass the +correct locations to `configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +`make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, `make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +`${prefix}'. Any directories that were specified during `configure', +but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of +makefile variable overrides for each directory variable is required by +the GNU Coding Standards, and ideally causes no recompilation. +However, some platforms have known limitations with the semantics of +shared libraries that end up requiring recompilation when using this +method, particularly noticeable in packages that use GNU Libtool. + + The second method involves providing the `DESTDIR' variable. For +example, `make install DESTDIR=/alternate/directory' will prepend +`/alternate/directory' before all installation names. The approach of +`DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of `${prefix}' +at `configure' time. + +Optional Features +================= + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + + Some packages offer the ability to configure how verbose the +execution of `make' will be. For these packages, running `./configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with `make V=1'; while running `./configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with `make V=0'. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU +CC is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + HP-UX `make' updates targets which have the same time stamps as +their prerequisites, which makes it generally unusable when shipped +generated files such as `configure' are involved. Use GNU `make' +instead. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its `' header file. The option `-nodtk' can be used as +a workaround. If GNU CC is not installed, it is therefore recommended +to try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + + On Solaris, don't put `/usr/ucb' early in your `PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in `/usr/bin'. So, if you need `/usr/ucb' +in your `PATH', put it _after_ `/usr/bin'. + + On Haiku, software installed for all users goes in `/boot/common', +not `/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS + KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: + + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/jni/desmume/Makefile.am b/jni/desmume/Makefile.am new file mode 100755 index 0000000..c059490 --- /dev/null +++ b/jni/desmume/Makefile.am @@ -0,0 +1,5 @@ +EXTRA_DIST = README.LIN README.MAC README.WIN dsm.txt dsv.txt autogen.sh \ + $(PO_FILES_IN) +DISTCLEANFILES = $(PO_FILES) +SUBDIRS = $(PO_DIR) src + diff --git a/jni/desmume/Makefile.in b/jni/desmume/Makefile.in new file mode 100755 index 0000000..93397d8 --- /dev/null +++ b/jni/desmume/Makefile.in @@ -0,0 +1,801 @@ +# Makefile.in generated by automake 1.11.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = . +DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in \ + $(top_srcdir)/autopackage/default.apspec.in \ + $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \ + compile config.guess config.sub depcomp install-sh missing +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/wxwin.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = autopackage/default.apspec +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir dist dist-all distcheck +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLADEUI_UNINSTALLED_DIR = @GLADEUI_UNINSTALLED_DIR@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_LIBS = @GLIB_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GREP = @GREP@ +GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ +GTHREAD_LIBS = @GTHREAD_LIBS@ +GTKGLEXT_CFLAGS = @GTKGLEXT_CFLAGS@ +GTKGLEXT_LIBS = @GTKGLEXT_LIBS@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_PKG = @HAVE_PKG@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +LDFLAGS = @LDFLAGS@ +LIBAGG_CFLAGS = @LIBAGG_CFLAGS@ +LIBAGG_LIBS = @LIBAGG_LIBS@ +LIBGLADE_CFLAGS = @LIBGLADE_CFLAGS@ +LIBGLADE_LIBS = @LIBGLADE_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSOUNDTOUCH_CFLAGS = @LIBSOUNDTOUCH_CFLAGS@ +LIBSOUNDTOUCH_LIBS = @LIBSOUNDTOUCH_LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +OBJEXT = @OBJEXT@ +OSMESA_LIBS = @OSMESA_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POFILES = @POFILES@ +POSUB = @POSUB@ +PO_DIR = @PO_DIR@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +RANLIB = @RANLIB@ +SDLCONFIG = @SDLCONFIG@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_LIBS = @SDL_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +UI_DIR = @UI_DIR@ +UPDATEDESKTOP = @UPDATEDESKTOP@ +USE_MAINTAINER_MODE = @USE_MAINTAINER_MODE@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WX_CFLAGS = @WX_CFLAGS@ +WX_CFLAGS_ONLY = @WX_CFLAGS_ONLY@ +WX_CONFIG_PATH = @WX_CONFIG_PATH@ +WX_CPPFLAGS = @WX_CPPFLAGS@ +WX_CXXFLAGS = @WX_CXXFLAGS@ +WX_CXXFLAGS_ONLY = @WX_CXXFLAGS_ONLY@ +WX_LIBS = @WX_LIBS@ +WX_LIBS_STATIC = @WX_LIBS_STATIC@ +WX_RESCOMP = @WX_RESCOMP@ +WX_VERSION = @WX_VERSION@ +XGETTEXT = @XGETTEXT@ +XMKMF = @XMKMF@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +desmume_arch = @desmume_arch@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = README.LIN README.MAC README.WIN dsm.txt dsv.txt autogen.sh \ + $(PO_FILES_IN) + +DISTCLEANFILES = $(PO_FILES) +SUBDIRS = $(PO_DIR) src +all: all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): +autopackage/default.apspec: $(top_builddir)/config.status $(top_srcdir)/autopackage/default.apspec.in + cd $(top_builddir) && $(SHELL) ./config.status $@ + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__remove_distdir) + +dist-lzma: distdir + tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma + $(am__remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lzma*) \ + lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am am--refresh check check-am clean clean-generic \ + ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \ + dist-lzip dist-lzma dist-shar dist-tarZ dist-xz dist-zip \ + distcheck distclean distclean-generic distclean-tags \ + distcleancheck distdir distuninstallcheck dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags tags-recursive uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/jni/desmume/NEWS b/jni/desmume/NEWS new file mode 100755 index 0000000..e69de29 diff --git a/jni/desmume/README b/jni/desmume/README new file mode 100755 index 0000000..5634b89 --- /dev/null +++ b/jni/desmume/README @@ -0,0 +1,97 @@ + DeSmuME + _________________________________________ + Copyright (C) 2006 yopyop + Copyright (C) 2006-2012 DeSmuME team + Last Updated: March 31, 2012 + +Contents: +1) About ................................................................... 14 +2) Credits ................................................................. 59 +3) Contact Information ..................................................... 72 +4) License ................................................................. 82 + + +1) About ______________________________________________________________________ + +DeSmuME is software that allows you to emulate a Nintendo DS system. Think of +it as a Swiss-Army knife for Nintendo DS emulation, giving you access to many +powerful tools for testing DS features, from viewing ROM properties to managing +Action Replay cheats. And best of all, this software is completely free and +open-source. + +For information on how to install or operate DeSmuME for your operating system, +please see the README file that should be present with your installation. + +Port-specific README files: + * README.LIN for the Linux port + * README.WIN for the Windows port + * README.MAC for the Macintosh port + +Note that each DeSmuME port may have a different feature set from another port. +You may see more feature parity between ports over time as we continue +developing DeSmuME. + +You can find our documentation on our online Wiki page. The major pages of +interest are: + +* Official Documentation: http://wiki.desmume.org/index.php?title=Main_Page + +This is the main Wiki page that contains all of our official documentation. + +* Manuals: http://wiki.desmume.org/index.php?title=Manual + +The manuals contain detailed information about how to operate DeSmuME for each +port. + +* FAQ: http://wiki.desmume.org/index.php?title=Faq + +The Frequently Asked Questions (FAQ) page has a lot of useful general +information about DeSmuME. Do note that some of the information may be platform +specific, and may not directly apply to your version of DeSmuME. + +* Build Instructions: +http://wiki.desmume.org/index.php?title=Installing_DeSmuME_from_source + +This page contains detailed port-specific instructions about how to make your +own build of DeSmuME directly from the source code. + + +2) Credits ____________________________________________________________________ + +See the AUTHORS file for list of DeSmuME team members. + +Special thanks go to: + + * yopyop (original author of DeSmuME), + for releasing the source code of this great emulator. + + * Martin Korth (author of GBATEK), + for his well-written Gameboy Advance and Nintendo DS documentation. + + +3) Contact Information ________________________________________________________ + +Official Website: http://desmume.org +Public Forum: http://forum.desmume.org +Developer Chat: irc://irc.freenode.net/desmume +Bug Reports: http://sourceforge.net/tracker/?group_id=164579&atid=832291 + +Please don't ask for ROMs, BIOS files, or any other copyrighted stuff. + + +4) License ____________________________________________________________________ + +This file 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 file 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 software. If not, see . + + + * See the GNU General Public License details in COPYING. diff --git a/jni/desmume/README.LIN b/jni/desmume/README.LIN new file mode 100755 index 0000000..e3ea8a0 --- /dev/null +++ b/jni/desmume/README.LIN @@ -0,0 +1,177 @@ + DeSmuME + _________________________________________ + Copyright (C) 2006 yopyop + Copyright (C) 2006-2007 DeSmuME team + + +1) Compiling instructions...................................13 +2) How to use DeSmuME.......................................53 +3) Contact information......................................142 +4) Disclaimer...............................................160 + + +1 Compiling instructions______________________________________ + +DeSmuME is written in C using the gtk+ and SDL libraries. +So you need a working C compiler, such as gcc and +the above libraries runtime and development packages: + + * http://www.gtk.org + + * http://www.libsdl.org/ + +Once these libraries are installed, you should be ready to +install DeSmuME. + +DeSmuME provides another interface based on libglade, to use +it, you'll need glade: + + * http://glade.gnome.org/ + +1.1 From a release archive____________________________________ + +Uncompress the DeSmuME archive, move to the newly created +directory, type "./configure", then "make". +It will generate three programs: +1) "desmume" in the "src/gtk" directory; +2) "desmume-cli" in the "src/cli" directory. +If glade is installed on your system, you'll get a third +binary: +3) "desmume-glade" in the "src/gtk-glade" directory. + +You can even type "make install" to install those programs on +your system (in /usr/local/ by default), then uninstalling is +done by typing "make uninstall". + +1.2 From a CVS copy___________________________________________ + +Move to the toplevel directory (the one that contains the +configure.ac file). Type "./autogen.sh" to generate the +configure/install scripts and needed Makefiles. Then you can follow the +same procedure as in 1.1 . + +2 How to use DeSmuME__________________________________________ + +There are three versions of DeSmuME under Linux. These are a +Gtk+ build, a Glade build and a CLI SDL build. All these builds +have some common command line options: + +--disable-limiter Disables the 60 fps limiter +--soft-convert Use software colour conversion during OpenGL + screen rendering. May produce better or worse + frame rates depending on hardware. + +--arm9gdb=PORT_NUM Enable the ARM9 GDB stub on the given port +--arm7gdb=PORT_NUM Enable the ARM7 GDB stub on the given port + +--cflash=PATH_TO_DISK_IMAGE + Enable disk image GBAMP compact flash emulation + +--help Display this message + + +NOTE: +The Gtk+ and Glade builds use gtkGLext to handle the OpenGL +rendering and contexts. You may get improved performance by +also passing the argument --gdk-gl-force-indirect. This has +been seen to improve things for Nvidia based graphics cards +under Linux. + + +GDB Debugger Stubs: +Source level debugging of ARM9 and/or ARM7 code is supported +using a GDB/Insight debugger. +The GDB stubs are enabled from the command line using the +following options: + +--arm9gdb= (for the ARM9) +--arm7gdb= (for the ARM7) + +The PORT_NUM is the TCP port upon which the stub will listen for +connections. Once enabled you can connect to the stub using the +following command at the GDB debugger prompt (assuming GDB and +DeSmuME are running on the same machine): + +target remote : + +NOTE: there are problems with the ARM support when stepping code +with GDB versions prior to version 6.6. It is recommended that +you use at least version 6.6 if possible. + + +GBAMP compact flash emulation: + +The default behaviour of DeSmumME is to attempt to emulate the +FAT image for the contents of the directory where the running +.nds file was located. +This behaviour can be altered using the +--cflash= command line option. Using this +option DeSmuME will emulation a GBAMP and read and write sectors +from/to the disk image file. +The disk image file must be created and populated with files +using some external tool. +NOTE: currently if desmume fails to open the disk image file it +will silently continue minus a working GBAMP emulation. + + +2.1 Gtk+ version______________________________________________ + +Type "desmume" in a shell, a window should appear, then open +a rom file using the "open" button, next use the "run" button +to start emulation. + +The following command line options are specific to the Gtk+ +build: + +--opengl-2d Enables using OpenGL for screen rendering +--disable-sound Disables the sound emulation +--disable-3d Disables the 3D emulation + + +2.2 CLI SDL version_______________________________________________ + +Just type "desmume-cli path-to-a-rom" in a shell. + +The following command line options are specific to the CLI +build: + +--opengl-2d Enables using OpenGL for screen rendering +--disable-sound Disables the sound emulation + + +3 Contact information_________________________________________ + +General inquiries should go to: +E-mail: guillaume@desmume.org + +Linux Port-related inquiries should go to: +E-mail: guillaume@desmume.org + +Web: http://desmume.org + +Please don't ask for roms, bios files or any other copyrighted +stuff. + +If you want to submit a bug report, please run desmume, go into +the "Help" menu, and click on "Submit a bug report". If you're +having trouble with it, please feel free to email. + + +4 Disclaimer__________________________________________________ + +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., 59 Temple Place, Suite 330, Boston, +MA 02111-1307 USA + +See the GNU General Public License details in COPYING. diff --git a/jni/desmume/README.MAC b/jni/desmume/README.MAC new file mode 100755 index 0000000..e0af928 --- /dev/null +++ b/jni/desmume/README.MAC @@ -0,0 +1,272 @@ + DeSmuME + _________________________________________ + Copyright (C) 2006 yopyop + Copyright (C) 2006-2012 DeSmuME team + Last Updated: March 31, 2012 + +Contents: +1) System Requirements ..................................................... 15 +2) Quick Start Guide for Using DeSmuME for OS X ............................ 36 +3) Additional Documentation ............................................... 108 +4) Contact Information .................................................... 138 +5) License ................................................................ 257 + + +1) System Requirements ________________________________________________________ + +DeSmuME is a very demanding app, especially for CPU usage. Before you begin, +make sure that your Mac meets the listed system requirements. + +If your Mac meets only the minimum requirements, then you should expect to run +most simple 2D-only games with some frameskip, but you will be unable to run +complex 2D games or any 3D-heavy games. However, if your Mac meets the +recommended requirements, then you should expect to run almost every game, +including very complex 3D-heavy games, with minimal to no frameskip. + +Operating System: OS X v10.5 (Leopard) or later + +CPU: Can run on any PowerPC G4, G5, or Intel processor + 2.1 GHz Intel Core 2 Duo (minimum) + 3.0 GHz Intel Core 2 Duo or faster (recommended) + +RAM: 512 MB (minimum) + 2 GB (recommended) + + +2) Quick Start Guide for Using DeSmuME for OS X _______________________________ + +Installing DeSmuME is as easy as copying DeSmuME.app to your Applications +folder (or other folder of your choice). Double-click the app to start DeSmuME. + +Note that DeSmuME for OS X may have a different feature set than DeSmuME for +Windows and DeSmuME for Linux. As of this writing, some features that are +present in DeSmuME for Windows are not present in DeSmuME for OS X. + +The rest of this section will be a guide to help you quickly get started using +DeSmuME for OS X. + +Loading a ROM and Starting the Emulator: +Simply double-click the desired ROM from the Finder to play the game. By +default, DeSmuME will load the ROM and start emulation. Also, there are +additional ROM loading options that you can change in DeSmuME > Preferences if +you need them. + +Using the DS Controller: +Each DS controller button can be mapped to a button of your choice on your +keyboard, gamepad, or joystick. You can view the mappings by clicking on Input +in DeSmuME > Preferences, and then clicking the Controller tab on the Input +page. To change a mapping, click on the DS control that you want to change, +then press the button on your input device to map it. + +By default, the DS controller is mapped to the following keys on your keyboard: + Up - Up Arrow + Down - Down Arrow + Left - Left Arrow + Right - Right Arrow + A Button - X + B Button - Z + X Button - S + Y Button - A + L Trigger - Q + R Trigger - W + Start - Return + Select - Tab + Lid - Delete (Backspace) + Debug - \ + Microphone - ` + +Using the DS Touch Pad: +Touch pad input is emulated using the left mouse button. Simply click in the +touch pad area of the DS display window to use the DS touch pad. + +Rotating the DS Display: +Some games require that the DS display be at a certain rotation in order to +look correct. Rotation options can be found by choosing +View > Display Rotation. You can also use the toolbar buttons Rotate Left and +Rotate Right to rotate the display by 90 degrees counterclockwise or clockwise, +respectively. + +Freezing and Restoring the Emulation State: +Save states are a powerful feature that allows you to freeze the emulation +state and restore it later. However, note that save states are only a +temporary means of saving -- more permanent saves must be done using the +in-game save (or ROM save). + +- To freeze the emulation state, choose File > Save State File. +- To restore the emulation state, choose File > Open State File. + +You can also freeze/restore emulation states without having to manage the +Open/Save dialogs. There are ten available save state "slots" that you can +use to quickly freeze/restore the emulation state. + +- To quick freeze the emulation state, choose File > Save State Slot > Slot #. + The default hotkey for this is (Shift-#). +- To quick restore the emulation state, choose File > Load State Slot > Slot #. + The default hotkey for this is (#). + + +3) Additional Documentation ___________________________________________________ + +The quick start guide in this Read Me is by no means a complete reference to +everything that DeSmuME can do! If you need any additional information about +DeSmuME, then you can reference our online Wiki pages for up-to-date +information. + +* Official Documentation: http://wiki.desmume.org/index.php?title=Main_Page + +This is the main Wiki page that contains all of our official documentation. + +* FAQ: http://wiki.desmume.org/index.php?title=Faq + +The Frequently Asked Questions (FAQ) page has a lot of useful general +information about DeSmuME. Do note that some of the information may be platform +specific, and may not directly apply to the OS X version of DeSmuME. + +* DeSmuME Manual for OS X: +http://wiki.desmume.org/index.php?title=DeSmuME_Manual_for_the_Macintosh_port + +This page contains complete and detailed information about how to operate +DeSmuME for OS X. + +* DeSmuME Build Instructions for OS X: +http://wiki.desmume.org/index.php?title=Installing_DeSmuME_from_source_on_OS_X + +This page contains complete and detailed instructions about how to make your +own build of DeSmuME for OS X directly from the source code. + + +4) Contact Information ________________________________________________________ + +Thank you for you interest in DeSmuME! If you want to tell us how useful +DeSmuME is in your life, your love (or hate) of certain NDS games, your passion +for NDS homebrew development, or anything else related to DeSmuME or NDS +emulation, then there are various ways for you to contact us! + +However, keep in mind that there are a few of rules that you need to follow: +- Do not ask us to provide ROMs, BIOS files, or any other copyrighted stuff. + We don't want to have to deal with any legal issues that could get us in + trouble, or worse, completely shut down. + +- When contacting us, please use the appropriate means to do it. For example, + if you simply want to tell us how much you love or hate us, then use the + comments on the official webpage. Another example: If you want to post on the + forum, be sure to keep the topic focused on DeSmuME; questions that ask for + things like us providing you the latest Pokemon cheats are not DeSmuME + related, and we will instead refer you to a Pokemon cheaters forum. Finally, + our developer chat channel is intended for furthering the development work of + DeSmuME; questions about how to use DeSmuME should not come here, but instead + go to the Support forum. In short, use the appropriate contact method. That's + why the different methods exist! + +* Official Website: http://desmume.org + +Our official website has the latest news on DeSmuME releases, and also has a +lot of other useful information about DeSmuME. You can comment on different +posts telling us how you feel about DeSmuME. Is DeSmuME the best thing in your +life? Is it making you cry? Or is it a bunch of blah? Let us know here! + +* Public Forum: http://forum.desmume.org + +If you have a question about DeSmuME, then this is the place to ask it. But +before you ask it, be aware that your question may have already been +answered before, so try the following things first: + +- Read the manual and the FAQ. A lot of questions people have are usually + already answered in our documentation. +- Do a forum search about your question. + +If you still need to ask a question, then be sure to provide us the following +information: + +- DeSmuME app version +- Your operating system and OS version +- The name of the ROM (if a ROM is involved) +- The serial code of the ROM (if a ROM is involved) + +The app version can be found by choosing DeSmuME > About DeSmuME in the DeSmuME +app. Alternatively, you can select the DeSmuME app in the Finder and choose +File > Get Info. + +You can find your operating system and OS version by choosing About This Mac in +the Apple menu. + +The ROM name and serial can be found by choosing File > ROM Info in the DeSmuME +application. + +It is very important that you provide us with this information! If you don't, +then it will take much longer for us to respond to your question. + +* Live Developer Chat Channel: irc://irc.freenode.net/desmume + +We have a live developer chatline on Freenode IRC at #desmume. This channel +is meant for discussing the development of DeSmuME, and shows the real work +that goes on behind the scenes. If you are interested in doing any sort of +software programming, software testing, documentation, or graphics work, then +please join our chat channel! We would love for you to join us! + +* Bug Reports: http://sourceforge.net/tracker/?group_id=164579&atid=832291 + +If you believe that you have found a bug, you may submit a bug report by +choosing Help > Submit a Bug Report in the DeSmuME application, or by +following the above link. This will take you to our bug tracker on SourceForge. +Do note that you will need a SourceForge account in order to submit a bug +report. + +Bug submissions are very welcome and encouraged. However, when you submit a bug +to us, you MUST provide the following information, or else your bug submission +may be rejected: + +- DeSmuME app version +- Your operating system and OS version +- Your Mac model identifier +- The name of the running ROM when the bug was observed (or "None", if no ROM + was running) +- The serial code of the running ROM when the bug was observed (or "None", if + no ROM was running) +- A description of the exact behavior you observed +- A description of the behavior you expected + +You can find your Mac model identifier in the System Profiler app. The app is +located in the Applications/Utilities folder. + +When you write your description, make sure that they are as detailed as +possible. The better your descriptions are, the faster we can test and fix +bugs. + +For example, if you observed a bug in the game Golden Sun: Dark Dawn, then the +bug report could look something like this: + + App Version: v0.9.8 + Operating System: OS X v10.6.8 + Mac Model Identifier: iMac 11,2 + ROM Name: GOLDENSUN_DD + ROM Serial: NTR-BO5E-USA + Observed Behavior: I tried to load a save state using the + File > Load State > Slot 3 menu option, but the game froze. If I reset, I + can get the game working again. + Expected Behavior: The game should continue running from the point where I + made the save state. + +We will try to get your bug tested as soon as possible, but any fixes may take +longer, depending on the complexity of the bug. Also, some bugs may require us +to ask you for certain files, such as your ROM saves, save states, or console +logs. For the above example, we would probably ask you for your save states to +help us track down the bug. + + +5) License ____________________________________________________________________ + +This file 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 file 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 software. If not, see . + + + * See the GNU General Public License details in COPYING. diff --git a/jni/desmume/README.WIN b/jni/desmume/README.WIN new file mode 100755 index 0000000..50dc7f4 --- /dev/null +++ b/jni/desmume/README.WIN @@ -0,0 +1,1092 @@ +Manual +From DeSmuME +Jump to: navigation, search +Contents +[hide] + + * 1 DeSmuME Platform Specific Manuals + * 2 DeSmuME Common command line arguments + o 2.1 --load-slot=NUM [gtk,win] + o 2.2 --play-movie=PATH_TO_PLAY_MOVIE [gtk,win] + o 2.3 --record-movie=PATH_TO_RECORD_MOVIE [gtk,win] + o 2.4 --start-paused=START_PAUSED [gtk,win] + o 2.5 --cflash-image=PATH_TO_DISK_IMAGE [gtk,win] + o 2.6 --cflash-path=PATH_TO_DISK_DIRECTORY [gtk,win] + o 2.7 --bios-arm9=BIOS_ARM9_PATH [gtk,win] + o 2.8 --bios-arm7=BIOS_ARM9_PATH [gtk,win] + o 2.9 --bios-swi=BIOS_SWI [gtk,win] + o 2.10 --num-cores=NUM [win] + o 2.11 --scanline-filter-a=NUM [win] + o 2.12 --scanline-filter-b=NUM [win] + o 2.13 --arm9gdb=PORT_NUM [gtk,win] + o 2.14 --arm7gdb=PORT_NUM [gtk,win] + o 2.15 -h, --help [gtk,win] + o 2.16 --opengl-2d [gtk] + o 2.17 --soft-convert [gtk] + o 2.18 --3d-engine=ENGINE [gtk] + o 2.19 --disable-sound [gtk] + o 2.20 --disable-limiter [gtk] + o 2.21 --save-type=TYPE [gtk] + o 2.22 --fwlang=LANG [gtk] + o 2.23 --timeout=SECONDS [gtk] + o 2.24 --display=DISPLAY [gtk] + o 2.25 -v, --version [gtk] + +[edit] DeSmuME Platform Specific Manuals + +DeSmuME places responsibility on the developers of each port to expose emulation features in a way that is tuned to the needs of that platform. As a consequence, some ports are able to move well ahead of the others. Conversely, some ports are far behind some others. As a consequence, some behaviours and menu structures are different in each port. Therefore, the decision was made to create separate manuals for each port as well: when a specific port is changed, only the manual for that specific port needs to be altered. + + + +DeSmuME Manual for the Windows port + +DeSmuME Manual for the Linux GTK+ port + +DeSmuME Manual for the Linux Glade port + +DeSmuME Manual for the Linux command line port + +DeSmuME Manual for the Macintosh port +[edit] DeSmuME Common command line arguments + +The GTK+ and windows ports share common command line arguments. We are trying slowly to move over to a common command line handling engine. The commandline arguments for these platforms are described here: +[edit] --load-slot=NUM [gtk,win] + +Loads savegame from slot NUM +[edit] --play-movie=PATH_TO_PLAY_MOVIE [gtk,win] + +Specifies a dsm format movie to play +[edit] --record-movie=PATH_TO_RECORD_MOVIE [gtk,win] + +Specifies a path to a new dsm format movie +[edit] --start-paused=START_PAUSED [gtk,win] + +Indicates that emulation should start paused +[edit] --cflash-image=PATH_TO_DISK_IMAGE [gtk,win] + +Requests cflash in gbaslot with fat image at this path +[edit] --cflash-path=PATH_TO_DISK_DIRECTORY [gtk,win] + +Requests cflash in gbaslot with filesystem rooted at this path +[edit] --bios-arm9=BIOS_ARM9_PATH [gtk,win] + +Specifies a path to an arm9 bios which will be used +[edit] --bios-arm7=BIOS_ARM9_PATH [gtk,win] + +Specifies a path to an arm7 bios which will be used +[edit] --bios-swi=BIOS_SWI [gtk,win] + +Set to 1 to enable the emulation of SWI via the provided bios files, which I hope you have provided with the above options. (default 0) +[edit] --num-cores=NUM [win] + +Overrides the emulator's autodetection for number of processors. Presently, any system with more than one core (this may inadvertantly include singlecore systems with hyperthreading, but I can't test it) will operate with somewhat reduced OSD functionality, with lower quality and no asynchronous composition. In the future, other optimizations will require higher numbers of cores (optimizations for quad-core are planned, but it won't be too impressive) +[edit] --scanline-filter-a=NUM [win] + +Intensity of fadeout for scanlines filter (edge) (default 2) +[edit] --scanline-filter-b=NUM [win] + +Intensity of fadeout for scanlines filter (corner) (default 4) +[edit] --arm9gdb=PORT_NUM [gtk,win] + +Enable the ARM9 GDB stub on the given port +[edit] --arm7gdb=PORT_NUM [gtk,win] + +Enable the ARM7 GDB stub on the given port +[edit] -h, --help [gtk,win] + +Show summary of options. +[edit] --opengl-2d [gtk] + +Enables using OpenGL for screen rendering +[edit] --soft-convert [gtk] + +Use software colour conversion during OpenGL screen rendering. May produce better or worse frame rates depending on hardware. +[edit] --3d-engine=ENGINE [gtk] + +Select available 3d emulation: + + 0 = 3d disabled + 1 = internal desmume software rasterizer (default) + 2 = osmesa or gtkglext opengl (if available, depending on compilation options, see desmume --help) + +[edit] --disable-sound [gtk] + +Disables the sound emulation +[edit] --disable-limiter [gtk] + +Disables the 60 fps limiter +[edit] --save-type=TYPE [gtk] + +Select savetype from the following: + + 0 = Autodetect + 1 = EEPROM 4kbit + 2 = EEPROM 64kbit + 3 = EEPROM 512kbit + 4 = FRAM 256kbit + 5 = FLASH 2mbit + 6 = FLASH 4mbit + +[edit] --fwlang=LANG [gtk] + +Set the language in the firmware, LANG as follows: + + 0 = Japanese + 1 = English + 2 = French + 3 = German + 4 = Italian + 5 = Spanish + +[edit] --timeout=SECONDS [gtk] + +Quit desmume after the specified seconds for testing purpose. +[edit] --display=DISPLAY [gtk] + +X display to use. +[edit] -v, --version [gtk] + +Show version of program. + +Retrieved from http://wiki.desmume.org/index.php?title=Manual +This page was last modified on 22 November 2009, at 18:17. + +==================================================================== + +DeSmuME Manual for the Windows port +From DeSmuME +Jump to: navigation, search + +NOTE: This refers to the 0.9.5 revision of desmume, and may or may not accurately reflect any other revision. + + +Contents +[hide] + + * 1 Quick Getting Started Guide + o 1.1 Menu Layout + + 1.1.1 File Menu + # 1.1.1.1 File | Open ROM + # 1.1.1.2 File | Recent ROM + # 1.1.1.3 File | ROM Info + # 1.1.1.4 File | Close ROM + # 1.1.1.5 File | Save State As... + # 1.1.1.6 File | Load State As... + # 1.1.1.7 File | Save State + # 1.1.1.8 File | Load State + # 1.1.1.9 File | Import Backup Memory + # 1.1.1.10 File | Export Backup Memory + # 1.1.1.11 File | Save Screenshot As... + # 1.1.1.12 File | Quick Screenshot + # 1.1.1.13 File | Record AVI + # 1.1.1.14 File | Stop AVI + # 1.1.1.15 File | Record WAV + # 1.1.1.16 File | Record Movie + # 1.1.1.17 File | Play Movie + # 1.1.1.18 File | Stop Movie + # 1.1.1.19 File | Lua Scripting | New Lua Script Window + # 1.1.1.20 File | Lua Scripting | Close All Script Windows + # 1.1.1.21 File | Quit + + 1.1.2 Emulation Menu + # 1.1.2.1 Emulation | Pause + # 1.1.2.2 Emulation | Reset + # 1.1.2.3 Emulation | Shut Up + # 1.1.2.4 Emulation | GBA Slot + # 1.1.2.5 Emulation | Cheats + # 1.1.2.6 Emulation | Cheats | List + # 1.1.2.7 Emulation | Cheats | Search + # 1.1.2.8 Emulation | Cheats | Disable + + 1.1.3 View Menu + # 1.1.3.1 View | LCDs layout + # 1.1.3.2 View | Rotation + # 1.1.3.3 View | Window size + # 1.1.3.4 View | Window size | Always On Top + # 1.1.3.5 View | Screen Separation + # 1.1.3.6 View | Screen Separation | White,Gray,Black + # 1.1.3.7 View | Screen Separation | Editable via border dragging + # 1.1.3.8 View | Render + # 1.1.3.9 View | Force Maintain Ratio + # 1.1.3.10 View | Display Frame Counter + # 1.1.3.11 View | Display FPS + # 1.1.3.12 View | Display Input + # 1.1.3.13 View | Display Graphical Input + # 1.1.3.14 View | Display Lag Counter + # 1.1.3.15 View | Display Microphone + # 1.1.3.16 View | HUD Editing Mode + + 1.1.4 Config Menu + # 1.1.4.1 Config | Save Type + # 1.1.4.2 Config | 3D Settings + # 1.1.4.3 Config | Control Config + # 1.1.4.4 Config | Control Config | Allow Left+Rt/Up+Dn + # 1.1.4.5 Config | Hotkey Config + # 1.1.4.6 Config | Sound Settings + # 1.1.4.7 Config | WIFI Settings + # 1.1.4.8 Config | Firmware Settings + # 1.1.4.9 Config | Emulation Settings + # 1.1.4.10 Config | Microphone Settings + # 1.1.4.11 Config | Path Settings + # 1.1.4.12 Config | Frame Skip + # 1.1.4.13 Config | Language + # 1.1.4.14 Config | Background Pause + # 1.1.4.15 Config | Enable State Rewinding + + 1.1.5 Tools Menu + # 1.1.5.1 Tools | Disassembler + # 1.1.5.2 Tools | View Memory + # 1.1.5.3 Tools | View Registers + # 1.1.5.4 Tools | View Palette + # 1.1.5.5 Tools | View Tiles + # 1.1.5.6 Tools | View Maps + # 1.1.5.7 Tools | View OAM + # 1.1.5.8 Tools | View Matrices + # 1.1.5.9 Tools | View Lights + # 1.1.5.10 Tools | View Sound State + # 1.1.5.11 View | RAM Watch + # 1.1.5.12 View | RAM Search + # 1.1.5.13 Tools | View Layers + + 1.1.6 Help Menu + # 1.1.6.1 Help | Website + # 1.1.6.2 Help | Forums + # 1.1.6.3 Help | Submit a bug report + # 1.1.6.4 Help | About + +[edit] Quick Getting Started Guide + +When you start the emulator for the first time, you probably just want to play a certain game. You can do this by going to 'File' in the menu, and selecting 'Open Rom'. This will open up an explorer window, within which you can browse to the rom (nds file) that you wish to play. Once the game has finished loading (and this should only take a few seconds at most), your game will automatically start running. But if you want, you can also compile from source. See the article Installing DeSmuME from source on Windows for details. +[edit] Menu Layout + +The rest of this manual will be spend on explaining all the other options in the menu. + + +[edit] File Menu +[edit] File | Open ROM + +This option is for loading games. A game is typically called a rom file. Just use the explorer window to browse to the file, and click on open. The game should just load and start. The desmume windows port is also able to load some compressed formats, like zip, rar, and 7z. Just as long as there is a valid game (rom) file in the compressed archive ending with an .nds extension, it should load fine. +[edit] File | Recent ROM + +This menu option contains a list of the roms that you have most recently loaded. You can quickly access a game that way, without having browse to the right directory with the 'Open Rom' option. +[edit] File | ROM Info + +This option offers some information about the internals of the rom file, like name, code, manufacturer, and size. This should not concern the casual gamer, but may come in handy for developers. +[edit] File | Close ROM + +Just ends the current game and leaves the emulator more or less how it was when you first launched it. +[edit] File | Save State As... + +Imagine you have gotten to a certian point in a game, and you need to do something else. The emulator let's you save the current state of the game, so that you can continue the game later at precisely the same point somewhere in the future. + +Please note that the use of SAVESTATES is discouraged, as these are likely to break between emulator versions. Instead use SAVE FILES. These are likely to survive between emulator versions. This means that you will have to use save points within the game. SAVE FILES are stored in .dsv files. +[edit] File | Load State As... + +Once you have saved a game's position, or 'state', you can load it again with this option. +[edit] File | Save State + +This option works fairly similair to the 'Save As' option, altough it let's you save numbers instead os specifying a chosen name. Also, All the states saved via this option end up with a pre-determined name of 'game (rom) name'.dsx. So if the game is called MyGame, the first savefile will be called MyGame.ds0, the second one MyGame.ds1, etc. +[edit] File | Load State + +This option let's you load the states that you saved via the 'File | Save State' option +[edit] File | Import Backup Memory + +Backup Memory is the data the game uses to remember its own state. It is stored on the cart in a normal game. Desmume uses the .dsv extension and file format; other formats which can be imported are .duc and raw .sav, as well as no$gba savefiles (also using the .sav extension). People use pro action replays to capture duc files from their card and post it online without using emulators. These are frequently found on gamefaqs.com. See the faq for details on how to use this function, where it has been documented better. +[edit] File | Export Backup Memory + +This lets you export the game's state for use in other Nintendo DS Emulators. It will write a 'raw' sav file or a no$gba savefile. +[edit] File | Save Screenshot As... + +This lets you take a screenshot of the current view of the emulator, and specify it's name to save as a bitmap (.bmp) file. +[edit] File | Quick Screenshot + +This option also dumps a screencapture, but it has a pre-determined filename and location. The name will be based on the name of the rom and somehow sequentially numbered, and placed in the directory specified in the Path Settings. +[edit] File | Record AVI + +This option lets you capture what's going on in the emulator, and save it in an avi file. +[edit] File | Stop AVI + +The 'Record AVI' option continues to record the game, untill you press the 'Stop Avi' option. +[edit] File | Record WAV + +This option lets you capture the sound played in the emulator, and save it in a wav file. In contrast to the other option, this records, as faithfully as possible, the exact emulated audio output (which is not necessarily what you hear), although it will use the interpolation you have specified in the sound config. +[edit] File | Record Movie + +This option lets you record the gameplay in TAS format, see http://tasvideos.org for details on TAS (tool-assisted speedruns). +[edit] File | Play Movie + +This option lets you playback a pre-recorded TAS movie. +[edit] File | Stop Movie + +This options lets you stop a movie which is playing or recording. +[edit] File | Lua Scripting | New Lua Script Window + +Launches a lua scripting dashboard. Reference the FAQ for more information on lua in emulators. +[edit] File | Lua Scripting | Close All Script Windows + +Closes all the lua dashboards. +[edit] File | Quit + +Choosing this option exits the emulator. +[edit] Emulation Menu +[edit] Emulation | Pause + +This option will pause the emulation, freezing it at the current moment of execution. Selecting it again will resume the execution of the ROM at the exact moment where you paused it. +[edit] Emulation | Reset + +This option will reset the ROM that is currently loaded to the very start of the ROM, just as if you chose 'File | Open Rom' again. +[edit] Emulation | Shut Up + +This option turns off all the currently-running sounds, effectively killing streams and decoded music and voiceovers. Sequenced music and sound effects will continue to play, and when you enter a new area in the game or someone else speaks, the sounds will play again. Use this to Shut Up an annoying sound. +[edit] Emulation | GBA Slot + +This menu option pop-ups a new window, which lets you specirfy what to do with the GBA slot of the Nintendo DS. It has the following choices : NONE, Compact Flash, Rumble Pack, GBA Game, Guitar Grip. Rumble pack allows some games to use vibration. Memory extension... Extends memory, as introduced by the NDS Opera browser. And some DS games can have bonuses, unlockable by GBA cart. For example in Megaman ZX you can fight some Megaman Zero Bosses when correct cartridge is inserted. This is also commonly used by pokemon players for finding some pokemons from older GBA games. There are some GBA slot extensions which are not yet emulated by desmume. Compact Flash is is used for homebrew software emulation, for example that uses DLDI (Dynamically Linked Device Interface). As usual, see the FAQ for more up-to-date information on that. +[edit] Emulation | Cheats + +This option pulls down a drop-down menu, and presents the options list and search. Be aware though, that cheats are sort of half baked right now. If you are not having luck, wait for some news on an improved cheat system. Also, it is impossible yet to use "commercial" codes, such as Action Replay and Codebreaker, so what you'll have to do is manually search for, and alter the memory positions to your advantage. They are called 'raw' or 'internal' cheats. There's an excellent article in the wiki on Using Cheats in DeSmuMe . In post-0.9.2 development builds, there is also the support for Action Replay cheat codes. +[edit] Emulation | Cheats | List + +Choosing 'list' will list all the currently known cheats. Please refer to the article Using Cheats in DeSmuMe for further details on how to use the cheat mechanism in desmume. +[edit] Emulation | Cheats | Search + +Choosing 'search' will let you search for cheats. Please refer to the article Using Cheats in DeSmuMe for further details on how to use the cheat mechanism in desmume. +[edit] Emulation | Cheats | Disable + +Disables the cheat engine, and all active cheats. +[edit] View Menu +[edit] View | LCDs layout + +This powerful menu controls how the NDS screens will be arranged into the window. Vertical and Horizontal will choose to stack them in the specified manner (vertical being traditional and default and horizontal being wide-screen). One LCD shows just one screen--whichever one is "first" (top) as described below. "Top First" means that the top screen is First and will be displayed on top. "Bottom first" means that the bottom screen is First and will be displayed on top (effectively switching the usual ordering of the screens for this game). "Main screen first" selects the main graphics engine (the one with 3d on it) to consider as first. This option will help you track the action and discard the useless status screen in many games. "Sub screen first" is added for the sake of completeness and you may occasionally find it helpful. Please note that these last two options may not work well in the case of dual screen 3d games, as the screens are always toggling around. +[edit] View | Rotation + +This option will let you rotate the screen a pre-determined amount of degrees clockwise in order to adjust the angle of the display. Some programs require that you normally turn the DS on its side. You can set it up in that manner using this. The options are 0 (no rotation), 90, 180, and 270. +[edit] View | Window size + +This option will let you enlarge the windows a pre-determined size. The resize options are: 1x, 1.5x, 2x, 3x, and 4x the default size. You can also adjust the window size by resizing the window as usual in Windows apps. +[edit] View | Window size | Always On Top + +As featured in media players and IM programs and other emulators, etc., this will prevent other apps from displaying on top of desmume. +[edit] View | Screen Separation + +This option controls how far the two windows should be apart of each other, in other words: how big the border between them should be. Valid choices are: None (which is the default), narrow border (which is slightly larger), DS (which is about the same amount of room there is on a real Nintendo DS). +[edit] View | Screen Separation | White,Gray,Black + +Changes the colour of the gap. Savvy users may discover that they can edit this in the ini file to be any color they want. +[edit] View | Screen Separation | Editable via border dragging + +When enabled, you can pick any gap size you want by dragging the bottom edge (not a corner) of the main window. +[edit] View | Render + +These options will apply different resizing filters to the emulator screen display. +[edit] View | Force Maintain Ratio + +Here you can choose, when re-sizing the windows, if you wan to maintain the ratio of the windows. Sometimes when the window size is changed it doesn't look correct on the screen. This option forces the window to maintain a correct ratio so it looks correct. +[edit] View | Display Frame Counter + +Selecting this option will display the emulation frame number. This way you can tell how long you have been playing the game. It is also useful for timestamping emulation events (for example, you can tell if you made it out of a level faster than last time) +[edit] View | Display FPS + +Selecting this option causes the 'frames-per-second' (or 'fps', for short) to be displayed. It also displays an additional '3D' counter, which tells how frequently the game is updating its 3d graphics. But unlike the fps counter, the 3d counter has nothing to do with the power of your system. If it is low, then the game is running slow on a retail cart, and so it runs slow in an emulator. The last number in parentheses is the arm9 load average, which indicates how hard the emulated CPU is working. This has nothing to do with the power of your system either. +[edit] View | Display Input + +Selecting this option displays the emulated input that the emulator is recognizing and sending to the game software. +[edit] View | Display Graphical Input + +Same as Display Input but it is a super-spiffy graphical version. +[edit] View | Display Lag Counter + +This option displays the lag counter, which records frames where the game does not poll input. +[edit] View | Display Microphone + +This option is somewhat less exciting than it sounds, but it displays some numbers which may help you diagnose whether your microphone is hooked up correctly. +[edit] View | HUD Editing Mode + +This option will let you drag around hud elements to pick their position. +[edit] Config Menu +[edit] Config | Save Type + +This option lets you specify the save type of a particular game. The default is 'automatic'. However, this is not fail-safe in all cases, so you might need to manually select one of the other savetypes. You may also need to set this before important a savefile from some other source, as they do not always contain sufficient information to guess the correct size. +[edit] Config | 3D Settings + +This option lets you select the method that is used to draw the screen. You can choose between OpenGL (hardware accelerated) or SoftRasterizer (desmume's custom-crafted software renderer). Note that however hardware accelerated it may be, oftentimes SoftRasterizer will run faster. + +Furthermore, you have three toggles for SoftRasterizer: + + * Unrealistically High-Precision Color Interpolation - this affects how material colors get handled when polygons are clipped. + * Enable Edge Marking / Enable Fog - Using these you can prohibit emulation of these hardware features to gain a minor speedup. + +Desmume 0.9.4 had an option called "Alternate Flush Mode" which fixed some games with flickering graphics, but this was removed in 0.9.5. +[edit] Config | Control Config + +This option lets you configure keyboard keys or a joystick. The joystick support is implemented using a DirectInput control interface. + +Here are the default control mappings (they may be subject to change): + + Up arrow - Up + Left arrow - Left + Down arrow - Down + Right arrow - Right + x - A button + z - B button + s - X button + a - Y button + q - Left Trigger + w - Right Trigger + Enter - Start button + Right Shift - Select button + Backspace - Lid fold/unfold + +[edit] Config | Control Config | Allow Left+Rt/Up+Dn + +It is nearly impossible on an actual console to press left and right at the same time. You may accidentally (or on purpose!) be glitching games by sending input they did not expect if you enable this option. Most casual users can emulate the hardware better by leaving this unchecked. +[edit] Config | Hotkey Config + +This menu option lets you define keys, that can be used to quickly select other options without having to go through the entire menu structure. Some examples are a hotkey for 'pause', or a hotkey for loading a specific savestate. + +Here are the default hotkey mappings (they may be subject to change): + + n - Frame advance + Space - Pause/Unpause + p - Load current state + 1,2,3,4,5,6,7,8,9,0 - Select current state + F1-F10 - Load relevant state + Shift+F1-F10 - Save relevant state + +[edit] Config | Sound Settings + +This option lets you configure the way sound is generated. +The sync/async modes and sync methods give you different output: + + * Dual sync/async: the traditional mode, which generates more sound when the game slows down. Gives clear sound in most cases but can cause streamed sounds to be garbled sometimes. + * Sync: always generates the same amount of sound, and uses one of the three available methods to compensate for too low or too high framerates. This mode shouldn't make streamed sounds garbled. + o Sync method 'N': created by Nitsuja. Basically stretches the sound. Sounds like No$GBA (without the crackling). + o Sync method 'Z': created by Zeromus. Stretches the sound to compensate for slowdowns, and resamples it to compensate for too high framerates. That resampling causes latency and can behave weird sometimes. + o Sync method 'P': taken from SPU2-X, an SPU2 plugin for PCSX2. Stretches the sound intelligently, giving clear sound in most cases, but also latency. + + +The sound core setting allows you to choose between the DirectX sound core and the dummy one which produces no sound. The WAV write core has been removed since the new "Record WAV" option made it useless. +The buffer size setting should be kept to its original value. However, if your sound isn't clear even at 60 fps, you can try increasing it. +The interpolation setting allows you to choose between three interpolation methods: + + * None: Fast, but may sound bad. + * Linear: typical, sounds good + * Cosine: maybe slower than linear, but doesn't sound much better + +Note that the DS has no interpolation method. While sometimes interpolation can make a noticeable improvement, it can also be unnoticeable or distort some sounds. + +The ADPCM caching has been removed. It was needed due to a bug in ADPCM decoding which has been fixed. If you are still using 0.9.4, then enabling this can speed up some games while breaking the sound in others. +[edit] Config | WIFI Settings + +WIFI support is currently under heavy development, but it is not useful yet. Therefore, you may find this option missing, or simply 'greyed-out' for now. Even if you can fiddle with it, it won't do anything useful. +[edit] Config | Firmware Settings + +This option provides you with the same set of options that a real Nintendo DS firmware does. The most important here is the language, because multi-lingual games will often look at how this option is set. +[edit] Config | Emulation Settings + +These options let you boot from the extracted BIOS and Firmware of a real Nintendo DS. unless you have extracted/downloaded the firmware or bios from a Nintendo DS that you actually own yourself, these settings have no value for you as desmume does not generally require them to run correctly. Occasionally, however, a game may require them in order to work. +[edit] Config | Microphone Settings + +You can choose one of four modes. The first will attempt to use the windows default recording device (it is up to you to make your microphone take this role) and feed its input to the emulator. This works, but not perfectly, and it suffers from some unresolved conceptual issues, similar in nature to the emulator audio synchronization problem. The remainder of the options are triggered when using the mic hotkey. You can "Use internal noise sample" which works for many games that want you to blow on the mic; you can "Use rand() whitenoise" which will work for games that require blowing, but which don't work with the internal noise sample (note that this is NONDETERMINISTIC and not tas-safe); and finally you can supply your own microphone sample, which may be noise, or your nintendog's name, or any other thing. It has even been tested with bangai-o spirits level loading. This must be an 8bit mono pcm wav file. +[edit] Config | Path Settings + +Use this dialog to configure the default paths for roms, savestates, screenshots, etc. Some people like everything in one directory and some people like using 50 directories; you can have it your way. +[edit] Config | Frame Skip + +The first option, "Limit framerate" engages the throttler and prohibits the emulator from running more than 60fps. With this disabled, a fast computer may run the game doubly or triply fast. + +The fixed skip options allow you to specify how many frames should be skipped, constantly. It is generally safe to choose 1 or 2 if you don't mind a slightly choppier game, in order to get a speedup. You may get accustomed to the degraded game performance and not notice. Note, however, that frameskipping can sometimes entirely fail in dual-screen 3d games or games that use capture. + +The auto skip options will try engaging the frameskipping when the emulator is running slow, to keep the game from slowing down, but render all the frames when possible to maintain 60fps. This can make a game look sort of like a modern console 3d game which slows down when the action gets intense or too much of the world is visible. + +Note that you can use the fast-forward hotkey to engage a special mode which disables the throttler and skips some large number of frames in order to run the game as quickly as possible. This may help you speed through cutscenes or other slow grinding in games and is easier to use than constantly fiddling with these menu options. +[edit] Config | Language + +This lets you set the language the emulator displays its menus and options in. This won't change everything in the emulator, as due to the way it is coded, some things aren't translateable through this system, and it may very well be the case that your desired translation is incomplete. +[edit] Config | Background Pause + +Selecting this option will pause the emulation whenever you put desmume in the background, or the window loses focus. +[edit] Config | Enable State Rewinding + +This is a bit of an experimental option which will suck up a ton of your cpu power taking secret savestates every 0.25 seconds or so. With this enabled, the use of a rewind hotkey will permit you to rewind time a little bit in case you die. +[edit] Tools Menu +[edit] Tools | Disassembler + +This option displays the ARM9 and ARM7 disassembler. Be aware though, that the windows are drawn exactly on top of each other, so that you have to move (drag n drop) the first windows before the second window shows. +[edit] Tools | View Memory + +This tool displays the ARM7 and ARM9 memory. Be aware though, that the windows are drawn exactly on top of each other, so that you have to move (drag n drop) the first windows before the second window shows. + +The "View mode" radio buttons allow you to choose how the memory will be shown: + + * 8-bit : shows the memory as bytes + * 16-bit : shows the memory as words + * 32-bit : shows the memory as dwords + +The "View address" textbox and button allow you to jump to a different address: + + * Enter an hexadecimal address without 0x prefix, with up to 8 digits + * Click "Go" to jump to the entered address + +The "View dump" buttons allow you to dump the current view: + + * Text dump : dumps the view to a text file, in an human-readable form + * Raw dump : dumps the memory directly to a binary file which can be read with an hex editor + +Note that if you dump memory to a file already containing (a) dump(s), the new dump will be appended to the existing one(s). + +The scrollbar... well, you surely know how a scrollbar works. + +The viewers additionally allow to edit the memory. For it, click on the value you want to edit, then type the new value. The new value is applied only once you've entirely entered it. +[edit] Tools | View Registers + +This option lets you view the ARM7 and ARM9 I/O registers. +[edit] Tools | View Palette + +This option lets you view the palette in detail. +[edit] Tools | View Tiles + +This option lets you view the tiles in detail. +[edit] Tools | View Maps + +This option lets you view the maps in detail. +[edit] Tools | View OAM + +This option lets you view the OAM layer in detail. +[edit] Tools | View Matrices + +This option lets you view the matrices in detail. +[edit] Tools | View Lights + +This option lets you view the lights in detail. +[edit] Tools | View Sound State + +This option displays the sound output. +[edit] View | RAM Watch + +This option will pop-up a new window, with extensive and advanced features to watch the emulated RAM memory. +[edit] View | RAM Search + +This option will pop-up a new window, with extensive and advanced features to search through the emulated RAM memory. +[edit] Tools | View Layers + +This option lets you toggle BG layer visibility one by one. You can also toggle the rendering for an entire GPU engine, which can help your framerate in games where one screen is pointless. +[edit] Help Menu +[edit] Help | Website + +This option directs your browser to the desmume homepage. +[edit] Help | Forums + +This option directs your browser to the desmume forums. +[edit] Help | Submit a bug report + +This option directs your browser to the SourceForge bugtracker for desmume. +[edit] Help | About + +This option displays the authors of the emulator. + +Retrieved from "http://wiki.desmume.org/index.php?title=DeSmuME_Manual_for_the_Windows_port" +This page was last modified on 22 November 2009, at 22:09. + +==================================================================== + +Faq +From DeSmuME +Jump to: navigation, search + +DesMuMe FAQ + +This FAQ holds a list of many commonly asked questions about DeSmuME. + +If the FAQ is unable to answer any questions you have, then please make sure that you also consult the manual. If this doesn't help, either, post your question on the forums. +Contents +[hide] + + * 1 Release 0.9.4 Topics + o 1.1 Using old DeSmuME save files in 0.9.4 + o 1.2 What is this NOSSE and dev stuff? / Why does desmume.exe crash when it loads? / Which EXE do I use? + * 2 Savegames and Savestates + o 2.1 Why does this game fail to save? / I get the error "Data could not be accessed. Turn off the power and reinsert the DS card." or "Unable to write data. Please turn off the power and reinsert the game card." + o 2.2 Why was the save file format and extension changed from .sav to .dsv ? + o 2.3 Can I use my save states across versions? + o 2.4 Can I convert an ideas or no$gba nocash .sav savefile to DeSmuME .dsv? + o 2.5 How do I make Pokemon saves? + o 2.6 Why can't Pokemon save after beating the elite 4? + * 3 Wi-Fi and WFC + o 3.1 Does DeSmuME support wifi? + o 3.2 Why do I get an assert in wifi.cpp which keeps me from playing a game? + o 3.3 If DeSmuME doesn't support wifi, then why does it make my firewall alert since 0.9.2? + o 3.4 Why did my build come with winpcap.dll? / Why do I get crashes when I run DeSmuME on vista which mention something about winpcap? + o 3.5 What is WFC / Nintendo WiFi Connection? + * 4 Troubleshooting and Errors + o 4.1 Help! My desmume window disappeared! Maybe I can hear sound and it is in the taskbar but I can't see the window + o 4.2 Does Scribblenauts work? + o 4.3 How do I use external BIOS files or firmware? + o 4.4 Why does my touch screen not work? Oh yes you did read my mind, I was using external firmware + o 4.5 I have a gameplay related question + o 4.6 Why doesn't my DeSmuME play this game? + o 4.7 Why doesn't my game boot or progress into the main game engine? + o 4.8 Why does the emulator take a long time to start up and/or devastate my system or unarchiver when I run it? + o 4.9 Why doesn't OpenGL 3D work in Linux? + o 4.10 Why doesn't OpenGL 3D work in windows? + o 4.11 My display is incorrect or corrupted or something is missing + o 4.12 My display has flickering graphics in a certain game + o 4.13 Why does music and FMV sound bad/distorted sometimes? + * 5 Performance + o 5.1 Why is the emulator slow? + o 5.2 Does DeSmuME make use of multiple CPU's or multiple cores? + o 5.3 In 0.9.4, what does the number/percentage in the DeSmuME title bar mean + o 5.4 In 0.9.5, what does the percentage in the FPS display mean + o 5.5 Why are there Two/Numbers in the FPS display? + * 6 Using The Emulator + o 6.1 What are the minimum hardware requirements for DeSmuME ? + o 6.2 What are the recommended hardware requirements for DeSmuME? + o 6.3 It is hard to zoom in on a widescreen display due to the unusual aspect ratio of the DS + o 6.4 But will you please add screen splitting / window tearing apart / fullscreen modes? + o 6.5 How do I enter 'cheat codes' in DeSmuME? + o 6.6 I entered a 'cheat code', and now the emulator freezes. + o 6.7 Does DeSmuME support the microphone? + o 6.8 Does the 'GBA slot' option let me play GBA games? + o 6.9 How do I "Close the DS"? + o 6.10 How do I use the stylus (pen) to 'touch' the screen? + o 6.11 How can I touch two points on the screen at once, as required by Hotel Dusk? + * 7 General Questions + o 7.1 What does DeSmuME emulate and on what systems? + o 7.2 What does DeSmuME mean? + o 7.3 Under what license is DeSmuME distributed ? + o 7.4 Can I freely copy DeSmuME ? + o 7.5 Where can I report bugs? + o 7.6 Can I attach files to bug reports I did not create myself ? + o 7.7 What is 'TAS' ? + o 7.8 What hardware features are emulated? + o 7.9 Does the GDB stub still work? + o 7.10 How do I enable the GDB stub on the Windows port ? + o 7.11 Does compact flash works? + o 7.12 Where/what is IRC? + o 7.13 Where is the manual? + o 7.14 Where is release 0.9.3? + o 7.15 What is DLDI? + o 7.16 How can I post a save file or AVI capture on the DeSmuME forum? + o 7.17 How can I record an AVI with a gap between the screens? + o 7.18 How can I post a large log or other text file on the DeSmuME IRC chat room? + o 7.19 What are the origins of DeSmuME? + * 8 SVN and Compiling + o 8.1 Why doesn't the DeSmuME team release pre-build SVN binaries ? + o 8.2 How do I get the latest svn code and build DeSmuME myself? + o 8.3 What is 'SVN' ? + o 8.4 What compilers are supported for building DeSmuME from source? + o 8.5 I'm Compiling using MSVC Express On Windows, and I get the error : "ml.exe" not found. + * 9 Development and Technical Questions + o 9.1 I have a patch, modification or other code addition + o 9.2 I'm a developer, and would like to contribute to the codebase. What can I do? + o 9.3 Im not a developer, but would like to help out anyway. What can I do? + o 9.4 What is this Lua stuff I see? + o 9.5 How do I easily capture the ASM code for troubleshooting purposes? + o 9.6 Where can I find technical details on the Nintendo DS and GBA? + * 10 Mac Users + o 10.1 Why can't I find a Mac binary? + o 10.2 Why does my Mac binary say something about being unsupported? + o 10.3 Why doesn't a menu option or tool exist in my Linux or Mac build? + +[edit] Release 0.9.4 Topics +[edit] Using old DeSmuME save files in 0.9.4 + +DeSmuME will first try to load a dsv file. If the dsv is missing, it will try to load a sav and then it will immediately dump the dsv. The conversion process is supposed to be seamless. +[edit] What is this NOSSE and dev stuff? / Why does desmume.exe crash when it loads? / Which EXE do I use? + +Use dev if you are a developer and want the gdb stub. Use nosse if the regular exe crashes for you because you are on an old computer. desmume.exe uses some SSE2 optimizations for 3D matrix calculations which have been disabled in desmume_nosse.exe. Any modern Intel CPU (AMD or intel) will support SSE2. +[edit] Savegames and Savestates +[edit] Why does this game fail to save? / I get the error "Data could not be accessed. Turn off the power and reinsert the DS card." or "Unable to write data. Please turn off the power and reinsert the game card." + +Until version 0.9.4 DeSmuME's save size autodetection was poor. With 0.9.4, autodetection should work almost all the time. In fact, here is the entire list of games we currently know of that fail to autodetect correctly: + + * Spider-Man 3 (should be autodetect_size=1, detected as 3) + * Over The Hedge (should be autodetect_size=1, detected as 3; same failure mechanism) + +If you find any other game for which automatic savetype detection does not work, please let the developers know by posting on the forum or submitting a bug. If you want to fix it yourself, you may need to manually specify the correct save type for your game. Consult the manual for details on how to do this for your platform. You may also consult http://www.advanscene.com/ to easily identify the save type for your game. +[edit] Why was the save file format and extension changed from .sav to .dsv ? + +Because it is better now. These raw save files that everyone uses aren't good enough and were causing problems with autodetection. See our bug tracker or forum for more details; the dsv format has been documented in the svn source tree as dsv.txt and if you don't like the degree of interoperability with other emulators, then go tell the other emulators to support our format. +[edit] Can I use my save states across versions? + +Maybe, maybe not. Due to constant internal changes in DeSmuME, it is possible that a save state created with one version may not work with another version of DeSmuME. Savestate compatibility is preserved wherever possible, but it is not always possible. Please note that for easily confused gamers, the use of SAVESTATES is discouraged, as these are likely to break between emulator versions. Instead use SAVE FILES. These are likely to survive between emulator versions. This means that you will have to use save points within the game. SAVE FILES are stored in .dsv files. Also, see this article for further details : Savefile or savestate +[edit] Can I convert an ideas or no$gba nocash .sav savefile to DeSmuME .dsv? + +1. Convert the save file using http://shunyweb.info/convert.php ; the target format should be "Acekard RPG | EZFlash V | RAW Format [Autodetection] (.sav)" 2. Load the game. Let it get to the main menu 3. Select the correct backup size*, as specified by advanscene.com (which is not always right, by the way) 4. Use File > Import Backup Memory and pick the converted save file 5. Reset the game + + * Step 3 is not always necessary, if you are smart, however, it will never hurt to do it. + +[edit] How do I make Pokemon saves? + +Update to 0.9.4, which ensures the save type is detected automatically and correctly. +[edit] Why can't Pokemon save after beating the elite 4? + +Your save file is 9KB. It should be 513KB. Your save file is broken due to you never having established the right savefile size. That means you made it all the way through the game without saving and then testing it by loading (which would not have worked, if you had tried it). See the above discussion for why that was a very bad idea. In 0.9.5+ or post-0.9.4 svn or 0.9.4+ rr builds you may see an option in the savetypes menu called FORCE AS CURRENT which, when used after picking the correct pokemon savefile size (4mbit) will hopefully permit subsequent saves to create a correct savefile. + + +In order to do that youll have to load your savestate first. If you have been using 0.9.4, since savestate compatibility between versions is not warranted, and definitely won't work between 0.9.4 and 0.9.5, you'll have to use Gocha's 0.9.4+ build which is located at http://tasvideos.org/forum/viewtopic.php?p=210670 which will be able to load an 0.9.4 savestate. + + +These instructions were not explicit enough for one user. In an effort to tailor this information to the intellectual capacity of the audience for this question, I will paste the instructions which apparently were simple enough for him to follow: go to the faq. follow the link to gocha's build. download gocha's build. load the savestate. set the size (4Mbit). use force as current. save the game. exit the emulator and verify that you can load the game from the savefile. if you can, then load it and play through to complete the game. +[edit] Wi-Fi and WFC +[edit] Does DeSmuME support wifi? + +Wifi is not supported. It is currently under slow and incomplete development. Therefore, you may find this option missing, or simply 'greyed-out' for now. Also, since WIFI support does not work yet, don't ask any questions about it's functioning because it still is unfinished and does not work yet. Furthermore, current development activities focus mainly on the Windows build. +[edit] Why do I get an assert in wifi.cpp which keeps me from playing a game? + +This was a glitch in 0.9.2 release which was fixed in 0.9.4. +[edit] If DeSmuME doesn't support wifi, then why does it make my firewall alert since 0.9.2? + +Your firewall is stupid, or winsock is stupid, (I am not sure which yet) for alerting just when winsock gets initialized. The emulator hasnt actually tried to connect to the internet yet. How could it? There isn't any wifi. All we are doing is some network initialization code. For those of you who are still not satisfied, then I will admit that there is actually some wifi code--but it doesn't actually do anything yet! Except alert your firewall. Sorry. Also, maybe that is actually a good, unobtrusive time for firewalls to alert. But I am not sorry for calling them stupid. They are hyperactive crybabies. +[edit] Why did my build come with winpcap.dll? / Why do I get crashes when I run DeSmuME on vista which mention something about winpcap? + +Because you are running an unofficial build, from dubious origins, made by unknown people. The DeSmuME team cannot support builds it did not create itself. Therefore, you are advised to stop using unofficial builds, as you can expect no support from the DeSmuME team or on the DeSmuME forums. Only use builds you downloaded from the DeSmuME website. +[edit] What is WFC / Nintendo WiFi Connection? + +See the article Nintendo wifi config utility for more information. +[edit] Troubleshooting and Errors +[edit] Help! My desmume window disappeared! Maybe I can hear sound and it is in the taskbar but I can't see the window + +Delete your ini file. This is caused by exiting the app while you have executed win+d show desktop mode. Desmume tries to remember the window position, but windows implements show desktop by setting the window position to something like x=-32000 and so that gets saved. There is supposed to be some code to handle that case, but I guess it is not working well. This is a problem in many windows apps and this solution will usually fix it. If you don't want to lose all the other settings in your ini file, poke around in it and find the offending items which should look like this: + +[Video] +Window Size=0 +Window width=0 +Window height=0 +WindowPosX=-32000 +WindowPosY=-32000 + +Delete the -32000 items +[edit] Does Scribblenauts work? + +It works in 0.9.4 but you must use external bios files and "emulate swi's with bios images". Speaking of work, it has come to my attention that several people worked for some years making this game. If that means anything to you people. +[edit] How do I use external BIOS files or firmware? + +Config > emulation settings and supply the path. Do not ask us for BIOS files as we don't have them. It is only my psychic skills which enable me to know that this fixes Scribblenauts. + +Since the menu option doesn't exist in the OS X port, it is impossible to play scribblenauts on it. + +Like to MAC/OSX port, the Linux port(s) don't allow you to use external BIOS or Firmware files either. +[edit] Why does my touch screen not work? Oh yes you did read my mind, I was using external firmware + +It's a bug. It is not a high priority since nobody yet has proven that they actually need the external firmware. If there was a way around it, I wouldve just told you. +[edit] I have a gameplay related question + +Please check a site like http://www.gamefaqs.com, and don't post gameplay related questions on the forum or IRC *unless* you believe there is a bug in the emulation of DeSmuME. +[edit] Why doesn't my DeSmuME play this game? + +Go to desmume.org and make sure you are using the latest version. The latest version is 0.9.4. Hint: DeSmuME 0.8 and 0.3.4 are very old, being numbers smaller than the latest version. Older versions will not be supported, under any circumstances. +[edit] Why doesn't my game boot or progress into the main game engine? + +DeSmuME is not perfect yet. Some games may fail due to wifi emulation. You might find ways to patch the games to work better on emulators by searching on the internet, but that is not something you should seek help with on the DeSmuME forums. If it really doesn't boot up, you can submit a bug report for the game on the sourceforge bugtracker. +[edit] Why does the emulator take a long time to start up and/or devastate my system or unarchiver when I run it? + +This is a problem with the DeSmuME 0.9.2 that some people impolitely distribute themselves. Redownload 0.9.2 from sourceforge.net or get a newer version. It isn't a virus or anything, it is a bug in the application that can just bring a system to its knees. It tries to allocate 1GB of virtual memory. This also crashes or freezes some virus scanners (I've seen it on AVG). +[edit] Why doesn't OpenGL 3D work in Linux? + +Blame NVIDIA and ATI for putting out shoddy and/or closed source drivers. Then switch to software rasterizer. +[edit] Why doesn't OpenGL 3D work in windows? + +You are probably using an ATI video card. ATI driver support of OpenGL is known to be poor. NVIDIA cards have a much more robust support of OpenGL, so getting one of those will help. Alternatively, you can switch to software rasterizer. +[edit] My display is incorrect or corrupted or something is missing + +Try switching the 3D Renderer from OpenGL or SoftRasterizer, or vice versa, to see if that resolves the bug. In Windows, the default hotkey to do this quickly is numpad minus. +[edit] My display has flickering graphics in a certain game + +In the 0.9.4 Windows port, you can choose 'Alternate Flush Mode' in the 'Config | 3D Settings' menu. This fixes some games with flickering graphics. This option is no longer necessary in 0.9.5. If you still have flickering graphics, find the discussion about frameskipping in this doc (try turning it off.) +[edit] Why does music and FMV sound bad/distorted sometimes? + +Most DS music is sequenced music, loaded from the cart entirely when the level loads. This works mostly fine, but bonus points for you if your ears are good enough to spot the bugs. Your music that doesn't work well at all is probably streaming music, which loads from the cart on the fly and goes straight to the speakers, and possibly decoded along the way. This includes FMVs. This is much harder to emulate as it requires correct timing, which is not one of DeSmuME's strengths right now. At any rate, in 0.9.5 support for a synchronized SPU was added for the windows builds which can be optionally enabled to make these streaming sounds work correctly. Synchronizing audio is a hard problem to solve, and we're not finished solving it. The synchronous SPU comes with some other issues, which is why it is optional. Also available, if you are using the windows build, is a command from the menu Emulation > Shut Up to make the offending music go away. +[edit] Performance +[edit] Why is the emulator slow? + +Because nobody pays us to work on it full time and it runs fast enough for us to be happy. Well, almost. + +New releases may always be a step backwards in some (or many) cases from earlier releases in terms of speed. There is a delicate balance between compatibility and speed and sometimes one advances further than the other. At any rate, we have introduced a few speed hacks and toggles which you may find helpful: + + * (0.9.4) If you are in Windows, make sure you're not using the NOSSE build. That one is slower. + * (0.9.5) If you are in Windows, try using the SSE2 build. It may be a little faster. + * (0.9.5) If you are in linux, try making a build with SSE and SSE2 extensions enabled because the code is ready to handle it. Someone should provide details on how to do this. + * If you are using someone else's unofficial "SVN" build, it probably is not fully optimized, since we make our Windows releases using some profiler-guided optimization, which helps by several FPS. For all I know, they are also carriers of viruses, and lately they tend to crash on Vista. + * If you can handle it, turn off the sound. + * Use frame skip. Even frameskipping by 1 will help and many games will stay playable. Frameskipping is continually tweaked in each release to get more bang for the buck, but beware that dual screen 3d games still may not work well under frameskip. If screens seem stuck, pick a different frameskip value. + * (0.9.4+) In the sound options, set interpolation to none which should help a little bit. + * (0.9.4 only) Turn on the sound option "ADPCM Caching"; this is new and experimental, and will break some things, but it should offer a substantial speedup in some cases. + * (0.9.5+) Use dual/asynch SPU mode -- even if you turn off the sound. Try alternate synch methods if you must use synch spu mode. + * (0.9.4+) There is now the option of disabling an entire screen. (Tools > View Layers > Main GPU, etc) Consider disabling a screen which is useless in the game you are playing. + * Try the software rasterizer. In many cases, especially games which make only light use of the 3d hardware, this will actually run faster, by as many as 10 FPS. But it might also run slower, again, by as many as 10 FPS. + * (0.9.5+) If you are using the software rasterizer, disable edge marking and fog if you feel like they aren't needed. If the game isn't using those features then this won't help. + * Buying a newer, faster computer is somewhat more expensive, but it has other side benefits. + * A faster CPU is more helpful than a bleeding edge graphics card. DeSmuME is more CPU intensive than it is GPU intensive. It just needs a graphics card that is glitch-free, and currently the NVIDIA cards have a better track record. A newer graphics card has a slim possibility of increasing speed. + * The cheapest way to get 60fps is to buy the cart. You may find that this is not enough, and you need to buy a console as well. Here are some steps that have worked well for me in the past: + o Look for neighbors that are mowing their own lawns. Ask them if they would like for you to do it instead. + o Borrow your daddy's lawn mower and mow the neighbor's lawn. + o After this, they will generally give you cash. As you repeat the above steps, this cash can accumulate to large values. + o Once the accumulated cash is sufficient, it can be taken to a merchant where it can be exchanged for games and consoles. + * My lawn needs mowing. It wont make your game run any faster if you mow it for me, but I am less likely to get evicted, which would be bad for my productivity. + +[edit] Does DeSmuME make use of multiple CPU's or multiple cores? + +Currently, the Windows port has two particular multicore optimizations (in 0.9.5+): first, the display logic runs in its own thread independent from the emulator. This is used to make the OSD run frame-rate independent from emulation. This thread performs color conversion, filtering, and directdraw presentation. The net result is a speedup by a few FPS. This codepath is disabled on single core systems, and may be disabled forcefully by the user with the --num-cores=1 command line argument. Second, the software rasterizer will run in a SLI mode using as many cores as you have specified (or have been detected) up to four. Still, DeSmuMe benefits MUCH more from a single CPU with a higher GHz than from multiple cores or from multiple CPUs. +[edit] In 0.9.4, what does the number/percentage in the DeSmuME title bar mean + + * For the Windows port, the percentage is the emulated ARM9 CPU load average. The CPU in an actual Nintendo DS is an ARM9 CPU. The percentage shows us how busy the emulated CPU is. This number isnt really for you. You are far too curious. But go ahead and brag about how emulated games run at 99% on your system, it makes us laugh. + * For the Linux GTK and Glade ports, it's frames per second (fps). + +[edit] In 0.9.5, what does the percentage in the FPS display mean + +See above, it was moved here to save 915 million people from asking what it means in the title bar. +[edit] Why are there Two/Numbers in the FPS display? + +The first is your actual FPS which is how fast the emu is running on your system. If it is less than 60 then you need speed hacks or more a more powerful CPU. The second is the 3d FPS, which is a rough gauge of how fast the game is supposed to be running. If you are seeing 60/15 then the game will feel slow because it is sloppily coded but theres NOTHING YOU CAN DO ABOUT IT short of turning off speed throttling and playing at 100fps. +[edit] Using The Emulator +[edit] What are the minimum hardware requirements for DeSmuME ? + +From a purely technical viewpoint, there are no minimum requirements. However, for 'real-world' playable speeds, you would need at least the following : + + * Windows OS: Windows XP or Vista + * Linux OS: Any recent Linux distribution with a 2.6 kernel. + * 2 GHz Processor + * 512 MB Available System Memory + * Available Hard Drive Space: A few MB for the emulator + * 128 MB 3D Video Card (Nvidia GeForce 6800 or better), ATI cards are not recommended. + * Optional: Sound Card, if you want sound support + * Optional: Microphone, if you wish to make use the Windows Microphone feature + +[edit] What are the recommended hardware requirements for DeSmuME? + +From a purely technical viewpoint, there are no recommended requirements. However, for 'real-world' playable speeds, the following gives you good performance: + + * Windows OS: Windows XP or Vista + * Linux OS: Any recent Linux distribution with a 2.6 kernel. + * 3 GHz Processor + * 1 GB Available System Memory + * Available Hard Drive Space: A few MB for DeSmuME, 100MB or so for a bunch of savestates and savefiles. + * 512 MB 3D Video Card (Nvidia GeForce), ATI cards are not recommended. + * Sound Card. + * Microphone. + +In general, the more GHz, the better. The faster memory, the better. DeSmuME 0.9.4 won't benefit from multiple cores. DeSmuME is at the moment, unfortunately, slower than no$gba. +[edit] It is hard to zoom in on a widescreen display due to the unusual aspect ratio of the DS + +In fact it is hard to zoom in on a 4:3 screen, too. In 0.9.5, you can configure the screens to be side-by-side, so maybe this will make you happy. Additionally you can choose to display only one screen. I don't think anyone wants to add tear-apart windows, though. +[edit] But will you please add screen splitting / window tearing apart / fullscreen modes? + +You think youre the first person to have thought of this? The answer is no. Of all the things in the world to code, we hate this the most. +[edit] How do I enter 'cheat codes' in DeSmuME? + +As of 0.9.4, there are two types of cheat codes: Action Replay and 'raw' or 'internal' cheats. The 'raw' or 'internal' cheats include cheat-finding facilities where you may manually search for and alter the memory positions which work to your advantage. There's an excellent article on 'raw' or 'internal' cheats in the wiki on Using Cheats in DeSmuMe . For Action Replay Cheats, You can find codes for the NTSC games at http://us.codejunkies.com/Departments/DS-and-GBA.aspx and for the PAL at http://uk.codejunkies.com/Departments/DS-and-GBA.aspx. +[edit] I entered a 'cheat code', and now the emulator freezes. + +Most likely it's a problem from the (Action Replay) cheat code you used. Using codes modify the game and can make it crash/freeze if it comes to an unexpected situation. It just depends on the code you use and what it's used for in the game. Find the .dct file in your emulator's folder that matches the game's filename, and then erase it to solve the 'freezing' problem. +[edit] Does DeSmuME support the microphone? + +Yes, but only on the Windows and GNU/Linux ports. You do need to have an actual microphone attached to your PC, though. In 0.9.2 the microphone in Windows really only works for noise, but this was fixed in 0.9.4; it was fixed even further in 0.9.5. Linux support will exist in 0.9.5+ -- please note that it requires libasound. + +When in windows, if it seems that the microphone is not working, bear in mind that it has no idea what kind of how many microphones you have. You will need to use the windows control panel to specify the correct microphone as the default audio input device, and then make sure in the recording level properties (volume control) that it is selected and at an appropriate volume. +[edit] Does the 'GBA slot' option let me play GBA games? + +No. A 'real' DS can use the gba slot to play gba games, but DeSmuME does not emulate this. But a 'real' DS can also use the gba slot to access gba roms and sram so that ds games can import savefiles, and that part is emulated by DeSmuME. (please note that in 0.9.4 this is reportedly buggy for some games, including pokemon; this is supposed to have been fixed in 0.9.5) If you are looking for a Game Boy Advance (GBA) emulator, perhaps you can try mednafen or VisualBoy Advance. +[edit] How do I "Close the DS"? + +This can be done using the 'lid' command or BACKSPACE key (this can be changed in the control configuration). +[edit] How do I use the stylus (pen) to 'touch' the screen? + +You can use your mouse to emulate the stylus. Move the mouse cursor to the desired position, and then press the left mouse button in order to 'touch' the screen at the position the mouse cursor is located. Yes, we have really been asked this question before. +[edit] How can I touch two points on the screen at once, as required by Hotel Dusk? + +One user got past this by first switching on one of the switches, then pausing the game, and sort of switching on an imaginary switch in the middle of the two switches while manipulating the frame advance hotkey. See, gbatek says that when two points are touched, that the hardware appears as if the average of the two points is actually pressed. But the game expects you to touch them at not-exactly-the-same-time. +[edit] General Questions +[edit] What does DeSmuME emulate and on what systems? + +DeSmuME attempts to emulate, as faithfully as possible, the Nintendo DS and Nintendo DS Lite handheld game consoles (NDS). It currently runs on Windows, Linux, and mac OSX. DSi is not supported. +[edit] What does DeSmuME mean? + +DeSmuME is a Nintendo DS emulator and the name is a play of words - DS Emu + ME (like FlashMe - firmware hack and PassMe mod-chip for DS) The name DeSmuME derives from the popular use of ME in Nintendo DS products by homebrew developers. So DeSmuME would equal DSemuMe. Other popular uses of ME include: + + * LoadMe - a generic patcher for commercial DS roms that works with any GBA Flash Card + * PassMe - "mod-chip" using which takes authentication from an original DS card an allows execution of unauthenticated DS rom code - from the GBA cartridge slot / GBA flash card. + * FlashMe - a hacked firmware for DS that allows you to start code in DS mode from a flash card in the GBA slot. + * WifiMe - are a set of a custom drivers and software by FireFly for RALink based wireless network cards enabling to boot homebrew code on DS via Nintendo Wireless Multiboot method. + +Its name is derived from emu which is short for emulator, DS and me. It's possibly supposed to mean "DS emulator for me". +[edit] Under what license is DeSmuME distributed ? + +DeSmuME is distributed under the GNU General Public License, or GPL: http://www.gnu.org/licenses/old-licenses/gpl-2.0.html +[edit] Can I freely copy DeSmuME ? + +Yes you can, as long as you adhere to the license as specified in the GNU GPL. +[edit] Where can I report bugs? + +In the official bug tracker. Feel free to post to the bug tracker as long as you are willing to take ownership of testing that bug and letting the developers know when it is resolved to your satisfaction. Just don't submit a bug report and run. You may also request features around the same location, too, but in the other trackers. +[edit] Can I attach files to bug reports I did not create myself ? + +SourceForge likes for folks to only respond on items they submit. If you see a ticket that represents something you are encountering, SourceForge doesn't necessarily want you commenting on that. The reasoning for this given by SourceForge is that they feel it is best to open your own ticket, which helps appreciate the extent of issues in many cases. The authors of DeSmuME may or may not agree with this point of view from SourceForge. +[edit] What is 'TAS' ? + +TAS lets you record the gameplay in TAS format, see http://tasvideos.org for details on TAS (tool-assisted speedruns). +[edit] What hardware features are emulated? + + * All known 2D graphics features are correct. Mosaics work but are imperfect. There may be small issues with colors as the correct color bit depths are not used at all points in the pipeline. + + * All 3D features are emulated, except the following: wireframes and antialising. In 0.9.5, support for fog is added, as well as edge marking which mostly-works but is not perfect. In 0.9.5 the box test was significantly improved (dare I say perfected?) which fixed a number of games. The OpenGL engine is near its limit and renders some things incorrectly. Eventually the software rasterizer will support more features and be far more precise in the basic features. Both engines have trouble with some shadows, but software rasterizer is better. Software rasterizer has some noticeable texturing issues right now, especially in 2d games. Software rasterizer supports more correct lighting interpolation than opengl ever will (e.g. glitches at the edge of the screen while scrolling.) In software rasterizer, there are issues similar to 2d with incorrect bit depth being used in the pipeline. There are unfavorable edge conditions in each renderer; in OpenGL, textures tend to get overdrawn; in software rasterizer, edges of textures tend to be jittery (like the real DS) + +One last thing -- if buttons and labels and menus rendering on the 3d screen are obscured (for example, a button but no label is on it) then you may need to use the software rasterizer. Or you may need to use OpenGL instead. Each renderer has strengths and weaknesses, which is why both are provided. + + * All sound features are emulated. The microphone support is new and the manual should be consulted, where you will find out, among other things, that it is only supported in windows right now. + + * Wifi is not supported. It is currently under slow and incomplete development. Therefore, you may find this option missing, or simply 'greyed-out' for now. Also, since WIFI support does not work yet, please don't ask any questions regarding it, because it still is unfinished and does not work yet. + + * We are unaware of any outstanding issues in the core system hardware (CPU, DMA, MMU) but there are certainly still some. The instruction and memory timings are quite incorrect; however, this seems not to hurt most titles. + + * DLDI - Dynamically Linked Driver Interface, commonly known as DLDI, is a driver framework that allows NDS and GBA homebrew to easily read and write to any number of different devices, just by substituting a driver file. The MPCF driver (GBA MoviePlayer CF-version) is the only one that is supported, so you will need to install it into your application before using it in desmume. You will find that a directory or fat image must be mounted via the commandline or UI for the "gbaslot" configuration. Right now, our codebase really only has libfat support for SLOT-2 devices and CF devices so more thorough support for other DLDI drivers is unlikely at this time. + + * RTC (real-time clock) works; If it didn't, then the time in your games stays at 00:00:00, and your random number values always come up the same. + +[edit] Does the GDB stub still work? + +It seems as if it works in 0.9.4, tested with the Insight GDB variant on windows with a recent devKitPro. This support has been compiled into the dev+ build. +[edit] How do I enable the GDB stub on the Windows port ? + +Add #define GDB_STUB to src/windows/userconfig/userconfig.h which you have created according to the instructions in src/windows/defaultconfig/userconfig.h ; sorry for this confusing system, but that's how it is for now. +[edit] Does compact flash works? + +In 0.9.2+ it works, somewhat buggily, at least for directory scanning (i.e. not fat16 image) in windows via the gba slot. There is a bug that breaks it in linux, which has been fixed for 0.9.5+ along with some other work on that system. +[edit] Where/what is IRC? + +IRC is an on-line communication system. + +data you need: + + * server: irc.freenode.net + * port: 6667 + * channel: #desmume + +what to use: + + * mIRC - Windows + * ChatZilla - FireFox add-on + * xchat - X + * plenty other, see wikipedia + +Language: + + * Most of the people on the channel speak, or try to speak the English language. + +[edit] Where is the manual? + +A manual for DeSmuME is over at http://wiki.desmume.org/index.php?title=Manual. It may not have the information that other entries in this FAQ promised that it would. +[edit] Where is release 0.9.3? + +Who cares? 0.9.4 is out now. DeSmuME 0.9.3 does not exist. It was sneaked out of our staging area. It has bugs, which is why we hadn't released it yet. So we decided not to release it at all. Any release claiming to be 0.9.3 won't be supported. +[edit] What is DLDI? + +DLDI is a patching system for homebrew ROMs using libfat which makes DS homebrew much easier to write and much more user friendly. As you may know, there are many various flash cartridges for DS. These 'flashcarts' use different hardware, so to make a program run on all cards, you’d have to write support for each and every card into the program. But no-one needs support for any other cards than their own. So a libfat developer, chism, developed DLDI. The program itself knows nothing about the hardware. However, when a “DLDI patch” is applied, libfat can use this patch to know how to write to the flashcart. So, if one user has an M3 flashcart, and downloads a program, they could patch it with the M3 DLDI patch and the program would work with it. Then, another user with a Supercart could download it, apply the Supercard DLDI patch, and it would work on their flashcart, too. The same patch should let the flashcart work with any libfat based program. +[edit] How can I post a save file or AVI capture on the DeSmuME forum? + +After you created it, you can upload it to a free external service provider like MediaFire (http://www.mediafire.com/), and then put the provided links to the page in the message you post on the forum. +[edit] How can I record an AVI with a gap between the screens? + +Learn how to use virtualdub and avisynth. Then use the following avisynth script which we have developed for this purpose: + +####configuration#### +gap = 64 +#color = $aaaaaa +#color = $000000 +color = $ffffff +################## +A = AviSource("c:\ds.avi", pixel_type="RGB32") +B = AviSource("c:\ds.avi", pixel_type="RGB32") +C = blankclip(fps=A.FrameRate, width=256, height=192+gap+192, color=color, length=A.FrameCount) +A = A.crop(0,0,256,192) +B = B.crop(0,192,256,192) +D = overlay(C,A) +D = overlay(D,B,0,192+gap) +return AudioDub(D,A) + +We really don't want to put any smarts into the desmume avi dumper, preferring to do it with avisynth instead. It is a slippery slope, as there are about 50 things that people want avi dumpers to do and theyre better off learning how to do it outside the emu with other tools. To that end, if you have any particular needs regarding this do not hesitate to post in our forum and maybe we'll help you make a new avisynth script. +[edit] How can I post a large log or other text file on the DeSmuME IRC chat room? + +Make use of an external text storage site, such as 'pastebin' (http://pastebin.com/), and post the url to it on the IRC channel. +[edit] What are the origins of DeSmuME? + +DeSmuME is a freeware emulator for the Nintendo DS originally created by YopYop156. The original website was http://yopyop156.ifrance.com + +Due to change in French laws regarding emulation YopYop decided to stop development of DeSmuME. However, he released the source under the GPL, and other programmers have picked it up and kept it under active development. + +Yopyop said: + + It’s release under GPL. I have just removed the new 3D engine because it’s too much bugged. Hopefully it will be helpful for some of you. + + +The latest statement heard from yopyop was: + + DeSmuME project is over. + You may don’t know but there are a new law in France that could put me in big trouble. + With DeSmuME, I have closed the doors of game company but I can not offer to pay for it. + + The worst thing is that I have found the bad coded instructions. + For those how have download the sources you have to look in sbc, rsbc instructions the Carry flag updating is wrong. + Sorry for the home brew programmers. + + For the illegality the demonstration seemed to me convincing thus without proof clarify I prefer to stick to this decision. + + It is also the fact that few people seem interested by the project. Put besides some people who sent demonstrations to me which did not go, I received only malls to wonder to make function such or such plays or to ask me why moved is in French . + Thus I will not do something of useless and illegal. + + For the site it would not obstruct me if there were not the bond on the left which does nothing but add to confusion on the goal of the project. + + And for the sources it is the same problem as for the project. + + good week end + + yopyop + + edit the law relates to the royalties and the rights close, not? + +[edit] SVN and Compiling +[edit] Why doesn't the DeSmuME team release pre-build SVN binaries ? + +Because the DeSmuME team doesn't have trusted people to make the builds, and don't want to get involved on builds that could include whatever the author wants. Every newbie coder could do a version that, after 10 minutes of gameplay, for example, starts corrupting stuff from the hard disk. Also, anyone incapable of building it's own builds, probably isn't very helpful for submitting bug reports or helping the development team on SVN releases, so there isn't much point on them getting a SVN build. +[edit] How do I get the latest svn code and build DeSmuME myself? + +Please check out the instructions related to your platform, over at Installing DeSmuME from source +[edit] What is 'SVN' ? + +svn is a developers tool. It's used to let multiple developers work on the same codebase without conflicts. If youre an end-user, don't worry about it. And if you're a developer, see the question on how to get the latest svn code and build DeSmuME yourself. See wikipedia for more info +[edit] What compilers are supported for building DeSmuME from source? + + * At the moment, for Windows Microsoft Visual C++ 2005 and 2008 are the only supported compilers. Dev-C++ is not supported. Microsoft's Visual C++ Express is free to install and use, so there's no reason not to use it. + * For Linux, any recent version of GCC and toolchain should work. + +[edit] I'm Compiling using MSVC Express On Windows, and I get the error : "ml.exe" not found. + +ml.exe was not included in earlier downloads of MSVC++ 2008 Express Edition. Uninstall, redownload and install again. 'ml.exe' shoud be located in the "Microsoft Visual Studio 9.0\VC\bin" directory. +[edit] Development and Technical Questions +[edit] I have a patch, modification or other code addition + +Please add them to the appropriate sourceforge tracker. Patches go to the 'Patches' tracker : http://sourceforge.net/tracker/?group_id=164579&atid=832293 +[edit] I'm a developer, and would like to contribute to the codebase. What can I do? + +To start you off in the right direction, the best thing you can do is join the developer team on IRC and discuss your intentions with the developers. +[edit] Im not a developer, but would like to help out anyway. What can I do? + +The most helpful thing you can do is use DeSmuME, learn its ins and outs, and learn how to compile svn builds. Then monitor it for regressions and report bugs. You can patrol the bug tracker for bugs which could use elucidation or which, based on your awareness of how the emulator is changing, might be fixed without us having specifically addressed the bug. Basically, be a super user. And hang out on irc. Also, adding to or perfecting the documentation in the wiki is useful. You could also watch for and answer questions placed on the DeSmuME forum. +[edit] What is this Lua stuff I see? + +It is sort of a macro language for interacting with the running game software. Here is an example of it working with an NES game in another emulator, and youtubing for "fceux lua" should suffice to explain it if you don't get the picture from this url: http://www.youtube.com/watch?v=1XNTjVScm_8 +[edit] How do I easily capture the ASM code for troubleshooting purposes? + +Savestate during the problem or just before your problem occurs, and #define WANTASMLISTING in armcpu.cpp. Recompile. Then redirect stdout to a file. I know it isn't easy but its what we have for now. + +A newer, and possibly better way, is to search for LOG_ARM9 in ndssystem.cpp and uncomment it. You will also need to trigger the condition for logging by setting dolog=true. Beware that this is very verbose, and can dump around 100MBytes of logs per frame. +[edit] Where can I find technical details on the Nintendo DS and GBA? + +http://nocash.emubase.de/gbatek.htm +[edit] Mac Users +[edit] Why can't I find a Mac binary? + +Maybe we haven't made it yet. There aren't a lot of people willing to compile Mac software. Just to be sure, go to https://sourceforge.net/project/showfiles.php?group_id=164579&package_id=186413 +[edit] Why does my Mac binary say something about being unsupported? + +You have probably downloaded the i386 version of DeSmuME for MAC, and are running on the PPC platform (or the other way around). Please verify if you're running on Intel (i386) hardware, or on PPC (G4, G5) hardware, and download the appropriate binary. +[edit] Why doesn't a menu option or tool exist in my Linux or Mac build? + +Because making portable tools and platform harnesses are not our cup of tea and so a developer puts a feature into whichever ports he cares about. This policy is never going to change, although some features might migrate to other platforms over time. Better check the manual. + +Retrieved from "http://wiki.desmume.org/index.php?title=Faq" +This page was last modified on 21 November 2009, at 21:55. diff --git a/jni/desmume/aclocal.m4 b/jni/desmume/aclocal.m4 new file mode 100755 index 0000000..08229c8 --- /dev/null +++ b/jni/desmume/aclocal.m4 @@ -0,0 +1,1856 @@ +# generated automatically by aclocal 1.11.5 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, +# Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.68],, +[m4_warning([this file was generated for autoconf 2.68. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically `autoreconf'.])]) + +# Copyright (C) 1995-2002 Free Software Foundation, Inc. +# Copyright (C) 2001-2003,2004 Red Hat, Inc. +# +# This file is free software, distributed under the terms of the GNU +# General Public License. As a special exception to the GNU General +# Public License, this file may be distributed as part of a program +# that contains a configuration script generated by Autoconf, under +# the same distribution terms as the rest of that program. +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# +# Macro to add for using GNU gettext. +# Ulrich Drepper , 1995, 1996 +# +# Modified to never use included libintl. +# Owen Taylor , 12/15/1998 +# +# Major rework to remove unused code +# Owen Taylor , 12/11/2002 +# +# Added better handling of ALL_LINGUAS from GNU gettext version +# written by Bruno Haible, Owen Taylor 5/30/3002 +# +# Modified to require ngettext +# Matthias Clasen 08/06/2004 +# +# We need this here as well, since someone might use autoconf-2.5x +# to configure GLib then an older version to configure a package +# using AM_GLIB_GNU_GETTEXT +AC_PREREQ(2.53) + +dnl +dnl We go to great lengths to make sure that aclocal won't +dnl try to pull in the installed version of these macros +dnl when running aclocal in the glib directory. +dnl +m4_copy([AC_DEFUN],[glib_DEFUN]) +m4_copy([AC_REQUIRE],[glib_REQUIRE]) +dnl +dnl At the end, if we're not within glib, we'll define the public +dnl definitions in terms of our private definitions. +dnl + +# GLIB_LC_MESSAGES +#-------------------- +glib_DEFUN([GLIB_LC_MESSAGES], + [AC_CHECK_HEADERS([locale.h]) + if test $ac_cv_header_locale_h = yes; then + AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, + [AC_TRY_LINK([#include ], [return LC_MESSAGES], + am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) + if test $am_cv_val_LC_MESSAGES = yes; then + AC_DEFINE(HAVE_LC_MESSAGES, 1, + [Define if your file defines LC_MESSAGES.]) + fi + fi]) + +# GLIB_PATH_PROG_WITH_TEST +#---------------------------- +dnl GLIB_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +glib_DEFUN([GLIB_PATH_PROG_WITH_TEST], +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_path_$1, +[case "[$]$1" in + /*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in ifelse([$5], , $PATH, [$5]); do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + +# GLIB_WITH_NLS +#----------------- +glib_DEFUN([GLIB_WITH_NLS], + dnl NLS is obligatory + [USE_NLS=yes + AC_SUBST(USE_NLS) + + gt_cv_have_gettext=no + + CATOBJEXT=NONE + XGETTEXT=: + INTLLIBS= + + AC_CHECK_HEADER(libintl.h, + [gt_cv_func_dgettext_libintl="no" + libintl_extra_libs="" + + # + # First check in libc + # + AC_CACHE_CHECK([for ngettext in libc], gt_cv_func_ngettext_libc, + [AC_TRY_LINK([ +#include +], + [return !ngettext ("","", 1)], + gt_cv_func_ngettext_libc=yes, + gt_cv_func_ngettext_libc=no) + ]) + + if test "$gt_cv_func_ngettext_libc" = "yes" ; then + AC_CACHE_CHECK([for dgettext in libc], gt_cv_func_dgettext_libc, + [AC_TRY_LINK([ +#include +], + [return !dgettext ("","")], + gt_cv_func_dgettext_libc=yes, + gt_cv_func_dgettext_libc=no) + ]) + fi + + if test "$gt_cv_func_ngettext_libc" = "yes" ; then + AC_CHECK_FUNCS(bind_textdomain_codeset) + fi + + # + # If we don't have everything we want, check in libintl + # + if test "$gt_cv_func_dgettext_libc" != "yes" \ + || test "$gt_cv_func_ngettext_libc" != "yes" \ + || test "$ac_cv_func_bind_textdomain_codeset" != "yes" ; then + + AC_CHECK_LIB(intl, bindtextdomain, + [AC_CHECK_LIB(intl, ngettext, + [AC_CHECK_LIB(intl, dgettext, + gt_cv_func_dgettext_libintl=yes)])]) + + if test "$gt_cv_func_dgettext_libintl" != "yes" ; then + AC_MSG_CHECKING([if -liconv is needed to use gettext]) + AC_MSG_RESULT([]) + AC_CHECK_LIB(intl, ngettext, + [AC_CHECK_LIB(intl, dcgettext, + [gt_cv_func_dgettext_libintl=yes + libintl_extra_libs=-liconv], + :,-liconv)], + :,-liconv) + fi + + # + # If we found libintl, then check in it for bind_textdomain_codeset(); + # we'll prefer libc if neither have bind_textdomain_codeset(), + # and both have dgettext and ngettext + # + if test "$gt_cv_func_dgettext_libintl" = "yes" ; then + glib_save_LIBS="$LIBS" + LIBS="$LIBS -lintl $libintl_extra_libs" + unset ac_cv_func_bind_textdomain_codeset + AC_CHECK_FUNCS(bind_textdomain_codeset) + LIBS="$glib_save_LIBS" + + if test "$ac_cv_func_bind_textdomain_codeset" = "yes" ; then + gt_cv_func_dgettext_libc=no + else + if test "$gt_cv_func_dgettext_libc" = "yes" \ + && test "$gt_cv_func_ngettext_libc" = "yes"; then + gt_cv_func_dgettext_libintl=no + fi + fi + fi + fi + + if test "$gt_cv_func_dgettext_libc" = "yes" \ + || test "$gt_cv_func_dgettext_libintl" = "yes"; then + gt_cv_have_gettext=yes + fi + + if test "$gt_cv_func_dgettext_libintl" = "yes"; then + INTLLIBS="-lintl $libintl_extra_libs" + fi + + if test "$gt_cv_have_gettext" = "yes"; then + AC_DEFINE(HAVE_GETTEXT,1, + [Define if the GNU gettext() function is already present or preinstalled.]) + GLIB_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl + if test "$MSGFMT" != "no"; then + glib_save_LIBS="$LIBS" + LIBS="$LIBS $INTLLIBS" + AC_CHECK_FUNCS(dcgettext) + MSGFMT_OPTS= + AC_MSG_CHECKING([if msgfmt accepts -c]) + GLIB_RUN_PROG([$MSGFMT -c -o /dev/null],[ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Project-Id-Version: test 1.0\n" +"PO-Revision-Date: 2007-02-15 12:01+0100\n" +"Last-Translator: test \n" +"Language-Team: C \n" +"MIME-Version: 1.0\n" +"Content-Transfer-Encoding: 8bit\n" +], [MSGFMT_OPTS=-c; AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])]) + AC_SUBST(MSGFMT_OPTS) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + GLIB_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + AC_TRY_LINK(, [extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr], + [CATOBJEXT=.gmo + DATADIRNAME=share], + [case $host in + *-*-solaris*) + dnl On Solaris, if bind_textdomain_codeset is in libc, + dnl GNU format message catalog is always supported, + dnl since both are added to the libc all together. + dnl Hence, we'd like to go with DATADIRNAME=share and + dnl and CATOBJEXT=.gmo in this case. + AC_CHECK_FUNC(bind_textdomain_codeset, + [CATOBJEXT=.gmo + DATADIRNAME=share], + [CATOBJEXT=.mo + DATADIRNAME=lib]) + ;; + *-*-openbsd*) + CATOBJEXT=.mo + DATADIRNAME=share + ;; + *) + CATOBJEXT=.mo + DATADIRNAME=lib + ;; + esac]) + LIBS="$glib_save_LIBS" + INSTOBJEXT=.mo + else + gt_cv_have_gettext=no + fi + fi + ]) + + if test "$gt_cv_have_gettext" = "yes" ; then + AC_DEFINE(ENABLE_NLS, 1, + [always defined to indicate that i18n is enabled]) + fi + + dnl Test whether we really found GNU xgettext. + if test "$XGETTEXT" != ":"; then + dnl If it is not GNU xgettext we define it as : so that the + dnl Makefiles still can work. + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + AC_MSG_RESULT( + [found xgettext program is not GNU xgettext; ignore it]) + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + + AC_OUTPUT_COMMANDS( + [case "$CONFIG_FILES" in *po/Makefile.in*) + sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile + esac]) + + dnl These rules are solely for the distribution goal. While doing this + dnl we only have to keep exactly one list of the available catalogs + dnl in configure.ac. + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + dnl Make all variables we use known to autoconf. + AC_SUBST(CATALOGS) + AC_SUBST(CATOBJEXT) + AC_SUBST(DATADIRNAME) + AC_SUBST(GMOFILES) + AC_SUBST(INSTOBJEXT) + AC_SUBST(INTLLIBS) + AC_SUBST(PO_IN_DATADIR_TRUE) + AC_SUBST(PO_IN_DATADIR_FALSE) + AC_SUBST(POFILES) + AC_SUBST(POSUB) + ]) + +# AM_GLIB_GNU_GETTEXT +# ------------------- +# Do checks necessary for use of gettext. If a suitable implementation +# of gettext is found in either in libintl or in the C library, +# it will set INTLLIBS to the libraries needed for use of gettext +# and AC_DEFINE() HAVE_GETTEXT and ENABLE_NLS. (The shell variable +# gt_cv_have_gettext will be set to "yes".) It will also call AC_SUBST() +# on various variables needed by the Makefile.in.in installed by +# glib-gettextize. +dnl +glib_DEFUN([GLIB_GNU_GETTEXT], + [AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_HEADER_STDC])dnl + + GLIB_LC_MESSAGES + GLIB_WITH_NLS + + if test "$gt_cv_have_gettext" = "yes"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + AC_MSG_CHECKING(for catalogs to be installed) + NEW_LINGUAS= + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "${LINGUAS-%UNSET%}"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + NEW_LINGUAS="$NEW_LINGUAS $presentlang" + fi + done + LINGUAS=$NEW_LINGUAS + AC_MSG_RESULT($LINGUAS) + fi + + dnl Construct list of names of catalog files to be constructed. + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly + dnl find the mkinstalldirs script in another subdir but ($top_srcdir). + dnl Try to locate is. + MKINSTALLDIRS= + if test -n "$ac_aux_dir"; then + MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" + fi + if test -z "$MKINSTALLDIRS"; then + MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" + fi + AC_SUBST(MKINSTALLDIRS) + + dnl Generate list of files to be processed by xgettext which will + dnl be included in po/Makefile. + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + ]) + +# AM_GLIB_DEFINE_LOCALEDIR(VARIABLE) +# ------------------------------- +# Define VARIABLE to the location where catalog files will +# be installed by po/Makefile. +glib_DEFUN([GLIB_DEFINE_LOCALEDIR], +[glib_REQUIRE([GLIB_GNU_GETTEXT])dnl +glib_save_prefix="$prefix" +glib_save_exec_prefix="$exec_prefix" +glib_save_datarootdir="$datarootdir" +test "x$prefix" = xNONE && prefix=$ac_default_prefix +test "x$exec_prefix" = xNONE && exec_prefix=$prefix +datarootdir=`eval echo "${datarootdir}"` +if test "x$CATOBJEXT" = "x.mo" ; then + localedir=`eval echo "${libdir}/locale"` +else + localedir=`eval echo "${datadir}/locale"` +fi +prefix="$glib_save_prefix" +exec_prefix="$glib_save_exec_prefix" +datarootdir="$glib_save_datarootdir" +AC_DEFINE_UNQUOTED($1, "$localedir", + [Define the location where the catalogs will be installed]) +]) + +dnl +dnl Now the definitions that aclocal will find +dnl +ifdef(glib_configure_ac,[],[ +AC_DEFUN([AM_GLIB_GNU_GETTEXT],[GLIB_GNU_GETTEXT($@)]) +AC_DEFUN([AM_GLIB_DEFINE_LOCALEDIR],[GLIB_DEFINE_LOCALEDIR($@)]) +])dnl + +# GLIB_RUN_PROG(PROGRAM, TEST-FILE, [ACTION-IF-PASS], [ACTION-IF-FAIL]) +# +# Create a temporary file with TEST-FILE as its contents and pass the +# file name to PROGRAM. Perform ACTION-IF-PASS if PROGRAM exits with +# 0 and perform ACTION-IF-FAIL for any other exit status. +AC_DEFUN([GLIB_RUN_PROG], +[cat >conftest.foo <<_ACEOF +$2 +_ACEOF +if AC_RUN_LOG([$1 conftest.foo]); then + m4_ifval([$3], [$3], [:]) +m4_ifvaln([$4], [else $4])dnl +echo "$as_me: failed input was:" >&AS_MESSAGE_LOG_FD +sed 's/^/| /' conftest.foo >&AS_MESSAGE_LOG_FD +fi]) + + + +dnl IT_PROG_INTLTOOL([MINIMUM-VERSION], [no-xml]) +# serial 42 IT_PROG_INTLTOOL +AC_DEFUN([IT_PROG_INTLTOOL], [ +AC_PREREQ([2.50])dnl +AC_REQUIRE([AM_NLS])dnl + +case "$am__api_version" in + 1.[01234]) + AC_MSG_ERROR([Automake 1.5 or newer is required to use intltool]) + ;; + *) + ;; +esac + +INTLTOOL_REQUIRED_VERSION_AS_INT=`echo $1 | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'` +INTLTOOL_APPLIED_VERSION=`intltool-update --version | head -1 | cut -d" " -f3` +INTLTOOL_APPLIED_VERSION_AS_INT=`echo $INTLTOOL_APPLIED_VERSION | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'` +if test -n "$1"; then + AC_MSG_CHECKING([for intltool >= $1]) + AC_MSG_RESULT([$INTLTOOL_APPLIED_VERSION found]) + test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge "$INTLTOOL_REQUIRED_VERSION_AS_INT" || + AC_MSG_ERROR([Your intltool is too old. You need intltool $1 or later.]) +fi + +AC_PATH_PROG(INTLTOOL_UPDATE, [intltool-update]) +AC_PATH_PROG(INTLTOOL_MERGE, [intltool-merge]) +AC_PATH_PROG(INTLTOOL_EXTRACT, [intltool-extract]) +if test -z "$INTLTOOL_UPDATE" -o -z "$INTLTOOL_MERGE" -o -z "$INTLTOOL_EXTRACT"; then + AC_MSG_ERROR([The intltool scripts were not found. Please install intltool.]) +fi + +if test -z "$AM_DEFAULT_VERBOSITY"; then + AM_DEFAULT_VERBOSITY=1 +fi +AC_SUBST([AM_DEFAULT_VERBOSITY]) + +INTLTOOL_V_MERGE='$(INTLTOOL__v_MERGE_$(V))' +INTLTOOL__v_MERGE_='$(INTLTOOL__v_MERGE_$(AM_DEFAULT_VERBOSITY))' +INTLTOOL__v_MERGE_0='@echo " ITMRG " [$]@;' +AC_SUBST(INTLTOOL_V_MERGE) +AC_SUBST(INTLTOOL__v_MERGE_) +AC_SUBST(INTLTOOL__v_MERGE_0) + +INTLTOOL_V_MERGE_OPTIONS='$(intltool__v_merge_options_$(V))' +intltool__v_merge_options_='$(intltool__v_merge_options_$(AM_DEFAULT_VERBOSITY))' +intltool__v_merge_options_0='-q' +AC_SUBST(INTLTOOL_V_MERGE_OPTIONS) +AC_SUBST(intltool__v_merge_options_) +AC_SUBST(intltool__v_merge_options_0) + + INTLTOOL_DESKTOP_RULE='%.desktop: %.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' +INTLTOOL_DIRECTORY_RULE='%.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_KEYS_RULE='%.keys: %.keys.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -k -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_PROP_RULE='%.prop: %.prop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_OAF_RULE='%.oaf: %.oaf.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -o -p $(top_srcdir)/po $< [$]@' + INTLTOOL_PONG_RULE='%.pong: %.pong.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_SERVER_RULE='%.server: %.server.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -o -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_SHEET_RULE='%.sheet: %.sheet.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' +INTLTOOL_SOUNDLIST_RULE='%.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_UI_RULE='%.ui: %.ui.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_XML_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' +if test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge 5000; then + INTLTOOL_XML_NOMERGE_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u --no-translations $< [$]@' +else + INTLTOOL_XML_NOMERGE_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) ; $(INTLTOOL_V_MERGE)_it_tmp_dir=tmp.intltool.[$][$]RANDOM && mkdir [$][$]_it_tmp_dir && LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u [$][$]_it_tmp_dir $< [$]@ && rmdir [$][$]_it_tmp_dir' +fi + INTLTOOL_XAM_RULE='%.xam: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_KBD_RULE='%.kbd: %.kbd.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -m -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_CAVES_RULE='%.caves: %.caves.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_SCHEMAS_RULE='%.schemas: %.schemas.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -s -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_THEME_RULE='%.theme: %.theme.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_SERVICE_RULE='%.service: %.service.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_POLICY_RULE='%.policy: %.policy.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + +_IT_SUBST(INTLTOOL_DESKTOP_RULE) +_IT_SUBST(INTLTOOL_DIRECTORY_RULE) +_IT_SUBST(INTLTOOL_KEYS_RULE) +_IT_SUBST(INTLTOOL_PROP_RULE) +_IT_SUBST(INTLTOOL_OAF_RULE) +_IT_SUBST(INTLTOOL_PONG_RULE) +_IT_SUBST(INTLTOOL_SERVER_RULE) +_IT_SUBST(INTLTOOL_SHEET_RULE) +_IT_SUBST(INTLTOOL_SOUNDLIST_RULE) +_IT_SUBST(INTLTOOL_UI_RULE) +_IT_SUBST(INTLTOOL_XAM_RULE) +_IT_SUBST(INTLTOOL_KBD_RULE) +_IT_SUBST(INTLTOOL_XML_RULE) +_IT_SUBST(INTLTOOL_XML_NOMERGE_RULE) +_IT_SUBST(INTLTOOL_CAVES_RULE) +_IT_SUBST(INTLTOOL_SCHEMAS_RULE) +_IT_SUBST(INTLTOOL_THEME_RULE) +_IT_SUBST(INTLTOOL_SERVICE_RULE) +_IT_SUBST(INTLTOOL_POLICY_RULE) + +# Check the gettext tools to make sure they are GNU +AC_PATH_PROG(XGETTEXT, xgettext) +AC_PATH_PROG(MSGMERGE, msgmerge) +AC_PATH_PROG(MSGFMT, msgfmt) +AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) +if test -z "$XGETTEXT" -o -z "$MSGMERGE" -o -z "$MSGFMT"; then + AC_MSG_ERROR([GNU gettext tools not found; required for intltool]) +fi +xgversion="`$XGETTEXT --version|grep '(GNU ' 2> /dev/null`" +mmversion="`$MSGMERGE --version|grep '(GNU ' 2> /dev/null`" +mfversion="`$MSGFMT --version|grep '(GNU ' 2> /dev/null`" +if test -z "$xgversion" -o -z "$mmversion" -o -z "$mfversion"; then + AC_MSG_ERROR([GNU gettext tools not found; required for intltool]) +fi + +AC_PATH_PROG(INTLTOOL_PERL, perl) +if test -z "$INTLTOOL_PERL"; then + AC_MSG_ERROR([perl not found]) +fi +AC_MSG_CHECKING([for perl >= 5.8.1]) +$INTLTOOL_PERL -e "use 5.8.1;" > /dev/null 2>&1 +if test $? -ne 0; then + AC_MSG_ERROR([perl 5.8.1 is required for intltool]) +else + IT_PERL_VERSION=`$INTLTOOL_PERL -e "printf '%vd', $^V"` + AC_MSG_RESULT([$IT_PERL_VERSION]) +fi +if test "x$2" != "xno-xml"; then + AC_MSG_CHECKING([for XML::Parser]) + if `$INTLTOOL_PERL -e "require XML::Parser" 2>/dev/null`; then + AC_MSG_RESULT([ok]) + else + AC_MSG_ERROR([XML::Parser perl module is required for intltool]) + fi +fi + +# Substitute ALL_LINGUAS so we can use it in po/Makefile +AC_SUBST(ALL_LINGUAS) + +# Set DATADIRNAME correctly if it is not set yet +# (copied from glib-gettext.m4) +if test -z "$DATADIRNAME"; then + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[]], + [[extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr]])], + [DATADIRNAME=share], + [case $host in + *-*-solaris*) + dnl On Solaris, if bind_textdomain_codeset is in libc, + dnl GNU format message catalog is always supported, + dnl since both are added to the libc all together. + dnl Hence, we'd like to go with DATADIRNAME=share + dnl in this case. + AC_CHECK_FUNC(bind_textdomain_codeset, + [DATADIRNAME=share], [DATADIRNAME=lib]) + ;; + *) + [DATADIRNAME=lib] + ;; + esac]) +fi +AC_SUBST(DATADIRNAME) + +IT_PO_SUBDIR([po]) + +]) + + +# IT_PO_SUBDIR(DIRNAME) +# --------------------- +# All po subdirs have to be declared with this macro; the subdir "po" is +# declared by IT_PROG_INTLTOOL. +# +AC_DEFUN([IT_PO_SUBDIR], +[AC_PREREQ([2.53])dnl We use ac_top_srcdir inside AC_CONFIG_COMMANDS. +dnl +dnl The following CONFIG_COMMANDS should be executed at the very end +dnl of config.status. +AC_CONFIG_COMMANDS_PRE([ + AC_CONFIG_COMMANDS([$1/stamp-it], [ + if [ ! grep "^# INTLTOOL_MAKEFILE$" "$1/Makefile.in" > /dev/null ]; then + AC_MSG_ERROR([$1/Makefile.in.in was not created by intltoolize.]) + fi + rm -f "$1/stamp-it" "$1/stamp-it.tmp" "$1/POTFILES" "$1/Makefile.tmp" + >"$1/stamp-it.tmp" + [sed '/^#/d + s/^[[].*] *// + /^[ ]*$/d + '"s|^| $ac_top_srcdir/|" \ + "$srcdir/$1/POTFILES.in" | sed '$!s/$/ \\/' >"$1/POTFILES" + ] + [sed '/^POTFILES =/,/[^\\]$/ { + /^POTFILES =/!d + r $1/POTFILES + } + ' "$1/Makefile.in" >"$1/Makefile"] + rm -f "$1/Makefile.tmp" + mv "$1/stamp-it.tmp" "$1/stamp-it" + ]) +])dnl +]) + +# _IT_SUBST(VARIABLE) +# ------------------- +# Abstract macro to do either _AM_SUBST_NOTMAKE or AC_SUBST +# +AC_DEFUN([_IT_SUBST], +[ +AC_SUBST([$1]) +m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([$1])]) +] +) + +# deprecated macros +AU_ALIAS([AC_PROG_INTLTOOL], [IT_PROG_INTLTOOL]) +# A hint is needed for aclocal from Automake <= 1.9.4: +# AC_DEFUN([AC_PROG_INTLTOOL], ...) + + +# nls.m4 serial 5 (gettext-0.18) +dnl Copyright (C) 1995-2003, 2005-2006, 2008-2010 Free Software Foundation, +dnl Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2003. + +AC_PREREQ([2.50]) + +AC_DEFUN([AM_NLS], +[ + AC_MSG_CHECKING([whether NLS is requested]) + dnl Default is enabled NLS + AC_ARG_ENABLE([nls], + [ --disable-nls do not use Native Language Support], + USE_NLS=$enableval, USE_NLS=yes) + AC_MSG_RESULT([$USE_NLS]) + AC_SUBST([USE_NLS]) +]) + +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# serial 1 (pkg-config-0.24) +# +# Copyright Š 2004 Scott James Remnant . +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# PKG_PROG_PKG_CONFIG([MIN-VERSION]) +# ---------------------------------- +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])# PKG_PROG_PKG_CONFIG + +# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# +# Check to see whether a particular set of modules exists. Similar +# to PKG_CHECK_MODULES(), but does not set variables or print errors. +# +# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +# only at the first occurence in configure.ac, so if the first place +# it's called might be skipped (such as if it is within an "if", you +# have to call PKG_CHECK_EXISTS manually +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +# --------------------------------------------- +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])# _PKG_CONFIG + +# _PKG_SHORT_ERRORS_SUPPORTED +# ----------------------------- +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])# _PKG_SHORT_ERRORS_SUPPORTED + + +# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# +# +# Note that if there is a possibility the first call to +# PKG_CHECK_MODULES might not happen, you should be sure to include an +# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +# +# +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])# PKG_CHECK_MODULES + +# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008, 2011 Free Software +# Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.11' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.11.5], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.11.5])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 9 + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ(2.52)dnl + ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009, +# 2010, 2011 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 12 + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "GCJ", or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], UPC, [depcc="$UPC" am_compiler_list=], + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +#serial 5 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2008, 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 16 + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.62])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AM_PROG_MKDIR_P])dnl +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES(OBJC)], + [define([AC_PROG_OBJC], + defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl +]) +_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl +dnl The `parallel-tests' driver may need to know about EXEEXT, so add the +dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro +dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl +]) + +dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001, 2003, 2005, 2008, 2011 Free Software Foundation, +# Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST(install_sh)]) + +# Copyright (C) 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- +# From Jim Meyering + +# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008, +# 2011 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# AM_MAINTAINER_MODE([DEFAULT-MODE]) +# ---------------------------------- +# Control maintainer-specific portions of Makefiles. +# Default is to disable them, unless `enable' is passed literally. +# For symmetry, `disable' may be passed as well. Anyway, the user +# can override the default with the --enable/--disable switch. +AC_DEFUN([AM_MAINTAINER_MODE], +[m4_case(m4_default([$1], [disable]), + [enable], [m4_define([am_maintainer_other], [disable])], + [disable], [m4_define([am_maintainer_other], [enable])], + [m4_define([am_maintainer_other], [enable]) + m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) +AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode's default is 'disable' unless 'enable' is passed + AC_ARG_ENABLE([maintainer-mode], +[ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful + (and sometimes confusing) to the casual installer], + [USE_MAINTAINER_MODE=$enableval], + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) + AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST([MAINT])dnl +] +) + +AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 4 + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 6 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# Copyright (C) 2003, 2004, 2005, 2006, 2011 Free Software Foundation, +# Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# AM_PROG_MKDIR_P +# --------------- +# Check for `mkdir -p'. +AC_DEFUN([AM_PROG_MKDIR_P], +[AC_PREREQ([2.60])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, +dnl while keeping a definition of mkdir_p for backward compatibility. +dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. +dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of +dnl Makefile.ins that do not define MKDIR_P, so we do our own +dnl adjustment using top_builddir (which is defined more often than +dnl MKDIR_P). +AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl +case $mkdir_p in + [[\\/$]]* | ?:[[\\/]]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2008, 2010 Free Software +# Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; +esac + +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + +# Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006, 2008, 2010 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 3 + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004, 2005, 2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of `v7', `ustar', or `pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of `-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + diff --git a/jni/desmume/autogen.sh b/jni/desmume/autogen.sh new file mode 100755 index 0000000..56c493b --- /dev/null +++ b/jni/desmume/autogen.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# intltoolize is optionnal as it's only required for the gtk-glade UI. + +if test ! "x$(which intltoolize)" = "x"; then + echo "Running intltoolize" + intltoolize --copy --force --automake +else + if test ! "x$(which gintltoolize)" = "x"; then + echo "Running gintltoolize" + gintltoolize --copy --force --automake + fi +fi + +autoreconf --install --force --verbose diff --git a/jni/desmume/compile b/jni/desmume/compile new file mode 100755 index 0000000..1b1d232 --- /dev/null +++ b/jni/desmume/compile @@ -0,0 +1,142 @@ +#! /bin/sh +# Wrapper for compilers which do not understand `-c -o'. + +scriptversion=2005-05-14.22 + +# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# 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, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand `-c -o'. +Remove `-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file `INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; +esac + +ofile= +cfile= +eat= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as `compile cc -o foo foo.c'. + # So we strip `-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no `-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # `.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'` + +# Create the lock directory. +# Note: use `[/.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/jni/desmume/config.guess b/jni/desmume/config.guess new file mode 100755 index 0000000..d622a44 --- /dev/null +++ b/jni/desmume/config.guess @@ -0,0 +1,1530 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +timestamp='2012-02-10' + +# This file 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, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/jni/desmume/config.sub b/jni/desmume/config.sub new file mode 100755 index 0000000..c894da4 --- /dev/null +++ b/jni/desmume/config.sub @@ -0,0 +1,1773 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +timestamp='2012-02-10' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file 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, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 \ + | ns16k | ns32k \ + | open8 \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i386-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/jni/desmume/configure b/jni/desmume/configure new file mode 100755 index 0000000..b9298ef --- /dev/null +++ b/jni/desmume/configure @@ -0,0 +1,10423 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.68 for desmume 0.9.8. +# +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software +# Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + # We cannot yet assume a decent shell, so we have to provide a + # neutralization value for shells without unset; and this also + # works around shells that cannot unset nonexistent variables. + # Preserve -v and -x to the replacement shell. + BASH_ENV=/dev/null + ENV=/dev/null + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV + export CONFIG_SHELL + case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; + esac + exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='desmume' +PACKAGE_TARNAME='desmume' +PACKAGE_VERSION='0.9.8' +PACKAGE_STRING='desmume 0.9.8' +PACKAGE_BUGREPORT='' +PACKAGE_URL='' + +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +USE_MAINTAINER_MODE +MAINT +MAINTAINER_MODE_FALSE +MAINTAINER_MODE_TRUE +HAVE_GDB_STUB_FALSE +HAVE_GDB_STUB_TRUE +PO_DIR +UI_DIR +X_EXTRA_LIBS +X_LIBS +X_PRE_LIBS +X_CFLAGS +XMKMF +MKINSTALLDIRS +POSUB +POFILES +PO_IN_DATADIR_FALSE +PO_IN_DATADIR_TRUE +INTLLIBS +INSTOBJEXT +GMOFILES +CATOBJEXT +CATALOGS +MSGFMT_OPTS +GETTEXT_PACKAGE +HAVE_WX_FALSE +HAVE_WX_TRUE +WX_RESCOMP +WX_VERSION +WX_LIBS_STATIC +WX_LIBS +WX_CXXFLAGS_ONLY +WX_CFLAGS_ONLY +WX_CXXFLAGS +WX_CFLAGS +WX_CPPFLAGS +WX_CONFIG_PATH +HAVE_LIBSOUNDTOUCH_FALSE +HAVE_LIBSOUNDTOUCH_TRUE +LIBSOUNDTOUCH_LIBS +LIBSOUNDTOUCH_CFLAGS +HAVE_LIBAGG_FALSE +HAVE_LIBAGG_TRUE +LIBAGG_LIBS +LIBAGG_CFLAGS +HAVE_ALSA_FALSE +HAVE_ALSA_TRUE +ALSA_LIBS +ALSA_CFLAGS +HAVE_LUA_FALSE +HAVE_LUA_TRUE +LUA_LIBS +LUA_CFLAGS +UPDATEDESKTOP +GTKGLEXT_LIBS +GTKGLEXT_CFLAGS +GLADEUI_UNINSTALLED_DIR +LIBGLADE_LIBS +LIBGLADE_CFLAGS +GTHREAD_LIBS +GTHREAD_CFLAGS +GTK_LIBS +GTK_CFLAGS +GLIB_LIBS +GLIB_CFLAGS +HAVE_OPENAL_FALSE +HAVE_OPENAL_TRUE +HAVE_LIBOSMESA_FALSE +HAVE_LIBOSMESA_TRUE +OSMESA_LIBS +HAVE_GL_FALSE +HAVE_GL_TRUE +SDL_LIBS +SDL_CFLAGS +SDLCONFIG +HAVE_PKG +DATADIRNAME +ALL_LINGUAS +INTLTOOL_PERL +GMSGFMT +MSGFMT +MSGMERGE +XGETTEXT +INTLTOOL_POLICY_RULE +INTLTOOL_SERVICE_RULE +INTLTOOL_THEME_RULE +INTLTOOL_SCHEMAS_RULE +INTLTOOL_CAVES_RULE +INTLTOOL_XML_NOMERGE_RULE +INTLTOOL_XML_RULE +INTLTOOL_KBD_RULE +INTLTOOL_XAM_RULE +INTLTOOL_UI_RULE +INTLTOOL_SOUNDLIST_RULE +INTLTOOL_SHEET_RULE +INTLTOOL_SERVER_RULE +INTLTOOL_PONG_RULE +INTLTOOL_OAF_RULE +INTLTOOL_PROP_RULE +INTLTOOL_KEYS_RULE +INTLTOOL_DIRECTORY_RULE +INTLTOOL_DESKTOP_RULE +intltool__v_merge_options_0 +intltool__v_merge_options_ +INTLTOOL_V_MERGE_OPTIONS +INTLTOOL__v_MERGE_0 +INTLTOOL__v_MERGE_ +INTLTOOL_V_MERGE +AM_DEFAULT_VERBOSITY +INTLTOOL_EXTRACT +INTLTOOL_MERGE +INTLTOOL_UPDATE +USE_NLS +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG +EGREP +GREP +CPP +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +ac_ct_CC +CFLAGS +CC +RANLIB +am__fastdepCXX_FALSE +am__fastdepCXX_TRUE +CXXDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CXX +CPPFLAGS +LDFLAGS +CXXFLAGS +CXX +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +desmume_arch +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_dependency_tracking +enable_nls +enable_osmesa +enable_hud +enable_macosxhack +enable_openal +enable_glade +enable_wxwidgets +enable_wifi +with_x +enable_gdb_stub +enable_hardcore +enable_debug +enable_gpu_debug +enable_div_debug +enable_sqrt_debug +enable_dma_debug +enable_maintainer_mode +' + ac_precious_vars='build_alias +host_alias +target_alias +CXX +CXXFLAGS +LDFLAGS +LIBS +CPPFLAGS +CCC +CC +CFLAGS +CPP +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR +GLIB_CFLAGS +GLIB_LIBS +GTK_CFLAGS +GTK_LIBS +GTHREAD_CFLAGS +GTHREAD_LIBS +LIBGLADE_CFLAGS +LIBGLADE_LIBS +GTKGLEXT_CFLAGS +GTKGLEXT_LIBS +LUA_CFLAGS +LUA_LIBS +ALSA_CFLAGS +ALSA_LIBS +LIBAGG_CFLAGS +LIBAGG_LIBS +LIBSOUNDTOUCH_CFLAGS +LIBSOUNDTOUCH_LIBS +XMKMF' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used" >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures desmume 0.9.8 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/desmume] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +X features: + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of desmume 0.9.8:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors + --disable-nls do not use Native Language Support + --enable-osmesa use off-screen mesa + --enable-hud Enable HUD rendering, requires libagg + --enable-macosxhack hack to build MacOSX package + --enable-openal enable experimental OpenAL microphone input + --enable-glade enable glade frontend + --enable-wxwidgets Enable cross platform wx widgets frontend + --enable-wifi enable experimental wifi comm support + --enable-gdb-stub enable gdb stub + --enable-hardcore turn on -W -Wall -Werror + --enable-debug enable debug information + --enable-gpu-debug enable gpu debug information + --enable-div-debug enable div debug information + --enable-sqrt-debug enable sqrt debug information + --enable-dma-debug enable dma debug information + --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-x use the X Window System + +Some influential environment variables: + CXX C++ compiler command + CXXFLAGS C++ compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CC C compiler command + CFLAGS C compiler flags + CPP C preprocessor + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path + GLIB_CFLAGS C compiler flags for GLIB, overriding pkg-config + GLIB_LIBS linker flags for GLIB, overriding pkg-config + GTK_CFLAGS C compiler flags for GTK, overriding pkg-config + GTK_LIBS linker flags for GTK, overriding pkg-config + GTHREAD_CFLAGS + C compiler flags for GTHREAD, overriding pkg-config + GTHREAD_LIBS + linker flags for GTHREAD, overriding pkg-config + LIBGLADE_CFLAGS + C compiler flags for LIBGLADE, overriding pkg-config + LIBGLADE_LIBS + linker flags for LIBGLADE, overriding pkg-config + GTKGLEXT_CFLAGS + C compiler flags for GTKGLEXT, overriding pkg-config + GTKGLEXT_LIBS + linker flags for GTKGLEXT, overriding pkg-config + LUA_CFLAGS C compiler flags for LUA, overriding pkg-config + LUA_LIBS linker flags for LUA, overriding pkg-config + ALSA_CFLAGS C compiler flags for ALSA, overriding pkg-config + ALSA_LIBS linker flags for ALSA, overriding pkg-config + LIBAGG_CFLAGS + C compiler flags for LIBAGG, overriding pkg-config + LIBAGG_LIBS linker flags for LIBAGG, overriding pkg-config + LIBSOUNDTOUCH_CFLAGS + C compiler flags for LIBSOUNDTOUCH, overriding pkg-config + LIBSOUNDTOUCH_LIBS + linker flags for LIBSOUNDTOUCH, overriding pkg-config + XMKMF Path to xmkmf, Makefile generator for X Window System + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +desmume configure 0.9.8 +generated by GNU Autoconf 2.68 + +Copyright (C) 2010 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_compile + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by desmume $as_me 0.9.8, which was +generated by GNU Autoconf 2.68. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +case $host in + *linux*) desmume_arch=linux;; + *mingw*) desmume_arch=windows;; + *darwin*) desmume_arch=linux;; + *bsd*) desmume_arch=linux;; +esac + + +am__api_version='1.11' + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Just in case +sleep 1 +echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;; +esac + +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken +alias in your environment" "$LINENO" 5 + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +mkdir_p="$MKDIR_P" +case $mkdir_p in + [\\/$]* | ?:[\\/]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='desmume' + VERSION='0.9.8' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' + + + + + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler works" >&5 +$as_echo_n "checking whether the C++ compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C++ compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler default output file name" >&5 +$as_echo_n "checking for C++ compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C++ compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 +$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } +if ${ac_cv_cxx_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +$as_echo_n "checking whether $CXX accepts -g... " >&6; } +if ${ac_cv_prog_cxx_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +else + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +$as_echo "$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + +depcc="$CXX" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CXX_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + + +# took this from geany, hope it works +REVISION="r0" +SVN=`which svn 2>/dev/null` +if test -d ".svn" -a "x${SVN}" != "x" -a -x "${SVN}" ; then + REVISION=r`$SVN info|grep 'Last Changed Rev'|cut -d' ' -f4` +fi + +cat >>confdefs.h <<_ACEOF +#define SVN_REV "$REVISION" +_ACEOF + + + + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NLS is requested" >&5 +$as_echo_n "checking whether NLS is requested... " >&6; } + # Check whether --enable-nls was given. +if test "${enable_nls+set}" = set; then : + enableval=$enable_nls; USE_NLS=$enableval +else + USE_NLS=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 +$as_echo "$USE_NLS" >&6; } + + + + +case "$am__api_version" in + 1.01234) + as_fn_error $? "Automake 1.5 or newer is required to use intltool" "$LINENO" 5 + ;; + *) + ;; +esac + +INTLTOOL_REQUIRED_VERSION_AS_INT=`echo | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'` +INTLTOOL_APPLIED_VERSION=`intltool-update --version | head -1 | cut -d" " -f3` +INTLTOOL_APPLIED_VERSION_AS_INT=`echo $INTLTOOL_APPLIED_VERSION | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'` +if test -n ""; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for intltool >= " >&5 +$as_echo_n "checking for intltool >= ... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLTOOL_APPLIED_VERSION found" >&5 +$as_echo "$INTLTOOL_APPLIED_VERSION found" >&6; } + test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge "$INTLTOOL_REQUIRED_VERSION_AS_INT" || + as_fn_error $? "Your intltool is too old. You need intltool or later." "$LINENO" 5 +fi + +# Extract the first word of "intltool-update", so it can be a program name with args. +set dummy intltool-update; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_INTLTOOL_UPDATE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $INTLTOOL_UPDATE in + [\\/]* | ?:[\\/]*) + ac_cv_path_INTLTOOL_UPDATE="$INTLTOOL_UPDATE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_INTLTOOL_UPDATE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +INTLTOOL_UPDATE=$ac_cv_path_INTLTOOL_UPDATE +if test -n "$INTLTOOL_UPDATE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLTOOL_UPDATE" >&5 +$as_echo "$INTLTOOL_UPDATE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "intltool-merge", so it can be a program name with args. +set dummy intltool-merge; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_INTLTOOL_MERGE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $INTLTOOL_MERGE in + [\\/]* | ?:[\\/]*) + ac_cv_path_INTLTOOL_MERGE="$INTLTOOL_MERGE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_INTLTOOL_MERGE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +INTLTOOL_MERGE=$ac_cv_path_INTLTOOL_MERGE +if test -n "$INTLTOOL_MERGE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLTOOL_MERGE" >&5 +$as_echo "$INTLTOOL_MERGE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "intltool-extract", so it can be a program name with args. +set dummy intltool-extract; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_INTLTOOL_EXTRACT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $INTLTOOL_EXTRACT in + [\\/]* | ?:[\\/]*) + ac_cv_path_INTLTOOL_EXTRACT="$INTLTOOL_EXTRACT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_INTLTOOL_EXTRACT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +INTLTOOL_EXTRACT=$ac_cv_path_INTLTOOL_EXTRACT +if test -n "$INTLTOOL_EXTRACT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLTOOL_EXTRACT" >&5 +$as_echo "$INTLTOOL_EXTRACT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test -z "$INTLTOOL_UPDATE" -o -z "$INTLTOOL_MERGE" -o -z "$INTLTOOL_EXTRACT"; then + as_fn_error $? "The intltool scripts were not found. Please install intltool." "$LINENO" 5 +fi + +if test -z "$AM_DEFAULT_VERBOSITY"; then + AM_DEFAULT_VERBOSITY=1 +fi + + +INTLTOOL_V_MERGE='$(INTLTOOL__v_MERGE_$(V))' +INTLTOOL__v_MERGE_='$(INTLTOOL__v_MERGE_$(AM_DEFAULT_VERBOSITY))' +INTLTOOL__v_MERGE_0='@echo " ITMRG " $@;' + + + + +INTLTOOL_V_MERGE_OPTIONS='$(intltool__v_merge_options_$(V))' +intltool__v_merge_options_='$(intltool__v_merge_options_$(AM_DEFAULT_VERBOSITY))' +intltool__v_merge_options_0='-q' + + + + + INTLTOOL_DESKTOP_RULE='%.desktop: %.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' +INTLTOOL_DIRECTORY_RULE='%.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_KEYS_RULE='%.keys: %.keys.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -k -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_PROP_RULE='%.prop: %.prop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_OAF_RULE='%.oaf: %.oaf.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -o -p $(top_srcdir)/po $< $@' + INTLTOOL_PONG_RULE='%.pong: %.pong.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_SERVER_RULE='%.server: %.server.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -o -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_SHEET_RULE='%.sheet: %.sheet.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' +INTLTOOL_SOUNDLIST_RULE='%.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_UI_RULE='%.ui: %.ui.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_XML_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' +if test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge 5000; then + INTLTOOL_XML_NOMERGE_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u --no-translations $< $@' +else + INTLTOOL_XML_NOMERGE_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) ; $(INTLTOOL_V_MERGE)_it_tmp_dir=tmp.intltool.$$RANDOM && mkdir $$_it_tmp_dir && LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u $$_it_tmp_dir $< $@ && rmdir $$_it_tmp_dir' +fi + INTLTOOL_XAM_RULE='%.xam: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_KBD_RULE='%.kbd: %.kbd.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -m -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_CAVES_RULE='%.caves: %.caves.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_SCHEMAS_RULE='%.schemas: %.schemas.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -s -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_THEME_RULE='%.theme: %.theme.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_SERVICE_RULE='%.service: %.service.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_POLICY_RULE='%.policy: %.policy.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# Check the gettext tools to make sure they are GNU +# Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_XGETTEXT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $XGETTEXT in + [\\/]* | ?:[\\/]*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_XGETTEXT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +XGETTEXT=$ac_cv_path_XGETTEXT +if test -n "$XGETTEXT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 +$as_echo "$XGETTEXT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "msgmerge", so it can be a program name with args. +set dummy msgmerge; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MSGMERGE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MSGMERGE in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGMERGE="$MSGMERGE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_MSGMERGE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +MSGMERGE=$ac_cv_path_MSGMERGE +if test -n "$MSGMERGE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGMERGE" >&5 +$as_echo "$MSGMERGE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MSGFMT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MSGFMT in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_MSGFMT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +MSGFMT=$ac_cv_path_MSGFMT +if test -n "$MSGFMT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 +$as_echo "$MSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GMSGFMT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GMSGFMT in + [\\/]* | ?:[\\/]*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT=$ac_cv_path_GMSGFMT +if test -n "$GMSGFMT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 +$as_echo "$GMSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test -z "$XGETTEXT" -o -z "$MSGMERGE" -o -z "$MSGFMT"; then + as_fn_error $? "GNU gettext tools not found; required for intltool" "$LINENO" 5 +fi +xgversion="`$XGETTEXT --version|grep '(GNU ' 2> /dev/null`" +mmversion="`$MSGMERGE --version|grep '(GNU ' 2> /dev/null`" +mfversion="`$MSGFMT --version|grep '(GNU ' 2> /dev/null`" +if test -z "$xgversion" -o -z "$mmversion" -o -z "$mfversion"; then + as_fn_error $? "GNU gettext tools not found; required for intltool" "$LINENO" 5 +fi + +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_INTLTOOL_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $INTLTOOL_PERL in + [\\/]* | ?:[\\/]*) + ac_cv_path_INTLTOOL_PERL="$INTLTOOL_PERL" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_INTLTOOL_PERL="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +INTLTOOL_PERL=$ac_cv_path_INTLTOOL_PERL +if test -n "$INTLTOOL_PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLTOOL_PERL" >&5 +$as_echo "$INTLTOOL_PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test -z "$INTLTOOL_PERL"; then + as_fn_error $? "perl not found" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl >= 5.8.1" >&5 +$as_echo_n "checking for perl >= 5.8.1... " >&6; } +$INTLTOOL_PERL -e "use 5.8.1;" > /dev/null 2>&1 +if test $? -ne 0; then + as_fn_error $? "perl 5.8.1 is required for intltool" "$LINENO" 5 +else + IT_PERL_VERSION=`$INTLTOOL_PERL -e "printf '%vd', $^V"` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $IT_PERL_VERSION" >&5 +$as_echo "$IT_PERL_VERSION" >&6; } +fi +if test "x" != "xno-xml"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XML::Parser" >&5 +$as_echo_n "checking for XML::Parser... " >&6; } + if `$INTLTOOL_PERL -e "require XML::Parser" 2>/dev/null`; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } + else + as_fn_error $? "XML::Parser perl module is required for intltool" "$LINENO" 5 + fi +fi + +# Substitute ALL_LINGUAS so we can use it in po/Makefile + + +# Set DATADIRNAME correctly if it is not set yet +# (copied from glib-gettext.m4) +if test -z "$DATADIRNAME"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + DATADIRNAME=share +else + case $host in + *-*-solaris*) + ac_fn_c_check_func "$LINENO" "bind_textdomain_codeset" "ac_cv_func_bind_textdomain_codeset" +if test "x$ac_cv_func_bind_textdomain_codeset" = xyes; then : + DATADIRNAME=share +else + DATADIRNAME=lib +fi + + ;; + *) + DATADIRNAME=lib + ;; + esac +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_HAVE_PKG+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$HAVE_PKG"; then + ac_cv_prog_HAVE_PKG="$HAVE_PKG" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_HAVE_PKG="${ac_tool_prefix}pkg-config" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +HAVE_PKG=$ac_cv_prog_HAVE_PKG +if test -n "$HAVE_PKG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_PKG" >&5 +$as_echo "$HAVE_PKG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_HAVE_PKG"; then + ac_ct_HAVE_PKG=$HAVE_PKG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_HAVE_PKG+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_HAVE_PKG"; then + ac_cv_prog_ac_ct_HAVE_PKG="$ac_ct_HAVE_PKG" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_HAVE_PKG="pkg-config" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_HAVE_PKG=$ac_cv_prog_ac_ct_HAVE_PKG +if test -n "$ac_ct_HAVE_PKG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_HAVE_PKG" >&5 +$as_echo "$ac_ct_HAVE_PKG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_HAVE_PKG" = x; then + HAVE_PKG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + HAVE_PKG=$ac_ct_HAVE_PKG + fi +else + HAVE_PKG="$ac_cv_prog_HAVE_PKG" +fi + +if test "xHAVE_PKG" = "x" ; then + as_fn_error $? "pkg-config is required to build desmume" "$LINENO" 5 +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gzopen in -lz" >&5 +$as_echo_n "checking for gzopen in -lz... " >&6; } +if ${ac_cv_lib_z_gzopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gzopen (); +int +main () +{ +return gzopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_z_gzopen=yes +else + ac_cv_lib_z_gzopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_gzopen" >&5 +$as_echo "$ac_cv_lib_z_gzopen" >&6; } +if test "x$ac_cv_lib_z_gzopen" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBZ 1 +_ACEOF + + LIBS="-lz $LIBS" + +else + as_fn_error $? "zlib was not found, we can't go further. Please install it or specify the location where it's installed." "$LINENO" 5 +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for zzip_open in -lzzip" >&5 +$as_echo_n "checking for zzip_open in -lzzip... " >&6; } +if ${ac_cv_lib_zzip_zzip_open+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lzzip $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char zzip_open (); +int +main () +{ +return zzip_open (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_zzip_zzip_open=yes +else + ac_cv_lib_zzip_zzip_open=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_zzip_zzip_open" >&5 +$as_echo "$ac_cv_lib_zzip_zzip_open" >&6; } +if test "x$ac_cv_lib_zzip_zzip_open" = xyes; then : + + LIBS="-lzzip $LIBS" + $as_echo "#define HAVE_LIBZZIP 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether zzip use void * as second parameter" >&5 +$as_echo_n "checking whether zzip use void * as second parameter... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + + void * v; + zzip_read(NULL, v, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + $as_echo "#define ZZIP_OLD_READ 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi + + +for ac_prog in sdl-config sdl11-config +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_SDLCONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $SDLCONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_SDLCONFIG="$SDLCONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_SDLCONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +SDLCONFIG=$ac_cv_path_SDLCONFIG +if test -n "$SDLCONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SDLCONFIG" >&5 +$as_echo "$SDLCONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$SDLCONFIG" && break +done + +if test ! "x$SDLCONFIG" = "x" ; then + SDL_CFLAGS=`$SDLCONFIG --cflags` + SDL_LIBS=`$SDLCONFIG --libs` + + +else + as_fn_error $? "sdl is required to build desmume" "$LINENO" 5 +fi + +for ac_header in GL/gl.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "GL/gl.h" "ac_cv_header_GL_gl_h" "$ac_includes_default" +if test "x$ac_cv_header_GL_gl_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GL_GL_H 1 +_ACEOF + for ac_header in GL/glu.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "GL/glu.h" "ac_cv_header_GL_glu_h" "$ac_includes_default" +if test "x$ac_cv_header_GL_glu_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GL_GLU_H 1 +_ACEOF + have_gl_h=yes LIBS="$LIBS -lGLU" +else + have_gl_h=no +fi + +done + +else + have_gl_h=no +fi + +done + +if test "have_gl_h" = "no" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Building without GL support because of missing headers." >&5 +$as_echo "$as_me: WARNING: Building without GL support because of missing headers." >&2;} +fi + if test "${have_gl_h}" = "yes"; then + HAVE_GL_TRUE= + HAVE_GL_FALSE='#' +else + HAVE_GL_TRUE='#' + HAVE_GL_FALSE= +fi + + +# Check whether --enable-osmesa was given. +if test "${enable_osmesa+set}" = set; then : + enableval=$enable_osmesa; osmesa=$enableval +else + osmesa=yes +fi + + +if test "x$osmesa" = "xyes" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -ldl" >&5 +$as_echo_n "checking for main in -ldl... " >&6; } +if ${ac_cv_lib_dl_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_main=yes +else + ac_cv_lib_dl_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_main" >&5 +$as_echo "$ac_cv_lib_dl_main" >&6; } +if test "x$ac_cv_lib_dl_main" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBDL 1 +_ACEOF + + LIBS="-ldl $LIBS" + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lGL" >&5 +$as_echo_n "checking for main in -lGL... " >&6; } +if ${ac_cv_lib_GL_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lGL $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_GL_main=yes +else + ac_cv_lib_GL_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_GL_main" >&5 +$as_echo "$ac_cv_lib_GL_main" >&6; } +if test "x$ac_cv_lib_GL_main" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBGL 1 +_ACEOF + + LIBS="-lGL $LIBS" + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lOSMesa" >&5 +$as_echo_n "checking for main in -lOSMesa... " >&6; } +if ${ac_cv_lib_OSMesa_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lOSMesa $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_OSMesa_main=yes +else + ac_cv_lib_OSMesa_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_OSMesa_main" >&5 +$as_echo "$ac_cv_lib_OSMesa_main" >&6; } +if test "x$ac_cv_lib_OSMesa_main" = xyes; then : + + useosmesa=yes + $as_echo "#define HAVE_LIBOSMESA 1" >>confdefs.h + + OSMESA_LIBS="-lOSMesa" + + +fi + +fi + if test "${useosmesa}" = "yes"; then + HAVE_LIBOSMESA_TRUE= + HAVE_LIBOSMESA_FALSE='#' +else + HAVE_LIBOSMESA_TRUE='#' + HAVE_LIBOSMESA_FALSE= +fi + + +# Check whether --enable-hud was given. +if test "${enable_hud+set}" = set; then : + enableval=$enable_hud; libagg=yes +fi + + +# Check whether --enable-macosxhack was given. +if test "${enable_macosxhack+set}" = set; then : + enableval=$enable_macosxhack; GTK_MACOSX_HACK=yes +fi + + +HAVE_OPENAL=no +# Check whether --enable-openal was given. +if test "${enable_openal+set}" = set; then : + enableval=$enable_openal; openal=yes +fi + + +if test "x$openal" = "xyes" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lopenal" >&5 +$as_echo_n "checking for main in -lopenal... " >&6; } +if ${ac_cv_lib_openal_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lopenal $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_openal_main=yes +else + ac_cv_lib_openal_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_openal_main" >&5 +$as_echo "$ac_cv_lib_openal_main" >&6; } +if test "x$ac_cv_lib_openal_main" = xyes; then : + + HAVE_OPENAL=yes + LIBS="$LIBS -lopenal" + +fi + +fi + if test "${HAVE_OPENAL}" = "yes"; then + HAVE_OPENAL_TRUE= + HAVE_OPENAL_FALSE='#' +else + HAVE_OPENAL_TRUE='#' + HAVE_OPENAL_FALSE= +fi + + +FOUND_GLIB=no +HAVE_ALSA=no +GLIB_VER=2.8 +GTK_VER=2.14 + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB" >&5 +$as_echo_n "checking for GLIB... " >&6; } + +if test -n "$GLIB_CFLAGS"; then + pkg_cv_GLIB_CFLAGS="$GLIB_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= \$GLIB_VER\""; } >&5 + ($PKG_CONFIG --exists --print-errors "glib-2.0 >= $GLIB_VER") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GLIB_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 >= $GLIB_VER" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GLIB_LIBS"; then + pkg_cv_GLIB_LIBS="$GLIB_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= \$GLIB_VER\""; } >&5 + ($PKG_CONFIG --exists --print-errors "glib-2.0 >= $GLIB_VER") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GLIB_LIBS=`$PKG_CONFIG --libs "glib-2.0 >= $GLIB_VER" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0 >= $GLIB_VER" 2>&1` + else + GLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0 >= $GLIB_VER" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GLIB_PKG_ERRORS" >&5 + + FOUND_GLIB=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + FOUND_GLIB=no +else + GLIB_CFLAGS=$pkg_cv_GLIB_CFLAGS + GLIB_LIBS=$pkg_cv_GLIB_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + FOUND_GLIB=yes +fi +if test "x$FOUND_GLIB" = "xno"; then + if test ! "x$GTK_MACOSX_HACK" = "xyes"; then + as_fn_error $? "Glib is required to build desmume" "$LINENO" 5 + fi +fi + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTK" >&5 +$as_echo_n "checking for GTK... " >&6; } + +if test -n "$GTK_CFLAGS"; then + pkg_cv_GTK_CFLAGS="$GTK_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-2.0 >= \$GTK_VER\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gtk+-2.0 >= $GTK_VER") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTK_CFLAGS=`$PKG_CONFIG --cflags "gtk+-2.0 >= $GTK_VER" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GTK_LIBS"; then + pkg_cv_GTK_LIBS="$GTK_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-2.0 >= \$GTK_VER\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gtk+-2.0 >= $GTK_VER") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTK_LIBS=`$PKG_CONFIG --libs "gtk+-2.0 >= $GTK_VER" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GTK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gtk+-2.0 >= $GTK_VER" 2>&1` + else + GTK_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gtk+-2.0 >= $GTK_VER" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GTK_PKG_ERRORS" >&5 + + HAVE_GTK=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + HAVE_GTK=no +else + GTK_CFLAGS=$pkg_cv_GTK_CFLAGS + GTK_LIBS=$pkg_cv_GTK_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + HAVE_GTK=yes +fi + + + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTHREAD" >&5 +$as_echo_n "checking for GTHREAD... " >&6; } + +if test -n "$GTHREAD_CFLAGS"; then + pkg_cv_GTHREAD_CFLAGS="$GTHREAD_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\"gthread-2.0\"\""; } >&5 + ($PKG_CONFIG --exists --print-errors ""gthread-2.0"") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTHREAD_CFLAGS=`$PKG_CONFIG --cflags ""gthread-2.0"" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GTHREAD_LIBS"; then + pkg_cv_GTHREAD_LIBS="$GTHREAD_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\"gthread-2.0\"\""; } >&5 + ($PKG_CONFIG --exists --print-errors ""gthread-2.0"") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTHREAD_LIBS=`$PKG_CONFIG --libs ""gthread-2.0"" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GTHREAD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs ""gthread-2.0"" 2>&1` + else + GTHREAD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs ""gthread-2.0"" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GTHREAD_PKG_ERRORS" >&5 + + HAVE_GTHREAD=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + HAVE_GTHREAD=no +else + GTHREAD_CFLAGS=$pkg_cv_GTHREAD_CFLAGS + GTHREAD_LIBS=$pkg_cv_GTHREAD_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + HAVE_GTHREAD=yes +fi + + + +# Check whether --enable-glade was given. +if test "${enable_glade+set}" = set; then : + enableval=$enable_glade; glade=$enableval +else + glade=yes +fi + + +if test "x$glade" = "xyes" ; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBGLADE" >&5 +$as_echo_n "checking for LIBGLADE... " >&6; } + +if test -n "$LIBGLADE_CFLAGS"; then + pkg_cv_LIBGLADE_CFLAGS="$LIBGLADE_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\"libglade-2.0\"\""; } >&5 + ($PKG_CONFIG --exists --print-errors ""libglade-2.0"") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBGLADE_CFLAGS=`$PKG_CONFIG --cflags ""libglade-2.0"" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBGLADE_LIBS"; then + pkg_cv_LIBGLADE_LIBS="$LIBGLADE_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\"libglade-2.0\"\""; } >&5 + ($PKG_CONFIG --exists --print-errors ""libglade-2.0"") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBGLADE_LIBS=`$PKG_CONFIG --libs ""libglade-2.0"" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LIBGLADE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs ""libglade-2.0"" 2>&1` + else + LIBGLADE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs ""libglade-2.0"" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBGLADE_PKG_ERRORS" >&5 + + HAVE_LIBGLADE=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + HAVE_LIBGLADE=no +else + LIBGLADE_CFLAGS=$pkg_cv_LIBGLADE_CFLAGS + LIBGLADE_LIBS=$pkg_cv_LIBGLADE_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + HAVE_LIBGLADE=yes +fi + + + + +cat >>confdefs.h <<_ACEOF +#define GLADEUI_UNINSTALLED_DIR "`pwd`/src/gtk-glade/glade/" +_ACEOF + + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTKGLEXT" >&5 +$as_echo_n "checking for GTKGLEXT... " >&6; } + +if test -n "$GTKGLEXT_CFLAGS"; then + pkg_cv_GTKGLEXT_CFLAGS="$GTKGLEXT_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\"gtkglext-1.0\"\""; } >&5 + ($PKG_CONFIG --exists --print-errors ""gtkglext-1.0"") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTKGLEXT_CFLAGS=`$PKG_CONFIG --cflags ""gtkglext-1.0"" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GTKGLEXT_LIBS"; then + pkg_cv_GTKGLEXT_LIBS="$GTKGLEXT_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\"gtkglext-1.0\"\""; } >&5 + ($PKG_CONFIG --exists --print-errors ""gtkglext-1.0"") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTKGLEXT_LIBS=`$PKG_CONFIG --libs ""gtkglext-1.0"" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GTKGLEXT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs ""gtkglext-1.0"" 2>&1` + else + GTKGLEXT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs ""gtkglext-1.0"" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GTKGLEXT_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (\"gtkglext-1.0\") were not met: + +$GTKGLEXT_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables GTKGLEXT_CFLAGS +and GTKGLEXT_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables GTKGLEXT_CFLAGS +and GTKGLEXT_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + GTKGLEXT_CFLAGS=$pkg_cv_GTKGLEXT_CFLAGS + GTKGLEXT_LIBS=$pkg_cv_GTKGLEXT_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + $as_echo "#define GTKGLEXT_AVAILABLE 1" >>confdefs.h + + +fi + + +fi + +# Extract the first word of "update-desktop-database", so it can be a program name with args. +set dummy update-desktop-database; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_UPDATEDESKTOP+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $UPDATEDESKTOP in + [\\/]* | ?:[\\/]*) + ac_cv_path_UPDATEDESKTOP="$UPDATEDESKTOP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_UPDATEDESKTOP="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +UPDATEDESKTOP=$ac_cv_path_UPDATEDESKTOP +if test -n "$UPDATEDESKTOP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $UPDATEDESKTOP" >&5 +$as_echo "$UPDATEDESKTOP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + +# Need check for both lua and lua5.1 to run on debian, see mysql bug #29945 + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LUA" >&5 +$as_echo_n "checking for LUA... " >&6; } + +if test -n "$LUA_CFLAGS"; then + pkg_cv_LUA_CFLAGS="$LUA_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua >= 5.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua >= 5.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_CFLAGS=`$PKG_CONFIG --cflags "lua >= 5.1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LUA_LIBS"; then + pkg_cv_LUA_LIBS="$LUA_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua >= 5.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua >= 5.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_LIBS=`$PKG_CONFIG --libs "lua >= 5.1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LUA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "lua >= 5.1" 2>&1` + else + LUA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "lua >= 5.1" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LUA_PKG_ERRORS" >&5 + + HAVE_LUA=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + HAVE_LUA=no +else + LUA_CFLAGS=$pkg_cv_LUA_CFLAGS + LUA_LIBS=$pkg_cv_LUA_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + HAVE_LUA=yes +fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LUA" >&5 +$as_echo_n "checking for LUA... " >&6; } + +if test -n "$LUA_CFLAGS"; then + pkg_cv_LUA_CFLAGS="$LUA_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua5.1 >= 5.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua5.1 >= 5.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_CFLAGS=`$PKG_CONFIG --cflags "lua5.1 >= 5.1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LUA_LIBS"; then + pkg_cv_LUA_LIBS="$LUA_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua5.1 >= 5.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "lua5.1 >= 5.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LUA_LIBS=`$PKG_CONFIG --libs "lua5.1 >= 5.1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LUA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "lua5.1 >= 5.1" 2>&1` + else + LUA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "lua5.1 >= 5.1" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LUA_PKG_ERRORS" >&5 + + HAVE_LUA=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + HAVE_LUA=no +else + LUA_CFLAGS=$pkg_cv_LUA_CFLAGS + LUA_LIBS=$pkg_cv_LUA_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + HAVE_LUA=yes +fi + + + if test "${HAVE_LUA}x" = "yes"; then + HAVE_LUA_TRUE= + HAVE_LUA_FALSE='#' +else + HAVE_LUA_TRUE='#' + HAVE_LUA_FALSE= +fi + + +if test ! "x$HAVE_OPENAL" = "xyes" ; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ALSA" >&5 +$as_echo_n "checking for ALSA... " >&6; } + +if test -n "$ALSA_CFLAGS"; then + pkg_cv_ALSA_CFLAGS="$ALSA_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"alsa >= 1.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "alsa >= 1.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_ALSA_CFLAGS=`$PKG_CONFIG --cflags "alsa >= 1.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$ALSA_LIBS"; then + pkg_cv_ALSA_LIBS="$ALSA_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"alsa >= 1.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "alsa >= 1.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_ALSA_LIBS=`$PKG_CONFIG --libs "alsa >= 1.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + ALSA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "alsa >= 1.0" 2>&1` + else + ALSA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "alsa >= 1.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$ALSA_PKG_ERRORS" >&5 + + HAVE_ALSA=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + HAVE_ALSA=no +else + ALSA_CFLAGS=$pkg_cv_ALSA_CFLAGS + ALSA_LIBS=$pkg_cv_ALSA_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + HAVE_ALSA=yes +fi + + +fi + if test "${HAVE_ALSA}" = "yes"; then + HAVE_ALSA_TRUE= + HAVE_ALSA_FALSE='#' +else + HAVE_ALSA_TRUE='#' + HAVE_ALSA_FALSE= +fi + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBAGG" >&5 +$as_echo_n "checking for LIBAGG... " >&6; } + +if test -n "$LIBAGG_CFLAGS"; then + pkg_cv_LIBAGG_CFLAGS="$LIBAGG_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libagg >= 2.5.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libagg >= 2.5.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBAGG_CFLAGS=`$PKG_CONFIG --cflags "libagg >= 2.5.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBAGG_LIBS"; then + pkg_cv_LIBAGG_LIBS="$LIBAGG_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libagg >= 2.5.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libagg >= 2.5.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBAGG_LIBS=`$PKG_CONFIG --libs "libagg >= 2.5.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LIBAGG_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libagg >= 2.5.0" 2>&1` + else + LIBAGG_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libagg >= 2.5.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBAGG_PKG_ERRORS" >&5 + + FOUND_LIBAGG=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + FOUND_LIBAGG=no +else + LIBAGG_CFLAGS=$pkg_cv_LIBAGG_CFLAGS + LIBAGG_LIBS=$pkg_cv_LIBAGG_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + FOUND_LIBAGG=yes +fi + if test "x$libagg" = "xyes" -a "${FOUND_LIBAGG}" = "yes"; then + HAVE_LIBAGG_TRUE= + HAVE_LIBAGG_FALSE='#' +else + HAVE_LIBAGG_TRUE='#' + HAVE_LIBAGG_FALSE= +fi + +if test "x$libagg" = "xyes" ; then + if test "x$FOUND_LIBAGG" = "xyes" ; then + + + $as_echo "#define HAVE_LIBAGG 1" >>confdefs.h + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: HUD rendering enabled, but libagg not found" >&5 +$as_echo "$as_me: WARNING: HUD rendering enabled, but libagg not found" >&2;} + fi +fi + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSOUNDTOUCH" >&5 +$as_echo_n "checking for LIBSOUNDTOUCH... " >&6; } + +if test -n "$LIBSOUNDTOUCH_CFLAGS"; then + pkg_cv_LIBSOUNDTOUCH_CFLAGS="$LIBSOUNDTOUCH_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"soundtouch >= 1.5.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "soundtouch >= 1.5.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBSOUNDTOUCH_CFLAGS=`$PKG_CONFIG --cflags "soundtouch >= 1.5.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBSOUNDTOUCH_LIBS"; then + pkg_cv_LIBSOUNDTOUCH_LIBS="$LIBSOUNDTOUCH_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"soundtouch >= 1.5.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "soundtouch >= 1.5.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBSOUNDTOUCH_LIBS=`$PKG_CONFIG --libs "soundtouch >= 1.5.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LIBSOUNDTOUCH_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "soundtouch >= 1.5.0" 2>&1` + else + LIBSOUNDTOUCH_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "soundtouch >= 1.5.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBSOUNDTOUCH_PKG_ERRORS" >&5 + + HAVE_LIBSOUNDTOUCH=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + HAVE_LIBSOUNDTOUCH=no +else + LIBSOUNDTOUCH_CFLAGS=$pkg_cv_LIBSOUNDTOUCH_CFLAGS + LIBSOUNDTOUCH_LIBS=$pkg_cv_LIBSOUNDTOUCH_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + HAVE_LIBSOUNDTOUCH=yes +fi + + + if test "${HAVE_LIBSOUNDTOUCH}" = "yes"; then + HAVE_LIBSOUNDTOUCH_TRUE= + HAVE_LIBSOUNDTOUCH_FALSE='#' +else + HAVE_LIBSOUNDTOUCH_TRUE='#' + HAVE_LIBSOUNDTOUCH_FALSE= +fi + +if test "x$HAVE_LIBSOUNDTOUCH" = "xyes"; then + $as_echo "#define HAVE_LIBSOUNDTOUCH 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: SoundTouch library not found, pcsx2 resampler will be disabled" >&5 +$as_echo "$as_me: WARNING: SoundTouch library not found, pcsx2 resampler will be disabled" >&2;} +fi + +if test "x$HAVE_ALSA" = "xno"; then + if test "x$HAVE_OPENAL" = "xno"; then + $as_echo "#define FAKE_MIC 1" >>confdefs.h + + fi +fi + + +# Check whether --enable-wxwidgets was given. +if test "${enable_wxwidgets+set}" = set; then : + enableval=$enable_wxwidgets; wxwidgets=$enableval +else + wxwidgets=no +fi + +if test "x$wxwidgets" = "xyes" ; then + + + + + + + + + + + + + + + + + if test x${WX_CONFIG_NAME+set} != xset ; then + WX_CONFIG_NAME=wx-config + fi + + if test "x$wx_config_name" != x ; then + WX_CONFIG_NAME="$wx_config_name" + fi + + if test x$wx_config_exec_prefix != x ; then + wx_config_args="$wx_config_args --exec-prefix=$wx_config_exec_prefix" + WX_LOOKUP_PATH="$wx_config_exec_prefix/bin" + fi + if test x$wx_config_prefix != x ; then + wx_config_args="$wx_config_args --prefix=$wx_config_prefix" + WX_LOOKUP_PATH="$WX_LOOKUP_PATH:$wx_config_prefix/bin" + fi + if test "$cross_compiling" = "yes"; then + wx_config_args="$wx_config_args --host=$host_alias" + fi + + if test -x "$WX_CONFIG_NAME" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wx-config" >&5 +$as_echo_n "checking for wx-config... " >&6; } + WX_CONFIG_PATH="$WX_CONFIG_NAME" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WX_CONFIG_PATH" >&5 +$as_echo "$WX_CONFIG_PATH" >&6; } + else + # Extract the first word of "$WX_CONFIG_NAME", so it can be a program name with args. +set dummy $WX_CONFIG_NAME; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_WX_CONFIG_PATH+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $WX_CONFIG_PATH in + [\\/]* | ?:[\\/]*) + ac_cv_path_WX_CONFIG_PATH="$WX_CONFIG_PATH" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_dummy=""$WX_LOOKUP_PATH:$PATH"" +for as_dir in $as_dummy +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_WX_CONFIG_PATH="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_WX_CONFIG_PATH" && ac_cv_path_WX_CONFIG_PATH="no" + ;; +esac +fi +WX_CONFIG_PATH=$ac_cv_path_WX_CONFIG_PATH +if test -n "$WX_CONFIG_PATH"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WX_CONFIG_PATH" >&5 +$as_echo "$WX_CONFIG_PATH" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi + + if test "$WX_CONFIG_PATH" != "no" ; then + WX_VERSION="" + + min_wx_version=2.4.0 + if test -z "" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wxWidgets version >= $min_wx_version" >&5 +$as_echo_n "checking for wxWidgets version >= $min_wx_version... " >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wxWidgets version >= $min_wx_version ()" >&5 +$as_echo_n "checking for wxWidgets version >= $min_wx_version ()... " >&6; } + fi + + WX_CONFIG_WITH_ARGS="$WX_CONFIG_PATH $wx_config_args " + + WX_VERSION=`$WX_CONFIG_WITH_ARGS --version 2>/dev/null` + wx_config_major_version=`echo $WX_VERSION | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'` + wx_config_minor_version=`echo $WX_VERSION | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'` + wx_config_micro_version=`echo $WX_VERSION | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'` + + wx_requested_major_version=`echo $min_wx_version | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'` + wx_requested_minor_version=`echo $min_wx_version | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'` + wx_requested_micro_version=`echo $min_wx_version | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'` + + + wx_ver_ok="" + if test "x$WX_VERSION" != x ; then + if test $wx_config_major_version -gt $wx_requested_major_version; then + wx_ver_ok=yes + else + if test $wx_config_major_version -eq $wx_requested_major_version; then + if test $wx_config_minor_version -gt $wx_requested_minor_version; then + wx_ver_ok=yes + else + if test $wx_config_minor_version -eq $wx_requested_minor_version; then + if test $wx_config_micro_version -ge $wx_requested_micro_version; then + wx_ver_ok=yes + fi + fi + fi + fi + fi + fi + + + if test -n "$wx_ver_ok"; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (version $WX_VERSION)" >&5 +$as_echo "yes (version $WX_VERSION)" >&6; } + WX_LIBS=`$WX_CONFIG_WITH_ARGS --libs` + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wxWidgets static library" >&5 +$as_echo_n "checking for wxWidgets static library... " >&6; } + WX_LIBS_STATIC=`$WX_CONFIG_WITH_ARGS --static --libs 2>/dev/null` + if test "x$WX_LIBS_STATIC" = "x"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + fi + + wx_has_cppflags="" + if test $wx_config_major_version -gt 2; then + wx_has_cppflags=yes + else + if test $wx_config_major_version -eq 2; then + if test $wx_config_minor_version -gt 2; then + wx_has_cppflags=yes + else + if test $wx_config_minor_version -eq 2; then + if test $wx_config_micro_version -ge 6; then + wx_has_cppflags=yes + fi + fi + fi + fi + fi + + wx_has_rescomp="" + if test $wx_config_major_version -gt 2; then + wx_has_rescomp=yes + else + if test $wx_config_major_version -eq 2; then + if test $wx_config_minor_version -ge 7; then + wx_has_rescomp=yes + fi + fi + fi + if test "x$wx_has_rescomp" = x ; then + WX_RESCOMP= + else + WX_RESCOMP=`$WX_CONFIG_WITH_ARGS --rescomp` + fi + + if test "x$wx_has_cppflags" = x ; then + WX_CFLAGS=`$WX_CONFIG_WITH_ARGS --cflags` + WX_CPPFLAGS=$WX_CFLAGS + WX_CXXFLAGS=$WX_CFLAGS + + WX_CFLAGS_ONLY=$WX_CFLAGS + WX_CXXFLAGS_ONLY=$WX_CFLAGS + else + WX_CPPFLAGS=`$WX_CONFIG_WITH_ARGS --cppflags` + WX_CXXFLAGS=`$WX_CONFIG_WITH_ARGS --cxxflags` + WX_CFLAGS=`$WX_CONFIG_WITH_ARGS --cflags` + + WX_CFLAGS_ONLY=`echo $WX_CFLAGS | sed "s@^$WX_CPPFLAGS *@@"` + WX_CXXFLAGS_ONLY=`echo $WX_CXXFLAGS | sed "s@^$WX_CFLAGS *@@"` + fi + + wxwin=yes + + else + + if test "x$WX_VERSION" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no (version $WX_VERSION is not new enough)" >&5 +$as_echo "no (version $WX_VERSION is not new enough)" >&6; } + fi + + WX_CFLAGS="" + WX_CPPFLAGS="" + WX_CXXFLAGS="" + WX_LIBS="" + WX_LIBS_STATIC="" + WX_RESCOMP="" + : + + fi + else + + WX_CFLAGS="" + WX_CPPFLAGS="" + WX_CXXFLAGS="" + WX_LIBS="" + WX_LIBS_STATIC="" + WX_RESCOMP="" + + : + + fi + + + + + + + + + + + + if test "x$wxwin" = "xyes"; then + + + $as_echo "#define WANT_WX 1" >>confdefs.h + + fi +fi + + if test "x$wxwidgets" = "xyes"; then + HAVE_WX_TRUE= + HAVE_WX_FALSE='#' +else + HAVE_WX_TRUE='#' + HAVE_WX_FALSE= +fi + + +PO_DIR="" +UI_DIR="cli $UI_DIR" +if test "x$HAVE_GTK" = "xyes"; then + UI_DIR="gtk $UI_DIR" +fi +if test "x$wxwin" = "xyes"; then + UI_DIR="wx $UI_DIR" +fi + +if test "x$HAVE_LIBGLADE" = "xyes"; then + + UI_DIR="gtk-glade $UI_DIR" + + GETTEXT_PACKAGE=desmume + +cat >>confdefs.h <<_ACEOF +#define GETTEXT_PACKAGE "$GETTEXT_PACKAGE" +_ACEOF + + + ALL_LINGUAS="fr nb pt_BR sv zh_CN zh_TW" + + for ac_header in locale.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "locale.h" "ac_cv_header_locale_h" "$ac_includes_default" +if test "x$ac_cv_header_locale_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LOCALE_H 1 +_ACEOF + +fi + +done + + if test $ac_cv_header_locale_h = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LC_MESSAGES" >&5 +$as_echo_n "checking for LC_MESSAGES... " >&6; } +if ${am_cv_val_LC_MESSAGES+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +return LC_MESSAGES + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + am_cv_val_LC_MESSAGES=yes +else + am_cv_val_LC_MESSAGES=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_val_LC_MESSAGES" >&5 +$as_echo "$am_cv_val_LC_MESSAGES" >&6; } + if test $am_cv_val_LC_MESSAGES = yes; then + +$as_echo "#define HAVE_LC_MESSAGES 1" >>confdefs.h + + fi + fi + USE_NLS=yes + + + gt_cv_have_gettext=no + + CATOBJEXT=NONE + XGETTEXT=: + INTLLIBS= + + ac_fn_c_check_header_mongrel "$LINENO" "libintl.h" "ac_cv_header_libintl_h" "$ac_includes_default" +if test "x$ac_cv_header_libintl_h" = xyes; then : + gt_cv_func_dgettext_libintl="no" + libintl_extra_libs="" + + # + # First check in libc + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ngettext in libc" >&5 +$as_echo_n "checking for ngettext in libc... " >&6; } +if ${gt_cv_func_ngettext_libc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include + +int +main () +{ +return !ngettext ("","", 1) + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_func_ngettext_libc=yes +else + gt_cv_func_ngettext_libc=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_ngettext_libc" >&5 +$as_echo "$gt_cv_func_ngettext_libc" >&6; } + + if test "$gt_cv_func_ngettext_libc" = "yes" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dgettext in libc" >&5 +$as_echo_n "checking for dgettext in libc... " >&6; } +if ${gt_cv_func_dgettext_libc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include + +int +main () +{ +return !dgettext ("","") + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_func_dgettext_libc=yes +else + gt_cv_func_dgettext_libc=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_dgettext_libc" >&5 +$as_echo "$gt_cv_func_dgettext_libc" >&6; } + fi + + if test "$gt_cv_func_ngettext_libc" = "yes" ; then + for ac_func in bind_textdomain_codeset +do : + ac_fn_c_check_func "$LINENO" "bind_textdomain_codeset" "ac_cv_func_bind_textdomain_codeset" +if test "x$ac_cv_func_bind_textdomain_codeset" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_BIND_TEXTDOMAIN_CODESET 1 +_ACEOF + +fi +done + + fi + + # + # If we don't have everything we want, check in libintl + # + if test "$gt_cv_func_dgettext_libc" != "yes" \ + || test "$gt_cv_func_ngettext_libc" != "yes" \ + || test "$ac_cv_func_bind_textdomain_codeset" != "yes" ; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for bindtextdomain in -lintl" >&5 +$as_echo_n "checking for bindtextdomain in -lintl... " >&6; } +if ${ac_cv_lib_intl_bindtextdomain+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char bindtextdomain (); +int +main () +{ +return bindtextdomain (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_intl_bindtextdomain=yes +else + ac_cv_lib_intl_bindtextdomain=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_bindtextdomain" >&5 +$as_echo "$ac_cv_lib_intl_bindtextdomain" >&6; } +if test "x$ac_cv_lib_intl_bindtextdomain" = xyes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ngettext in -lintl" >&5 +$as_echo_n "checking for ngettext in -lintl... " >&6; } +if ${ac_cv_lib_intl_ngettext+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ngettext (); +int +main () +{ +return ngettext (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_intl_ngettext=yes +else + ac_cv_lib_intl_ngettext=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_ngettext" >&5 +$as_echo "$ac_cv_lib_intl_ngettext" >&6; } +if test "x$ac_cv_lib_intl_ngettext" = xyes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dgettext in -lintl" >&5 +$as_echo_n "checking for dgettext in -lintl... " >&6; } +if ${ac_cv_lib_intl_dgettext+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dgettext (); +int +main () +{ +return dgettext (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_intl_dgettext=yes +else + ac_cv_lib_intl_dgettext=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_dgettext" >&5 +$as_echo "$ac_cv_lib_intl_dgettext" >&6; } +if test "x$ac_cv_lib_intl_dgettext" = xyes; then : + gt_cv_func_dgettext_libintl=yes +fi + +fi + +fi + + + if test "$gt_cv_func_dgettext_libintl" != "yes" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -liconv is needed to use gettext" >&5 +$as_echo_n "checking if -liconv is needed to use gettext... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 +$as_echo "" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ngettext in -lintl" >&5 +$as_echo_n "checking for ngettext in -lintl... " >&6; } +if ${ac_cv_lib_intl_ngettext+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl -liconv $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ngettext (); +int +main () +{ +return ngettext (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_intl_ngettext=yes +else + ac_cv_lib_intl_ngettext=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_ngettext" >&5 +$as_echo "$ac_cv_lib_intl_ngettext" >&6; } +if test "x$ac_cv_lib_intl_ngettext" = xyes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dcgettext in -lintl" >&5 +$as_echo_n "checking for dcgettext in -lintl... " >&6; } +if ${ac_cv_lib_intl_dcgettext+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl -liconv $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dcgettext (); +int +main () +{ +return dcgettext (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_intl_dcgettext=yes +else + ac_cv_lib_intl_dcgettext=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_dcgettext" >&5 +$as_echo "$ac_cv_lib_intl_dcgettext" >&6; } +if test "x$ac_cv_lib_intl_dcgettext" = xyes; then : + gt_cv_func_dgettext_libintl=yes + libintl_extra_libs=-liconv +else + : +fi + +else + : +fi + + fi + + # + # If we found libintl, then check in it for bind_textdomain_codeset(); + # we'll prefer libc if neither have bind_textdomain_codeset(), + # and both have dgettext and ngettext + # + if test "$gt_cv_func_dgettext_libintl" = "yes" ; then + glib_save_LIBS="$LIBS" + LIBS="$LIBS -lintl $libintl_extra_libs" + unset ac_cv_func_bind_textdomain_codeset + for ac_func in bind_textdomain_codeset +do : + ac_fn_c_check_func "$LINENO" "bind_textdomain_codeset" "ac_cv_func_bind_textdomain_codeset" +if test "x$ac_cv_func_bind_textdomain_codeset" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_BIND_TEXTDOMAIN_CODESET 1 +_ACEOF + +fi +done + + LIBS="$glib_save_LIBS" + + if test "$ac_cv_func_bind_textdomain_codeset" = "yes" ; then + gt_cv_func_dgettext_libc=no + else + if test "$gt_cv_func_dgettext_libc" = "yes" \ + && test "$gt_cv_func_ngettext_libc" = "yes"; then + gt_cv_func_dgettext_libintl=no + fi + fi + fi + fi + + if test "$gt_cv_func_dgettext_libc" = "yes" \ + || test "$gt_cv_func_dgettext_libintl" = "yes"; then + gt_cv_have_gettext=yes + fi + + if test "$gt_cv_func_dgettext_libintl" = "yes"; then + INTLLIBS="-lintl $libintl_extra_libs" + fi + + if test "$gt_cv_have_gettext" = "yes"; then + +$as_echo "#define HAVE_GETTEXT 1" >>confdefs.h + + # Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MSGFMT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case "$MSGFMT" in + /*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then + ac_cv_path_MSGFMT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="no" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test "$MSGFMT" != "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 +$as_echo "$MSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + if test "$MSGFMT" != "no"; then + glib_save_LIBS="$LIBS" + LIBS="$LIBS $INTLLIBS" + for ac_func in dcgettext +do : + ac_fn_c_check_func "$LINENO" "dcgettext" "ac_cv_func_dcgettext" +if test "x$ac_cv_func_dcgettext" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DCGETTEXT 1 +_ACEOF + +fi +done + + MSGFMT_OPTS= + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if msgfmt accepts -c" >&5 +$as_echo_n "checking if msgfmt accepts -c... " >&6; } + cat >conftest.foo <<_ACEOF + +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Project-Id-Version: test 1.0\n" +"PO-Revision-Date: 2007-02-15 12:01+0100\n" +"Last-Translator: test \n" +"Language-Team: C \n" +"MIME-Version: 1.0\n" +"Content-Transfer-Encoding: 8bit\n" + +_ACEOF +if { { $as_echo "$as_me:${as_lineno-$LINENO}: \$MSGFMT -c -o /dev/null conftest.foo"; } >&5 + ($MSGFMT -c -o /dev/null conftest.foo) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + MSGFMT_OPTS=-c; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +echo "$as_me: failed input was:" >&5 +sed 's/^/| /' conftest.foo >&5 +fi + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GMSGFMT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GMSGFMT in + [\\/]* | ?:[\\/]*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT=$ac_cv_path_GMSGFMT +if test -n "$GMSGFMT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 +$as_echo "$GMSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + # Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_XGETTEXT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case "$XGETTEXT" in + /*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test "$XGETTEXT" != ":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 +$as_echo "$XGETTEXT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + CATOBJEXT=.gmo + DATADIRNAME=share +else + case $host in + *-*-solaris*) + ac_fn_c_check_func "$LINENO" "bind_textdomain_codeset" "ac_cv_func_bind_textdomain_codeset" +if test "x$ac_cv_func_bind_textdomain_codeset" = xyes; then : + CATOBJEXT=.gmo + DATADIRNAME=share +else + CATOBJEXT=.mo + DATADIRNAME=lib +fi + + ;; + *-*-openbsd*) + CATOBJEXT=.mo + DATADIRNAME=share + ;; + *) + CATOBJEXT=.mo + DATADIRNAME=lib + ;; + esac +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$glib_save_LIBS" + INSTOBJEXT=.mo + else + gt_cv_have_gettext=no + fi + fi + +fi + + + + if test "$gt_cv_have_gettext" = "yes" ; then + +$as_echo "#define ENABLE_NLS 1" >>confdefs.h + + fi + + if test "$XGETTEXT" != ":"; then + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found xgettext program is not GNU xgettext; ignore it" >&5 +$as_echo "found xgettext program is not GNU xgettext; ignore it" >&6; } + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + + ac_config_commands="$ac_config_commands default-1" + + + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + + + + + + + + + + + + + if test "$gt_cv_have_gettext" = "yes"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for catalogs to be installed" >&5 +$as_echo_n "checking for catalogs to be installed... " >&6; } + NEW_LINGUAS= + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "${LINGUAS-%UNSET%}"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + NEW_LINGUAS="$NEW_LINGUAS $presentlang" + fi + done + LINGUAS=$NEW_LINGUAS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LINGUAS" >&5 +$as_echo "$LINGUAS" >&6; } + fi + + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + MKINSTALLDIRS= + if test -n "$ac_aux_dir"; then + MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" + fi + if test -z "$MKINSTALLDIRS"; then + MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" + fi + + + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + + PO_DIR="po" + PO_MAKEFILE="po/Makefile.in" + +fi + +# Check whether --enable-wifi was given. +if test "${enable_wifi+set}" = set; then : + enableval=$enable_wifi; + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpcap" >&5 +$as_echo_n "checking for main in -lpcap... " >&6; } +if ${ac_cv_lib_pcap_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpcap $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pcap_main=yes +else + ac_cv_lib_pcap_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcap_main" >&5 +$as_echo "$ac_cv_lib_pcap_main" >&6; } +if test "x$ac_cv_lib_pcap_main" = xyes; then : + + $as_echo "#define EXPERIMENTAL_WIFI_COMM 1" >>confdefs.h + + LIBS="$LIBS -lpcap" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pcap library not found, wifi will not work" >&5 +$as_echo "$as_me: WARNING: pcap library not found, wifi will not work" >&2;} +fi + + +fi + + +case $host in + *mingw*) + LIBS="$LIBS -ldxguid -ldxerr8 -ldsound -lopengl32 -lws2_32 -mwindows" + UI_DIR="windows" + ;; + *darwin*) + if test "x$GTK_MACOSX_HACK" = "xyes" ; then + LIBS="$LIBS -framework Gtk -framework GLib" + CPPFLAGS="$CPPFLAGS -I/Library/Frameworks/Cairo.framework/Headers -I/Library/Frameworks/Gtk.framework/Headers -I/Library/Frameworks/GLib.framework/Headers" + GLIB_LIBS="" + + fi + $as_echo "#define HAVE_OPENAL 1" >>confdefs.h + + LIBS="$LIBS -framework OpenGL -framework OpenAL" + CPPFLAGS="$CPPFLAGS -I/System/Library/Frameworks/OpenAL.framework/Headers" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X" >&5 +$as_echo_n "checking for X... " >&6; } + + +# Check whether --with-x was given. +if test "${with_x+set}" = set; then : + withval=$with_x; +fi + +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + case $x_includes,$x_libraries in #( + *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #( + *,NONE | NONE,*) if ${ac_cv_have_x+:} false; then : + $as_echo_n "(cached) " >&6 +else + # One or both of the vars are not set, and there is no cached value. +ac_x_includes=no ac_x_libraries=no +rm -f -r conftest.dir +if mkdir conftest.dir; then + cd conftest.dir + cat >Imakefile <<'_ACEOF' +incroot: + @echo incroot='${INCROOT}' +usrlibdir: + @echo usrlibdir='${USRLIBDIR}' +libdir: + @echo libdir='${LIBDIR}' +_ACEOF + if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. + for ac_var in incroot usrlibdir libdir; do + eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" + done + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl dylib la dll; do + if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" && + test -f "$ac_im_libdir/libX11.$ac_extension"; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case $ac_im_incroot in + /usr/include) ac_x_includes= ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; + esac + case $ac_im_usrlibdir in + /usr/lib | /usr/lib64 | /lib | /lib64) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; + esac + fi + cd .. + rm -f -r conftest.dir +fi + +# Standard set of common directories for X headers. +# Check X11 before X11Rn because it is often a symlink to the current release. +ac_x_header_dirs=' +/usr/X11/include +/usr/X11R7/include +/usr/X11R6/include +/usr/X11R5/include +/usr/X11R4/include + +/usr/include/X11 +/usr/include/X11R7 +/usr/include/X11R6 +/usr/include/X11R5 +/usr/include/X11R4 + +/usr/local/X11/include +/usr/local/X11R7/include +/usr/local/X11R6/include +/usr/local/X11R5/include +/usr/local/X11R4/include + +/usr/local/include/X11 +/usr/local/include/X11R7 +/usr/local/include/X11R6 +/usr/local/include/X11R5 +/usr/local/include/X11R4 + +/usr/X386/include +/usr/x386/include +/usr/XFree86/include/X11 + +/usr/include +/usr/local/include +/usr/unsupported/include +/usr/athena/include +/usr/local/x11r5/include +/usr/lpp/Xamples/include + +/usr/openwin/include +/usr/openwin/share/include' + +if test "$ac_x_includes" = no; then + # Guess where to find include files, by looking for Xlib.h. + # First, try using that file with no special directory specified. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # We can compile using X headers with no special include directory. +ac_x_includes= +else + for ac_dir in $ac_x_header_dirs; do + if test -r "$ac_dir/X11/Xlib.h"; then + ac_x_includes=$ac_dir + break + fi +done +fi +rm -f conftest.err conftest.i conftest.$ac_ext +fi # $ac_x_includes = no + +if test "$ac_x_libraries" = no; then + # Check for the libraries. + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS=$LIBS + LIBS="-lX11 $LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +XrmInitialize () + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + LIBS=$ac_save_LIBS +# We can link X programs with no special library path. +ac_x_libraries= +else + LIBS=$ac_save_LIBS +for ac_dir in `$as_echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` +do + # Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl dylib la dll; do + if test -r "$ac_dir/libX11.$ac_extension"; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi # $ac_x_libraries = no + +case $ac_x_includes,$ac_x_libraries in #( + no,* | *,no | *\'*) + # Didn't find X, or a directory has "'" in its name. + ac_cv_have_x="have_x=no";; #( + *) + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$ac_x_includes'\ + ac_x_libraries='$ac_x_libraries'" +esac +fi +;; #( + *) have_x=yes;; + esac + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_x" >&5 +$as_echo "$have_x" >&6; } + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$x_includes'\ + ac_x_libraries='$x_libraries'" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes" >&5 +$as_echo "libraries $x_libraries, headers $x_includes" >&6; } +fi + +if test "$no_x" = yes; then + # Not all programs may use this symbol, but it does not hurt to define it. + +$as_echo "#define X_DISPLAY_MISSING 1" >>confdefs.h + + X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= +else + if test -n "$x_includes"; then + X_CFLAGS="$X_CFLAGS -I$x_includes" + fi + + # It would also be nice to do this for all -L options, not just this one. + if test -n "$x_libraries"; then + X_LIBS="$X_LIBS -L$x_libraries" + # For Solaris; some versions of Sun CC require a space after -R and + # others require no space. Words are not sufficient . . . . + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -R must be followed by a space" >&5 +$as_echo_n "checking whether -R must be followed by a space... " >&6; } + ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries" + ac_xsave_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + X_LIBS="$X_LIBS -R$x_libraries" +else + LIBS="$ac_xsave_LIBS -R $x_libraries" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + X_LIBS="$X_LIBS -R $x_libraries" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: neither works" >&5 +$as_echo "neither works" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_c_werror_flag=$ac_xsave_c_werror_flag + LIBS=$ac_xsave_LIBS + fi + + # Check for system-dependent libraries X programs must link with. + # Do this before checking for the system-independent R6 libraries + # (-lICE), since we may need -lsocket or whatever for X linking. + + if test "$ISC" = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" + else + # Martyn Johnson says this is needed for Ultrix, if the X + # libraries were built with DECnet support. And Karl Berry says + # the Alpha needs dnet_stub (dnet does not exist). + ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XOpenDisplay (); +int +main () +{ +return XOpenDisplay (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet" >&5 +$as_echo_n "checking for dnet_ntoa in -ldnet... " >&6; } +if ${ac_cv_lib_dnet_dnet_ntoa+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldnet $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dnet_ntoa (); +int +main () +{ +return dnet_ntoa (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dnet_dnet_ntoa=yes +else + ac_cv_lib_dnet_dnet_ntoa=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 +$as_echo "$ac_cv_lib_dnet_dnet_ntoa" >&6; } +if test "x$ac_cv_lib_dnet_dnet_ntoa" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" +fi + + if test $ac_cv_lib_dnet_dnet_ntoa = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet_stub" >&5 +$as_echo_n "checking for dnet_ntoa in -ldnet_stub... " >&6; } +if ${ac_cv_lib_dnet_stub_dnet_ntoa+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldnet_stub $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dnet_ntoa (); +int +main () +{ +return dnet_ntoa (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dnet_stub_dnet_ntoa=yes +else + ac_cv_lib_dnet_stub_dnet_ntoa=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 +$as_echo "$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; } +if test "x$ac_cv_lib_dnet_stub_dnet_ntoa" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" +fi + + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$ac_xsave_LIBS" + + # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, + # to get the SysV transport functions. + # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4) + # needs -lnsl. + # The nsl library prevents programs from opening the X display + # on Irix 5.2, according to T.E. Dickey. + # The functions gethostbyname, getservbyname, and inet_addr are + # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking. + ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname" +if test "x$ac_cv_func_gethostbyname" = xyes; then : + +fi + + if test $ac_cv_func_gethostbyname = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 +$as_echo_n "checking for gethostbyname in -lnsl... " >&6; } +if ${ac_cv_lib_nsl_gethostbyname+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_nsl_gethostbyname=yes +else + ac_cv_lib_nsl_gethostbyname=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5 +$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; } +if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" +fi + + if test $ac_cv_lib_nsl_gethostbyname = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lbsd" >&5 +$as_echo_n "checking for gethostbyname in -lbsd... " >&6; } +if ${ac_cv_lib_bsd_gethostbyname+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbsd $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_bsd_gethostbyname=yes +else + ac_cv_lib_bsd_gethostbyname=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_gethostbyname" >&5 +$as_echo "$ac_cv_lib_bsd_gethostbyname" >&6; } +if test "x$ac_cv_lib_bsd_gethostbyname" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" +fi + + fi + fi + + # lieder@skyler.mavd.honeywell.com says without -lsocket, + # socket/setsockopt and other routines are undefined under SCO ODT + # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary + # on later versions), says Simon Leinen: it contains gethostby* + # variants that don't use the name server (or something). -lsocket + # must be given before -lnsl if both are needed. We assume that + # if connect needs -lnsl, so does gethostbyname. + ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect" +if test "x$ac_cv_func_connect" = xyes; then : + +fi + + if test $ac_cv_func_connect = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for connect in -lsocket" >&5 +$as_echo_n "checking for connect in -lsocket... " >&6; } +if ${ac_cv_lib_socket_connect+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $X_EXTRA_LIBS $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char connect (); +int +main () +{ +return connect (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_socket_connect=yes +else + ac_cv_lib_socket_connect=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_connect" >&5 +$as_echo "$ac_cv_lib_socket_connect" >&6; } +if test "x$ac_cv_lib_socket_connect" = xyes; then : + X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" +fi + + fi + + # Guillermo Gomez says -lposix is necessary on A/UX. + ac_fn_c_check_func "$LINENO" "remove" "ac_cv_func_remove" +if test "x$ac_cv_func_remove" = xyes; then : + +fi + + if test $ac_cv_func_remove = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for remove in -lposix" >&5 +$as_echo_n "checking for remove in -lposix... " >&6; } +if ${ac_cv_lib_posix_remove+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lposix $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char remove (); +int +main () +{ +return remove (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_posix_remove=yes +else + ac_cv_lib_posix_remove=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_posix_remove" >&5 +$as_echo "$ac_cv_lib_posix_remove" >&6; } +if test "x$ac_cv_lib_posix_remove" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" +fi + + fi + + # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. + ac_fn_c_check_func "$LINENO" "shmat" "ac_cv_func_shmat" +if test "x$ac_cv_func_shmat" = xyes; then : + +fi + + if test $ac_cv_func_shmat = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shmat in -lipc" >&5 +$as_echo_n "checking for shmat in -lipc... " >&6; } +if ${ac_cv_lib_ipc_shmat+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lipc $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shmat (); +int +main () +{ +return shmat (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ipc_shmat=yes +else + ac_cv_lib_ipc_shmat=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ipc_shmat" >&5 +$as_echo "$ac_cv_lib_ipc_shmat" >&6; } +if test "x$ac_cv_lib_ipc_shmat" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" +fi + + fi + fi + + # Check for libraries that X11R6 Xt/Xaw programs need. + ac_save_LDFLAGS=$LDFLAGS + test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" + # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to + # check for ICE first), but we must link in the order -lSM -lICE or + # we get undefined symbols. So assume we have SM if we have ICE. + # These have to be linked with before -lX11, unlike the other + # libraries we check for below, so use a different variable. + # John Interrante, Karl Berry + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IceConnectionNumber in -lICE" >&5 +$as_echo_n "checking for IceConnectionNumber in -lICE... " >&6; } +if ${ac_cv_lib_ICE_IceConnectionNumber+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lICE $X_EXTRA_LIBS $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char IceConnectionNumber (); +int +main () +{ +return IceConnectionNumber (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ICE_IceConnectionNumber=yes +else + ac_cv_lib_ICE_IceConnectionNumber=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 +$as_echo "$ac_cv_lib_ICE_IceConnectionNumber" >&6; } +if test "x$ac_cv_lib_ICE_IceConnectionNumber" = xyes; then : + X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" +fi + + LDFLAGS=$ac_save_LDFLAGS + +fi + + ;; +esac + + + + +# Check whether --enable-gdb-stub was given. +if test "${enable_gdb_stub+set}" = set; then : + enableval=$enable_gdb_stub; + $as_echo "#define GDB_STUB 1" >>confdefs.h + + wantgdbstub=yes + +fi + + if test "${wantgdbstub}" = "yes"; then + HAVE_GDB_STUB_TRUE= + HAVE_GDB_STUB_FALSE='#' +else + HAVE_GDB_STUB_TRUE='#' + HAVE_GDB_STUB_FALSE= +fi + + + +# for developer use, enable lots of compile warnings, +# but don't require this generally, because some system's +# header files (BSD) can't handle it +# +# NB: must add -Werror after AC_PROG_CC, etc., so do this last +# Check whether --enable-hardcore was given. +if test "${enable_hardcore+set}" = set; then : + enableval=$enable_hardcore; case "${enableval}" in + yes) ENABLE_HARDCORE=1 ;; + no) ENABLE_HARDCORE=0 ;; + *) as_fn_error $? "bad value ${enableval} for --enable-hardcore" "$LINENO" 5 ;; esac +else + ENABLE_HARDCORE=0 +fi + + +if test "x$ENABLE_HARDCORE" = "x1"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: enable hardcore compile warnings" >&5 +$as_echo "$as_me: WARNING: enable hardcore compile warnings" >&2;} + if test "x$CXX" = "x"; then + CPPFLAGS="$CPPFLAGS -Wmissing-prototypes" + fi + CPPFLAGS="$CPPFLAGS -Wall -Wextra -D_FORTIFY_SOURCE=2 -Wno-missing-field-initializers -Wpointer-arith -Wcast-align -Wwrite-strings -Wno-unused-parameter -Wmissing-declarations -Wundef -Wmissing-noreturn -Wredundant-decls -Wformat-nonliteral -Wformat-security -Winit-self -Wno-reorder" +fi + +# Check whether --enable-debug was given. +if test "${enable_debug+set}" = set; then : + enableval=$enable_debug; $as_echo "#define DEBUG 1" >>confdefs.h + +fi + +# Check whether --enable-gpu-debug was given. +if test "${enable_gpu_debug+set}" = set; then : + enableval=$enable_gpu_debug; $as_echo "#define GPUDEBUG 1" >>confdefs.h + +fi + +# Check whether --enable-div-debug was given. +if test "${enable_div_debug+set}" = set; then : + enableval=$enable_div_debug; $as_echo "#define DIVDEBUG 1" >>confdefs.h + +fi + +# Check whether --enable-sqrt-debug was given. +if test "${enable_sqrt_debug+set}" = set; then : + enableval=$enable_sqrt_debug; $as_echo "#define SQRTDEBUG 1" >>confdefs.h + +fi + +# Check whether --enable-dma-debug was given. +if test "${enable_dma_debug+set}" = set; then : + enableval=$enable_dma_debug; $as_echo "#define DMADEBUG 1" >>confdefs.h + +fi + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 +$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } + # Check whether --enable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then : + enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 +$as_echo "$USE_MAINTAINER_MODE" >&6; } + if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + + MAINT=$MAINTAINER_MODE_TRUE + + + + + +ac_config_files="$ac_config_files Makefile ${PO_MAKEFILE} src/Makefile src/cli/Makefile src/cli/doc/Makefile src/gtk/Makefile src/gtk/doc/Makefile src/gtk-glade/Makefile src/gtk-glade/doc/Makefile src/wx/Makefile src/gdbstub/Makefile autopackage/default.apspec" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +ac_script=' +:mline +/\\$/{ + N + s,\\\n,, + b mline +} +t clear +:clear +s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g +t quote +s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g +t quote +b any +:quote +s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g +s/\[/\\&/g +s/\]/\\&/g +s/\$/$$/g +H +:any +${ + g + s/^\n// + s/\n/ /g + p +} +' +DEFS=`sed -n "$ac_script" confdefs.h` + + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + + + ac_config_commands="$ac_config_commands po/stamp-it" + + +if test -z "${HAVE_GL_TRUE}" && test -z "${HAVE_GL_FALSE}"; then + as_fn_error $? "conditional \"HAVE_GL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_LIBOSMESA_TRUE}" && test -z "${HAVE_LIBOSMESA_FALSE}"; then + as_fn_error $? "conditional \"HAVE_LIBOSMESA\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_OPENAL_TRUE}" && test -z "${HAVE_OPENAL_FALSE}"; then + as_fn_error $? "conditional \"HAVE_OPENAL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_LUA_TRUE}" && test -z "${HAVE_LUA_FALSE}"; then + as_fn_error $? "conditional \"HAVE_LUA\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_ALSA_TRUE}" && test -z "${HAVE_ALSA_FALSE}"; then + as_fn_error $? "conditional \"HAVE_ALSA\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_LIBAGG_TRUE}" && test -z "${HAVE_LIBAGG_FALSE}"; then + as_fn_error $? "conditional \"HAVE_LIBAGG\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_LIBSOUNDTOUCH_TRUE}" && test -z "${HAVE_LIBSOUNDTOUCH_FALSE}"; then + as_fn_error $? "conditional \"HAVE_LIBSOUNDTOUCH\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_WX_TRUE}" && test -z "${HAVE_WX_FALSE}"; then + as_fn_error $? "conditional \"HAVE_WX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_GDB_STUB_TRUE}" && test -z "${HAVE_GDB_STUB_FALSE}"; then + as_fn_error $? "conditional \"HAVE_GDB_STUB\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then + as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by desmume $as_me 0.9.8, which was +generated by GNU Autoconf 2.68. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Configuration commands: +$config_commands + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +desmume config.status 0.9.8 +configured by $0, generated by GNU Autoconf 2.68, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2010 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h | --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "${PO_MAKEFILE}") CONFIG_FILES="$CONFIG_FILES ${PO_MAKEFILE}" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "src/cli/Makefile") CONFIG_FILES="$CONFIG_FILES src/cli/Makefile" ;; + "src/cli/doc/Makefile") CONFIG_FILES="$CONFIG_FILES src/cli/doc/Makefile" ;; + "src/gtk/Makefile") CONFIG_FILES="$CONFIG_FILES src/gtk/Makefile" ;; + "src/gtk/doc/Makefile") CONFIG_FILES="$CONFIG_FILES src/gtk/doc/Makefile" ;; + "src/gtk-glade/Makefile") CONFIG_FILES="$CONFIG_FILES src/gtk-glade/Makefile" ;; + "src/gtk-glade/doc/Makefile") CONFIG_FILES="$CONFIG_FILES src/gtk-glade/doc/Makefile" ;; + "src/wx/Makefile") CONFIG_FILES="$CONFIG_FILES src/wx/Makefile" ;; + "src/gdbstub/Makefile") CONFIG_FILES="$CONFIG_FILES src/gdbstub/Makefile" ;; + "autopackage/default.apspec") CONFIG_FILES="$CONFIG_FILES autopackage/default.apspec" ;; + "po/stamp-it") CONFIG_COMMANDS="$CONFIG_COMMANDS po/stamp-it" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + + +eval set X " :F $CONFIG_FILES :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "default-1":C) case "$CONFIG_FILES" in *po/Makefile.in*) + sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile + esac ;; + "po/stamp-it":C) + if ! grep "^# INTLTOOL_MAKEFILE$" "po/Makefile.in" > /dev/null ; then + as_fn_error $? "po/Makefile.in.in was not created by intltoolize." "$LINENO" 5 + fi + rm -f "po/stamp-it" "po/stamp-it.tmp" "po/POTFILES" "po/Makefile.tmp" + >"po/stamp-it.tmp" + sed '/^#/d + s/^[[].*] *// + /^[ ]*$/d + '"s|^| $ac_top_srcdir/|" \ + "$srcdir/po/POTFILES.in" | sed '$!s/$/ \\/' >"po/POTFILES" + + sed '/^POTFILES =/,/[^\\]$/ { + /^POTFILES =/!d + r po/POTFILES + } + ' "po/Makefile.in" >"po/Makefile" + rm -f "po/Makefile.tmp" + mv "po/stamp-it.tmp" "po/stamp-it" + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/jni/desmume/configure.ac b/jni/desmume/configure.ac new file mode 100755 index 0000000..acce114 --- /dev/null +++ b/jni/desmume/configure.ac @@ -0,0 +1,389 @@ +dnl --- Package name is first argument to AC_INIT +dnl --- Release version is second argument to AC_INIT + +AC_INIT(desmume, [0.9.8]) + +dnl -- find host architecture for some os specific libraries +AC_CANONICAL_HOST +case $host in + *linux*) desmume_arch=linux;; + *mingw*) desmume_arch=windows;; + *darwin*) desmume_arch=linux;; + *bsd*) desmume_arch=linux;; +esac +AC_SUBST(desmume_arch) + +AM_INIT_AUTOMAKE([1.10]) + +dnl -- make sure we have a c++ compiler +AC_PROG_CXX + +dnl -- use ranlib for libraries +AC_PROG_RANLIB + +dnl -- check for endianess +AC_C_BIGENDIAN + +# took this from geany, hope it works +REVISION="r0" +SVN=`which svn 2>/dev/null` +if test -d ".svn" -a "x${SVN}" != "x" -a -x "${SVN}" ; then + REVISION=r`$SVN info|grep 'Last Changed Rev'|cut -d' ' -f4` +fi +AC_DEFINE_UNQUOTED([SVN_REV], "$REVISION", [subversion revision number]) + + +dnl --- Other prerequisites --- +dnl - Check for pkg-config macros +m4_ifdef([PKG_PROG_PKG_CONFIG], [PKG_PROG_PKG_CONFIG]) +dnl - Check for intltool/gettext macros +m4_ifdef([IT_PROG_INTLTOOL],[IT_PROG_INTLTOOL]) + +AC_CHECK_TOOL(HAVE_PKG, pkg-config, []) +if test "xHAVE_PKG" = "x" ; then + AC_MSG_ERROR([pkg-config is required to build desmume]) +fi + +dnl - Check for zlib +AC_CHECK_LIB(z, gzopen, [], [AC_MSG_ERROR([zlib was not found, we can't go further. Please install it or specify the location where it's installed.])]) + +dnl - Check for zziplib +AC_CHECK_LIB(zzip, zzip_open, [ + LIBS="-lzzip $LIBS" + AC_DEFINE([HAVE_LIBZZIP]) + AC_MSG_CHECKING([[whether zzip use void * as second parameter]]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ + void * v; + zzip_read(NULL, v, 0);]])], + AC_MSG_RESULT(yes), + AC_DEFINE([ZZIP_OLD_READ]) + AC_MSG_RESULT(no)) +]) + +dnl - Check for SDL +AC_PATH_PROGS(SDLCONFIG, [sdl-config sdl11-config]) +if test ! "x$SDLCONFIG" = "x" ; then + SDL_CFLAGS=`$SDLCONFIG --cflags` + SDL_LIBS=`$SDLCONFIG --libs` + AC_SUBST(SDL_CFLAGS) + AC_SUBST(SDL_LIBS) +else + AC_MSG_ERROR([sdl is required to build desmume]) +fi + +dnl - Check for the OpenGL includes +AC_CHECK_HEADERS([GL/gl.h], + [AC_CHECK_HEADERS([GL/glu.h], [have_gl_h=yes LIBS="$LIBS -lGLU"], [have_gl_h=no])], + [have_gl_h=no]) +if test "have_gl_h" = "no" ; then + AC_MSG_WARN([Building without GL support because of missing headers.]) +fi +AM_CONDITIONAL([HAVE_GL], [test "${have_gl_h}" = "yes"]) + +dnl - if --enable-osmesa is used, check for it +AC_ARG_ENABLE([osmesa], + [AC_HELP_STRING([--enable-osmesa], [use off-screen mesa])], + [osmesa=$enableval], + [osmesa=yes]) + +if test "x$osmesa" = "xyes" ; then + AC_CHECK_LIB(dl, main) + AC_CHECK_LIB([GL], main) + AC_CHECK_LIB(OSMesa, main,[ + useosmesa=yes + AC_DEFINE(HAVE_LIBOSMESA) + OSMESA_LIBS="-lOSMesa" + AC_SUBST(OSMESA_LIBS) + ]) +fi +AM_CONDITIONAL([HAVE_LIBOSMESA], [test "${useosmesa}" = "yes"]) + +dnl - make the usage of libagg for HUD rendering configurable +AC_ARG_ENABLE([hud], + [AC_HELP_STRING([--enable-hud], [Enable HUD rendering, requires libagg])], + [libagg=yes]) + +dnl - hack to help zero build gtk frontend macos x package +AC_ARG_ENABLE(macosxhack, + [AC_HELP_STRING(--enable-macosxhack, hack to build MacOSX package)], + [GTK_MACOSX_HACK=yes]) + +HAVE_OPENAL=no +dnl - openal support +AC_ARG_ENABLE(openal, + [AC_HELP_STRING(--enable-openal, enable experimental OpenAL microphone input)], + [openal=yes]) + +if test "x$openal" = "xyes" ; then + AC_CHECK_LIB([openal], [main],[ + HAVE_OPENAL=yes + LIBS="$LIBS -lopenal" + ]) +fi +AM_CONDITIONAL([HAVE_OPENAL], [test "${HAVE_OPENAL}" = "yes"]) + +dnl - Check for GTK and/or libglade +FOUND_GLIB=no +HAVE_ALSA=no +GLIB_VER=2.8 +GTK_VER=2.14 + +PKG_CHECK_MODULES(GLIB, + glib-2.0 >= $GLIB_VER, + FOUND_GLIB=yes, + FOUND_GLIB=no) +if test "x$FOUND_GLIB" = "xno"; then + if test ! "x$GTK_MACOSX_HACK" = "xyes"; then + AC_MSG_ERROR([Glib is required to build desmume]) + fi +fi + +PKG_CHECK_MODULES(GTK, + gtk+-2.0 >= $GTK_VER, + HAVE_GTK=yes, + HAVE_GTK=no) +AC_SUBST(GTK_CFLAGS) +AC_SUBST(GTK_LIBS) + + +PKG_CHECK_MODULES(GTHREAD, + "gthread-2.0", + HAVE_GTHREAD=yes, + HAVE_GTHREAD=no) +AC_SUBST(GTHREAD_CFLAGS) +AC_SUBST(GTHREAD_LIBS) + +AC_ARG_ENABLE([glade], + [AC_HELP_STRING([--enable-glade], [enable glade frontend])], + [glade=$enableval], + [glade=yes]) + +if test "x$glade" = "xyes" ; then + PKG_CHECK_MODULES(LIBGLADE, + "libglade-2.0", + HAVE_LIBGLADE=yes, + HAVE_LIBGLADE=no) + AC_SUBST(LIBGLADE_CFLAGS) + AC_SUBST(LIBGLADE_LIBS) + + dnl uninstalled glade ui dir + AC_DEFINE_UNQUOTED(GLADEUI_UNINSTALLED_DIR,"`pwd`/src/gtk-glade/glade/",[path to glade ui dir]) + AC_SUBST(GLADEUI_UNINSTALLED_DIR) + + PKG_CHECK_MODULES(GTKGLEXT, + "gtkglext-1.0", + AC_DEFINE([GTKGLEXT_AVAILABLE], [1]) + []) + AC_SUBST(GTKGLEXT_CFLAGS) + AC_SUBST(GTKGLEXT_LIBS) +fi + +AC_PATH_PROG(UPDATEDESKTOP, [update-desktop-database]) + +# Need check for both lua and lua5.1 to run on debian, see mysql bug #29945 +PKG_CHECK_MODULES(LUA, + lua >= 5.1, + HAVE_LUA=yes, + HAVE_LUA=no) +PKG_CHECK_MODULES(LUA, + lua5.1 >= 5.1, + HAVE_LUA=yes, + HAVE_LUA=no) +AC_SUBST(LUA_CFLAGS) +AC_SUBST(LUA_LIBS) +dnl -- force lua disabled +AM_CONDITIONAL([HAVE_LUA], [test "${HAVE_LUA}x" = "yes"]) + +if test ! "x$HAVE_OPENAL" = "xyes" ; then + PKG_CHECK_MODULES(ALSA, alsa >= 1.0, HAVE_ALSA=yes, HAVE_ALSA=no) + AC_SUBST(ALSA_CFLAGS) + AC_SUBST(ALSA_LIBS) +fi +AM_CONDITIONAL([HAVE_ALSA], [test "${HAVE_ALSA}" = "yes"]) + +PKG_CHECK_MODULES(LIBAGG, libagg >= 2.5.0, FOUND_LIBAGG=yes, FOUND_LIBAGG=no) +AM_CONDITIONAL([HAVE_LIBAGG], [test "x$libagg" = "xyes" -a "${FOUND_LIBAGG}" = "yes"]) +if test "x$libagg" = "xyes" ; then + if test "x$FOUND_LIBAGG" = "xyes" ; then + AC_SUBST(LIBAGG_CFLAGS) + AC_SUBST(LIBAGG_LIBS) + AC_DEFINE([HAVE_LIBAGG]) + else + AC_MSG_WARN([HUD rendering enabled, but libagg not found]) + fi +fi + +PKG_CHECK_MODULES(LIBSOUNDTOUCH, soundtouch >= 1.5.0, HAVE_LIBSOUNDTOUCH=yes, HAVE_LIBSOUNDTOUCH=no) +AC_SUBST(LIBSOUNDTOUCH_CFLAGS) +AC_SUBST(LIBSOUNDTOUCH_LIBS) +AM_CONDITIONAL([HAVE_LIBSOUNDTOUCH], [test "${HAVE_LIBSOUNDTOUCH}" = "yes"]) +if test "x$HAVE_LIBSOUNDTOUCH" = "xyes"; then + AC_DEFINE([HAVE_LIBSOUNDTOUCH]) +else + AC_MSG_WARN([SoundTouch library not found, pcsx2 resampler will be disabled]) +fi + +if test "x$HAVE_ALSA" = "xno"; then + if test "x$HAVE_OPENAL" = "xno"; then + AC_DEFINE([FAKE_MIC]) + fi +fi + +dnl - Check for wxWidgets + +dnl - if --enable-wxwidgets is used, check for it +AC_ARG_ENABLE([wxwidgets], + [AC_HELP_STRING([--enable-wxwidgets], [Enable cross platform wx widgets frontend])], + [wxwidgets=$enableval], + [wxwidgets=no]) +if test "x$wxwidgets" = "xyes" ; then + m4_include(wxwin.m4) + AM_PATH_WXCONFIG([2.4.0], wxwin=yes) + if test "x$wxwin" = "xyes"; then + AC_SUBST(WX_CPPFLAGS) + AC_SUBST(WX_LIBS) + AC_DEFINE([WANT_WX]) + fi +fi + +AM_CONDITIONAL([HAVE_WX], [test "x$wxwidgets" = "xyes"]) + +dnl - Determine which UIs to build and if po/ should be included +PO_DIR="" +UI_DIR="cli $UI_DIR" +if test "x$HAVE_GTK" = "xyes"; then + UI_DIR="gtk $UI_DIR" +fi +if test "x$wxwin" = "xyes"; then + UI_DIR="wx $UI_DIR" +fi + +if test "x$HAVE_LIBGLADE" = "xyes"; then + AC_PROVIDE_IFELSE([IT_PROG_INTLTOOL],[ + UI_DIR="gtk-glade $UI_DIR" + + dnl -- localization for gtk-glade UI + GETTEXT_PACKAGE=desmume + AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [Define to the gettext package name]) + AC_SUBST(GETTEXT_PACKAGE) + ALL_LINGUAS="fr nb pt_BR sv zh_CN zh_TW" + AM_GLIB_GNU_GETTEXT + PO_DIR="po" + PO_MAKEFILE="po/Makefile.in" + ],[ + echo "WARNING: intltool and/or gettext are not available therefore the gtk-glade interface won't be installed." + ]) +fi + +dnl - wifi support +AC_ARG_ENABLE(wifi, + [AC_HELP_STRING(--enable-wifi, enable experimental wifi comm support)], + [ + AC_CHECK_LIB(pcap, main,[ + AC_DEFINE(EXPERIMENTAL_WIFI_COMM) + LIBS="$LIBS -lpcap"], + [AC_MSG_WARN([pcap library not found, wifi will not work])]) + ]) + +dnl Set compiler library flags per host architecture +case $host in + *mingw*) + LIBS="$LIBS -ldxguid -ldxerr8 -ldsound -lopengl32 -lws2_32 -mwindows" + UI_DIR="windows" + ;; + *darwin*) + if test "x$GTK_MACOSX_HACK" = "xyes" ; then + LIBS="$LIBS -framework Gtk -framework GLib" + CPPFLAGS="$CPPFLAGS -I/Library/Frameworks/Cairo.framework/Headers -I/Library/Frameworks/Gtk.framework/Headers -I/Library/Frameworks/GLib.framework/Headers" + GLIB_LIBS="" + AC_SUBST(GLIB_LIBS) + fi + dnl - openal is required on mac os x and we are not able to figure out if it's installed or not + AC_DEFINE(HAVE_OPENAL) + LIBS="$LIBS -framework OpenGL -framework OpenAL" + CPPFLAGS="$CPPFLAGS -I/System/Library/Frameworks/OpenAL.framework/Headers" + AC_SUBST(CPPFLAGS) + dnl - extra hackery needed for X includes + AC_PATH_XTRA + ;; +esac + +AC_SUBST(UI_DIR) +AC_SUBST(PO_DIR) + +dnl - Gdb stub +AC_ARG_ENABLE(gdb-stub, + [AC_HELP_STRING(--enable-gdb-stub, enable gdb stub)], + [ + AC_DEFINE(GDB_STUB) + wantgdbstub=yes + ]) +AM_CONDITIONAL([HAVE_GDB_STUB], [test "${wantgdbstub}" = "yes"]) + +dnl - Compiler warnings + +# for developer use, enable lots of compile warnings, +# but don't require this generally, because some system's +# header files (BSD) can't handle it +# +# NB: must add -Werror after AC_PROG_CC, etc., so do this last +AC_ARG_ENABLE(hardcore, + [AC_HELP_STRING(--enable-hardcore, turn on -W -Wall -Werror)], + [case "${enableval}" in + yes) ENABLE_HARDCORE=1 ;; + no) ENABLE_HARDCORE=0 ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-hardcore) ;; esac], + [ENABLE_HARDCORE=0]) + +if test "x[$]ENABLE_HARDCORE" = "x1"; then + AC_MSG_WARN(enable hardcore compile warnings) + if test "x$CXX" = "x"; then + dnl - only valid for C with newer gcc's + CPPFLAGS="[$]CPPFLAGS -Wmissing-prototypes" + fi + dnl - -Wshadow + CPPFLAGS="[$]CPPFLAGS -Wall -Wextra -D_FORTIFY_SOURCE=2 -Wno-missing-field-initializers -Wpointer-arith -Wcast-align -Wwrite-strings -Wno-unused-parameter -Wmissing-declarations -Wundef -Wmissing-noreturn -Wredundant-decls -Wformat-nonliteral -Wformat-security -Winit-self -Wno-reorder" +fi + +dnl - Enable debug mode +AC_ARG_ENABLE(debug, + AC_HELP_STRING(--enable-debug, enable debug information), + AC_DEFINE(DEBUG)) +AC_ARG_ENABLE(gpu-debug, + AC_HELP_STRING(--enable-gpu-debug, enable gpu debug information), + AC_DEFINE(GPUDEBUG)) +AC_ARG_ENABLE(div-debug, + AC_HELP_STRING(--enable-div-debug, enable div debug information), + AC_DEFINE(DIVDEBUG)) +AC_ARG_ENABLE(sqrt-debug, + AC_HELP_STRING(--enable-sqrt-debug, enable sqrt debug information), + AC_DEFINE(SQRTDEBUG)) +AC_ARG_ENABLE(dma-debug, + AC_HELP_STRING(--enable-dma-debug, enable dma debug information), + AC_DEFINE(DMADEBUG)) + +dnl - Enable memory profiling (disabled) +dnl - AC_ARG_ENABLE(memory-profiling, +dnl - AC_HELP_STRING(--enable-memory-profiling, enable memory profiling information), +dnl - AC_DEFINE(PROFILE_MEMORY_ACCESS)) + +dnl -- set maintainer mode +AM_MAINTAINER_MODE +AC_SUBST(USE_MAINTAINER_MODE) + + +dnl --- Finally, output all the makefiles +AC_CONFIG_FILES([Makefile + ${PO_MAKEFILE} + src/Makefile + src/cli/Makefile + src/cli/doc/Makefile + src/gtk/Makefile + src/gtk/doc/Makefile + src/gtk-glade/Makefile + src/gtk-glade/doc/Makefile + src/wx/Makefile + src/gdbstub/Makefile + autopackage/default.apspec +]) +AC_OUTPUT diff --git a/jni/desmume/depcomp b/jni/desmume/depcomp new file mode 100755 index 0000000..25a39e6 --- /dev/null +++ b/jni/desmume/depcomp @@ -0,0 +1,708 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2012-03-27.16; # UTC + +# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +# 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, 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, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency informations. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the "deleted header file" problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' "$nl" < "$tmpdepfile" | +## Some versions of gcc put a space before the ':'. On the theory +## that the space means something, we add a space to the output as +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like '#:fec' to the end of the + # dependency line. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr "$nl" ' ' >> "$depfile" + echo >> "$depfile" + + # The second pass generates a dummy entry for each header file. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts '$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependent.h'. + # Do two passes, one to just change these to + # '$object: dependent.h' and one to simply 'dependent.h:'. + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'. + # However on + # $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\': + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + # tcc 0.9.26 (FIXME still under development at the moment of writing) + # will emit a similar output, but also prepend the continuation lines + # with horizontal tabulation characters. + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form 'foo.o: dependent.h', + # or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'. + # Do two passes, one to just change these to + # '$object: dependent.h' and one to simply 'dependent.h:'. + sed -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \ + < "$tmpdepfile" > "$depfile" + sed ' + s/[ '"$tab"'][ '"$tab"']*/ /g + s/^ *// + s/ *\\*$// + s/^[^:]*: *// + /^$/d + /:$/d + s/$/ :/ + ' < "$tmpdepfile" >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in 'foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # With Tru64 cc, shared objects can also be used to make a + # static library. This mechanism is used in libtool 1.4 series to + # handle both shared and static libraries in a single compilation. + # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. + # + # With libtool 1.5 this exception was removed, and libtool now + # generates 2 separate objects for the 2 libraries. These two + # compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 + tmpdepfile2=$dir$base.o.d # libtool 1.5 + tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 + tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.o.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + tmpdepfile4=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test "$stat" = 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for ':' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. + "$@" $dashmflag | + sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' "$nl" < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/jni/desmume/dsm.txt b/jni/desmume/dsm.txt new file mode 100755 index 0000000..2942abb --- /dev/null +++ b/jni/desmume/dsm.txt @@ -0,0 +1,74 @@ +DSM is ascii plain text. It is derived from the FCEUX FM2 format. +It consists of several key-value pairs followed by an inputlog section. +The inputlog section can be identified by its starting with a | (pipe). +The inputlog section terminates at eof. +Newlines may be \r\n or \n + +Key-value pairs consist of a key identifier, followed by a space separator, followed by the value text. +Value text is always terminated by a newline, which the value text will not include. +The value text is parsed differently depending on the type of the key. +The key-value pairs may be in any order, except that the first key must be version. + +Integer keys (also used for booleans, with a 1 or 0) will have a value that is a simple integer not to exceed 32bits + - version (required) - the version of the movie file format; for now it is always 3 + - emuVersion (required) - the version of the emulator used to produce the movie + - rerecordCount (optional) - the rerecord count + - romChecksum (optional) - the CRC32 of the rom used to make the movie. should match values specified on advanscene.com + - romSerial (optional) - a concatenation of other uniquely identifying information about the rom (name,gamecode,makercode) + - useExtBios (optional) - were bios files was used? defaults to false. + - swiFromBios (optional) - were swi emulated by ExtBios? (alternative is internal HLE bios). defaults to false. + +The rom identification information may be used at a later point to warn about mismatches between movies and roms, but is not right now. + +String keys have values that consist of the remainder of the key-value pair line. As a consequence, string values cannot contain newlines. + - romFilename (required) - the name of the file used to record the movie + - comment (optional) - simply a memo. + by convention, the first token in the comment value is the subject of the comment. + by convention, subsequent comments with the same subject will have their ordering preserved and may be used to approximate multiline comments. + by convention, the author of the movie should be stored in comment(s) with a subject of: author + +Hex string keys (used for binary blobs) will have a value that is like 0x0123456789ABCDEF... + - romChecksum (required) - this is currently unused. + +GUID keys have a value which is in the standard guid format: 452DE2C3-EF43-2FA9-77AC-0677FC51543B + - guid (required) a unique identifier for a movie, generated when the movie is created, which is used when loading a savestate to make sure it belongs to the current movie. + +The inputlog section consists of lines beginning and ending with a | (pipe). +The fields are as follows, except as noted in note C. +|c|.............XXX YYY Z| + +'R','L','D','U','T','S','B','A','Y','X','W','E','G' + +field c is a variable length decimal integer which is a bitfield corresponding to miscellaneous input states which are valid at the start of the frame. +Therefore, no miscellaneous commands is represented by a value of 0. +Here are the currently defined bit values: +0x01 - Microphone Noise (hardcoded noise sample; to be held through duration of frame) +0x02 - Reset +0x04 - Lid + + +the format of the main section is as follows: + + the field begins with 13 characters which constitute a bitfield. + any character other than ' ' or '.' means that the button was pressed. + by convention, the following mnemonics will be used in a column to remind us of which button corresponds to which column: + RLDUTSBAYXWEG (Right,Left,Down,Up,sTart,Select,B,A,Y,X,lshoulder,rshoulder,debuG) + This ordering is based on FCEUX to a certain extent, and arbitrary after that. + W and E were chosen for shoulders to suggest West and East for Left and Right. + While the emulator supports a 'lid' button, and to some extent a 'blow' button, these are not supported in the movies. + + XXX: %03d, the x position of the stylus (0,0 topleft, 255,191 bottomright) + YYY: %03d, the y position of the stylus + Z: %1d, 1 if the stylus is pressed pressed; 0 if not + +Additional fields after this main section may be added later without breaking the file format. + +* Notes * +A. There is no key-value pair that indicates the length of the movie. This must be read by scanning the inputlog and counting the number of lines. + +B. All movies start from power-on. + +C. The emulator uses these framerate constants + arm7_cycles_per_frame = 560190 + frames_per_second = 59.8261 + diff --git a/jni/desmume/dsv.txt b/jni/desmume/dsv.txt new file mode 100755 index 0000000..2f5b63b --- /dev/null +++ b/jni/desmume/dsv.txt @@ -0,0 +1,39 @@ +The desmume save file format is merely a raw save file with a FOOTER. + +This was chosen in order to maximize compatibility with other emulators, +which tend load the savefile as-is and let the game read out of whatever range +it is expecting. To assist with this, before writing the save file, desmume +will pad the raw save file out to the next highest known length. Note that this +may sometimes be incorrect if the savefile hasnt been written through to the end +during initialization. This could cause other emulators to fail to recognize the +save file. + +Additionally, the footer makes it easier to analyze save files, because the +game's data will be at the correct addresses starting at offset 0x0000. + +The footer format can be identified by locating the 16Byte ascii string +"|-DESMUME SAVE-|" +at the end of the file. This corresponds with the following save structure: + +struct Footer { + u32 actually_written_size; + u32 padded_size; + u32 save_type; //(not currently used) + u32 address_size; //address bus size + u32 save_size; //size parameter of the save type (not currently used) + u32 version_number; //should be 0 + char cookie[16]; +}; + +note that padded_size should be where you see the end of the raw save data +and the beginning of desmume-specific information, including some junk before +the actual footer. + +actually_written_size is the highest address (plus one) written to by the game. + +The new desmume savefile system tries to make as few decisions as possible, +which is the reason for the behavior of actually_written_size and the disuse +of save_type and save_size. If few decisions are made, then few mistakes can +be made. That is the idea, anyway. We'll make decisions later if we need to. +save_type and save_size are reserved in case we do. + diff --git a/jni/desmume/install-sh b/jni/desmume/install-sh new file mode 100755 index 0000000..a9244eb --- /dev/null +++ b/jni/desmume/install-sh @@ -0,0 +1,527 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2011-01-19.21; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + # Protect names problematic for `test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for `test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for `test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/jni/desmume/missing b/jni/desmume/missing new file mode 100755 index 0000000..86a8fc3 --- /dev/null +++ b/jni/desmume/missing @@ -0,0 +1,331 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2012-01-06.13; # UTC + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, +# 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# 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, 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, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: +sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' +sed_minuso='s/.* -o \([^ ]*\).*/\1/p' + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case $1 in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + autom4te touch the output file, or create a stub one + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and +\`g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# normalize program name to check for. +program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). This is about non-GNU programs, so use $1 not +# $program. +case $1 in + lex*|yacc*) + # Not GNU programs, they don't have --version. + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case $program in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case $f in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te*) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison*|yacc*) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if test $# -ne 1; then + eval LASTARG=\${$#} + case $LASTARG in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if test ! -f y.tab.h; then + echo >y.tab.h + fi + if test ! -f y.tab.c; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex*|flex*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if test $# -ne 1; then + eval LASTARG=\${$#} + case $LASTARG in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if test ! -f lex.yy.c; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit $? + fi + ;; + + makeinfo*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + # The file to touch is that specified with -o ... + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -z "$file"; then + # ... or it is the one specified with @setfilename ... + infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n ' + /^@setfilename/{ + s/.* \([^ ]*\) *$/\1/ + p + q + }' $infile` + # ... or it is derived from the source name (dir/f.texi becomes f.info) + test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info + fi + # If the file does not exist, the user really needs makeinfo; + # let's fail without touching anything. + test -f $file || exit 1 + touch $file + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/jni/desmume/src/Disassembler.cpp b/jni/desmume/src/Disassembler.cpp new file mode 100755 index 0000000..49f18c4 --- /dev/null +++ b/jni/desmume/src/Disassembler.cpp @@ -0,0 +1,3782 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2006-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ + +#include +#include +#include "Disassembler.h" +#include "bits.h" + +#define ROR(i, j) ((((u32)(i))>>(j)) | (((u32)(i))<<(32-(j)))) + +const char Condition[16][3] = { + "EQ", + "NE", + "CS", + "CC", + "MI", + "PL", + "VS", + "VC", + "HI", + "LS", + "GE", + "LT", + "GT", + "LE", + "", + "" + }; + +const char Registre[16][4] = { + "R0", + "R1", + "R2", + "R3", + "R4", + "R5", + "R6", + "R7", + "R8", + "R9", + "R10", + "R11", + "R12", + "SP", + "LR", + "PC", + }; + +const char MSR_FIELD[16][5] = { + "", + "c", + "x", + "xc", + "s", + "sc", + "sx", + "sxc", + "f", + "fc", + "fx", + "fxc", + "fs", + "fsc", + "fsx", + "fsxc" + }; + +#define DATAPROC_LSL_IMM(nom, s) char tmp[10] = "";\ + if(((i>>7)&0x1F)!=0)\ + sprintf(tmp, ", LSL #%X", (int)((i>>7)&0x1F));\ + sprintf(txt, "%s%s%s %s, %s, %s%s",\ + #nom,\ + Condition[CONDITION(i)],\ + s,\ + Registre[REG_POS(i,12)],\ + Registre[REG_POS(i,16)],\ + Registre[REG_POS(i,0)],\ + tmp); +#define DATAPROC_ROR_IMM(nom, s) char tmp[10] = "";\ + if(((i>>7)&0x1F)!=0)\ + sprintf(tmp, ", RRX");\ + sprintf(txt, "%s%s%s %s, %s, %s%s",\ + #nom,\ + Condition[CONDITION(i)],\ + s,\ + Registre[REG_POS(i,12)],\ + Registre[REG_POS(i,16)],\ + Registre[REG_POS(i,0)],\ + tmp\ + ); + +#define DATAPROC_REG_SHIFT(nom, shift,s) sprintf(txt, "%s%s%s %s, %s, %s, %s %s",\ + #nom,\ + Condition[CONDITION(i)],\ + s,\ + Registre[REG_POS(i,12)],\ + Registre[REG_POS(i,16)],\ + Registre[REG_POS(i,0)],\ + #shift,\ + Registre[REG_POS(i,8)]\ + ); + +#define DATAPROC_IMM_SHIFT(nom, shift, s) sprintf(txt, "%s%s%s %s, %s, %s, %s #%X",\ + #nom,\ + Condition[CONDITION(i)],\ + s,\ + Registre[REG_POS(i,12)],\ + Registre[REG_POS(i,16)],\ + Registre[REG_POS(i,0)],\ + #shift,\ + (int)((i>>7)&0x1F)\ + ); + +#define DATAPROC_IMM_VALUE(nom,s) u32 shift_op = ROR((i&0xFF), (i>>7)&0x1E);\ + sprintf(txt, "%s%s%s %s, %s, #%X",\ + #nom,\ + Condition[CONDITION(i)],\ + s,\ + Registre[REG_POS(i,12)],\ + Registre[REG_POS(i,16)],\ + (int)shift_op\ + ); + +#define DATAPROC_ONE_OP_LSL_IMM(nom, s, v) char tmp[10] = "";\ + if(((i>>7)&0x1F)!=0)\ + sprintf(tmp, ", LSL #%X", (int)((i>>7)&0x1F));\ + sprintf(txt, "%s%s%s %s, %s%s",\ + #nom,\ + Condition[CONDITION(i)],\ + s,\ + Registre[REG_POS(i,v)],\ + Registre[REG_POS(i,0)],\ + tmp); + +#define DATAPROC_ONE_OP_ROR_IMM(nom, s, v) char tmp[10] = "";\ + if(((i>>7)&0x1F)==0)\ + sprintf(tmp, ", RRX");\ + else\ + sprintf(tmp, ", ROR %d", (int)((i>>7)&0x1F));\ + sprintf(txt, "%s%s%s %s, %s%s",\ + #nom,\ + Condition[CONDITION(i)],\ + s,\ + Registre[REG_POS(i,v)],\ + Registre[REG_POS(i,0)],\ + tmp\ + ); + +#define DATAPROC_ONE_OP_REG_SHIFT(nom, shift,s, v) sprintf(txt, "%s%s%s %s, %s, %s %s",\ + #nom,\ + Condition[CONDITION(i)],\ + s,\ + Registre[REG_POS(i,v)],\ + Registre[REG_POS(i,0)],\ + #shift,\ + Registre[REG_POS(i,8)]\ + ); + +#define DATAPROC_ONE_OP_IMM_SHIFT(nom, shift, s, v) sprintf(txt, "%s%s%s %s, %s, %s #%X",\ + #nom,\ + Condition[CONDITION(i)],\ + s,\ + Registre[REG_POS(i,v)],\ + Registre[REG_POS(i,0)],\ + #shift,\ + (int)((i>>7)&0x1F)\ + ); + +#define DATAPROC_ONE_OP_IMM_VALUE(nom, s, v)\ + u32 shift_op = ROR((i&0xFF), (i>>7)&0x1E);\ + sprintf(txt, "%s%s%s %s, #%X",\ + #nom,\ + Condition[CONDITION(i)],\ + s,\ + Registre[REG_POS(i,v)],\ + (int)shift_op\ + ); + +#define SIGNEXTEND_24(i) (((i)&0xFFFFFF)|(0xFF000000*BIT23(i))) + +#define LDRSTR_LSL_IMM(nom, op, op2, op3) char tmp[10] = "";\ + if(((i>>7)&0x1F)!=0)\ + sprintf(tmp, ", LSL #%X", (int)((i>>7)&0x1F));\ + sprintf(txt, "%s%s %s, [%s%s, %s%s%s%s",\ + #nom,\ + Condition[CONDITION(i)],\ + Registre[REG_POS(i,12)],\ + Registre[REG_POS(i,16)],\ + op2,\ + op,\ + Registre[REG_POS(i,0)],\ + tmp,\ + op3); +#define LDRSTR_ROR_IMM(nom, op, op2, op3) char tmp[10] = "";\ + if(((i>>7)&0x1F)!=0)\ + sprintf(tmp, ", RRX");\ + sprintf(txt, "%s%s %s, [%s%s, %s%s%s%s",\ + #nom,\ + Condition[CONDITION(i)],\ + Registre[REG_POS(i,12)],\ + Registre[REG_POS(i,16)],\ + op2,\ + op,\ + Registre[REG_POS(i,0)],\ + tmp,\ + op3\ + ); + +#define LDRSTR_IMM_SHIFT(nom, shift, op, op2, op3)\ + sprintf(txt, "%s%s %s, [%s%s, %s%s, %s #%X%s",\ + #nom,\ + Condition[CONDITION(i)],\ + Registre[REG_POS(i,12)],\ + Registre[REG_POS(i,16)],\ + op2,\ + op,\ + Registre[REG_POS(i,0)],\ + #shift,\ + (int)((i>>7)&0x1F),\ + op3\ + ); + +#define RegList(nb) char lreg[100] = "";\ + int prec = 0;\ + int j;\ + for(j = 0; j < nb; j++)\ + {\ + if(prec)\ + {\ + if((!BIT_N(i, j+1))||(j==nb-1))\ + {\ + sprintf(lreg + strlen(lreg), "%s,", Registre[j]);\ + prec = 0;\ + }\ + }\ + else\ + {\ + if(BIT_N(i, j))\ + {\ + if((BIT_N(i, j+1))&&(j!=nb-1))\ + {\ + sprintf(lreg + strlen(lreg), "%s-", Registre[j]);\ + prec = 1;\ + }\ + else\ + sprintf(lreg + strlen(lreg), "%s,", Registre[j]);\ + }\ + }\ + }\ + if(*lreg) lreg[strlen(lreg)-1]='\0'; + +static char * OP_UND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "----"); + return txt; +} + +//-----------------------AND------------------------------------ +static char * OP_AND_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_LSL_IMM(AND, ""); + return txt; +} + +static char * OP_AND_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(AND, LSL, ""); + return txt; +} + +static char * OP_AND_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(AND, LSR, ""); + return txt; +} + +static char * OP_AND_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(AND, LSR, ""); + return txt; +} + +static char * OP_AND_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(AND, ASR, ""); + return txt; +} + +static char * OP_AND_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(AND, ASR, ""); + return txt; +} + +static char * OP_AND_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ROR_IMM(AND, ""); + return txt; +} + +static char * OP_AND_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(AND, ROR, ""); + return txt; +} + +static char * OP_AND_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_VALUE(AND, ""); + return txt; +} + +static char * OP_AND_S_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_LSL_IMM(AND, "S"); + return txt; +} + +static char * OP_AND_S_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(AND, LSL, "S"); + return txt; +} + +static char * OP_AND_S_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(AND, LSR, "S"); + return txt; +} + +static char * OP_AND_S_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(AND, LSR, "S"); + return txt; +} + +static char * OP_AND_S_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(AND, ASR, "S"); + return txt; +} + +static char * OP_AND_S_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(AND, ASR, "S"); + return txt; +} + +static char * OP_AND_S_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ROR_IMM(AND, "S"); + return txt; +} + +static char * OP_AND_S_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(AND, ROR, "S"); + return txt; +} + +static char * OP_AND_S_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_VALUE(AND, "S"); + return txt; +} + +//--------------EOR------------------------------ +static char * OP_EOR_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_LSL_IMM(EOR, ""); + return txt; +} + +static char * OP_EOR_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(EOR, LSL, ""); + return txt; +} + +static char * OP_EOR_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(EOR, LSR, ""); + return txt; +} + +static char * OP_EOR_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(EOR, LSR, ""); + return txt; +} + +static char * OP_EOR_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(EOR, ASR, ""); + return txt; +} + +static char * OP_EOR_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(EOR, ASR, ""); + return txt; +} + +static char * OP_EOR_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ROR_IMM(EOR, ""); + return txt; +} + +static char * OP_EOR_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(EOR, ROR, ""); + return txt; +} + +static char * OP_EOR_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_VALUE(EOR, ""); + return txt; +} + +static char * OP_EOR_S_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_LSL_IMM(EOR, "S"); + return txt; +} + +static char * OP_EOR_S_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(EOR, LSL, "S"); + return txt; +} + +static char * OP_EOR_S_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(EOR, LSR, "S"); + return txt; +} + +static char * OP_EOR_S_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(EOR, LSR, "S"); + return txt; +} + +static char * OP_EOR_S_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(EOR, ASR, "S"); + return txt; +} + +static char * OP_EOR_S_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(EOR, ASR, "S"); + return txt; +} + +static char * OP_EOR_S_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ROR_IMM(EOR, "S"); + return txt; +} + +static char * OP_EOR_S_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(EOR, ROR, "S"); + return txt; +} + +static char * OP_EOR_S_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_VALUE(EOR, "S"); + return txt; +} + +//-------------SUB------------------------------------- + +static char * OP_SUB_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_LSL_IMM(SUB, ""); + return txt; +} + +static char * OP_SUB_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(SUB, LSL, ""); + return txt; +} + +static char * OP_SUB_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(SUB, LSR, ""); + return txt; +} + +static char * OP_SUB_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(SUB, LSR, ""); + return txt; +} + +static char * OP_SUB_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(SUB, ASR, ""); + return txt; +} + +static char * OP_SUB_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(SUB, ASR, ""); +return txt;} + +static char * OP_SUB_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ROR_IMM(SUB, ""); +return txt;} + +static char * OP_SUB_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(SUB, ROR, ""); +return txt;} + +static char * OP_SUB_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_VALUE(SUB, ""); +return txt;} + +static char * OP_SUB_S_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_LSL_IMM(SUB, "S"); +return txt;} + +static char * OP_SUB_S_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(SUB, LSL, "S"); +return txt;} + +static char * OP_SUB_S_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(SUB, LSR, "S"); +return txt;} + +static char * OP_SUB_S_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(SUB, LSR, "S"); +return txt;} + +static char * OP_SUB_S_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(SUB, ASR, "S"); +return txt;} + +static char * OP_SUB_S_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(SUB, ASR, "S"); +return txt;} + +static char * OP_SUB_S_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ROR_IMM(SUB, "S"); +return txt;} + +static char * OP_SUB_S_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(SUB, ROR, "S"); +return txt;} + +static char * OP_SUB_S_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_VALUE(SUB, "S"); +return txt;} + +//------------------RSB------------------------ + +static char * OP_RSB_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_LSL_IMM(RSB, ""); +return txt;} + +static char * OP_RSB_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(RSB, LSL, ""); +return txt;} + +static char * OP_RSB_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(RSB, LSR, ""); +return txt;} + +static char * OP_RSB_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(RSB, LSR, ""); +return txt;} + +static char * OP_RSB_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(RSB, ASR, ""); +return txt;} + +static char * OP_RSB_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(RSB, ASR, ""); +return txt;} + +static char * OP_RSB_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ROR_IMM(RSB, ""); +return txt;} + +static char * OP_RSB_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(RSB, ROR, ""); +return txt;} + +static char * OP_RSB_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_VALUE(RSB, ""); +return txt;} + +static char * OP_RSB_S_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_LSL_IMM(RSB, "S"); +return txt;} + +static char * OP_RSB_S_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(RSB, LSL, "S"); +return txt;} + +static char * OP_RSB_S_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(RSB, LSR, "S"); +return txt;} + +static char * OP_RSB_S_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(RSB, LSR, "S"); +return txt;} + +static char * OP_RSB_S_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(RSB, ASR, "S"); +return txt;} + +static char * OP_RSB_S_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(RSB, ASR, "S"); +return txt;} + +static char * OP_RSB_S_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ROR_IMM(RSB, "S"); +return txt;} + +static char * OP_RSB_S_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(RSB, ROR, "S"); +return txt;} + +static char * OP_RSB_S_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_VALUE(RSB, "S"); +return txt;} + +//------------------ADD----------------------------------- + +static char * OP_ADD_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_LSL_IMM(ADD, ""); +return txt;} + +static char * OP_ADD_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ADD, LSL, ""); +return txt;} + +static char * OP_ADD_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(ADD, LSR, ""); +return txt;} + +static char * OP_ADD_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ADD, LSR, ""); +return txt;} + +static char * OP_ADD_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(ADD, ASR, ""); +return txt;} + +static char * OP_ADD_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ADD, ASR, ""); +return txt;} + +static char * OP_ADD_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ROR_IMM(ADD, ""); +return txt;} + +static char * OP_ADD_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ADD, ROR, ""); +return txt;} + +static char * OP_ADD_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_VALUE(ADD, ""); +return txt;} + +static char * OP_ADD_S_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_LSL_IMM(ADD, "S"); +return txt;} + +static char * OP_ADD_S_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ADD, LSL, "S"); +return txt;} + +static char * OP_ADD_S_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(ADD, LSR, "S"); +return txt;} + +static char * OP_ADD_S_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ADD, LSR, "S"); +return txt;} + +static char * OP_ADD_S_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(ADD, ASR, "S"); +return txt;} + +static char * OP_ADD_S_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ADD, ASR, "S"); +return txt;} + +static char * OP_ADD_S_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ROR_IMM(ADD, "S"); +return txt;} + +static char * OP_ADD_S_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ADD, ROR, "S"); +return txt;} + +static char * OP_ADD_S_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_VALUE(ADD, "S"); +return txt;} + +//------------------ADC----------------------------------- + +static char * OP_ADC_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_LSL_IMM(ADC, ""); +return txt;} + +static char * OP_ADC_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ADC, LSL, ""); +return txt;} + +static char * OP_ADC_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(ADC, LSR, ""); +return txt;} + +static char * OP_ADC_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ADC, LSR, ""); +return txt;} + +static char * OP_ADC_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(ADC, ASR, ""); +return txt;} + +static char * OP_ADC_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ADC, ASR, ""); +return txt;} + +static char * OP_ADC_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ROR_IMM(ADC, ""); +return txt;} + +static char * OP_ADC_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ADC, ROR, ""); +return txt;} + +static char * OP_ADC_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_VALUE(ADC, ""); +return txt;} + +static char * OP_ADC_S_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_LSL_IMM(ADC, "S"); +return txt;} + +static char * OP_ADC_S_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ADC, LSL, "S"); +return txt;} + +static char * OP_ADC_S_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(ADC, LSR, "S"); +return txt;} + +static char * OP_ADC_S_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ADC, LSR, "S"); +return txt;} + +static char * OP_ADC_S_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(ADC, ASR, "S"); +return txt;} + +static char * OP_ADC_S_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ADC, ASR, "S"); +return txt;} + +static char * OP_ADC_S_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ROR_IMM(ADC, "S"); +return txt;} + +static char * OP_ADC_S_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ADC, ROR, "S"); +return txt;} + +static char * OP_ADC_S_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_VALUE(ADC, "S"); +return txt;} + +//-------------SBC------------------------------------- + +static char * OP_SBC_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_LSL_IMM(SBC, ""); +return txt;} + +static char * OP_SBC_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(SBC, LSL, ""); +return txt;} + +static char * OP_SBC_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(SBC, LSR, ""); +return txt;} + +static char * OP_SBC_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(SBC, LSR, ""); +return txt;} + +static char * OP_SBC_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(SBC, ASR, ""); +return txt;} + +static char * OP_SBC_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(SBC, ASR, ""); +return txt;} + +static char * OP_SBC_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ROR_IMM(SBC, ""); +return txt;} + +static char * OP_SBC_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(SBC, ROR, ""); +return txt;} + +static char * OP_SBC_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_VALUE(SBC, ""); +return txt;} + +static char * OP_SBC_S_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_LSL_IMM(SBC, "S"); +return txt;} + +static char * OP_SBC_S_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(SBC, LSL, "S"); +return txt;} + +static char * OP_SBC_S_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(SBC, LSR, "S"); +return txt;} + +static char * OP_SBC_S_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(SBC, LSR, "S"); +return txt;} + +static char * OP_SBC_S_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(SBC, ASR, "S"); +return txt;} + +static char * OP_SBC_S_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(SBC, ASR, "S"); +return txt;} + +static char * OP_SBC_S_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ROR_IMM(SBC, "S"); +return txt;} + +static char * OP_SBC_S_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(SBC, ROR, "S"); +return txt;} + +static char * OP_SBC_S_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_VALUE(SBC, "S"); +return txt;} + +//---------------RSC---------------------------------- + +static char * OP_RSC_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_LSL_IMM(RSC, ""); +return txt;} + +static char * OP_RSC_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(RSC, LSL, ""); +return txt;} + +static char * OP_RSC_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(RSC, LSR, ""); +return txt;} + +static char * OP_RSC_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(RSC, LSR, ""); +return txt;} + +static char * OP_RSC_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(RSC, ASR, ""); +return txt;} + +static char * OP_RSC_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(RSC, ASR, ""); +return txt;} + +static char * OP_RSC_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ROR_IMM(RSC, ""); +return txt;} + +static char * OP_RSC_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(RSC, ROR, ""); +return txt;} + +static char * OP_RSC_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_VALUE(RSC, ""); +return txt;} + +static char * OP_RSC_S_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_LSL_IMM(RSC, "S"); +return txt;} + +static char * OP_RSC_S_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(RSC, LSL, "S"); +return txt;} + +static char * OP_RSC_S_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(RSC, LSR, "S"); +return txt;} + +static char * OP_RSC_S_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(RSC, LSR, "S"); +return txt;} + +static char * OP_RSC_S_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(RSC, ASR, "S"); +return txt;} + +static char * OP_RSC_S_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(RSC, ASR, "S"); +return txt;} + +static char * OP_RSC_S_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ROR_IMM(RSC, "S"); +return txt;} + +static char * OP_RSC_S_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(RSC, ROR, "S"); +return txt;} + +static char * OP_RSC_S_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_VALUE(RSC, "S"); +return txt;} + +//-------------------TST---------------------------- + +static char * OP_TST_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_LSL_IMM(TST, "", 16); +return txt;} + +static char * OP_TST_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(TST, LSL, "", 16); +return txt;} + +static char * OP_TST_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_SHIFT(TST, LSR, "", 16); +return txt;} + +static char * OP_TST_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(TST, LSR, "", 16); +return txt;} + +static char * OP_TST_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_SHIFT(TST, ASR, "", 16); +return txt;} + +static char * OP_TST_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(TST, ASR, "", 16); +return txt;} + +static char * OP_TST_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_ROR_IMM(TST, "", 16); +return txt;} + +static char * OP_TST_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(TST, ROR, "", 16); +return txt;} + +static char * OP_TST_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_VALUE(TST, "", 16); +return txt;} + +//-------------------TEQ---------------------------- + +static char * OP_TEQ_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_LSL_IMM(TEQ, "", 16); +return txt;} + +static char * OP_TEQ_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(TEQ, LSL, "", 16); +return txt;} + +static char * OP_TEQ_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_SHIFT(TEQ, LSR, "", 16); +return txt;} + +static char * OP_TEQ_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(TEQ, LSR, "", 16); +return txt;} + +static char * OP_TEQ_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_SHIFT(TEQ, ASR, "", 16); +return txt;} + +static char * OP_TEQ_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(TEQ, ASR, "", 16); +return txt;} + +static char * OP_TEQ_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_ROR_IMM(TEQ, "", 16); +return txt;} + +static char * OP_TEQ_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(TEQ, ROR, "", 16); +return txt;} + +static char * OP_TEQ_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_VALUE(TEQ, "", 16); +return txt;} + +//-------------CMP------------------------------------- + +static char * OP_CMP_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_LSL_IMM(CMP, "", 16); +return txt;} + +static char * OP_CMP_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(CMP, LSL, "", 16); +return txt;} + +static char * OP_CMP_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_SHIFT(CMP, LSR, "", 16); +return txt;} + +static char * OP_CMP_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(CMP, LSR, "", 16); +return txt;} + +static char * OP_CMP_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_SHIFT(CMP, ASR, "", 16); +return txt;} + +static char * OP_CMP_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(CMP, ASR, "", 16); +return txt;} + +static char * OP_CMP_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_ROR_IMM(CMP, "", 16); +return txt;} + +static char * OP_CMP_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(CMP, ROR, "", 16); +return txt;} + +static char * OP_CMP_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_VALUE(CMP, "", 16); +return txt;} + +//---------------CMN--------------------------- + +static char * OP_CMN_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_LSL_IMM(CMN, "", 16); +return txt;} + +static char * OP_CMN_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(CMN, LSL, "", 16); +return txt;} + +static char * OP_CMN_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_SHIFT(CMP, ASR, "", 16); +return txt;} + +static char * OP_CMN_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(CMN, LSR, "", 16); +return txt;} + +static char * OP_CMN_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_SHIFT(CMN, ASR, "", 16); +return txt;} + +static char * OP_CMN_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(CMN, ASR, "", 16); +return txt;} + +static char * OP_CMN_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_ROR_IMM(CMN, "", 16); +return txt;} + +static char * OP_CMN_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(CMN, ROR, "", 16); +return txt;} + +static char * OP_CMN_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_VALUE(CMN, "", 16); +return txt;} + +//------------------ORR------------------- + +static char * OP_ORR_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_LSL_IMM(ORR, ""); +return txt;} + +static char * OP_ORR_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ORR, LSL, ""); +return txt;} + +static char * OP_ORR_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(ORR, LSR, ""); +return txt;} + +static char * OP_ORR_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ORR, LSR, ""); +return txt;} + +static char * OP_ORR_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(ORR, ASR, ""); +return txt;} + +static char * OP_ORR_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ORR, ASR, ""); +return txt;} + +static char * OP_ORR_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ROR_IMM(ORR, ""); +return txt;} + +static char * OP_ORR_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ORR, ROR, ""); +return txt;} + +static char * OP_ORR_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_VALUE(ORR, ""); +return txt;} + +static char * OP_ORR_S_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_LSL_IMM(ORR, "S"); +return txt;} + +static char * OP_ORR_S_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ORR, LSL, "S"); +return txt;} + +static char * OP_ORR_S_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(ORR, LSR, "S"); +return txt;} + +static char * OP_ORR_S_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ORR, LSR, "S"); +return txt;} + +static char * OP_ORR_S_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(ORR, ASR, "S"); +return txt;} + +static char * OP_ORR_S_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ORR, ASR, "S"); +return txt;} + +static char * OP_ORR_S_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ROR_IMM(ORR, "S"); +return txt;} + +static char * OP_ORR_S_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(ORR, ROR, "S"); +return txt;} + +static char * OP_ORR_S_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_VALUE(ORR, "S"); +return txt;} + +//------------------MOV------------------- + +static char * OP_MOV_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_LSL_IMM(MOV, "", 12); +return txt;} + +static char * OP_MOV_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(MOV, LSL, "", 12); +return txt;} + +static char * OP_MOV_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_SHIFT(MOV, LSR, "", 12); +return txt;} + +static char * OP_MOV_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(MOV, LSR, "", 12); +return txt;} + +static char * OP_MOV_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_SHIFT(MOV, ASR, "", 12); +return txt;} + +static char * OP_MOV_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(MOV, ASR, "", 12); +return txt;} + +static char * OP_MOV_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_ROR_IMM(MOV, "", 12); +return txt;} + +static char * OP_MOV_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(MOV, ROR, "", 12); +return txt;} + +static char * OP_MOV_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_VALUE(MOV, "", 12); +return txt;} + +static char * OP_MOV_S_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_LSL_IMM(MOV, "S", 12); +return txt;} + +static char * OP_MOV_S_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(MOV, LSL, "S", 12); +return txt;} + +static char * OP_MOV_S_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_SHIFT(MOV, LSR, "S", 12); +return txt;} + +static char * OP_MOV_S_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(MOV, LSR, "S", 12); +return txt;} + +static char * OP_MOV_S_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_SHIFT(MOV, ASR, "S", 12); +return txt;} + +static char * OP_MOV_S_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(MOV, ASR, "S", 12); +return txt;} + +static char * OP_MOV_S_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_ROR_IMM(MOV, "S", 12); +return txt;} + +static char * OP_MOV_S_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(MOV, ROR, "S", 12); +return txt;} + +static char * OP_MOV_S_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_VALUE(MOV, "S", 12); +return txt;} + +//------------------BIC------------------- + +static char * OP_BIC_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_LSL_IMM(BIC, ""); +return txt;} + +static char * OP_BIC_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(BIC, LSL, ""); +return txt;} + +static char * OP_BIC_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(BIC, LSR, ""); +return txt;} + +static char * OP_BIC_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(BIC, LSR, ""); +return txt;} + +static char * OP_BIC_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(BIC, ASR, ""); +return txt;} + +static char * OP_BIC_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(BIC, ASR, ""); +return txt;} + +static char * OP_BIC_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ROR_IMM(BIC, ""); +return txt;} + +static char * OP_BIC_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(BIC, ROR, ""); +return txt;} + +static char * OP_BIC_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_VALUE(BIC, ""); +return txt;} + +static char * OP_BIC_S_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_LSL_IMM(BIC, "S"); +return txt;} + +static char * OP_BIC_S_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(BIC, LSL, "S"); +return txt;} + +static char * OP_BIC_S_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(BIC, LSR, "S"); +return txt;} + +static char * OP_BIC_S_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(BIC, LSR, "S"); +return txt;} + +static char * OP_BIC_S_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_SHIFT(BIC, ASR, "S"); +return txt;} + +static char * OP_BIC_S_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(BIC, ASR, "S"); +return txt;} + +static char * OP_BIC_S_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ROR_IMM(BIC, "S"); +return txt;} + +static char * OP_BIC_S_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_REG_SHIFT(BIC, ROR, "S"); +return txt;} + +static char * OP_BIC_S_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_IMM_VALUE(BIC, "S"); +return txt;} + +//------------------MVN------------------- + +static char * OP_MVN_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_LSL_IMM(MVN, "", 12); +return txt;} + +static char * OP_MVN_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(MVN, LSL, "", 12); +return txt;} + +static char * OP_MVN_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_SHIFT(MVN, LSR, "", 12); +return txt;} + +static char * OP_MVN_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(MVN, LSR, "", 12); +return txt;} + +static char * OP_MVN_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_SHIFT(MVN, ASR, "", 12); +return txt;} + +static char * OP_MVN_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(MVN, ASR, "", 12); +return txt;} + +static char * OP_MVN_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_ROR_IMM(MVN, "", 12); +return txt;} + +static char * OP_MVN_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(MVN, ROR, "", 12); +return txt;} + +static char * OP_MVN_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_VALUE(MVN, "", 12); +return txt;} + +static char * OP_MVN_S_LSL_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_LSL_IMM(MVN, "S", 12); +return txt;} + +static char * OP_MVN_S_LSL_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(MVN, LSL, "S", 12); +return txt;} + +static char * OP_MVN_S_LSR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_SHIFT(MVN, LSR, "S", 12); +return txt;} + +static char * OP_MVN_S_LSR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(MVN, LSR, "S", 12); +return txt;} + +static char * OP_MVN_S_ASR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_SHIFT(MOV, ASR, "S", 12); +return txt;} + +static char * OP_MVN_S_ASR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(MVN, ASR, "S", 12); +return txt;} + +static char * OP_MVN_S_ROR_IMM(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_ROR_IMM(MVN, "S", 12); +return txt;} + +static char * OP_MVN_S_ROR_REG(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_REG_SHIFT(MVN, ROR, "S", 12); +return txt;} + +static char * OP_MVN_S_IMM_VAL(u32 adr, u32 i, char * txt) +{ + DATAPROC_ONE_OP_IMM_VALUE(MVN, "S", 12); +return txt;} + + +//-------------MUL------------------------ + +static char * OP_MUL(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "MUL%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); +return txt;} + +static char * OP_MLA(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "MLA%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)], Registre[REG_POS(i,12)]); +return txt;} + +static char * OP_MUL_S(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "MUL%sS %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); +return txt;} + +static char * OP_MLA_S(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "MLA%sS %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)], Registre[REG_POS(i,12)]); +return txt;} + + +//----------UMUL-------------------------- + +static char * OP_UMULL(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "UMULL%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); +return txt;} + +static char * OP_UMLAL(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "UMLAL%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); +return txt;} + +static char * OP_UMULL_S(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "UMULL%sS %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); +return txt;} + +static char * OP_UMLAL_S(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "UMLAL%sS %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); +return txt;} + +//----------SMUL-------------------------- + +static char * OP_SMULL(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SMULL%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); +return txt;} + +static char * OP_SMLAL(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SMLAL%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); +return txt;} + +static char * OP_SMULL_S(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SMULL%sS %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); +return txt;} + +static char * OP_SMLAL_S(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SMLAL%sS %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); +return txt;} + +//---------------SWP------------------------------ + +static char * OP_SWP(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SWP%s %s, %s, [%s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,0)], Registre[REG_POS(i,16)]); +return txt;} + +static char * OP_SWPB(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SWPB%s %s, %s, [%s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,0)], Registre[REG_POS(i,16)]); +return txt;} + +//------------LDRH----------------------------- + +static char * OP_LDRH_P_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRH%s %s, [%s, #%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_LDRH_M_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRH%s %s, [%s, -#%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_LDRH_P_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRH%s %s, [%s, %s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_LDRH_M_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRH%s %s, [%s, -%s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_LDRH_PRE_INDE_P_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRH%s %s, [%s, #%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_LDRH_PRE_INDE_M_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRH%s %s, [%s, -#%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_LDRH_PRE_INDE_P_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRH%s %s, [%s, %s]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_LDRH_PRE_INDE_M_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRH%s %s, [%s, -%s]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_LDRH_POS_INDE_P_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRH%s %s, [%s], #%X", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_LDRH_POS_INDE_M_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRH%s %s, [%s], -#%X", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_LDRH_POS_INDE_P_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRH%s %s, [%s], %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_LDRH_POS_INDE_M_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRH%s %s, [%s], -%s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +//------------STRH----------------------------- + +static char * OP_STRH_P_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRH%s %s, [%s, #%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_STRH_M_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRH%s %s, [%s, -#%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_STRH_P_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRH%s %s, [%s, %s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_STRH_M_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRH%s %s, [%s, -%s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_STRH_PRE_INDE_P_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRH%s %s, [%s, #%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_STRH_PRE_INDE_M_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRH%s %s, [%s, -#%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_STRH_PRE_INDE_P_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRH%s %s, [%s, %s]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_STRH_PRE_INDE_M_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRH%s %s, [%s, -%s]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_STRH_POS_INDE_P_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRH%s %s, [%s], #%X", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_STRH_POS_INDE_M_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRH%s %s, [%s], -#%X", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_STRH_POS_INDE_P_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRH%s %s, [%s], %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_STRH_POS_INDE_M_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRH%s %s, [%s], -%s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +//----------------LDRSH-------------------------- + +static char * OP_LDRSH_P_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSH%s %s, [%s, #%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_LDRSH_M_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSH%s %s, [%s, -#%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_LDRSH_P_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSH%s %s, [%s, %s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_LDRSH_M_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSH%s %s, [%s, -%s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_LDRSH_PRE_INDE_P_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSH%s %s, [%s, #%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_LDRSH_PRE_INDE_M_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSH%s %s, [%s, -#%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_LDRSH_PRE_INDE_P_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSH%s %s, [%s, %s]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_LDRSH_PRE_INDE_M_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSH%s %s, [%s, -%s]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_LDRSH_POS_INDE_P_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSH%s %s, [%s], #%X", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_LDRSH_POS_INDE_M_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSH%s %s, [%s], -#%X", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_LDRSH_POS_INDE_P_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSH%s %s, [%s], %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_LDRSH_POS_INDE_M_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSH%s %s, [%s], -%s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +//----------------------LDRSB---------------------- + +static char * OP_LDRSB_P_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSB%s %s, [%s, #%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_LDRSB_M_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSB%s %s, [%s, -#%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_LDRSB_P_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSB%s %s, [%s, %s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_LDRSB_M_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSB%s %s, [%s, -%s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_LDRSB_PRE_INDE_P_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSB%s %s, [%s, #%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_LDRSB_PRE_INDE_M_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSB%s %s, [%s, -#%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_LDRSB_PRE_INDE_P_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSB%s %s, [%s, %s]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_LDRSB_PRE_INDE_M_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSB%s %s, [%s, -%s]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_LDRSB_POS_INDE_P_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSB%s %s, [%s], #%X", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_LDRSB_POS_INDE_M_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSB%s %s, [%s], -#%X", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(((i>>4)&0xF0)|(i&0xF))); +return txt;} + +static char * OP_LDRSB_POS_INDE_P_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSB%s %s, [%s], %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_LDRSB_POS_INDE_M_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSB%s %s, [%s], -%s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +//--------------MRS-------------------------------- + +static char * OP_MRS_CPSR(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "MRS%s %s, CPSR", Condition[CONDITION(i)], Registre[REG_POS(i,12)]); +return txt;} + +static char * OP_MRS_SPSR(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "MRS%s %s, SPSR", Condition[CONDITION(i)], Registre[REG_POS(i,12)]); +return txt;} + +//--------------MSR-------------------------------- + +static char * OP_MSR_CPSR(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "MSR%s CPSR_%s, %s", Condition[CONDITION(i)], MSR_FIELD[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_MSR_SPSR(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "MSR%s SPSR_%s, %s", Condition[CONDITION(i)], MSR_FIELD[REG_POS(i,16)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_MSR_CPSR_IMM_VAL(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "MSR%s CPSR_%s, #%X", Condition[CONDITION(i)], MSR_FIELD[REG_POS(i,16)], (int)ROR((i&0xFF), ((i>>7)&0x1E))); +return txt;} + +static char * OP_MSR_SPSR_IMM_VAL(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "MSR%s SPSR_%s, #%X", Condition[CONDITION(i)], MSR_FIELD[REG_POS(i,16)], (int)ROR((i&0xFF), (i>>7)&0x1E)); +return txt;} + +//-----------------BRANCH-------------------------- + +static char * OP_BX(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "BX%s %s", Condition[CONDITION(i)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_BLX_REG(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "BLX%s %s", Condition[CONDITION(i)], Registre[REG_POS(i,0)]); +return txt;} + +static char * OP_B(u32 adr, u32 i, char * txt) +{ + if(CONDITION(i)==0xF) + { + sprintf(txt, "BLX%s %08X", Condition[CONDITION(i)], (int)(adr+(SIGNEXTEND_24(i)<<2)+8)); + return txt;} + sprintf(txt, "B%s %08X", Condition[CONDITION(i)], (int)(adr+(SIGNEXTEND_24(i)<<2)+8)); +return txt;} + +static char * OP_BL(u32 adr, u32 i, char * txt) +{ + if(CONDITION(i)==0xF) + { + sprintf(txt, "BLX%s %08X", Condition[CONDITION(i)], (int)(adr+(SIGNEXTEND_24(i)<<2)+10)); + return txt;} + sprintf(txt, "BL%s %08X", Condition[CONDITION(i)], (int)(adr+(SIGNEXTEND_24(i)<<2)+8)); +return txt;} + +//----------------CLZ------------------------------- + +static char * OP_CLZ(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "CLZ%s %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,0)]); +return txt;} + + +//--------------------QADD--QSUB------------------------------ + +static char * OP_QADD(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "QADD%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,0)], Registre[REG_POS(i,16)]); +return txt;} + +static char * OP_QSUB(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "QSUB%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,0)], Registre[REG_POS(i,16)]); +return txt;} + +static char * OP_QDADD(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "QDADD%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,0)], Registre[REG_POS(i,16)]); +return txt;} + +static char * OP_QDSUB(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "QDSUB%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,0)], Registre[REG_POS(i,16)]); +return txt;} + +//-----------------SMUL------------------------------- + +static char * OP_SMUL_B_B(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SMULBB%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); +return txt;} + +static char * OP_SMUL_B_T(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SMULBT%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); +return txt;} + +static char * OP_SMUL_T_B(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SMULTB%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); +return txt;} + +static char * OP_SMUL_T_T(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SMULTT%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); +return txt;} + +//-----------SMLA---------------------------- + +static char * OP_SMLA_B_B(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SMLABB%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)], Registre[REG_POS(i,12)]); +return txt;} + +static char * OP_SMLA_B_T(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SMLABT%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)], Registre[REG_POS(i,12)]); +return txt;} + +static char * OP_SMLA_T_B(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SMLATB%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)], Registre[REG_POS(i,12)]); +return txt;} + +static char * OP_SMLA_T_T(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SMLATT%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)], Registre[REG_POS(i,12)]); +return txt;} + +//--------------SMLAL--------------------------------------- + +static char * OP_SMLAL_B_B(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SMLABB%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); +return txt;} + +static char * OP_SMLAL_B_T(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SMLABT%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); +return txt;} + +static char * OP_SMLAL_T_B(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SMLATB%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); +return txt;} + +static char * OP_SMLAL_T_T(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SMLATT%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); +return txt;} + +//--------------SMULW-------------------- + +static char * OP_SMULW_B(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SMULWB%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); +return txt;} + +static char * OP_SMULW_T(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SMULWT%s %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)]); +return txt;} + +//--------------SMLAW------------------- +static char * OP_SMLAW_B(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SMLAWB%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)], Registre[REG_POS(i,12)]); +return txt;} + +static char * OP_SMLAW_T(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SMLAWT%s %s, %s, %s, %s", Condition[CONDITION(i)], Registre[REG_POS(i,16)], Registre[REG_POS(i,0)], Registre[REG_POS(i,8)], Registre[REG_POS(i,12)]); +return txt;} + +//------------LDR--------------------------- + +static char * OP_LDR_P_IMM_OFF(u32 adr, u32 i, char * txt) +{ + if(REG_POS(i,16) == 15) + sprintf(txt, "LDR%s %s, [%08X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], (adr + 8 + (int)(i&0x7FF))); + else + sprintf(txt, "LDR%s %s, [%s, #%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_LDR_M_IMM_OFF(u32 adr, u32 i, char * txt) +{ + if(REG_POS(i,16) == 15) + sprintf(txt, "LDR%s %s, [%08X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], (adr + 8 - (int)(i&0x7FF))); + else + sprintf(txt, "LDR%s %s, [%s, -#%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_LDREX(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDREX%s %s, [%s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)]); +return txt;} + +static char * OP_LDR_P_LSL_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(LDR, "", "", "]"); +return txt;} + +static char * OP_LDR_M_LSL_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(LDR, "-", "", "]"); +return txt;} + +static char * OP_LDR_P_LSR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDR, LSR, "", "", "]"); +return txt;} + +static char * OP_LDR_M_LSR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDR, LSR, "M", "", "]"); +return txt;} + +static char * OP_LDR_P_ASR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDR, ASR, "", "", "]"); +return txt;} + +static char * OP_LDR_M_ASR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDR, ASR, "-", "", "]"); +return txt;} + +static char * OP_LDR_P_ROR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(LDR, "", "", "]"); +return txt;} + +static char * OP_LDR_M_ROR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(LDR, "-", "", "]"); +return txt;} + +static char * OP_LDR_P_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDR%s %s, [%s, #%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_LDR_M_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDR%s %s, [%s, -#%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_LDR_P_LSL_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(LDR, "", "", "]!"); +return txt;} + +static char * OP_LDR_M_LSL_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(LDR, "-", "", "]!"); +return txt;} + +static char * OP_LDR_P_LSR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDR, LSR, "", "", "]!"); +return txt;} + +static char * OP_LDR_M_LSR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDR, LSR, "-", "", "]!"); +return txt;} + +static char * OP_LDR_P_ASR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDR, ASR, "", "", "]!"); +return txt;} + +static char * OP_LDR_M_ASR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDR, ASR, "-", "", "]!"); +return txt;} + +static char * OP_LDR_P_ROR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(LDR, "", "", "]!"); +return txt;} + +static char * OP_LDR_M_ROR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(LDR, "-", "", "]!"); +return txt;} + +static char * OP_LDR_P_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDR%s %s, [%s], #%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_LDR_P_IMM_OFF_POSTIND2(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDR%s %s, [%s], #%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_LDR_M_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDR%s %s, [%s], -#%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_LDR_P_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(LDR, "", "]", ""); +return txt;} + +static char * OP_LDR_M_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(LDR, "-", "]", ""); +return txt;} + +static char * OP_LDR_P_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDR, LSR, "", "]", ""); +return txt;} + +static char * OP_LDR_M_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDR, LSR, "-", "]", ""); +return txt;} + +static char * OP_LDR_P_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDR, ASR, "", "]", ""); +return txt;} + +static char * OP_LDR_M_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDR, ASR, "-", "]", ""); +return txt;} + +static char * OP_LDR_P_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(LDR, "", "]", ""); +return txt;} + +static char * OP_LDR_M_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(LDR, "-", "]", ""); +return txt;} + +//-----------------LDRB------------------------------------------- + +static char * OP_LDRB_P_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRB%s %s, [%s, #%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_LDRB_M_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRB%s %s, [%s, -#%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_LDRB_P_LSL_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(LDRB, "", "", "]"); +return txt;} + +static char * OP_LDRB_M_LSL_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(LDRB, "-", "", "]"); +return txt;} + +static char * OP_LDRB_P_LSR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDRB, LSR, "", "", "]"); +return txt;} + +static char * OP_LDRB_M_LSR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDRB, LSR, "M", "", "]"); +return txt;} + +static char * OP_LDRB_P_ASR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDRB, ASR, "", "", "]"); +return txt;} + +static char * OP_LDRB_M_ASR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDRB, ASR, "-", "", "]"); +return txt;} + +static char * OP_LDRB_P_ROR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(LDRB, "", "", "]"); +return txt;} + +static char * OP_LDRB_M_ROR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(LDRB, "-", "", "]"); +return txt;} + +static char * OP_LDRB_P_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRB%s %s, [%s, #%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_LDRB_M_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRB%s %s, [%s, -#%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_LDRB_P_LSL_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(LDRB, "", "", "]!"); +return txt;} + +static char * OP_LDRB_M_LSL_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(LDRB, "-", "", "]!"); +return txt;} + +static char * OP_LDRB_P_LSR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDRB, LSR, "", "", "]!"); +return txt;} + +static char * OP_LDRB_M_LSR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDRB, LSR, "-", "", "]!"); +return txt;} + +static char * OP_LDRB_P_ASR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDRB, ASR, "", "", "]!"); +return txt;} + +static char * OP_LDRB_M_ASR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDRB, ASR, "-", "", "]!"); +return txt;} + +static char * OP_LDRB_P_ROR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(LDRB, "", "", "]!"); +return txt;} + +static char * OP_LDRB_M_ROR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(LDRB, "-", "", "]!"); +return txt;} + +static char * OP_LDRB_P_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRB%s %s, [%s], #%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_LDRB_M_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRB%s %s, [%s], -#%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_LDRB_P_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(LDRB, "", "]", ""); +return txt;} + +static char * OP_LDRB_M_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(LDRB, "-", "]", ""); +return txt;} + +static char * OP_LDRB_P_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDRB, LSR, "", "]", ""); +return txt;} + +static char * OP_LDRB_M_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDRB, LSR, "-", "]", ""); +return txt;} + +static char * OP_LDRB_P_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDRB, ASR, "", "]", ""); +return txt;} + +static char * OP_LDRB_M_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDRB, ASR, "-", "]", ""); +return txt;} + +static char * OP_LDRB_P_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(LDRB, "", "]", ""); +return txt;} + +static char * OP_LDRB_M_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(LDRB, "-", "]", ""); +return txt;} + +//----------------------STR-------------------------------- + +static char * OP_STR_P_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STR%s %s, [%s, #%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_STR_M_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STR%s %s, [%s, -#%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_STREX(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STREX%s %s, %s, [%s]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,0)], Registre[REG_POS(i,16)]); +return txt;} + +static char * OP_STR_P_LSL_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(STR, "", "", "]"); +return txt;} + +static char * OP_STR_M_LSL_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(STR, "-", "", "]"); +return txt;} + +static char * OP_STR_P_LSR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STR, LSR, "", "", "]"); +return txt;} + +static char * OP_STR_M_LSR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STR, LSR, "M", "", "]"); +return txt;} + +static char * OP_STR_P_ASR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STR, ASR, "", "", "]"); +return txt;} + +static char * OP_STR_M_ASR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STR, ASR, "-", "", "]"); +return txt;} + +static char * OP_STR_P_ROR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(STR, "", "", "]"); +return txt;} + +static char * OP_STR_M_ROR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(STR, "-", "", "]"); +return txt;} + +static char * OP_STR_P_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STR%s %s, [%s, #%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_STR_M_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STR%s %s, [%s, -#%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_STR_P_LSL_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(STR, "", "", "]!"); +return txt;} + +static char * OP_STR_M_LSL_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(STR, "-", "", "]!"); +return txt;} + +static char * OP_STR_P_LSR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STR, LSR, "", "", "]!"); +return txt;} + +static char * OP_STR_M_LSR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STR, LSR, "-", "", "]!"); +return txt;} + +static char * OP_STR_P_ASR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STR, ASR, "", "", "]!"); +return txt;} + +static char * OP_STR_M_ASR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STR, ASR, "-", "", "]!"); +return txt;} + +static char * OP_STR_P_ROR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(STR, "", "", "]!"); +return txt;} + +static char * OP_STR_M_ROR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(STR, "-", "", "]!"); +return txt;} + +static char * OP_STR_P_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STR%s %s, [%s], #%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_STR_M_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STR%s %s, [%s], -#%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_STR_P_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(STR, "", "]", ""); +return txt;} + +static char * OP_STR_M_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(STR, "-", "]", ""); +return txt;} + +static char * OP_STR_P_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STR, LSR, "", "]", ""); +return txt;} + +static char * OP_STR_M_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STR, LSR, "-", "]", ""); +return txt;} + +static char * OP_STR_P_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STR, ASR, "", "]", ""); +return txt;} + +static char * OP_STR_M_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STR, ASR, "-", "]", ""); +return txt;} + +static char * OP_STR_P_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(STR, "", "]", ""); +return txt;} + +static char * OP_STR_M_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(STR, "-", "]", ""); +return txt;} + +//-----------------------STRB------------------------------------- + +static char * OP_STRB_P_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRB%s %s, [%s, #%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_STRB_M_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRB%s %s, [%s, -#%X]", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_STRB_P_LSL_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(STRB, "", "", "]"); +return txt;} + +static char * OP_STRB_M_LSL_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(STRB, "-", "", "]"); +return txt;} + +static char * OP_STRB_P_LSR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STRB, LSR, "", "", "]"); +return txt;} + +static char * OP_STRB_M_LSR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STRB, LSR, "M", "", "]"); +return txt;} + +static char * OP_STRB_P_ASR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STRB, ASR, "", "", "]"); +return txt;} + +static char * OP_STRB_M_ASR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STRB, ASR, "-", "", "]"); +return txt;} + +static char * OP_STRB_P_ROR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(STRB, "", "", "]"); +return txt;} + +static char * OP_STRB_M_ROR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(STRB, "-", "", "]"); +return txt;} + +static char * OP_STRB_P_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRB%s %s, [%s, #%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_STRB_M_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRB%s %s, [%s, -#%X]!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_STRB_P_LSL_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(STRB, "", "", "]!"); +return txt;} + +static char * OP_STRB_M_LSL_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(STRB, "-", "", "]!"); +return txt;} + +static char * OP_STRB_P_LSR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STRB, LSR, "", "", "]!"); +return txt;} + +static char * OP_STRB_M_LSR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STRB, LSR, "-", "", "]!"); +return txt;} + +static char * OP_STRB_P_ASR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STRB, ASR, "", "", "]!"); +return txt;} + +static char * OP_STRB_M_ASR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STRB, ASR, "-", "", "]!"); +return txt;} + +static char * OP_STRB_P_ROR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(STRB, "", "", "]!"); +return txt;} + +static char * OP_STRB_M_ROR_IMM_OFF_PREIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(STRB, "-", "", "]!"); +return txt;} + +static char * OP_STRB_P_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRB%s %s, [%s], #%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_STRB_M_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRB%s %s, [%s], -#%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_STRB_P_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(STRB, "", "]", ""); +return txt;} + +static char * OP_STRB_M_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(STRB, "-", "]", ""); +return txt;} + +static char * OP_STRB_P_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STRB, LSR, "", "]", ""); +return txt;} + +static char * OP_STRB_M_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STRB, LSR, "-", "]", ""); +return txt;} + +static char * OP_STRB_P_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STRB, ASR, "", "]", ""); +return txt;} + +static char * OP_STRB_M_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STRB, ASR, "-", "]", ""); +return txt;} + +static char * OP_STRB_P_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(STRB, "", "]", ""); +return txt;} + +static char * OP_STRB_M_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(STRB, "-", "]", ""); +return txt;} + +//-----------------------LDRBT------------------------------------- + +#if 0 +static char * OP_LDRBT_P_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRBT%s %s, [%s], #%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_LDRBT_M_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRBT%s %s, [%s], -#%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_LDRBT_P_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(LDRBT, "", "]", ""); +return txt;} + +static char * OP_LDRBT_M_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(LDRBT, "-", "]", ""); +return txt;} + +static char * OP_LDRBT_P_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDRBT, LSR, "", "]", ""); +return txt;} + +static char * OP_LDRBT_M_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDRBT, LSR, "-", "]", ""); +return txt;} + +static char * OP_LDRBT_P_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDRBT, ASR, "", "]", ""); +return txt;} + +static char * OP_LDRBT_M_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(LDRBT, ASR, "-", "]", ""); +return txt;} + +static char * OP_LDRBT_P_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(LDRBT, "", "]", ""); +return txt;} + +static char * OP_LDRBT_M_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(LDRBT, "-", "]", ""); +return txt;} + +//----------------------STRBT---------------------------- + +static char * OP_STRBT_P_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRBT%s %s, [%s], #%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_STRBT_M_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRBT%s %s, [%s], -#%X!", Condition[CONDITION(i)], Registre[REG_POS(i,12)], Registre[REG_POS(i,16)], (int)(i&0x7FF)); +return txt;} + +static char * OP_STRBT_P_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(STRBT, "", "]", ""); +return txt;} + +static char * OP_STRBT_M_LSL_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_LSL_IMM(STRBT, "-", "]", ""); +return txt;} + +static char * OP_STRBT_P_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STRBT, LSR, "", "]", ""); +return txt;} + +static char * OP_STRBT_M_LSR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STRBT, LSR, "-", "]", ""); +return txt;} + +static char * OP_STRBT_P_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STRBT, ASR, "", "]", ""); +return txt;} + +static char * OP_STRBT_M_ASR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_IMM_SHIFT(STRBT, ASR, "-", "]", ""); +return txt;} + +static char * OP_STRBT_P_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(STRBT, "", "]", ""); +return txt;} + +static char * OP_STRBT_M_ROR_IMM_OFF_POSTIND(u32 adr, u32 i, char * txt) +{ + LDRSTR_ROR_IMM(STRBT, "-", "]", ""); +return txt;} +#endif + +//---------------------LDM----------------------------- + +static char * OP_LDMIA(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "LDMIA%s %s, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_LDMIB(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "LDMIB%s %s, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_LDMDA(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "LDMDA%s %s, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_LDMDB(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "LDMDB%s %s, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_LDMIA_W(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "LDMIA%s %s!, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_LDMIB_W(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "LDMIB%s %s!, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_LDMDA_W(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "LDMDA%s %s!, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_LDMDB_W(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "LDMDB%s %s!, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_LDMIA2(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "LDMIA%s %s, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_LDMIB2(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "LDMIB%s %s, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_LDMDA2(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "LDMDA%s %s, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_LDMDB2(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "LDMDB%s %s, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_LDMIA2_W(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "LDMIA%s %s!, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); + if(BIT15(i)==0) sprintf(txt, "%s ?????", txt); +return txt;} + +static char * OP_LDMIB2_W(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "LDMIB%s %s!, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); + if(BIT15(i)==0) sprintf(txt, "%s ?????", txt); +return txt;} + +static char * OP_LDMDA2_W(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "LDMDA%s %s!, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); + if(BIT15(i)==0) sprintf(txt, "%s ?????", txt); +return txt;} + +static char * OP_LDMDB2_W(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "LDMDB%s %s!, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); + if(BIT15(i)==0) sprintf(txt, "%s ?????", txt); +return txt;} + +//------------------------------STM---------------------------------- + +static char * OP_STMIA(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "STMIA%s %s, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_STMIB(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "STMIB%s %s, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_STMDA(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "STMDA%s %s, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_STMDB(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "STMDB%s %s, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_STMIA_W(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "STMIA%s %s!, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_STMIB_W(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "STMIB%s %s!, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_STMDA_W(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "STMDA%s %s!, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_STMDB_W(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "STMDB%s %s!, {%s}", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_STMIA2(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "STMIA%s %s, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_STMIB2(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "STMIB%s %s, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_STMDA2(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "STMDA%s %s, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_STMDB2(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "STMDB%s %s, {%s}^", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_STMIA2_W(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "STMIA%s %s!, {%s}^ ?????", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_STMIB2_W(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "STMIB%s %s!, {%s}^ ?????", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); +return txt;} + +static char * OP_STMDA2_W(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "STMDA%s %s!, {%s}^ ?????", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); + return txt; +} + +static char * OP_STMDB2_W(u32 adr, u32 i, char * txt) +{ + RegList(16); + sprintf(txt, "STMDB%s %s!, {%s}^ ?????", Condition[CONDITION(i)], Registre[REG_POS(i,16)], lreg); + return txt; +} + +//---------------------STC---------------------------------- + +static char * OP_STC_P_IMM_OFF(u32 adr, u32 i, char * txt) +{ + if(CONDITION(i)==0xF) + { + sprintf(txt, "STC2 CP%X, CR%X, [%s, #%X]", (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)],(int)((i&0xFF)<<2)); + return txt; + } + sprintf(txt, "STC%s %X, CP%X, [%s, #%X]",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)],(int)((i&0xFF)<<2)); + return txt; +} + +static char * OP_STC_M_IMM_OFF(u32 adr, u32 i, char * txt) +{ + if(CONDITION(i)==0xF) + { + sprintf(txt, "STC2 CP%X, CR%X, [%s, #-%X]",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)],(int)((i&0xFF)<<2)); + return txt; + } + sprintf(txt, "STC%s CP%X, CR%X, [%s, #-%X]",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; +} + +static char * OP_STC_P_PREIND(u32 adr, u32 i, char * txt) +{ + if(CONDITION(i)==0xF) + { + sprintf(txt, "STC2 CP%X, CR%X, [%s, #%X]!",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; + } + sprintf(txt, "STC%s CP%X, CR%X, [%s, #%X]!",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; +} + +static char * OP_STC_M_PREIND(u32 adr, u32 i, char * txt) +{ + if(CONDITION(i)==0xF) + { + sprintf(txt, "STC2 CP%X, CR%X, [%s, #-%X]!",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; + } + sprintf(txt, "STC%s CP%X, CR%X, [%s, #-%X]!",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; +} + +static char * OP_STC_P_POSTIND(u32 adr, u32 i, char * txt) +{ + if(CONDITION(i)==0xF) + { + sprintf(txt, "STC2 CP%X, CR%X, [%s], #%X",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; + } + sprintf(txt, "STC%s CP%X, CR%X, [%s], #%X",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; +} + +static char * OP_STC_M_POSTIND(u32 adr, u32 i, char * txt) +{ + if(CONDITION(i)==0xF) + { + sprintf(txt, "STC2 CP%X, CR%X, [%s], #-%X",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; + } + sprintf(txt, "STC%s CP%X, CR%X, [%s], #-%X",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; +} + +static char * OP_STC_OPTION(u32 adr, u32 i, char * txt) +{ + if(CONDITION(i)==0xF) + { + sprintf(txt, "STC2 CP%X, CR%X, [%s], {%X}",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)(i&0xFF)); + return txt; + } + sprintf(txt, "STC%s CP%X, CR%X, [%s], {%X}",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)(i&0xFF)); + return txt; +} + +//---------------------LDC---------------------------------- + +static char * OP_LDC_P_IMM_OFF(u32 adr, u32 i, char * txt) +{ + if(CONDITION(i)==0xF) + { + sprintf(txt, "LDC2 CP%X, CR%X, [%s, #%X]",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; + } + sprintf(txt, "LDC%s CP%X, CR%X, [%s, #%X]",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; +} + +static char * OP_LDC_M_IMM_OFF(u32 adr, u32 i, char * txt) +{ + if(CONDITION(i)==0xF) + { + sprintf(txt, "LDC2 CP%X, CR%X, [%s, #-%X]",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; + } + sprintf(txt, "LDC%s CP%X, CR%X, [%s, #-%X]",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; +} + +static char * OP_LDC_P_PREIND(u32 adr, u32 i, char * txt) +{ + if(CONDITION(i)==0xF) + { + sprintf(txt, "LDC2 CP%X, CR%X, [%s, #%X]!",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; + } + sprintf(txt, "LDC%s CP%X, CR%X, [%s, #%X]!",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; +} + +static char * OP_LDC_M_PREIND(u32 adr, u32 i, char * txt) +{ + if(CONDITION(i)==0xF) + { + sprintf(txt, "LDC2 CP%X, CR%X, [%s, #-%X]!",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; + } + sprintf(txt, "LDC%s CP%X, CR%X, [%s, #-%X]!",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; +} + +static char * OP_LDC_P_POSTIND(u32 adr, u32 i, char * txt) +{ + if(CONDITION(i)==0xF) + { + sprintf(txt, "LDC2 CP%X, CR%X, [%s], #%X",(int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; + } + sprintf(txt, "LDC%s CP%X, CR%X, [%s], #%X",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; +} + +static char * OP_LDC_M_POSTIND(u32 adr, u32 i, char * txt) +{ + if(CONDITION(i)==0xF) + { + sprintf(txt, "LDC2 CP%X, CR%X, [%s], #-%X", (int)REG_POS(i, 8), (int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; + } + sprintf(txt, "LDC%s CP%X, CR%X, [%s], #-%X",Condition[CONDITION(i)], (int)REG_POS(i, 8),(int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)((i&0xFF)<<2)); + return txt; +} + +static char * OP_LDC_OPTION(u32 adr, u32 i, char * txt) +{ + if(CONDITION(i)==0xF) + { + sprintf(txt, "LDC2 CP%X, CR%X, [%s], {%X}", (int)REG_POS(i, 8), (int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)(i&0xFF)); + return txt; + } + sprintf(txt, "LDC%s CP%X, CR%X, [%s], {%X}",Condition[CONDITION(i)], (int)REG_POS(i, 8), (int)REG_POS(i, 12), Registre[REG_POS(i, 16)], (int)(i&0xFF)); + return txt; +} + + +/* + * + * The Enhanced DSP Extension LDRD and STRD instructions. + * + */ +static char * +OP_LDRD_STRD_POST_INDEX(u32 adr, u32 i, char * txt) { + const char *direction = + BIT5(i) ? "STR" : "LDR"; + /* U bit - set = add, clear = sub */ + char sign = BIT23(i) ? '+' : '-'; + int txt_index = 0; + + txt_index += sprintf( &txt[txt_index], "%s%sD R%d, [R%d], ", + direction, Condition[CONDITION(i)], + (int)REG_POS(i, 12), + (int)REG_POS(i, 16)); + + /* I bit - set = immediate, clear = reg */ + if ( BIT22(i)) { + sprintf( &txt[txt_index], "#%c%d", + sign, (int)(((i>>4) & 0xF0) | (i&0xF)) ); + } + else { + sprintf( &txt[txt_index], "%cR%d", + sign, (int)REG_POS(i, 0)); + } + return txt; +} +static char * +OP_LDRD_STRD_OFFSET_PRE_INDEX(u32 adr, u32 i, char * txt) { + const char *direction = + BIT5(i) ? "STR" : "LDR"; + /* U bit - set = add, clear = sub */ + char sign = BIT23(i) ? '+' : '-'; + int txt_index = 0; + + txt_index += sprintf( &txt[txt_index], "%s%sD R%d, [R%d, ", + direction, Condition[CONDITION(i)], + (int)REG_POS(i, 12), + (int)REG_POS(i, 16)); + + /* I bit - set = immediate, clear = reg */ + if ( BIT22(i)) { + if ( BIT21(i)) { + /* pre-index */ + sprintf( &txt[txt_index], "#%c%d]!", + sign, (int)(((i>>4)&0xF0)|(i&0xF))); + } + else { + /* offset */ + sprintf( &txt[txt_index], "#%c%d]", + sign, (int)(((i>>4)&0xF0)|(i&0xF))); + } + } + else { + if ( BIT21(i)) { + /* pre-index */ + sprintf( &txt[txt_index], "%c%d]!", + sign, (int)REG_POS(i, 0)); + } + else { + /* offset */ + sprintf( &txt[txt_index], "%c%d]", + sign, (int)REG_POS(i, 0)); + } + } + + return txt; +} + + +//----------------MCR----------------------- + +static char * OP_MCR(u32 adr, u32 i, char * txt) +{ + if(CONDITION(i)==0xF) + { + sprintf(txt, "MCR2 CP%d, %X, %s, CR%d, CR%d, %X",(int)REG_POS(i, 8), (int)((i>>21)&7), Registre[REG_POS(i, 12)], (int)REG_POS(i, 16), (int)REG_POS(i, 0), (int)((i>>5)&0x7)); + return txt; + } + sprintf(txt, "MCR%s CP%d, %X, %s, CR%d, CR%d, %X",Condition[CONDITION(i)], (int)REG_POS(i, 8), (int)((i>>21)&7), Registre[REG_POS(i, 12)], (int)REG_POS(i, 16), (int)REG_POS(i, 0), (int)((i>>5)&0x7)); + return txt; +} + +//----------------MRC----------------------- + +static char * OP_MRC(u32 adr, u32 i, char * txt) +{ + if(CONDITION(i)==0xF) + { + sprintf(txt, "MRC2 CP%d, %X, %s, CR%d, CR%d, %X",(int)REG_POS(i, 8), (int)((i>>21)&7), Registre[REG_POS(i, 12)], (int)REG_POS(i, 16), (int)REG_POS(i, 0), (int)((i>>5)&0x7)); + return txt; + } + sprintf(txt, "MRC%s CP%d, %X, %s, CR%d, CR%d, %X",Condition[CONDITION(i)], (int)REG_POS(i, 8), (int)((i>>21)&7), Registre[REG_POS(i, 12)], (int)REG_POS(i, 16), (int)REG_POS(i, 0), (int)((i>>5)&0x7)); + return txt; +} + +//--------------SWI-------------------------- + +static char * OP_SWI(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SWI%s %X",Condition[CONDITION(i)], (int)((i&0xFFFFFF)>>16)); + return txt; +} + +//----------------BKPT------------------------- +static char * OP_BKPT(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "BKPT #%X",(int)(((i>>4)&0xFFF)|(i&0xF))); + return txt; +} + +//----------------CDP----------------------- + +static char * OP_CDP(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "CDP-------------------------------"); + return txt; +} + +//------------------------------------------------------------ +// THUMB +//------------------------------------------------------------ +#define REG_NUM(i, n) (((i)>>n)&0x7) + +static char * OP_UND_THUMB(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "----"); + return txt; +} + +static char * OP_LSL_0(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LSL %s, %s, #0", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); + return txt; +} + +static char * OP_LSL(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LSL %s, %s, #%X", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)((i>>6) & 0x1F)); + return txt; +} + +static char * OP_LSR_0(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LSR %s, %s, #0", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); + return txt; +} + +static char * OP_LSR(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LSR %s, %s, #%X", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)((i>>6) & 0x1F)); + return txt; +} + +static char * OP_ASR_0(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "ASR %s, %s, #0", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); + return txt; +} + +static char * OP_ASR(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "ASR %s, %s, #%X", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)((i>>6) & 0x1F)); + return txt; +} + +static char * OP_ADD_REG(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "ADD %s, %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], Registre[REG_NUM(i, 6)]); + return txt; +} + +static char * OP_SUB_REG(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SUB %s, %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], Registre[REG_NUM(i, 6)]); + return txt; +} + +static char * OP_ADD_IMM3(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "ADD %s, %s, #%X", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)REG_NUM(i, 6)); + return txt; +} + +static char * OP_SUB_IMM3(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SUB %s, %s, #%X", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)REG_NUM(i, 6)); + return txt; +} + +static char * OP_MOV_IMM8(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "MOV %s, #%X", Registre[REG_NUM(i, 8)], (int)(i&0xFF)); + return txt; +} + +static char * OP_CMP_IMM8(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "CMP %s, #%X", Registre[REG_NUM(i, 8)], (int)(i&0xFF)); + return txt; +} + +static char * OP_ADD_IMM8(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "ADD %s, #%X", Registre[REG_NUM(i, 8)], (int)(i&0xFF)); + return txt; +} + +static char * OP_SUB_IMM8(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SUB %s, #%X", Registre[REG_NUM(i, 8)], (int)(i&0xFF)); + return txt; +} + +static char * OP_AND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "AND %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); + return txt; +} + +static char * OP_EOR(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "EOR %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); + return txt; +} + +static char * OP_LSL_REG(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LSL %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); + return txt; +} + +static char * OP_LSR_REG(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LSR %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); + return txt; +} + +static char * OP_ASR_REG(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "ASR %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); + return txt; +} + +static char * OP_ADC_REG(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "ADC %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); + return txt; +} + +static char * OP_SBC_REG(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SBC %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); + return txt; +} + +static char * OP_ROR_REG(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "ROR %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); + return txt; +} + +static char * OP_TST(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "TST %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); + return txt; +} + +static char * OP_NEG(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "NEG %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); + return txt; +} + +static char * OP_CMP(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "CMP %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); + return txt; +} + +static char * OP_CMN(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "CMN %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); + return txt; +} + +static char * OP_ORR(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "ORR %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); + return txt; +} + +static char * OP_MUL_REG(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "MUL %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); + return txt; +} + +static char * OP_BIC(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "BIC %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); + return txt; +} + +static char * OP_MVN(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "MVN %s, %s", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)]); + return txt; +} + +static char * OP_ADD_SPE(u32 adr, u32 i, char * txt) +{ + u8 Rd = (i&7) | ((i>>4)&8); + sprintf(txt, "ADD %s, %s", Registre[Rd], Registre[REG_POS(i, 3)]); + return txt; +} + +static char * OP_CMP_SPE(u32 adr, u32 i, char * txt) +{ + u8 Rd = (i&7) | ((i>>4)&8); + sprintf(txt, "CMP %s, %s", Registre[Rd], Registre[REG_POS(i, 3)]); + return txt; +} + +static char * OP_MOV_SPE(u32 adr, u32 i, char * txt) +{ + u8 Rd = (i&7) | ((i>>4)&8); + sprintf(txt, "MOV %s, %s", Registre[Rd], Registre[REG_POS(i, 3)]); + return txt; +} + +static char * OP_BX_THUMB(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "BX %s", Registre[REG_POS(i, 3)]); + return txt; +} + +static char * OP_BLX_THUMB(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "BLX %s", Registre[REG_POS(i, 3)]); + return txt; +} + +static char * OP_LDR_PCREL(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDR %s, [PC, #%X]", Registre[REG_NUM(i, 8)], (int)((i&0xFF)<<2)); + return txt; +} + +static char * OP_STR_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STR %s, [%s, %s]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], Registre[REG_NUM(i, 6)]); + return txt; +} + +static char * OP_STRH_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRH %s, [%s, %s]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], Registre[REG_NUM(i, 6)]); + return txt; +} + +static char * OP_STRB_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRB %s, [%s, %s]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], Registre[REG_NUM(i, 6)]); + return txt; +} + +static char * OP_LDRSB_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSB %s, [%s, %s]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], Registre[REG_NUM(i, 6)]); + return txt; +} + +static char * OP_LDR_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDR %s, [%s, %s]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], Registre[REG_NUM(i, 6)]); + return txt; +} + +static char * OP_LDRH_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRH %s, [%s, %s]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], Registre[REG_NUM(i, 6)]); + return txt; +} + +static char * OP_LDRB_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRB %s, [%s, %s]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], Registre[REG_NUM(i, 6)]); + return txt; +} + +static char * OP_LDRSH_REG_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRSH %s, [%s, %s]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], Registre[REG_NUM(i, 6)]); + return txt; +} + +static char * OP_STR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STR %s, [%s, #%X]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)((i>>4)&0x7C)); + return txt; +} + +static char * OP_LDR_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDR %s, [%s, #%X]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)((i>>4)&0x7C)); + return txt; +} + +static char * OP_STRB_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRB %s, [%s, #%X]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)((i>>6)&0x1F)); + return txt; +} + +static char * OP_LDRB_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRB %s, [%s, #%X]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)((i>>6)&0x1F)); + return txt; +} + +static char * OP_STRH_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STRH %s, [%s, #%X]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)((i>>5)&0x3E)); + return txt; +} + +static char * OP_LDRH_IMM_OFF(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDRH %s, [%s, #%X]", Registre[REG_NUM(i, 0)], Registre[REG_NUM(i, 3)], (int)((i>>5)&0x3E)); + return txt; +} + +static char * OP_STR_SPREL(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "STR %s, [SP, #%X]", Registre[REG_NUM(i, 8)], (int)((i&0xFF)<<2)); + return txt; +} + +static char * OP_LDR_SPREL(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "LDR %s, [SP, #%X]", Registre[REG_NUM(i, 8)], (int)((i&0xFF)<<2)); + return txt; +} + +static char * OP_ADD_2PC(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "ADD %s, PC, #%X", Registre[REG_NUM(i, 8)], (int)((i&0xFF)<<2)); + return txt; +} + +static char * OP_ADD_2SP(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "ADD %s, SP, #%X", Registre[REG_NUM(i, 8)], (int)((i&0xFF)<<2)); + return txt; +} + +static char * OP_ADJUST_P_SP(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "ADD SP, #%X", (int)((i&0x7F)<<2)); + return txt; +} + +static char * OP_ADJUST_M_SP(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SUB SP, #%X", (int)((i&0x7F)<<2)); + return txt; +} + +static char * OP_PUSH(u32 adr, u32 i, char * txt) +{ + RegList(8); + sprintf(txt, "PUSH {%s}", lreg); + return txt; +} + +static char * OP_PUSH_LR(u32 adr, u32 i, char * txt) +{ + RegList(8); + sprintf(txt, "PUSH {%s, LR}", lreg); + return txt; +} + +static char * OP_POP(u32 adr, u32 i, char * txt) +{ + RegList(8); + sprintf(txt, "POP {%s}", lreg); + return txt; +} + +static char * OP_POP_PC(u32 adr, u32 i, char * txt) +{ + RegList(8); + sprintf(txt, "POP {%s, PC}", lreg); + return txt; +} + +static char * OP_BKPT_THUMB(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "BKPT"); + return txt; +} + +static char * OP_STMIA_THUMB(u32 adr, u32 i, char * txt) +{ + RegList(8); + sprintf(txt, "STMIA %s!, {%s}", Registre[REG_NUM(i, 8)], lreg); + return txt; +} + +static char * OP_LDMIA_THUMB(u32 adr, u32 i, char * txt) +{ + RegList(8); + sprintf(txt, "LDMIA %s!, {%s}", Registre[REG_NUM(i, 8)], lreg); + return txt; +} + +static char * OP_B_COND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "B%s #%X", Condition[(i>>8)&0xF], (int)(adr+(((s32)((signed char)(i&0xFF)))<<1)+4)); + return txt; +} + +static char * OP_SWI_THUMB(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "SWI #%X", (int)(i & 0xFF)); + return txt; +} + +#define SIGNEEXT_IMM11(i) (((i)&0x7FF) | (BIT10(i) * 0xFFFFF800)) + +static char * OP_B_UNCOND(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "B #%X", (int)(adr+(SIGNEEXT_IMM11(i)<<1)+4)); + return txt; +} + +u32 part = 0; + +static char * OP_BLX(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "BLX #%X", (int)(part + ((i&0x7FF)<<1))&0xFFFFFFFC); + return txt; +} + +static char * OP_BL_10(u32 adr, u32 i, char * txt) +{ + part = adr+4 + (SIGNEEXT_IMM11(i)<<12); + sprintf(txt, "calculating high part of the address"); + return txt; + +} + +static char * OP_BL_11(u32 adr, u32 i, char * txt) +{ + sprintf(txt, "BL #%X", (int)(part + ((i&0x7FF)<<1))&0xFFFFFFFC); + return txt; +} + + + +#define TABDECL(x) x + +const DisasmOpFunc des_arm_instructions_set[4096] = { +#include "instruction_tabdef.inc" +}; + +const DisasmOpFunc des_thumb_instructions_set[1024] = { +#include "thumb_tabdef.inc" +}; diff --git a/jni/desmume/src/Disassembler.h b/jni/desmume/src/Disassembler.h new file mode 100755 index 0000000..752df76 --- /dev/null +++ b/jni/desmume/src/Disassembler.h @@ -0,0 +1,31 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2006-2009 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ + +#ifndef DISASSEMBLER_H +#define DISASSEMBLER_H + +#include "types.h" + +typedef char* (* DisasmOpFunc)(u32 adr, u32 i, char * txt); + +extern const DisasmOpFunc des_arm_instructions_set[4096]; +extern const DisasmOpFunc des_thumb_instructions_set[1024]; + +#endif + + diff --git a/jni/desmume/src/FIFO.cpp b/jni/desmume/src/FIFO.cpp new file mode 100755 index 0000000..0f24cf0 --- /dev/null +++ b/jni/desmume/src/FIFO.cpp @@ -0,0 +1,323 @@ +/* + Copyright 2006 yopyop + Copyright 2007 shash + Copyright 2007-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ + +#include "FIFO.h" +#include +#include "armcpu.h" +#include "debug.h" +#include "mem.h" +#include "MMU.h" +#include "NDSSystem.h" +#include "gfx3d.h" + +// ========================================================= IPC FIFO +IPC_FIFO ipc_fifo[2]; + +void IPC_FIFOinit(u8 proc) +{ + memset(&ipc_fifo[proc], 0, sizeof(IPC_FIFO)); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, 0x00000101); +} + +void IPC_FIFOsend(u8 proc, u32 val) +{ + u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184); + if (!(cnt_l & IPCFIFOCNT_FIFOENABLE)) return; // FIFO disabled + u8 proc_remote = proc ^ 1; + + if (ipc_fifo[proc].size > 15) + { + cnt_l |= IPCFIFOCNT_FIFOERROR; + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l); + return; + } + + u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc_remote][0x40], 0x184); + + //LOG("IPC%s send FIFO 0x%08X size %03i (l 0x%X, tail %02i) (r 0x%X, tail %02i)\n", + // proc?"7":"9", val, ipc_fifo[proc].size, cnt_l, ipc_fifo[proc].tail, cnt_r, ipc_fifo[proc^1].tail); + + cnt_l &= 0xBFFC; // clear send empty bit & full + cnt_r &= 0xBCFF; // set recv empty bit & full + ipc_fifo[proc].buf[ipc_fifo[proc].tail] = val; + ipc_fifo[proc].tail++; + ipc_fifo[proc].size++; + if (ipc_fifo[proc].tail > 15) ipc_fifo[proc].tail = 0; + + if (ipc_fifo[proc].size > 15) + { + cnt_l |= IPCFIFOCNT_SENDFULL; // set send full bit + cnt_r |= IPCFIFOCNT_RECVFULL; // set recv full bit + } + + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l); + T1WriteWord(MMU.MMU_MEM[proc_remote][0x40], 0x184, cnt_r); + + if(cnt_r&IPCFIFOCNT_RECVIRQEN) + NDS_makeIrq(proc_remote, IRQ_BIT_IPCFIFO_RECVNONEMPTY); + + NDS_Reschedule(); +} + +u32 IPC_FIFOrecv(u8 proc) +{ + u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184); + if (!(cnt_l & IPCFIFOCNT_FIFOENABLE)) return (0); // FIFO disabled + u8 proc_remote = proc ^ 1; + + u32 val = 0; + + if ( ipc_fifo[proc_remote].size == 0 ) // remote FIFO error + { + cnt_l |= IPCFIFOCNT_FIFOERROR; + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l); + return (0); + } + + u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc_remote][0x40], 0x184); + + cnt_l &= 0xBCFF; // clear send full bit & empty + cnt_r &= 0xBFFC; // set recv full bit & empty + + val = ipc_fifo[proc_remote].buf[ipc_fifo[proc_remote].head]; + ipc_fifo[proc_remote].head++; + ipc_fifo[proc_remote].size--; + if (ipc_fifo[proc_remote].head > 15) ipc_fifo[proc_remote].head = 0; + + //LOG("IPC%s recv FIFO 0x%08X size %03i (l 0x%X, tail %02i) (r 0x%X, tail %02i)\n", + // proc?"7":"9", val, ipc_fifo[proc].size, cnt_l, ipc_fifo[proc].tail, cnt_r, ipc_fifo[proc^1].tail); + + if ( ipc_fifo[proc_remote].size == 0 ) // FIFO empty + { + cnt_l |= IPCFIFOCNT_RECVEMPTY; + cnt_r |= IPCFIFOCNT_SENDEMPTY; + + if(cnt_r&IPCFIFOCNT_SENDIRQEN) + NDS_makeIrq(proc_remote, IRQ_BIT_IPCFIFO_SENDEMPTY); + } + + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l); + T1WriteWord(MMU.MMU_MEM[proc_remote][0x40], 0x184, cnt_r); + + NDS_Reschedule(); + + return (val); +} + +void IPC_FIFOcnt(u8 proc, u16 val) +{ + u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184); + u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc^1][0x40], 0x184); + + if (val & IPCFIFOCNT_FIFOERROR) + { + //at least SPP uses this, maybe every retail game + cnt_l &= ~IPCFIFOCNT_FIFOERROR; + } + + if (val & IPCFIFOCNT_SENDCLEAR) + { + ipc_fifo[proc].head = 0; ipc_fifo[proc].tail = 0; ipc_fifo[proc].size = 0; + + cnt_l |= IPCFIFOCNT_SENDEMPTY; + cnt_r |= IPCFIFOCNT_RECVEMPTY; + + cnt_l &= ~IPCFIFOCNT_SENDFULL; + cnt_r &= ~IPCFIFOCNT_RECVFULL; + + } + cnt_l &= ~IPCFIFOCNT_WRITEABLE; + cnt_l |= val & IPCFIFOCNT_WRITEABLE; + + //IPCFIFOCNT_SENDIRQEN may have been set (and/or the fifo may have been cleared) so we may need to trigger this irq + //(this approach is used by libnds fifo system on occasion in fifoInternalSend, and began happening frequently for value32 with r4326) + if(cnt_l&IPCFIFOCNT_SENDIRQEN) if(cnt_l & IPCFIFOCNT_SENDEMPTY) + NDS_makeIrq(proc, IRQ_BIT_IPCFIFO_SENDEMPTY); + + //IPCFIFOCNT_RECVIRQEN may have been set so we may need to trigger this irq + if(cnt_l&IPCFIFOCNT_RECVIRQEN) if(!(cnt_l & IPCFIFOCNT_RECVEMPTY)) + NDS_makeIrq(proc, IRQ_BIT_IPCFIFO_RECVNONEMPTY); + + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l); + T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, cnt_r); + + NDS_Reschedule(); +} + +// ========================================================= GFX FIFO +GFX_PIPE gxPIPE; +GFX_FIFO gxFIFO; + +void GFX_PIPEclear() +{ + gxPIPE.head = 0; + gxPIPE.tail = 0; + gxPIPE.size = 0; + gxFIFO.matrix_stack_op_size = 0; +} + +void GFX_FIFOclear() +{ + gxFIFO.head = 0; + gxFIFO.tail = 0; + gxFIFO.size = 0; + gxFIFO.matrix_stack_op_size = 0; +} + +static void GXF_FIFO_handleEvents() +{ + bool low = gxFIFO.size <= 127; + bool lowchange = MMU_new.gxstat.fifo_low ^ low; + MMU_new.gxstat.fifo_low = low; + if(low) triggerDma(EDMAMode_GXFifo); + + bool empty = gxFIFO.size == 0; + bool emptychange = MMU_new.gxstat.fifo_empty ^ empty; + MMU_new.gxstat.fifo_empty = empty; + + + MMU_new.gxstat.sb = gxFIFO.matrix_stack_op_size != 0; + + if(emptychange||lowchange) NDS_Reschedule(); +} + +static bool IsMatrixStackCommand(u8 cmd) +{ + return cmd == 0x11 || cmd == 0x12; +} + +void GFX_FIFOsend(u8 cmd, u32 param) +{ + //INFO("gxFIFO: send 0x%02X = 0x%08X (size %03i/0x%02X) gxstat 0x%08X\n", cmd, param, gxFIFO.size, gxFIFO.size, gxstat); + //printf("fifo recv: %02X: %08X upto:%d\n",cmd,param,gxFIFO.size+1); + + //TODO - WOAH ! NOT HANDLING A TOO-BIG FIFO RIGHT NOW! + //if (gxFIFO.size > 255) + //{ + // GXF_FIFO_handleEvents(); + // //NEED TO HANDLE THIS!!!!!!!!!!!!!!!!!!!!!!!!!! + + // //gxstat |= 0x08000000; // busy + // NDS_RescheduleGXFIFO(1); + // //INFO("ERROR: gxFIFO is full (cmd 0x%02X = 0x%08X) (prev cmd 0x%02X = 0x%08X)\n", cmd, param, gxFIFO.cmd[255], gxFIFO.param[255]); + // return; + //} + + + gxFIFO.cmd[gxFIFO.tail] = cmd; + gxFIFO.param[gxFIFO.tail] = param; + gxFIFO.tail++; + gxFIFO.size++; + if (gxFIFO.tail > HACK_GXIFO_SIZE-1) gxFIFO.tail = 0; + + //if a matrix op is entering the pipeline, do accounting for it + //(this is tested by wild west, which will jam a few ops in the fifo and then wait for the matrix stack to be + //un-busy so it can read back the current matrix stack position) + if(IsMatrixStackCommand(cmd)) + gxFIFO.matrix_stack_op_size++; + + if(gxFIFO.size>=HACK_GXIFO_SIZE) { + printf("--FIFO FULL-- : %d\n",gxFIFO.size); + } + + //gxstat |= 0x08000000; // set busy flag + + GXF_FIFO_handleEvents(); + + NDS_RescheduleGXFIFO(1); +} + +// this function used ONLY in gxFIFO +BOOL GFX_PIPErecv(u8 *cmd, u32 *param) +{ + //gxstat &= 0xF7FFFFFF; // clear busy flag + + if (gxFIFO.size == 0) + { + GXF_FIFO_handleEvents(); + return FALSE; + } + + *cmd = gxFIFO.cmd[gxFIFO.head]; + *param = gxFIFO.param[gxFIFO.head]; + + //see the associated increment in another function + if(IsMatrixStackCommand(*cmd)) + { + gxFIFO.matrix_stack_op_size--; + if(gxFIFO.matrix_stack_op_size>0x10000000) + printf("bad news disaster in matrix_stack_op_size\n"); + } + + gxFIFO.head++; + gxFIFO.size--; + if (gxFIFO.head > HACK_GXIFO_SIZE-1) gxFIFO.head = 0; + + GXF_FIFO_handleEvents(); + + return (TRUE); +} + +void GFX_FIFOcnt(u32 val) +{ + ////INFO("gxFIFO: write cnt 0x%08X (prev 0x%08X) FIFO size %03i PIPE size %03i\n", val, gxstat, gxFIFO.size, gxPIPE.size); + + if (val & (1<<29)) // clear? (only in homebrew?) + { + GFX_PIPEclear(); + GFX_FIFOclear(); + return; + } + + //zeromus says: what happened to clear stack? + //if (val & (1<<15)) // projection stack pointer reset + //{ + // gfx3d_ClearStack(); + // val &= 0xFFFF5FFF; // clear reset (bit15) & stack level (bit13) + //} + + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, val); +} + +// ========================================================= DISP FIFO +DISP_FIFO disp_fifo; + +void DISP_FIFOinit() +{ + memset(&disp_fifo, 0, sizeof(DISP_FIFO)); +} + +void DISP_FIFOsend(u32 val) +{ + //INFO("DISP_FIFO send value 0x%08X (head 0x%06X, tail 0x%06X)\n", val, disp_fifo.head, disp_fifo.tail); + disp_fifo.buf[disp_fifo.tail] = val; + disp_fifo.tail++; + if (disp_fifo.tail > 0x5FFF) + disp_fifo.tail = 0; +} + +u32 DISP_FIFOrecv() +{ + //if (disp_fifo.tail == disp_fifo.head) return (0); // FIFO is empty + u32 val = disp_fifo.buf[disp_fifo.head]; + disp_fifo.head++; + if (disp_fifo.head > 0x5FFF) + disp_fifo.head = 0; + return (val); +} diff --git a/jni/desmume/src/FIFO.h b/jni/desmume/src/FIFO.h new file mode 100755 index 0000000..f96c4fa --- /dev/null +++ b/jni/desmume/src/FIFO.h @@ -0,0 +1,91 @@ +/* + Copyright 2006 yopyop + Copyright 2007 shash + Copyright 2007-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ + + +#ifndef FIFO_H +#define FIFO_H + +#include "types.h" + +//=================================================== IPC FIFO +typedef struct +{ + u32 buf[16]; + + u8 head; + u8 tail; + u8 size; +} IPC_FIFO; + +extern IPC_FIFO ipc_fifo[2]; +extern void IPC_FIFOinit(u8 proc); +extern void IPC_FIFOsend(u8 proc, u32 val); +extern u32 IPC_FIFOrecv(u8 proc); +extern void IPC_FIFOcnt(u8 proc, u16 val); + +//=================================================== GFX FIFO + +//yeah, its oversize for now. thats a simpler solution +//moon seems to overdrive the fifo with immediate dmas +//i think this might be nintendo code too +#define HACK_GXIFO_SIZE 200000 + +typedef struct +{ + u8 cmd[HACK_GXIFO_SIZE]; + u32 param[HACK_GXIFO_SIZE]; + + u32 head; // start position + u32 tail; // tail + u32 size; // size FIFO buffer + u32 matrix_stack_op_size; //number of matrix stack items in the fifo (stack is busy when this is nonzero) +} GFX_FIFO; + +typedef struct +{ + u8 cmd[4]; + u32 param[4]; + + u8 head; + u8 tail; + u8 size; +} GFX_PIPE; + +extern GFX_PIPE gxPIPE; +extern GFX_FIFO gxFIFO; +extern void GFX_PIPEclear(); +extern void GFX_FIFOclear(); +extern void GFX_FIFOsend(u8 cmd, u32 param); +extern BOOL GFX_PIPErecv(u8 *cmd, u32 *param); +extern void GFX_FIFOcnt(u32 val); + +//=================================================== Display memory FIFO +typedef struct +{ + u32 buf[0x6000]; // 256x192 32K color + u32 head; // head + u32 tail; // tail +} DISP_FIFO; + +extern DISP_FIFO disp_fifo; +extern void DISP_FIFOinit(); +extern void DISP_FIFOsend(u32 val); +extern u32 DISP_FIFOrecv(); + +#endif diff --git a/jni/desmume/src/GPU.cpp b/jni/desmume/src/GPU.cpp new file mode 100755 index 0000000..4c771a7 --- /dev/null +++ b/jni/desmume/src/GPU.cpp @@ -0,0 +1,2780 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2006-2007 Theo Berkau + Copyright (C) 2007 shash + Copyright (C) 2008-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ + + +#include +#include +#include +#include +#include +#include "MMU.h" +#include "GPU.h" +#include "debug.h" +#include "render3D.h" +#include "gfx3d.h" +#include "debug.h" +#include "GPU_osd.h" +#include "NDSSystem.h" +#include "readwrite.h" + +#ifdef FASTBUILD + #undef FORCEINLINE + #define FORCEINLINE + //compilation speed hack (cuts time exactly in half by cutting out permutations) + #define DISABLE_MOSAIC +#endif + +extern BOOL click; +NDS_Screen MainScreen; +NDS_Screen SubScreen; + +//instantiate static instance +GPU::MosaicLookup GPU::mosaicLookup; + +//#define DEBUG_TRI + +CACHE_ALIGN u8 GPU_screen[4*256*192]; +CACHE_ALIGN u8 sprWin[256]; + + +u16 gpu_angle = 0; + +const size sprSizeTab[4][4] = +{ + {{8, 8}, {16, 8}, {8, 16}, {8, 8}}, + {{16, 16}, {32, 8}, {8, 32}, {8, 8}}, + {{32, 32}, {32, 16}, {16, 32}, {8, 8}}, + {{64, 64}, {64, 32}, {32, 64}, {8, 8}}, +}; + + + +const BGType GPU_mode2type[8][4] = +{ + {BGType_Text, BGType_Text, BGType_Text, BGType_Text}, + {BGType_Text, BGType_Text, BGType_Text, BGType_Affine}, + {BGType_Text, BGType_Text, BGType_Affine, BGType_Affine}, + {BGType_Text, BGType_Text, BGType_Text, BGType_AffineExt}, + {BGType_Text, BGType_Text, BGType_Affine, BGType_AffineExt}, + {BGType_Text, BGType_Text, BGType_AffineExt, BGType_AffineExt}, + {BGType_Invalid, BGType_Invalid, BGType_Large8bpp, BGType_Invalid}, + {BGType_Invalid, BGType_Invalid, BGType_Invalid, BGType_Invalid} +}; + +//dont ever think of changing these to bits because you could avoid the multiplies in the main tile blitter. +//it doesnt really help any +const short sizeTab[8][4][2] = +{ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, //Invalid + {{256,256}, {512,256}, {256,512}, {512,512}}, //text + {{128,128}, {256,256}, {512,512}, {1024,1024}}, //affine + {{512,1024}, {1024,512}, {0,0}, {0,0}}, //large 8bpp + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, //affine ext (to be elaborated with another value) + {{128,128}, {256,256}, {512,512}, {1024,1024}}, //affine ext 256x16 + {{128,128}, {256,256}, {512,256}, {512,512}}, //affine ext 256x1 + {{128,128}, {256,256}, {512,256}, {512,512}}, //affine ext direct +}; + +static GraphicsInterface_struct *GFXCore=NULL; + +// This should eventually be moved to the port specific code +GraphicsInterface_struct *GFXCoreList[] = { +&GFXDummy, +NULL +}; + +static const CACHE_ALIGN u8 win_empty[256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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 CACHE_ALIGN u16 fadeInColors[17][0x8000]; +CACHE_ALIGN u16 fadeOutColors[17][0x8000]; + +//this should be public, because it gets used somewhere else +CACHE_ALIGN u8 gpuBlendTable555[17][17][32][32]; + + +/*****************************************************************************/ +// INITIALIZATION +/*****************************************************************************/ + + +static void GPU_InitFadeColors() +{ + /* + NOTE: gbatek (in the reference above) seems to expect 6bit values + per component, but as desmume works with 5bit per component, + we use 31 as top, instead of 63. Testing it on a few games, + using 63 seems to give severe color wraping, and 31 works + nicely, so for now we'll just that, until proven wrong. + + i have seen pics of pokemon ranger getting white with 31, with 63 it is nice. + it could be pb of alpha or blending or... + + MightyMax> created a test NDS to check how the brightness values work, + and 31 seems to be correct. FactorEx is a override for max brighten/darken + See: http://mightymax.org/gfx_test_brightness.nds + The Pokemon Problem could be a problem with 8/32 bit writes not recognized yet, + i'll add that so you can check back. + + */ + + for(int i = 0; i <= 16; i++) + { + for(int j = 0x8000; j < 0x10000; j++) + { + COLOR cur; + + cur.val = j; + cur.bits.red = (cur.bits.red + ((31 - cur.bits.red) * i / 16)); + cur.bits.green = (cur.bits.green + ((31 - cur.bits.green) * i / 16)); + cur.bits.blue = (cur.bits.blue + ((31 - cur.bits.blue) * i / 16)); + cur.bits.alpha = 0; + fadeInColors[i][j & 0x7FFF] = cur.val; + + cur.val = j; + cur.bits.red = (cur.bits.red - (cur.bits.red * i / 16)); + cur.bits.green = (cur.bits.green - (cur.bits.green * i / 16)); + cur.bits.blue = (cur.bits.blue - (cur.bits.blue * i / 16)); + cur.bits.alpha = 0; + fadeOutColors[i][j & 0x7FFF] = cur.val; + } + } + + + for(int c0=0;c0<=31;c0++) + for(int c1=0;c1<=31;c1++) + for(int eva=0;eva<=16;eva++) + for(int evb=0;evb<=16;evb++) + { + int blend = ((c0 * eva) + (c1 * evb) ) / 16; + int final = std::min(31,blend); + gpuBlendTable555[eva][evb][c0][c1] = final; + } +} + +static CACHE_ALIGN GPU GPU_main, GPU_sub; + +GPU * GPU_Init(u8 l) +{ + GPU * g; + + if(l==0) g = &GPU_main; + else g = &GPU_sub; + + GPU_Reset(g, l); + GPU_InitFadeColors(); + + g->curr_win[0] = win_empty; + g->curr_win[1] = win_empty; + g->need_update_winh[0] = true; + g->need_update_winh[1] = true; + g->setFinalColorBck_funcNum = 0; + g->setFinalColor3d_funcNum = 0; + g->setFinalColorSpr_funcNum = 0; + + return g; +} + +void GPU_Reset(GPU *g, u8 l) +{ + memset(g, 0, sizeof(GPU)); + + //important for emulator stability for this to initialize, since we have to setup a table based on it + g->BLDALPHA_EVA = 0; + g->BLDALPHA_EVB = 0; + //make sure we have our blend table setup even if the game blends without setting the blend variables + g->updateBLDALPHA(); + + g->setFinalColorBck_funcNum = 0; + g->setFinalColor3d_funcNum = 0; + g->setFinalColorSpr_funcNum = 0; + g->core = l; + g->BGSize[0][0] = g->BGSize[1][0] = g->BGSize[2][0] = g->BGSize[3][0] = 256; + g->BGSize[0][1] = g->BGSize[1][1] = g->BGSize[2][1] = g->BGSize[3][1] = 256; + + g->spriteRenderMode = GPU::SPRITE_1D; + + g->bgPrio[4] = 0xFF; + + g->bg0HasHighestPrio = TRUE; + + if(g->core == GPU_SUB) + { + g->oam = (OAM *)(MMU.ARM9_OAM + ADDRESS_STEP_1KB); + g->sprMem = MMU_BOBJ; + // GPU core B + g->dispx_st = (REG_DISPx*)(&MMU.ARM9_REG[REG_DISPB]); + } + else + { + g->oam = (OAM *)(MMU.ARM9_OAM); + g->sprMem = MMU_AOBJ; + // GPU core A + g->dispx_st = (REG_DISPx*)(&MMU.ARM9_REG[0]); + } +} + +void GPU_DeInit(GPU * gpu) +{ + if(gpu==&GPU_main || gpu==&GPU_sub) return; + free(gpu); +} + +static void GPU_resortBGs(GPU *gpu) +{ + int i, prio; + struct _DISPCNT * cnt = &gpu->dispx_st->dispx_DISPCNT.bits; + itemsForPriority_t * item; + + // we don't need to check for windows here... +// if we tick boxes, invisible layers become invisible & vice versa +#define OP ^ ! +// if we untick boxes, layers become invisible +//#define OP && + gpu->LayersEnable[0] = CommonSettings.dispLayers[gpu->core][0] OP(cnt->BG0_Enable/* && !(cnt->BG0_3D && (gpu->core==0))*/); + gpu->LayersEnable[1] = CommonSettings.dispLayers[gpu->core][1] OP(cnt->BG1_Enable); + gpu->LayersEnable[2] = CommonSettings.dispLayers[gpu->core][2] OP(cnt->BG2_Enable); + gpu->LayersEnable[3] = CommonSettings.dispLayers[gpu->core][3] OP(cnt->BG3_Enable); + gpu->LayersEnable[4] = CommonSettings.dispLayers[gpu->core][4] OP(cnt->OBJ_Enable); + + // KISS ! lower priority first, if same then lower num + for (i=0;iitemsForPriority[i]); + item->nbBGs=0; + item->nbPixelsX=0; + } + for (i=NB_BG; i>0; ) { + i--; + if (!gpu->LayersEnable[i]) continue; + prio = (gpu->dispx_st)->dispx_BGxCNT[i].bits.Priority; + item = &(gpu->itemsForPriority[prio]); + item->BGs[item->nbBGs]=i; + item->nbBGs++; + } + + int bg0Prio = gpu->dispx_st->dispx_BGxCNT[0].bits.Priority; + gpu->bg0HasHighestPrio = TRUE; + for(i = 1; i < 4; i++) + { + if(gpu->LayersEnable[i]) + { + if(gpu->dispx_st->dispx_BGxCNT[i].bits.Priority < bg0Prio) + { + gpu->bg0HasHighestPrio = FALSE; + break; + } + } + } + +#if 0 +//debug + for (i=0;iitemsForPriority[i]); + printf("%d : ", i); + for (j=0; jnbBGs) + printf("BG%d ", item->BGs[j]); + else + printf("... ", item->BGs[j]); + } + } + printf("\n"); +#endif +} + +static FORCEINLINE u16 _blend(u16 colA, u16 colB, GPU::TBlendTable* blendTable) +{ + u8 r = (*blendTable)[colA&0x1F][colB&0x1F]; + u8 g = (*blendTable)[(colA>>5)&0x1F][(colB>>5)&0x1F]; + u8 b = (*blendTable)[(colA>>10)&0x1F][(colB>>10)&0x1F]; + + return r|(g<<5)|(b<<10); +} + +FORCEINLINE u16 GPU::blend(u16 colA, u16 colB) +{ + return _blend(colA, colB, blendTable); +} + + +void GPU_setMasterBrightness (GPU *gpu, u16 val) +{ + if(!nds.isInVblank()) { + PROGINFO("Changing master brightness outside of vblank\n"); + } + gpu->MasterBrightFactor = (val & 0x1F); + gpu->MasterBrightMode = (val>>14); + //printf("MASTER BRIGHTNESS %d to %d at %d\n",gpu->core,gpu->MasterBrightFactor,nds.VCount); + +} + +void SetupFinalPixelBlitter (GPU *gpu) +{ + u8 windowUsed = (gpu->WIN0_ENABLED | gpu->WIN1_ENABLED | gpu->WINOBJ_ENABLED); + u8 blendMode = (gpu->BLDCNT >> 6)&3; + + gpu->setFinalColorSpr_funcNum = windowUsed*4 + blendMode; + gpu->setFinalColorBck_funcNum = windowUsed*4 + blendMode; + gpu->setFinalColor3d_funcNum = windowUsed*4 + blendMode; + +} + +//Sets up LCD control variables for Display Engines A and B for quick reading +void GPU_setVideoProp(GPU * gpu, u32 p) +{ + struct _DISPCNT * cnt; + cnt = &(gpu->dispx_st)->dispx_DISPCNT.bits; + + T1WriteLong((u8 *)&(gpu->dispx_st)->dispx_DISPCNT.val, 0, p); + + gpu->WIN0_ENABLED = cnt->Win0_Enable; + gpu->WIN1_ENABLED = cnt->Win1_Enable; + gpu->WINOBJ_ENABLED = cnt->WinOBJ_Enable; + + SetupFinalPixelBlitter (gpu); + + gpu->dispMode = cnt->DisplayMode & ((gpu->core)?1:3); + + gpu->vramBlock = cnt->VRAM_Block; + + switch (gpu->dispMode) + { + case 0: // Display Off + break; + case 1: // Display BG and OBJ layers + break; + case 2: // Display framebuffer + gpu->VRAMaddr = (u8 *)MMU.ARM9_LCD + (gpu->vramBlock * 0x20000); + break; + case 3: // Display from Main RAM + // nothing to be done here + // see GPU_RenderLine who gets data from FIFO. + break; + } + + if(cnt->OBJ_Tile_mapping) + { + //1-d sprite mapping boundaries: + //32k, 64k, 128k, 256k + gpu->sprBoundary = 5 + cnt->OBJ_Tile_1D_Bound ; + + //do not be deceived: even though a sprBoundary==8 (256KB region) is impossible to fully address + //in GPU_SUB, it is still fully legal to address it with that granularity. + //so don't do this: //if((gpu->core == GPU_SUB) && (cnt->OBJ_Tile_1D_Bound == 3)) gpu->sprBoundary = 7; + + gpu->spriteRenderMode = GPU::SPRITE_1D; + } else { + //2d sprite mapping + //boundary : 32k + gpu->sprBoundary = 5; + gpu->spriteRenderMode = GPU::SPRITE_2D; + } + + if(cnt->OBJ_BMP_1D_Bound && (gpu->core == GPU_MAIN)) + gpu->sprBMPBoundary = 8; + else + gpu->sprBMPBoundary = 7; + + gpu->sprEnable = cnt->OBJ_Enable; + + GPU_setBGProp(gpu, 3, T1ReadWord(MMU.ARM9_REG, gpu->core * ADDRESS_STEP_4KB + 14)); + GPU_setBGProp(gpu, 2, T1ReadWord(MMU.ARM9_REG, gpu->core * ADDRESS_STEP_4KB + 12)); + GPU_setBGProp(gpu, 1, T1ReadWord(MMU.ARM9_REG, gpu->core * ADDRESS_STEP_4KB + 10)); + GPU_setBGProp(gpu, 0, T1ReadWord(MMU.ARM9_REG, gpu->core * ADDRESS_STEP_4KB + 8)); + + //GPU_resortBGs(gpu); +} + +//this handles writing in BGxCNT +void GPU_setBGProp(GPU * gpu, u16 num, u16 p) +{ + struct _BGxCNT * cnt = &((gpu->dispx_st)->dispx_BGxCNT[num].bits); + struct _DISPCNT * dispCnt = &(gpu->dispx_st)->dispx_DISPCNT.bits; + + T1WriteWord((u8 *)&(gpu->dispx_st)->dispx_BGxCNT[num].val, 0, p); + + GPU_resortBGs(gpu); + + if(gpu->core == GPU_SUB) + { + gpu->BG_tile_ram[num] = MMU_BBG; + gpu->BG_bmp_ram[num] = MMU_BBG; + gpu->BG_bmp_large_ram[num] = MMU_BBG; + gpu->BG_map_ram[num] = MMU_BBG; + } + else + { + gpu->BG_tile_ram[num] = MMU_ABG + dispCnt->CharacBase_Block * ADDRESS_STEP_64KB ; + gpu->BG_bmp_ram[num] = MMU_ABG; + gpu->BG_bmp_large_ram[num] = MMU_ABG; + gpu->BG_map_ram[num] = MMU_ABG + dispCnt->ScreenBase_Block * ADDRESS_STEP_64KB; + } + + gpu->BG_tile_ram[num] += (cnt->CharacBase_Block * ADDRESS_STEP_16KB); + gpu->BG_bmp_ram[num] += (cnt->ScreenBase_Block * ADDRESS_STEP_16KB); + gpu->BG_map_ram[num] += (cnt->ScreenBase_Block * ADDRESS_STEP_2KB); + + switch(num) + { + case 0: + case 1: + gpu->BGExtPalSlot[num] = cnt->PaletteSet_Wrap * 2 + num ; + break; + + default: + gpu->BGExtPalSlot[num] = (u8)num; + break; + } + + BGType mode = GPU_mode2type[dispCnt->BG_Mode][num]; + + //clarify affine ext modes + if(mode == BGType_AffineExt) + { + //see: http://nocash.emubase.de/gbatek.htm#dsvideobgmodescontrol + u8 affineModeSelection = (cnt->Palette_256 << 1) | (cnt->CharacBase_Block & 1) ; + switch(affineModeSelection) + { + case 0: + case 1: + mode = BGType_AffineExt_256x16; + break; + case 2: + mode = BGType_AffineExt_256x1; + break; + case 3: + mode = BGType_AffineExt_Direct; + break; + } + } + + gpu->BGTypes[num] = mode; + + gpu->BGSize[num][0] = sizeTab[mode][cnt->ScreenSize][0]; + gpu->BGSize[num][1] = sizeTab[mode][cnt->ScreenSize][1]; + + gpu->bgPrio[num] = (p & 0x3); +} + +/*****************************************************************************/ +// ENABLING / DISABLING LAYERS +/*****************************************************************************/ + +void GPU_remove(GPU * gpu, u8 num) +{ + CommonSettings.dispLayers[gpu->core][num] = false; + GPU_resortBGs(gpu); +} +void GPU_addBack(GPU * gpu, u8 num) +{ + CommonSettings.dispLayers[gpu->core][num] = true; + GPU_resortBGs(gpu); +} + + +/*****************************************************************************/ +// ROUTINES FOR INSIDE / OUTSIDE WINDOW CHECKS +/*****************************************************************************/ + +template +FORCEINLINE u8 GPU::withinRect(u16 x) const +{ + assert(x<256); //only way to be >256 is in debug views, and mosaic shouldnt be enabled for those + return curr_win[WIN_NUM][x]; +} + + + +// Now assumes that *draw and *effect are different from 0 when called, so we can avoid +// setting some values twice +FORCEINLINE void GPU::renderline_checkWindows(u16 x, bool &draw, bool &effect) const +{ + // Check if win0 if enabled, and only check if it is + // howevever, this has already been taken care of by the window precalculation + //if (WIN0_ENABLED) + { + // it is in win0, do we display ? + // high priority + if (withinRect<0>(x)) + { + //INFO("bg%i passed win0 : (%i %i) was within (%i %i)(%i %i)\n", bgnum, x, gpu->currLine, gpu->WIN0H0, gpu->WIN0V0, gpu->WIN0H1, gpu->WIN0V1); + draw = (WININ0 >> currBgNum)&1; + effect = (WININ0_SPECIAL); + return; + } + } + + // Check if win1 if enabled, and only check if it is + //if (WIN1_ENABLED) + // howevever, this has already been taken care of by the window precalculation + { + // it is in win1, do we display ? + // mid priority + if(withinRect<1>(x)) + { + //INFO("bg%i passed win1 : (%i %i) was within (%i %i)(%i %i)\n", bgnum, x, gpu->currLine, gpu->WIN1H0, gpu->WIN1V0, gpu->WIN1H1, gpu->WIN1V1); + draw = (WININ1 >> currBgNum)&1; + effect = (WININ1_SPECIAL); + return; + } + } + + //if(true) //sprwin test hack + if (WINOBJ_ENABLED) + { + // it is in winOBJ, do we display ? + // low priority + if (sprWin[x]) + { + draw = (WINOBJ >> currBgNum)&1; + effect = (WINOBJ_SPECIAL); + return; + } + } + + if (WINOBJ_ENABLED | WIN1_ENABLED | WIN0_ENABLED) + { + draw = (WINOUT >> currBgNum) & 1; + effect = (WINOUT_SPECIAL); + } +} + +/*****************************************************************************/ +// PIXEL RENDERING +/*****************************************************************************/ + +template +FORCEINLINE FASTCALL void GPU::_master_setFinal3dColor(int dstX, int srcX) +{ + int x = dstX; + int passing = dstX<<1; + u8* color = &_3dColorLine[srcX<<2]; + u8 red = color[0]; + u8 green = color[1]; + u8 blue = color[2]; + u8 alpha = color[3]; + u8* dst = currDst; + u16 final; + + bool windowEffect = blend1; //bomberman land touch dialogbox will fail without setting to blend1 + + //TODO - should we do an alpha==0 -> bail out entirely check here? + + if(WINDOW) + { + bool windowDraw = false; + renderline_checkWindows(dstX, windowDraw, windowEffect); + + //we never have anything more to do if the window rejected us + if(!windowDraw) return; + } + + int bg_under = bgPixels[dstX]; + if(blend2[bg_under]) + { + alpha++; + if(alpha<32) + { + //if the layer underneath is a blend bottom layer, then 3d always alpha blends with it + COLOR c2, cfinal; + + c2.val = HostReadWord(dst, passing); + + cfinal.bits.red = ((red * alpha) + ((c2.bits.red<<1) * (32 - alpha)))>>6; + cfinal.bits.green = ((green * alpha) + ((c2.bits.green<<1) * (32 - alpha)))>>6; + cfinal.bits.blue = ((blue * alpha) + ((c2.bits.blue<<1) * (32 - alpha)))>>6; + + final = cfinal.val; + } + else final = R6G6B6TORGB15(red,green,blue); + } + else + { + final = R6G6B6TORGB15(red,green,blue); + //perform the special effect + if(windowEffect) + switch(FUNC) { + case Increase: final = currentFadeInColors[final&0x7FFF]; break; + case Decrease: final = currentFadeOutColors[final&0x7FFF]; break; + case None: + case Blend: + break; + } + } + + HostWriteWord(dst, passing, (final | 0x8000)); + bgPixels[x] = 0; +} + + +template +FORCEINLINE FASTCALL bool GPU::_master_setFinalBGColor(u16 &color, const u32 x) +{ + //no further analysis for no special effects. on backdrops. just draw it. + if(FUNC==None && BACKDROP) return true; + + //blend backdrop with what?? this doesn't make sense + if(FUNC==Blend && BACKDROP) return true; + + bool windowEffect = true; + + if(WINDOW) + { + bool windowDraw = false; + renderline_checkWindows(x, windowDraw, windowEffect); + + //backdrop must always be drawn + if(BACKDROP) windowDraw = true; + + //we never have anything more to do if the window rejected us + if(!windowDraw) return false; + } + + //special effects rejected. just draw it. + if(!(blend1 && windowEffect)) + return true; + + const u8 bg_under = bgPixels[x]; + + //perform the special effect + switch(FUNC) { + case Blend: if(blend2[bg_under]) color = blend(color,HostReadWord(currDst, x<<1)); break; + case Increase: color = currentFadeInColors[color]; break; + case Decrease: color = currentFadeOutColors[color]; break; + case None: break; + } + return true; +} + +template +static FORCEINLINE void _master_setFinalOBJColor(GPU *gpu, u8 *dst, u16 color, u8 alpha, u8 type, u16 x) +{ + bool windowDraw = true, windowEffect = true; + + if(WINDOW) + { + gpu->renderline_checkWindows(x, windowDraw, windowEffect); + if(!windowDraw) + return; + } + + const bool sourceEffectSelected = gpu->blend1; + + //note that the fadein and fadeout is done here before blending, + //so that a fade and blending can be applied at the same time (actually, I don't think that is legal..) + bool forceBlendingForNormal = false; + if(windowEffect && sourceEffectSelected) + switch(FUNC) + { + //zero 13-jun-2010 : if(allowBlend) was removed from these; + //it should be possible to increase/decrease and also blend + //(the effect would be increase, but the obj properties permit blending and the target layers are configured correctly) + case Increase: color = gpu->currentFadeInColors[color&0x7FFF]; break; + case Decrease: color = gpu->currentFadeOutColors[color&0x7FFF]; break; + + //only when blend color effect is selected, ordinarily opaque sprites are blended with the color effect params + case Blend: forceBlendingForNormal = true; break; + case None: break; + } + + //this inspects the layer beneath the sprite to see if the current blend flags make it a candidate for blending + const int bg_under = gpu->bgPixels[x]; + const bool allowBlend = (bg_under != 4) && gpu->blend2[bg_under]; + + if(allowBlend) + { + u16 backColor = HostReadWord(dst,x<<1); + //this hasn't been tested: this blending occurs without regard to the color effect, + //but rather purely from the sprite's alpha + if(type == GPU_OBJ_MODE_Bitmap) + color = _blend(color,backColor,&gpuBlendTable555[alpha+1][15-alpha]); + else if(type == GPU_OBJ_MODE_Transparent || forceBlendingForNormal) + color = gpu->blend(color,backColor); + } + + HostWriteWord(dst, x<<1, (color | 0x8000)); + gpu->bgPixels[x] = 4; +} + +//FUNCNUM is only set for backdrop, for an optimization of looking it up early +template +FORCEINLINE void GPU::setFinalColorBG(u16 color, const u32 x) +{ + //It is not safe to assert this here. + //This is probably the best place to enforce it, since almost every single color that comes in here + //will be pulled from a palette that needs the top bit stripped off anyway. + //assert((color&0x8000)==0); + if(!BACKDROP) color &= 0x7FFF; //but for the backdrop we can easily guarantee earlier that theres no bit here + + bool draw; + + const int test = BACKDROP?FUNCNUM:setFinalColorBck_funcNum; + switch(test) + { + case 0: draw = _master_setFinalBGColor(color,x); break; + case 1: draw = _master_setFinalBGColor(color,x); break; + case 2: draw = _master_setFinalBGColor(color,x); break; + case 3: draw = _master_setFinalBGColor(color,x); break; + case 4: draw = _master_setFinalBGColor(color,x); break; + case 5: draw = _master_setFinalBGColor(color,x); break; + case 6: draw = _master_setFinalBGColor(color,x); break; + case 7: draw = _master_setFinalBGColor(color,x); break; + default: draw = false; break; + }; + + if(BACKDROP || draw) //backdrop must always be drawn + { + HostWriteWord(currDst, x<<1, color | 0x8000); + if(!BACKDROP) bgPixels[x] = currBgNum; //lets do this in the backdrop drawing loop, should be faster + } +} + + +FORCEINLINE void GPU::setFinalColor3d(int dstX, int srcX) +{ + switch(setFinalColor3d_funcNum) + { + case 0x0: _master_setFinal3dColor(dstX,srcX); break; + case 0x1: _master_setFinal3dColor(dstX,srcX); break; + case 0x2: _master_setFinal3dColor(dstX,srcX); break; + case 0x3: _master_setFinal3dColor(dstX,srcX); break; + case 0x4: _master_setFinal3dColor(dstX,srcX); break; + case 0x5: _master_setFinal3dColor(dstX,srcX); break; + case 0x6: _master_setFinal3dColor(dstX,srcX); break; + case 0x7: _master_setFinal3dColor(dstX,srcX); break; + }; +} + +FORCEINLINE void setFinalColorSpr(GPU* gpu, u8 *dst, u16 color, u8 alpha, u8 type, u16 x) +{ + switch(gpu->setFinalColorSpr_funcNum) + { + case 0x0: _master_setFinalOBJColor(gpu, dst, color, alpha, type, x); break; + case 0x1: _master_setFinalOBJColor(gpu, dst, color, alpha, type, x); break; + case 0x2: _master_setFinalOBJColor(gpu, dst, color, alpha, type, x); break; + case 0x3: _master_setFinalOBJColor(gpu, dst, color, alpha, type, x); break; + case 0x4: _master_setFinalOBJColor(gpu, dst, color, alpha, type, x); break; + case 0x5: _master_setFinalOBJColor(gpu, dst, color, alpha, type, x); break; + case 0x6: _master_setFinalOBJColor(gpu, dst, color, alpha, type, x); break; + case 0x7: _master_setFinalOBJColor(gpu, dst, color, alpha, type, x); break; + }; +} + +template +FORCEINLINE void GPU::__setFinalColorBck(u16 color, const u32 x, const int opaque) +{ + return ___setFinalColorBck(color,x,opaque); +} + +//this was forced inline because most of the time it just falls through to setFinalColorBck() and the function call +//overhead was ridiculous and terrible +template +FORCEINLINE void GPU::___setFinalColorBck(u16 color, const u32 x, const int opaque) +{ + //under ordinary circumstances, nobody should pass in something >=256 + //but in fact, someone is going to try. specifically, that is the map viewer debug tools + //which try to render the enter BG. in cases where that is large, it could be up to 1024 wide. + assert(debug || x<256); + + int x_int; + + //due to this early out, we will get incorrect behavior in cases where + //we enable mosaic in the middle of a frame. this is deemed unlikely. + if(!MOSAIC) { + if(opaque) goto finish; + else return; + } + + if(!opaque) color = 0xFFFF; + else color &= 0x7FFF; + + //due to the early out, enabled must always be true + //x_int = enabled ? GPU::mosaicLookup.width[x].trunc : x; + x_int = GPU::mosaicLookup.width[x].trunc; + + if(GPU::mosaicLookup.width[x].begin && GPU::mosaicLookup.height[currLine].begin) {} + else color = mosaicColors.bg[currBgNum][x_int]; + mosaicColors.bg[currBgNum][x] = color; + + if(color != 0xFFFF) + { +finish: + setFinalColorBG(color,x); + } +} + +//this is fantastically inaccurate. +//we do the early return even though it reduces the resulting accuracy +//because we need the speed, and because it is inaccurate anyway +static void mosaicSpriteLinePixel(GPU * gpu, int x, u16 l, u8 * dst, u8 * dst_alpha, u8 * typeTab, u8 * prioTab) +{ + int x_int; + int y = l; + + _OAM_ * spriteInfo = (_OAM_ *)(gpu->oam + gpu->sprNum[x]); + bool enabled = spriteInfo->Mosaic; + if(!enabled) + return; + + bool opaque = prioTab[x] <= 4; + + GPU::MosaicColor::Obj objColor; + objColor.color = T1ReadWord(dst,x<<1); + objColor.alpha = dst_alpha[x]; + objColor.opaque = opaque; + + x_int = enabled ? GPU::mosaicLookup.width[x].trunc : x; + + if(enabled) + { + if(GPU::mosaicLookup.width[x].begin && GPU::mosaicLookup.height[y].begin) {} + else objColor = gpu->mosaicColors.obj[x_int]; + } + gpu->mosaicColors.obj[x] = objColor; + + T1WriteWord(dst,x<<1,objColor.color); + dst_alpha[x] = objColor.alpha; + if(!objColor.opaque) prioTab[x] = 0xFF; +} + +FORCEINLINE static void mosaicSpriteLine(GPU * gpu, u16 l, u8 * dst, u8 * dst_alpha, u8 * typeTab, u8 * prioTab) +{ + //don't even try this unless the mosaic is effective + if(gpu->mosaicLookup.widthValue != 0 || gpu->mosaicLookup.heightValue != 0) + for(int i=0;i<256;i++) + mosaicSpriteLinePixel(gpu,i,l,dst,dst_alpha,typeTab,prioTab); +} + +template void lineLarge8bpp(GPU * gpu) +{ + if(gpu->core == 1) { + PROGINFO("Cannot use large 8bpp screen on sub core\n"); + return; + } + + u8 num = gpu->currBgNum; + u16 XBG = gpu->getHOFS(gpu->currBgNum); + u16 YBG = gpu->currLine + gpu->getVOFS(gpu->currBgNum); + u16 lg = gpu->BGSize[num][0]; + u16 ht = gpu->BGSize[num][1]; + u16 wmask = (lg-1); + u16 hmask = (ht-1); + YBG &= hmask; + + //TODO - handle wrapping / out of bounds correctly from rot_scale_op? + + u32 tmp_map = gpu->BG_bmp_large_ram[num] + lg * YBG; + u8* map = (u8 *)MMU_gpu_map(tmp_map); + + u8* pal = MMU.ARM9_VMEM + gpu->core * ADDRESS_STEP_1KB; + + for(int x = 0; x < lg; ++x, ++XBG) + { + XBG &= wmask; + u8 pixel = map[XBG]; + u16 color = T1ReadWord(pal, pixel<<1); + gpu->__setFinalColorBck(color,x,color); + } + +} + +/*****************************************************************************/ +// BACKGROUND RENDERING -TEXT- +/*****************************************************************************/ +// render a text background to the combined pixelbuffer +template INLINE void renderline_textBG(GPU * gpu, u16 XBG, u16 YBG, u16 LG) +{ + u8 num = gpu->currBgNum; + struct _BGxCNT *bgCnt = &(gpu->dispx_st)->dispx_BGxCNT[num].bits; + struct _DISPCNT *dispCnt = &(gpu->dispx_st)->dispx_DISPCNT.bits; + u16 lg = gpu->BGSize[num][0]; + u16 ht = gpu->BGSize[num][1]; + u16 wmask = (lg-1); + u16 hmask = (ht-1); + u16 tmp = ((YBG & hmask) >> 3); + u32 map; + u8 *pal, *line; + u32 tile; + u16 color; + u16 xoff; + u16 yoff; + u32 x = 0; + u32 xfin; + + s8 line_dir = 1; + u32 mapinfo; + TILEENTRY tileentry; + + u32 tmp_map = gpu->BG_map_ram[num] + (tmp&31) * 64; + if(tmp>31) + tmp_map+= ADDRESS_STEP_512B << bgCnt->ScreenSize ; + + map = tmp_map; + tile = gpu->BG_tile_ram[num]; + + xoff = XBG; + pal = MMU.ARM9_VMEM + gpu->core * ADDRESS_STEP_1KB; + + if(!bgCnt->Palette_256) // color: 16 palette entries + { + yoff = ((YBG&7)<<2); + xfin = 8 - (xoff&7); + for(x = 0; x < LG; xfin = std::min(x+8, LG)) + { + u16 tilePalette = 0; + tmp = ((xoff&wmask)>>3); + mapinfo = map + (tmp&0x1F) * 2; + if(tmp>31) mapinfo += 32*32*2; + tileentry.val = T1ReadWord(MMU_gpu_map(mapinfo), 0); + + tilePalette = (tileentry.bits.Palette*16); + + line = (u8*)MMU_gpu_map(tile + (tileentry.bits.TileNum * 0x20) + ((tileentry.bits.VFlip) ? (7*4)-yoff : yoff)); + + if(tileentry.bits.HFlip) + { + line += (3 - ((xoff&7)>>1)); + for(; x < xfin; line --) + { + u8 currLine = *line; + + if(!(xoff&1)) + { + color = T1ReadWord(pal, ((currLine>>4) + tilePalette) << 1); + gpu->__setFinalColorBck(color,x,currLine>>4); + x++; xoff++; + } + + if(x__setFinalColorBck(color,x,currLine&0xF); + x++; xoff++; + } + } + } else { + line += ((xoff&7)>>1); + for(; x < xfin; line ++) + { + u8 currLine = *line; + + if(!(xoff&1)) + { + color = T1ReadWord(pal, ((currLine&0xF) + tilePalette) << 1); + gpu->__setFinalColorBck(color,x,currLine&0xF); + x++; xoff++; + } + + if(x>4) + tilePalette) << 1); + gpu->__setFinalColorBck(color,x,currLine>>4); + x++; xoff++; + } + } + } + } + return; + } + + //256-color BG + + if(dispCnt->ExBGxPalette_Enable) // color: extended palette + { + pal = MMU.ExtPal[gpu->core][gpu->BGExtPalSlot[num]]; + if(!pal) return; + } + + yoff = ((YBG&7)<<3); + u8* tilePal; + xfin = 8 - (xoff&7); + u32 extPalMask = -dispCnt->ExBGxPalette_Enable; + for(x = 0; x < LG; xfin = std::min(x+8, LG)) + { + tmp = (xoff & (lg-1))>>3; + mapinfo = map + (tmp & 31) * 2; + if(tmp > 31) mapinfo += 32*32*2; + tileentry.val = T1ReadWord(MMU_gpu_map(mapinfo), 0); + tilePal = pal + ((tileentry.bits.Palette<<9)&extPalMask); + line = (u8*)MMU_gpu_map(tile + (tileentry.bits.TileNum*0x40) + ((tileentry.bits.VFlip) ? (7*8)-yoff : yoff)); + + if(tileentry.bits.HFlip) + { + line += (7 - (xoff&7)); + line_dir = -1; + } else { + line += (xoff&7); + line_dir = 1; + } + for(; x < xfin; ) + { + color = T1ReadWord(tilePal, (*line) << 1); + + gpu->__setFinalColorBck(color,x,*line); + + x++; xoff++; + + line += line_dir; + } + } +} + +/*****************************************************************************/ +// BACKGROUND RENDERING -ROTOSCALE- +/*****************************************************************************/ + +template FORCEINLINE void rot_tiled_8bit_entry(GPU * gpu, s32 auxX, s32 auxY, int lg, u32 map, u32 tile, u8 * pal, int i) { + u8 palette_entry; + u16 tileindex, x, y, color; + + tileindex = *(u8*)MMU_gpu_map(map + ((auxX>>3) + (auxY>>3) * (lg>>3))); + + x = (auxX&7); + y = (auxY&7); + + palette_entry = *(u8*)MMU_gpu_map(tile + ((tileindex<<6)+(y<<3)+x)); + color = T1ReadWord(pal, palette_entry << 1); + gpu->__setFinalColorBck(color,i,palette_entry); +} + +template FORCEINLINE void rot_tiled_16bit_entry(GPU * gpu, s32 auxX, s32 auxY, int lg, u32 map, u32 tile, u8 * pal, int i) { + void* const map_addr = MMU_gpu_map(map + (((auxX>>3) + (auxY>>3) * (lg>>3))<<1)); + + TILEENTRY tileentry; + tileentry.val = T1ReadWord(map_addr, 0); + + const u16 x = ((tileentry.bits.HFlip) ? 7 - (auxX) : (auxX))&7; + const u16 y = ((tileentry.bits.VFlip) ? 7 - (auxY) : (auxY))&7; + + const u8 palette_entry = *(u8*)MMU_gpu_map(tile + ((tileentry.bits.TileNum<<6)+(y<<3)+x)); + const u16 color = T1ReadWord(pal, (palette_entry + (extPal ? (tileentry.bits.Palette<<8) : 0)) << 1); + gpu->__setFinalColorBck(color, i, palette_entry); +} + +template FORCEINLINE void rot_256_map(GPU * gpu, s32 auxX, s32 auxY, int lg, u32 map, u32 tile, u8 * pal, int i) { + u8 palette_entry; + u16 color; + + u8* adr = (u8*)MMU_gpu_map((map) + ((auxX + auxY * lg))); + + palette_entry = *adr; + color = T1ReadWord(pal, palette_entry << 1); + gpu->__setFinalColorBck(color, i, palette_entry); +} + +template FORCEINLINE void rot_BMP_map(GPU * gpu, s32 auxX, s32 auxY, int lg, u32 map, u32 tile, u8 * pal, int i) { + u16 color; + void* adr = MMU_gpu_map((map) + ((auxX + auxY * lg) << 1)); + color = T1ReadWord(adr, 0); + gpu->__setFinalColorBck(color, i, color&0x8000); +} + +typedef void (*rot_fun)(GPU * gpu, s32 auxX, s32 auxY, int lg, u32 map, u32 tile, u8 * pal, int i); + +template +FORCEINLINE void rot_scale_op(GPU * gpu, s32 X, s32 Y, s16 PA, s16 PB, s16 PC, s16 PD, u16 LG, s32 wh, s32 ht, u32 map, u32 tile, u8 * pal) +{ + ROTOCOORD x, y; + x.val = X; + y.val = Y; + + const s32 dx = (s32)PA; + const s32 dy = (s32)PC; + + // as an optimization, specially handle the fairly common case of + // "unrotated + unscaled + no boundary checking required" + if(dx==0x100 && dy==0) + { + s32 auxX = x.bits.Integer; + s32 auxY = y.bits.Integer; + if(WRAP || (auxX + LG < wh && auxX >= 0 && auxY < ht && auxY >= 0)) + { + if(WRAP) + { + auxY = auxY & (ht-1); + auxX = auxX & (wh-1); + } + for(int i = 0; i < LG; ++i) + { + fun(gpu, auxX, auxY, wh, map, tile, pal, i); + auxX++; + if(WRAP) + auxX = auxX & (wh-1); + } + return; + } + } + + for(int i = 0; i < LG; ++i) + { + s32 auxX, auxY; + auxX = x.bits.Integer; + auxY = y.bits.Integer; + + if(WRAP) + { + auxX = auxX & (wh-1); + auxY = auxY & (ht-1); + } + + if(WRAP || ((auxX >= 0) && (auxX < wh) && (auxY >= 0) && (auxY < ht))) + fun(gpu, auxX, auxY, wh, map, tile, pal, i); + + x.val += dx; + y.val += dy; + } +} + +template +FORCEINLINE void apply_rot_fun(GPU * gpu, s32 X, s32 Y, s16 PA, s16 PB, s16 PC, s16 PD, u16 LG, u32 map, u32 tile, u8 * pal) +{ + struct _BGxCNT * bgCnt = &(gpu->dispx_st)->dispx_BGxCNT[gpu->currBgNum].bits; + s32 wh = gpu->BGSize[gpu->currBgNum][0]; + s32 ht = gpu->BGSize[gpu->currBgNum][1]; + if(bgCnt->PaletteSet_Wrap) + rot_scale_op(gpu, X, Y, PA, PB, PC, PD, LG, wh, ht, map, tile, pal); + else rot_scale_op(gpu, X, Y, PA, PB, PC, PD, LG, wh, ht, map, tile, pal); +} + + +template FORCEINLINE void rotBG2(GPU * gpu, s32 X, s32 Y, s16 PA, s16 PB, s16 PC, s16 PD, u16 LG) +{ + u8 num = gpu->currBgNum; + u8 * pal = MMU.ARM9_VMEM + gpu->core * 0x400; +// printf("rot mode\n"); + apply_rot_fun >(gpu,X,Y,PA,PB,PC,PD,LG, gpu->BG_map_ram[num], gpu->BG_tile_ram[num], pal); +} + +template FORCEINLINE void extRotBG2(GPU * gpu, s32 X, s32 Y, s16 PA, s16 PB, s16 PC, s16 PD, s16 LG) +{ + u8 num = gpu->currBgNum; + struct _DISPCNT * dispCnt = &(gpu->dispx_st)->dispx_DISPCNT.bits; + + u8 *pal; + + switch(gpu->BGTypes[num]) + { + case BGType_AffineExt_256x16: + if(dispCnt->ExBGxPalette_Enable) + pal = MMU.ExtPal[gpu->core][gpu->BGExtPalSlot[num]]; + else + pal = MMU.ARM9_VMEM + gpu->core * 0x400; + if (!pal) return; + // 16 bit bgmap entries + if(dispCnt->ExBGxPalette_Enable) + apply_rot_fun >(gpu,X,Y,PA,PB,PC,PD,LG, gpu->BG_map_ram[num], gpu->BG_tile_ram[num], pal); + else apply_rot_fun >(gpu,X,Y,PA,PB,PC,PD,LG, gpu->BG_map_ram[num], gpu->BG_tile_ram[num], pal); + return; + case BGType_AffineExt_256x1: + // 256 colors + pal = MMU.ARM9_VMEM + gpu->core * 0x400; + apply_rot_fun >(gpu,X,Y,PA,PB,PC,PD,LG, gpu->BG_bmp_ram[num], 0, pal); + return; + case BGType_AffineExt_Direct: + // direct colors / BMP + apply_rot_fun >(gpu,X,Y,PA,PB,PC,PD,LG, gpu->BG_bmp_ram[num], 0, NULL); + return; + case BGType_Large8bpp: + // large screen 256 colors + pal = MMU.ARM9_VMEM + gpu->core * 0x400; + apply_rot_fun >(gpu,X,Y,PA,PB,PC,PD,LG, gpu->BG_bmp_large_ram[num], 0, pal); + return; + default: break; + } +} + +/*****************************************************************************/ +// BACKGROUND RENDERING -HELPER FUNCTIONS- +/*****************************************************************************/ + +#if 0 +static void lineNull(GPU * gpu) +{ +} +#endif + +template void lineText(GPU * gpu) +{ + if(gpu->debug) + { + const s32 wh = gpu->BGSize[gpu->currBgNum][0]; + renderline_textBG(gpu, 0, gpu->currLine, wh); + } + else + { + const u16 vofs = gpu->getVOFS(gpu->currBgNum); + const u16 hofs = gpu->getHOFS(gpu->currBgNum); + renderline_textBG(gpu, hofs, gpu->currLine + vofs, 256); + } +} + +template void lineRot(GPU * gpu) +{ + BGxPARMS * parms; + if (gpu->currBgNum==2) { + parms = &(gpu->dispx_st)->dispx_BG2PARMS; + } else { + parms = &(gpu->dispx_st)->dispx_BG3PARMS; + } + + if(gpu->debug) + { + s32 wh = gpu->BGSize[gpu->currBgNum][0]; + rotBG2(gpu, 0, (s16)gpu->currLine*256, 256,0, 0,-77, wh); + } + else + { + rotBG2(gpu, + parms->BGxX, + parms->BGxY, + parms->BGxPA, + parms->BGxPB, + parms->BGxPC, + parms->BGxPD, + 256); + parms->BGxX += parms->BGxPB; + parms->BGxY += parms->BGxPD; + } +} + +template void lineExtRot(GPU * gpu) +{ + BGxPARMS * parms; + if (gpu->currBgNum==2) { + parms = &(gpu->dispx_st)->dispx_BG2PARMS; + } else { + parms = &(gpu->dispx_st)->dispx_BG3PARMS; + } + + if(gpu->debug) + { + s32 wh = gpu->BGSize[gpu->currBgNum][0]; + extRotBG2(gpu, 0, (s16)gpu->currLine*256, 256,0, 0,-77, wh); + } + else + { + extRotBG2(gpu, + parms->BGxX, + parms->BGxY, + parms->BGxPA, + parms->BGxPB, + parms->BGxPC, + parms->BGxPD, + 256); + parms->BGxX += parms->BGxPB; + parms->BGxY += parms->BGxPD; + } +} + +/*****************************************************************************/ +// SPRITE RENDERING -HELPER FUNCTIONS- +/*****************************************************************************/ + +#define nbShow 128 + +/* if i understand it correct, and it fixes some sprite problems in chameleon shot */ +/* we have a 15 bit color, and should use the pal entry bits as alpha ?*/ +/* http://nocash.emubase.de/gbatek.htm#dsvideoobjs */ +INLINE void render_sprite_BMP (GPU * gpu, u8 spriteNum, u16 l, u8 * dst, u32 srcadr, u8 * dst_alpha, u8 * typeTab, u8 * prioTab, u8 prio, int lg, int sprX, int x, int xdir, u8 alpha) +{ + int i; u16 color; + for(i = 0; i < lg; i++, ++sprX, x+=xdir) + { + u16* src = (u16*)MMU_gpu_map(srcadr+(x<<1)); + color = LE_TO_LOCAL_16(*src); + + // alpha bit = invisible + if ((color&0x8000)&&(priosprNum[sprX] = spriteNum; + } + } +} + +INLINE void render_sprite_256(GPU * gpu, u8 spriteNum, u16 l, u8 * dst, u32 srcadr, u16 * pal, u8 * dst_alpha, u8 * typeTab, u8 * prioTab, u8 prio, int lg, int sprX, int x, int xdir, u8 alpha) +{ + int i; + u8 palette_entry; + u16 color; + + for(i = 0; i < lg; i++, ++sprX, x+=xdir) + { + u32 adr = srcadr + (x&0x7) + ((x&0xFFF8)<<3); + u8* src = (u8 *)MMU_gpu_map(adr); + palette_entry = *src; + color = LE_TO_LOCAL_16(pal[palette_entry]); + + // palette entry = 0 means backdrop + if ((palette_entry>0)&&(priosprNum[sprX] = spriteNum; + } + } +} + +INLINE void render_sprite_16 ( GPU * gpu, u16 l, u8 * dst, u32 srcadr, u16 * pal, u8 * dst_alpha, u8 * typeTab, u8 * prioTab, u8 prio, int lg, int sprX, int x, int xdir, u8 alpha) +{ + int i; + u8 palette, palette_entry; + u16 color, x1; + + for(i = 0; i < lg; i++, ++sprX, x+=xdir) + { + x1 = x>>1; + + u32 adr = srcadr + (x1&0x3) + ((x1&0xFFFC)<<3); + u8* src = (u8 *)MMU_gpu_map(adr);// + palette = *src; + + if (x & 1) palette_entry = palette >> 4; + else palette_entry = palette & 0xF; + color = LE_TO_LOCAL_16(pal[palette_entry]); + + // palette entry = 0 means backdrop + if ((palette_entry>0)&&(prio>1; + palette = src[(x1&0x3) + ((x1&0xFFFC)<<3)]; + if (x & 1) palette_entry = palette >> 4; + else palette_entry = palette & 0xF; + //sprWin[sprX] = (palette_entry)?1:0; + if(palette_entry) + sprWin[sprX] = 1; + } + } +} + +// return val means if the sprite is to be drawn or not +FORCEINLINE BOOL compute_sprite_vars(_OAM_ * spriteInfo, u16 l, + size &sprSize, s32 &sprX, s32 &sprY, s32 &x, s32 &y, s32 &lg, int &xdir) { + + x = 0; + // get sprite location and size + sprX = (spriteInfo->X/*<<23*/)/*>>23*/; + sprY = spriteInfo->Y; + sprSize = sprSizeTab[spriteInfo->Size][spriteInfo->Shape]; + + lg = sprSize.x; + + if (sprY>=192) + sprY = (s32)((s8)(spriteInfo->Y)); + +// FIXME: for rot/scale, a list of entries into the sprite should be maintained, +// that tells us where the first pixel of a screenline starts in the sprite, +// and how a step to the right in a screenline translates within the sprite + + //this wasn't really tested by anything. very unlikely to get triggered + y = (l - sprY)&255; /* get the y line within sprite coords */ + if(y >= sprSize.y) + return FALSE; + + if((sprX==256)||(sprX+sprSize.x<=0)) /* sprite pixels outside of line */ + return FALSE; /* not to be drawn */ + + // sprite portion out of the screen (LEFT) + if(sprX<0) + { + lg += sprX; + x = -(sprX); + sprX = 0; + } + // sprite portion out of the screen (RIGHT) + if (sprX+sprSize.x >= 256) + lg = 256 - sprX; + + // switch TOP<-->BOTTOM + if (spriteInfo->VFlip) + y = sprSize.y - y -1; + + // switch LEFT<-->RIGHT + if (spriteInfo->HFlip) { + x = sprSize.x - x -1; + xdir = -1; + } else { + xdir = 1; + } + return TRUE; +} + +/*****************************************************************************/ +// SPRITE RENDERING +/*****************************************************************************/ + + +//TODO - refactor this so there isnt as much duped code between rotozoomed and non-rotozoomed versions + +static u32 bmp_sprite_address(GPU* gpu, _OAM_ * spriteInfo, size sprSize, s32 y) +{ + if (gpu->dispCnt().OBJ_BMP_mapping) + { + //tested by buffy sacrifice damage blood splatters in corner + return gpu->sprMem + (spriteInfo->TileIndex<sprBMPBoundary) + (y*sprSize.x*2); + } + else + { + //2d mapping: + //verified in rotozoomed mode by knights in the nightmare intro + + if (gpu->dispCnt().OBJ_BMP_2D_dim) + //256*256, verified by heroes of mana FMV intro + return gpu->sprMem + (((spriteInfo->TileIndex&0x3E0) * 64 + (spriteInfo->TileIndex&0x1F) *8 + ( y << 8)) << 1); + else + //128*512, verified by harry potter and the order of the phoenix conversation portraits + return gpu->sprMem + (((spriteInfo->TileIndex&0x3F0) * 64 + (spriteInfo->TileIndex&0x0F) *8 + ( y << 7)) << 1); + } +} + + +template +void GPU::_spriteRender(u8 * dst, u8 * dst_alpha, u8 * typeTab, u8 * prioTab) +{ + u16 l = currLine; + GPU *gpu = this; + + int cost = 0; + + struct _DISPCNT * dispCnt = &(gpu->dispx_st)->dispx_DISPCNT.bits; + _OAM_ * spriteInfo = (_OAM_ *)(gpu->oam); + u8 block = gpu->sprBoundary; + u8 i; + + //what the hell? why is all this here? the #ifdefs in the bitfields definition should take care of this. + //this needs to be fixed anyway since i changed the sprite render order + //better yet, just dont do it this way at all. _OAM_ is so small, why not just copy it and then twiddle it? + +//#ifdef WORDS_BIGENDIAN +// *(((u16*)spriteInfo)+1) = (*(((u16*)spriteInfo)+1) >> 1) | *(((u16*)spriteInfo)+1) << 15; +// *(((u16*)spriteInfo)+2) = (*(((u16*)spriteInfo)+2) >> 2) | *(((u16*)spriteInfo)+2) << 14; +//#endif + + for(i = 0; i> 15 +// ,*(((u16*)(spriteInfo+1))+2) = (*(((u16*)(spriteInfo+1))+2) << 2) | *(((u16*)(spriteInfo+1))+2) >> 14 +// ,*(((u16*)spriteInfo)+1) = (*(((u16*)spriteInfo)+1) >> 1) | *(((u16*)spriteInfo)+1) << 15 +// ,*(((u16*)spriteInfo)+2) = (*(((u16*)spriteInfo)+2) >> 2) | *(((u16*)spriteInfo)+2) << 14 +//#endif + ) + { + //for each sprite: + if(cost>=2130) + { + //out of sprite rendering time + //printf("sprite overflow!\n"); + //return; + } + + //do we incur a cost if a sprite is disabled?? we guess so. + cost += 2; + + size sprSize; + s32 sprX, sprY, x, y, lg; + int xdir; + u8 prio, * src; + u32 srcadr; + u16 j; + + // Check if sprite is disabled before everything + if (spriteInfo->RotScale == 2) + continue; + + prio = spriteInfo->Priority; + + + if (spriteInfo->RotScale & 1) + { + s32 fieldX, fieldY, auxX, auxY, realX, realY, offset; + u8 blockparameter, *pal; + s16 dx, dmx, dy, dmy; + u16 colour; + + // Get sprite positions and size + sprX = (spriteInfo->X<<23)>>23; + sprY = spriteInfo->Y; + sprSize = sprSizeTab[spriteInfo->Size][spriteInfo->Shape]; + + lg = sprSize.x; + + if (sprY>=192) + sprY = (s32)((s8)(spriteInfo->Y)); + + // Copy sprite size, to check change it if needed + fieldX = sprSize.x; + fieldY = sprSize.y; + + // If we are using double size mode, double our control vars + if (spriteInfo->RotScale & 2) + { + fieldX <<= 1; + fieldY <<= 1; + lg <<= 1; + } + + //check if the sprite is visible y-wise. unfortunately our logic for x and y is different due to our scanline based rendering + //tested thoroughly by many large sprites in Super Robot Wars K which wrap around the screen + y = (l - sprY)&255; + if(y >= fieldY) + continue; + + //check if sprite is visible x-wise. + if((sprX==256) || (sprX+fieldX<=0)) + continue; + + cost += sprSize.x*2 + 10; + + // Get which four parameter block is assigned to this sprite + blockparameter = (spriteInfo->RotScalIndex + (spriteInfo->HFlip<< 3) + (spriteInfo->VFlip << 4))*4; + + // Get rotation/scale parameters +#ifdef WORDS_BIGENDIAN + dx = ((s16)(gpu->oam + blockparameter+0)->attr31 << 8) | ((s16)(gpu->oam + blockparameter+0)->attr30); + dmx = ((s16)(gpu->oam + blockparameter+1)->attr31 << 8) | ((s16)(gpu->oam + blockparameter+1)->attr30); + dy = ((s16)(gpu->oam + blockparameter+2)->attr31 << 8) | ((s16)(gpu->oam + blockparameter+2)->attr30); + dmy = ((s16)(gpu->oam + blockparameter+3)->attr31 << 8) | ((s16)(gpu->oam + blockparameter+3)->attr30); +#else + dx = (s16)(gpu->oam + blockparameter+0)->attr3; + dmx = (s16)(gpu->oam + blockparameter+1)->attr3; + dy = (s16)(gpu->oam + blockparameter+2)->attr3; + dmy = (s16)(gpu->oam + blockparameter+3)->attr3; +#endif + + // Calculate fixed poitn 8.8 start offsets + realX = ((sprSize.x) << 7) - (fieldX >> 1)*dx - (fieldY>>1)*dmx + y * dmx; + realY = ((sprSize.y) << 7) - (fieldX >> 1)*dy - (fieldY>>1)*dmy + y * dmy; + + if(sprX<0) + { + // If sprite is not in the window + if(sprX + fieldX <= 0) + continue; + + // Otherwise, is partially visible + lg += sprX; + realX -= sprX*dx; + realY -= sprX*dy; + sprX = 0; + } + else + { + if(sprX+fieldX>256) + lg = 256 - sprX; + } + + // If we are using 1 palette of 256 colours + if(spriteInfo->Depth) + { + src = (u8 *)MMU_gpu_map(gpu->sprMem + (spriteInfo->TileIndex << block)); + + // If extended palettes are set, use them + if (dispCnt->ExOBJPalette_Enable) + pal = (MMU.ObjExtPal[gpu->core][0]+(spriteInfo->PaletteIndex*0x200)); + else + pal = (MMU.ARM9_VMEM + 0x200 + gpu->core *0x400); + + for(j = 0; j < lg; ++j, ++sprX) + { + // Get the integer part of the fixed point 8.8, and check if it lies inside the sprite data + auxX = (realX>>8); + auxY = (realY>>8); + + if (auxX >= 0 && auxY >= 0 && auxX < sprSize.x && auxY < sprSize.y) + { + if(MODE == SPRITE_2D) + offset = (auxX&0x7) + ((auxX&0xFFF8)<<3) + ((auxY>>3)<<10) + ((auxY&0x7)*8); + else + offset = (auxX&0x7) + ((auxX&0xFFF8)<<3) + ((auxY>>3)*sprSize.x*8) + ((auxY&0x7)*8); + + colour = src[offset]; + + if (colour && (prioMode; + prioTab[sprX] = prio; + } + } + + // Add the rotation/scale coeficients, here the rotation/scaling + // is performed + realX += dx; + realY += dy; + } + + continue; + } + // Rotozoomed direct color + else if(spriteInfo->Mode == 3) + { + //transparent (i think, dont bother to render?) if alpha is 0 + if(spriteInfo->PaletteIndex == 0) + continue; + + srcadr = bmp_sprite_address(this,spriteInfo,sprSize,0); + + for(j = 0; j < lg; ++j, ++sprX) + { + // Get the integer part of the fixed point 8.8, and check if it lies inside the sprite data + auxX = (realX>>8); + auxY = (realY>>8); + + //this is all very slow, and so much dup code with other rotozoomed modes. + //dont bother fixing speed until this whole thing gets reworked + + if (auxX >= 0 && auxY >= 0 && auxX < sprSize.x && auxY < sprSize.y) + { + if(dispCnt->OBJ_BMP_2D_dim) + //tested by knights in the nightmare + offset = (bmp_sprite_address(this,spriteInfo,sprSize,auxY)-srcadr)/2+auxX; + else //tested by lego indiana jones (somehow?) + //tested by buffy sacrifice damage blood splatters in corner + offset = auxX + (auxY*sprSize.x); + + + u16* mem = (u16*)MMU_gpu_map(srcadr + (offset<<1)); + + colour = T1ReadWord(mem,0); + + if((colour&0x8000) && (prioPaletteIndex; + typeTab[sprX] = spriteInfo->Mode; + prioTab[sprX] = prio; + } + } + + // Add the rotation/scale coeficients, here the rotation/scaling + // is performed + realX += dx; + realY += dy; + } + + continue; + } + // Rotozoomed 16/16 palette + else + { + if(MODE == SPRITE_2D) + { + src = (u8 *)MMU_gpu_map(gpu->sprMem + (spriteInfo->TileIndex<<5)); + pal = MMU.ARM9_VMEM + 0x200 + (gpu->core*0x400 + (spriteInfo->PaletteIndex*32)); + } + else + { + src = (u8 *)MMU_gpu_map(gpu->sprMem + (spriteInfo->TileIndex<sprBoundary)); + pal = MMU.ARM9_VMEM + 0x200 + gpu->core*0x400 + (spriteInfo->PaletteIndex*32); + } + + for(j = 0; j < lg; ++j, ++sprX) + { + // Get the integer part of the fixed point 8.8, and check if it lies inside the sprite data + auxX = (realX>>8); + auxY = (realY>>8); + + if (auxX >= 0 && auxY >= 0 && auxX < sprSize.x && auxY < sprSize.y) + { + if(MODE == SPRITE_2D) + offset = ((auxX>>1)&0x3) + (((auxX>>1)&0xFFFC)<<3) + ((auxY>>3)<<10) + ((auxY&0x7)*4); + else + offset = ((auxX>>1)&0x3) + (((auxX>>1)&0xFFFC)<<3) + ((auxY>>3)*sprSize.x)*4 + ((auxY&0x7)*4); + + colour = src[offset]; + + // Get 4bits value from the readed 8bits + if (auxX&1) colour >>= 4; + else colour &= 0xF; + + if(colour && (prioMode==2) + sprWin[sprX] = 1; + else + { + HostWriteWord(dst, (sprX<<1), LE_TO_LOCAL_16(HostReadWord(pal, colour << 1))); + dst_alpha[sprX] = 16; + typeTab[sprX] = spriteInfo->Mode; + prioTab[sprX] = prio; + } + } + } + + // Add the rotation/scale coeficients, here the rotation/scaling + // is performed + realX += dx; + realY += dy; + } + + continue; + } + } + else //NOT rotozoomed + { + u16 * pal; + + if (!compute_sprite_vars(spriteInfo, l, sprSize, sprX, sprY, x, y, lg, xdir)) + continue; + + cost += sprSize.x; + + if (spriteInfo->Mode == 2) + { + if(MODE == SPRITE_2D) + { + if (spriteInfo->Depth) + src = (u8 *)MMU_gpu_map(gpu->sprMem + ((spriteInfo->TileIndex)<<5) + ((y>>3)<<10) + ((y&0x7)*8)); + else + src = (u8 *)MMU_gpu_map(gpu->sprMem + ((spriteInfo->TileIndex)<<5) + ((y>>3)<<10) + ((y&0x7)*4)); + } + else + { + if (spriteInfo->Depth) + src = (u8 *)MMU_gpu_map(gpu->sprMem + (spriteInfo->TileIndex<>3)*sprSize.x*8) + ((y&0x7)*8)); + else + src = (u8 *)MMU_gpu_map(gpu->sprMem + (spriteInfo->TileIndex<>3)*sprSize.x*4) + ((y&0x7)*4)); + } + + render_sprite_Win (gpu, l, src, spriteInfo->Depth, lg, sprX, x, xdir); + continue; + } + + if (spriteInfo->Mode == 3) //sprite is in BMP format + { + srcadr = bmp_sprite_address(this,spriteInfo,sprSize, y); + + //transparent (i think, dont bother to render?) if alpha is 0 + if(spriteInfo->PaletteIndex == 0) + continue; + + render_sprite_BMP (gpu, i, l, dst, srcadr, dst_alpha, typeTab, prioTab, prio, lg, sprX, x, xdir, spriteInfo->PaletteIndex); + continue; + } + + if(spriteInfo->Depth) //256 colors + { + if(MODE == SPRITE_2D) + srcadr = gpu->sprMem + ((spriteInfo->TileIndex)<<5) + ((y>>3)<<10) + ((y&0x7)*8); + else + srcadr = gpu->sprMem + (spriteInfo->TileIndex<>3)*sprSize.x*8) + ((y&0x7)*8); + + if (dispCnt->ExOBJPalette_Enable) + pal = (u16*)(MMU.ObjExtPal[gpu->core][0]+(spriteInfo->PaletteIndex*0x200)); + else + pal = (u16*)(MMU.ARM9_VMEM + 0x200 + gpu->core *0x400); + + render_sprite_256(gpu, i, l, dst, srcadr, pal, dst_alpha, typeTab, prioTab, prio, lg, sprX, x, xdir, spriteInfo->Mode == 1); + + continue; + } + + // 16 colors + if(MODE == SPRITE_2D) + { + srcadr = gpu->sprMem + ((spriteInfo->TileIndex)<<5) + ((y>>3)<<10) + ((y&0x7)*4); + } + else + { + srcadr = gpu->sprMem + (spriteInfo->TileIndex<>3)*sprSize.x*4) + ((y&0x7)*4); + } + + pal = (u16*)(MMU.ARM9_VMEM + 0x200 + gpu->core * 0x400); + + pal += (spriteInfo->PaletteIndex<<4); + + render_sprite_16 (gpu, l, dst, srcadr, pal, dst_alpha, typeTab, prioTab, prio, lg, sprX, x, xdir, spriteInfo->Mode == 1); + } + } + +//#ifdef WORDS_BIGENDIAN +// *(((u16*)spriteInfo)+1) = (*(((u16*)spriteInfo)+1) << 1) | *(((u16*)spriteInfo)+1) >> 15; +// *(((u16*)spriteInfo)+2) = (*(((u16*)spriteInfo)+2) << 2) | *(((u16*)spriteInfo)+2) >> 14; +//#endif + +} + + +/*****************************************************************************/ +// SCREEN FUNCTIONS +/*****************************************************************************/ + +int Screen_Init(int coreid) +{ + MainScreen.gpu = GPU_Init(0); + SubScreen.gpu = GPU_Init(1); + + memset(GPU_screen, 0, sizeof(GPU_screen)); + for(int i = 0; i < (256*192*2); i++) + ((u16*)GPU_screen)[i] = 0x7FFF; + disp_fifo.head = disp_fifo.tail = 0; + + if (osd) {delete osd; osd =NULL; } + osd = new OSDCLASS(-1); + + return GPU_ChangeGraphicsCore(coreid); +} + +void Screen_Reset(void) +{ + GPU_Reset(MainScreen.gpu, 0); + GPU_Reset(SubScreen.gpu, 1); + + memset(GPU_screen, 0, sizeof(GPU_screen)); + for(int i = 0; i < (256*192*2); i++) + ((u16*)GPU_screen)[i] = 0x7FFF; + + disp_fifo.head = disp_fifo.tail = 0; + osd->clear(); +} + +void Screen_DeInit(void) +{ + GPU_DeInit(MainScreen.gpu); + GPU_DeInit(SubScreen.gpu); + + if (GFXCore) + GFXCore->DeInit(); + + if (osd) {delete osd; osd =NULL; } +} + +/*****************************************************************************/ +// GRAPHICS CORE +/*****************************************************************************/ + +// This is for future graphics core switching. This is by no means set in stone + +int GPU_ChangeGraphicsCore(int coreid) +{ + int i; + + // Make sure the old core is freed + if (GFXCore) + GFXCore->DeInit(); + + // So which core do we want? + if (coreid == GFXCORE_DEFAULT) + coreid = 0; // Assume we want the first one + + // Go through core list and find the id + for (i = 0; GFXCoreList[i] != NULL; i++) + { + if (GFXCoreList[i]->id == coreid) + { + // Set to current core + GFXCore = GFXCoreList[i]; + break; + } + } + + if (GFXCore == NULL) + { + GFXCore = &GFXDummy; + return -1; + } + + if (GFXCore->Init() == -1) + { + // Since it failed, instead of it being fatal, we'll just use the dummy + // core instead + GFXCore = &GFXDummy; + } + + return 0; +} + +int GFXDummyInit(); +void GFXDummyDeInit(); +void GFXDummyResize(int width, int height, BOOL fullscreen); +void GFXDummyOnScreenText(char *string, ...); + +GraphicsInterface_struct GFXDummy = { +GFXCORE_DUMMY, +"Dummy Graphics Interface", +0, +GFXDummyInit, +GFXDummyDeInit, +GFXDummyResize, +GFXDummyOnScreenText +}; + +int GFXDummyInit() +{ + return 0; +} + +void GFXDummyDeInit() +{ +} + +void GFXDummyResize(int width, int height, BOOL fullscreen) +{ +} + +void GFXDummyOnScreenText(char *string, ...) +{ +} + + +/*****************************************************************************/ +// GPU_RenderLine +/*****************************************************************************/ + +void GPU_set_DISPCAPCNT(u32 val) +{ + GPU * gpu = MainScreen.gpu; + struct _DISPCNT * dispCnt = &(gpu->dispx_st)->dispx_DISPCNT.bits; + + gpu->dispCapCnt.val = val; + gpu->dispCapCnt.EVA = std::min((u32)16, (val & 0x1F)); + gpu->dispCapCnt.EVB = std::min((u32)16, ((val >> 8) & 0x1F)); + gpu->dispCapCnt.writeBlock = (val >> 16) & 0x03; + gpu->dispCapCnt.writeOffset = (val >> 18) & 0x03; + gpu->dispCapCnt.readBlock = dispCnt->VRAM_Block; + + if (dispCnt->DisplayMode == 2) + gpu->dispCapCnt.readOffset = 0; + else + gpu->dispCapCnt.readOffset = (val >> 26) & 0x03; + + gpu->dispCapCnt.srcA = (val >> 24) & 0x01; + gpu->dispCapCnt.srcB = (val >> 25) & 0x01; + gpu->dispCapCnt.capSrc = (val >> 29) & 0x03; + + switch((val >> 20) & 0x03) + { + case 0: + gpu->dispCapCnt.capx = DISPCAPCNT::_128; + gpu->dispCapCnt.capy = 128; + break; + case 1: + gpu->dispCapCnt.capx = DISPCAPCNT::_256; + gpu->dispCapCnt.capy = 64; + break; + case 2: + gpu->dispCapCnt.capx = DISPCAPCNT::_256; + gpu->dispCapCnt.capy = 128; + break; + case 3: + gpu->dispCapCnt.capx = DISPCAPCNT::_256; + gpu->dispCapCnt.capy = 192; + break; + } + + /*INFO("Capture 0x%X:\n EVA=%i, EVB=%i, wBlock=%i, wOffset=%i, capX=%i, capY=%i\n rBlock=%i, rOffset=%i, srcCap=%i, dst=0x%X, src=0x%X\n srcA=%i, srcB=%i\n\n", + val, gpu->dispCapCnt.EVA, gpu->dispCapCnt.EVB, gpu->dispCapCnt.writeBlock, gpu->dispCapCnt.writeOffset, + gpu->dispCapCnt.capx, gpu->dispCapCnt.capy, gpu->dispCapCnt.readBlock, gpu->dispCapCnt.readOffset, + gpu->dispCapCnt.capSrc, gpu->dispCapCnt.dst - MMU.ARM9_LCD, gpu->dispCapCnt.src - MMU.ARM9_LCD, + gpu->dispCapCnt.srcA, gpu->dispCapCnt.srcB);*/ +} + +static void GPU_RenderLine_layer(NDS_Screen * screen, u16 l) +{ + CACHE_ALIGN u8 spr[512]; + CACHE_ALIGN u8 sprAlpha[256]; + CACHE_ALIGN u8 sprType[256]; + CACHE_ALIGN u8 sprPrio[256]; + + GPU * gpu = screen->gpu; + struct _DISPCNT * dispCnt = &(gpu->dispx_st)->dispx_DISPCNT.bits; + itemsForPriority_t * item; + u16 i16; + BOOL BG_enabled = TRUE; + + gpu->currentFadeInColors = &fadeInColors[gpu->BLDY_EVY][0]; + gpu->currentFadeOutColors = &fadeOutColors[gpu->BLDY_EVY][0]; + + u16 backdrop_color = T1ReadWord(MMU.ARM9_VMEM, gpu->core * 0x400) & 0x7FFF; + + //we need to write backdrop colors in the same way as we do BG pixels in order to do correct window processing + //this is currently eating up 2fps or so. it is a reasonable candidate for optimization. + gpu->currBgNum = 5; + switch(gpu->setFinalColorBck_funcNum) + { + //for backdrops, blend isnt applied (it's illogical, isnt it?) + case 0: + case 1: + memset_u16_le<256>(gpu->currDst,backdrop_color); + break; + + //for backdrops, fade in and fade out can be applied if it's a 1st target screen + case 2: + if(gpu->BLDCNT & 0x20) //backdrop is selected for color effect + memset_u16_le<256>(gpu->currDst,gpu->currentFadeInColors[backdrop_color]); + break; + case 3: + if(gpu->BLDCNT & 0x20) //backdrop is selected for color effect + memset_u16_le<256>(gpu->currDst,gpu->currentFadeOutColors[backdrop_color]); + break; + + //windowed cases apparently need special treatment? why? can we not render the backdrop? how would that even work? + case 4: for(int x=0;x<256;x++) gpu->___setFinalColorBck(backdrop_color,x,1); break; + case 5: for(int x=0;x<256;x++) gpu->___setFinalColorBck(backdrop_color,x,1); break; + case 6: for(int x=0;x<256;x++) gpu->___setFinalColorBck(backdrop_color,x,1); break; + case 7: for(int x=0;x<256;x++) gpu->___setFinalColorBck(backdrop_color,x,1); break; + } + + memset(gpu->bgPixels,5,256); + + // init background color & priorities + memset(sprAlpha, 0, 256); + memset(sprType, 0, 256); + memset(sprPrio, 0xFF, 256); + memset(sprWin, 0, 256); + + // init pixels priorities + assert(NB_PRIORITIES==4); + gpu->itemsForPriority[0].nbPixelsX = 0; + gpu->itemsForPriority[1].nbPixelsX = 0; + gpu->itemsForPriority[2].nbPixelsX = 0; + gpu->itemsForPriority[3].nbPixelsX = 0; + + // for all the pixels in the line + if (gpu->LayersEnable[4]) + { + //n.b. - this is clearing the sprite line buffer to the background color, + //but it has been changed to write u32 instead of u16 for a little speedup + for(int i = 0; i< 128; ++i) HostWriteTwoWords(spr, i << 2, backdrop_color | (backdrop_color<<16)); + //zero 06-may-09: I properly supported window color effects for backdrop, but I am not sure + //how it interacts with this. I wish we knew why we needed this + + gpu->spriteRender(spr, sprAlpha, sprType, sprPrio); + mosaicSpriteLine(gpu, l, spr, sprAlpha, sprType, sprPrio); + + for(int i = 0; i<256; i++) + { + // assign them to the good priority item + int prio = sprPrio[i]; + if (prio >=4) continue; + + item = &(gpu->itemsForPriority[prio]); + item->PixelsX[item->nbPixelsX]=i; + item->nbPixelsX++; + } + } + + + if (!gpu->LayersEnable[0] && !gpu->LayersEnable[1] && !gpu->LayersEnable[2] && !gpu->LayersEnable[3]) + BG_enabled = FALSE; + + for(int j=0;j<8;j++) + gpu->blend2[j] = (gpu->BLDCNT & (0x100 << j))!=0; + + // paint lower priorities first + // then higher priorities on top + for(int prio=NB_PRIORITIES; prio > 0; ) + { + prio--; + item = &(gpu->itemsForPriority[prio]); + // render BGs + if (BG_enabled) + { + for (int i=0; i < item->nbBGs; i++) + { + i16 = item->BGs[i]; + if (gpu->LayersEnable[i16]) + { + gpu->currBgNum = (u8)i16; + gpu->blend1 = (gpu->BLDCNT & (1 << gpu->currBgNum))!=0; + + struct _BGxCNT *bgCnt = &(gpu->dispx_st)->dispx_BGxCNT[i16].bits; + gpu->curr_mosaic_enabled = bgCnt->Mosaic_Enable; + + if (gpu->core == GPU_MAIN) + { + if (i16 == 0 && dispCnt->BG0_3D) + { + gpu->currBgNum = 0; + + const u16 hofs = gpu->getHOFS(i16); + + gfx3d_GetLineData(l, &gpu->_3dColorLine); + u8* colorLine = gpu->_3dColorLine; + + for(int k = 0; k < 256; k++) + { + int q = ((k + hofs) & 0x1FF); + + if((q < 0) || (q > 255)) + continue; + + if(colorLine[(q<<2)+3]) + gpu->setFinalColor3d(k, q); + } + + continue; + } + } + + //useful for debugging individual layers + //if(gpu->core == 1 || i16 != 2) continue; + + + + +#ifndef DISABLE_MOSAIC + if(gpu->curr_mosaic_enabled) + gpu->modeRender(i16); + else +#endif + gpu->modeRender(i16); + } //layer enabled + } + } + + // render sprite Pixels + if (gpu->LayersEnable[4]) + { + gpu->currBgNum = 4; + gpu->blend1 = (gpu->BLDCNT & (1 << gpu->currBgNum))!=0; + + for (int i=0; i < item->nbPixelsX; i++) + { + i16=item->PixelsX[i]; + setFinalColorSpr(gpu, gpu->currDst, HostReadWord(spr, (i16<<1)), sprAlpha[i16], sprType[i16], i16); + } + } + } +} + +template static void GPU_RenderLine_DispCapture(u16 l) +{ + //this macro takes advantage of the fact that there are only two possible values for capx + #define CAPCOPY(SRC,DST,SETALPHABIT) \ + switch(gpu->dispCapCnt.capx) { \ + case DISPCAPCNT::_128: \ + for (int i = 0; i < 128; i++) \ + HostWriteWord(DST, i << 1, HostReadWord(SRC, i << 1) | (SETALPHABIT?(1<<15):0)); \ + break; \ + case DISPCAPCNT::_256: \ + for (int i = 0; i < 256; i++) \ + HostWriteWord(DST, i << 1, HostReadWord(SRC, i << 1) | (SETALPHABIT?(1<<15):0)); \ + break; \ + default: assert(false); \ + } + + GPU * gpu = MainScreen.gpu; + + if (l == 0) + { + if (gpu->dispCapCnt.val & 0x80000000) + { + gpu->dispCapCnt.enabled = TRUE; + T1WriteLong(MMU.ARM9_REG, 0x64, gpu->dispCapCnt.val); + } + } + + bool skip = SKIP; + + if (gpu->dispCapCnt.enabled) + { + //128-wide captures should write linearly into memory, with no gaps + //this is tested by hotel dusk + u32 ofsmul = gpu->dispCapCnt.capx==DISPCAPCNT::_128?256:512; + u32 cap_src_adr = gpu->dispCapCnt.readOffset * 0x8000 + (l * 512); + u32 cap_dst_adr = gpu->dispCapCnt.writeOffset * 0x8000 + (l * ofsmul); + + //Read/Write block wrap to 00000h when exceeding 1FFFFh (128k) + //this has not been tested yet (I thought I needed it for hotel dusk, but it was fixed by the above) + cap_src_adr &= 0x1FFFF; + cap_dst_adr &= 0x1FFFF; + + cap_src_adr += gpu->dispCapCnt.readBlock * 0x20000; + cap_dst_adr += gpu->dispCapCnt.writeBlock * 0x20000; + + u8* cap_src = MMU.ARM9_LCD + cap_src_adr; + u8* cap_dst = MMU.ARM9_LCD + cap_dst_adr; + + //we must block captures when the capture dest is not mapped to LCDC + if(vramConfiguration.banks[gpu->dispCapCnt.writeBlock].purpose != VramConfiguration::LCDC) + skip = true; + + //we must return zero from reads from memory not mapped to lcdc + if(vramConfiguration.banks[gpu->dispCapCnt.readBlock].purpose != VramConfiguration::LCDC) + cap_src = MMU.blank_memory; + + if(!skip) + if (l < gpu->dispCapCnt.capy) + { + switch (gpu->dispCapCnt.capSrc) + { + case 0: // Capture source is SourceA + { + //INFO("Capture source is SourceA\n"); + switch (gpu->dispCapCnt.srcA) + { + case 0: // Capture screen (BG + OBJ + 3D) + { + //INFO("Capture screen (BG + OBJ + 3D)\n"); + + u8 *src; + src = (u8*)(gpu->tempScanline); + CAPCOPY(src,cap_dst,true); + } + break; + case 1: // Capture 3D + { + //INFO("Capture 3D\n"); + u16* colorLine; + gfx3d_GetLineData15bpp(l, &colorLine); + CAPCOPY(((u8*)colorLine),cap_dst,false); + } + break; + } + } + break; + case 1: // Capture source is SourceB + { + //INFO("Capture source is SourceB\n"); + switch (gpu->dispCapCnt.srcB) + { + case 0: + //Capture VRAM + CAPCOPY(cap_src,cap_dst,true); + break; + case 1: + //capture dispfifo + //(not yet tested) + for(int i=0; i < 128; i++) + T1WriteLong(cap_dst, i << 2, DISP_FIFOrecv()); + break; + } + } + break; + default: // Capture source is SourceA+B blended + { + //INFO("Capture source is SourceA+B blended\n"); + u16 *srcA = NULL; + u16 *srcB = NULL; + + if (gpu->dispCapCnt.srcA == 0) + { + // Capture screen (BG + OBJ + 3D) + srcA = (u16*)(gpu->tempScanline); + } + else + { + gfx3d_GetLineData15bpp(l, &srcA); + } + + static u16 fifoLine[256]; + + if (gpu->dispCapCnt.srcB == 0) // VRAM screen + srcB = (u16 *)cap_src; + else + { + //fifo - tested by splinter cell chaos theory thermal view + srcB = fifoLine; + for (int i=0; i < 128; i++) + T1WriteLong((u8*)srcB, i << 2, DISP_FIFOrecv()); + } + + + const int todo = (gpu->dispCapCnt.capx==DISPCAPCNT::_128?128:256); + + for(u16 i = 0; i < todo; i++) + { + u16 a,r,g,b; + + u16 a_alpha = srcA[i] & 0x8000; + u16 b_alpha = srcB[i] & 0x8000; + + if(a_alpha) + { + a = 0x8000; + r = ((srcA[i] & 0x1F) * gpu->dispCapCnt.EVA); + g = (((srcA[i] >> 5) & 0x1F) * gpu->dispCapCnt.EVA); + b = (((srcA[i] >> 10) & 0x1F) * gpu->dispCapCnt.EVA); + } + else + a = r = g = b = 0; + + if(b_alpha) + { + a = 0x8000; + r += ((srcB[i] & 0x1F) * gpu->dispCapCnt.EVB); + g += (((srcB[i] >> 5) & 0x1F) * gpu->dispCapCnt.EVB); + b += (((srcB[i] >> 10) & 0x1F) * gpu->dispCapCnt.EVB); + } + + r >>= 4; + g >>= 4; + b >>= 4; + + //freedom wings sky will overflow while doing some fsaa/motionblur effect without this + r = std::min((u16)31,r); + g = std::min((u16)31,g); + b = std::min((u16)31,b); + + HostWriteWord(cap_dst, i << 1, a | (b << 10) | (g << 5) | r); + } + } + break; + } + } + + if (l>=191) + { + gpu->dispCapCnt.enabled = FALSE; + gpu->dispCapCnt.val &= 0x7FFFFFFF; + T1WriteLong(MMU.ARM9_REG, 0x64, gpu->dispCapCnt.val); + return; + } + } +} + +static INLINE void GPU_RenderLine_MasterBrightness(NDS_Screen * screen, u16 l) +{ + GPU * gpu = screen->gpu; + + u8 * dst = GPU_screen + (screen->offset + l) * 512; + u16 i16; + + //isn't it odd that we can set uselessly high factors here? + //factors above 16 change nothing. curious. + int factor = gpu->MasterBrightFactor; + if(factor==0) return; + if(factor>16) factor=16; + + + //Apply final brightness adjust (MASTER_BRIGHT) + //http://nocash.emubase.de/gbatek.htm#dsvideo (Under MASTER_BRIGHTNESS) + + switch (gpu->MasterBrightMode) + { + // Disabled + case 0: + break; + + // Bright up + case 1: + { + if(factor != 16) + { + for(i16 = 0; i16 < 256; ++i16) + { + ((u16*)dst)[i16] = fadeInColors[factor][((u16*)dst)[i16]&0x7FFF]; + } + } + else + { + // all white (optimization) + for(i16 = 0; i16 < 256; ++i16) + ((u16*)dst)[i16] = 0x7FFF; + } + break; + } + + // Bright down + case 2: + { + if(factor != 16) + { + for(i16 = 0; i16 < 256; ++i16) + { + ((u16*)dst)[i16] = fadeOutColors[factor][((u16*)dst)[i16]&0x7FFF]; + } + } + else + { + // all black (optimization) + memset(dst, 0, 512); + } + break; + } + + // Reserved + case 3: + break; + } + +} + +template +FORCEINLINE void GPU::setup_windows() +{ + u8 y = currLine; + u16 startY,endY; + + if(WIN_NUM==0) + { + startY = WIN0V0; + endY = WIN0V1; + } + else + { + startY = WIN1V0; + endY = WIN1V1; + } + + if(WIN_NUM == 0 && !WIN0_ENABLED) goto allout; + if(WIN_NUM == 1 && !WIN1_ENABLED) goto allout; + + if(startY > endY) + { + if((y < startY) && (y > endY)) goto allout; + } + else + { + if((y < startY) || (y >= endY)) goto allout; + } + + //the x windows will apply for this scanline + curr_win[WIN_NUM] = h_win[WIN_NUM]; + return; + +allout: + curr_win[WIN_NUM] = win_empty; +} + +void GPU::update_winh(int WIN_NUM) +{ + //dont even waste any time in here if the window isnt enabled + if(WIN_NUM==0 && !WIN0_ENABLED) return; + if(WIN_NUM==1 && !WIN1_ENABLED) return; + + need_update_winh[WIN_NUM] = false; + u16 startX,endX; + + if(WIN_NUM==0) + { + startX = WIN0H0; + endX = WIN0H1; + } + else + { + startX = WIN1H0; + endX = WIN1H1; + } + + //the original logic: if you doubt the window code, please check it against the newer implementation below + //if(startX > endX) + //{ + // if((x < startX) && (x > endX)) return false; + //} + //else + //{ + // if((x < startX) || (x >= endX)) return false; + //} + + if(startX > endX) + { + for(int i=0;i<=endX;i++) + h_win[WIN_NUM][i] = 1; + for(int i=endX+1;igpu; + + //here is some setup which is only done on line 0 + if(l == 0) { + //this is speculative. the idea is as follows: + //whenever the user updates the affine start position regs, it goes into the active regs immediately + //(this is handled on the set event from MMU) + //maybe it shouldnt take effect until the next hblank or something.. + //this is a based on a combination of: + //heroes of mana intro FMV + //SPP level 3-8 rotoscale room + //NSMB raster fx backdrops + //bubble bobble revolution classic mode + //NOTE: + //I am REALLY unsatisfied with this logic now. But it seems to be working.. + gpu->refreshAffineStartRegs(-1,-1); + } + + if(skip) + { + gpu->currLine = l; + if (gpu->core == GPU_MAIN) + { + GPU_RenderLine_DispCapture(l); + if (l == 191) { disp_fifo.head = disp_fifo.tail = 0; } + } + return; + } + + //blacken the screen if it is turned off by the user + if(!CommonSettings.showGpu.screens[gpu->core]) + { + u8 * dst = GPU_screen + (screen->offset + l) * 512; + memset(dst,0,512); + return; + } + + // skip some work if master brightness makes the screen completely white or completely black + if(gpu->MasterBrightFactor >= 16 && (gpu->MasterBrightMode == 1 || gpu->MasterBrightMode == 2)) + { + // except if it could cause any side effects (for example if we're capturing), then don't skip anything + if(!(gpu->core == GPU_MAIN && (gpu->dispCapCnt.enabled || l == 0 || l == 191))) + { + gpu->currLine = l; + GPU_RenderLine_MasterBrightness(screen, l); + return; + } + } + + //cache some parameters which are assumed to be stable throughout the rendering of the entire line + gpu->currLine = l; + u16 mosaic_control = T1ReadWord((u8 *)&gpu->dispx_st->dispx_MISC.MOSAIC, 0); + u16 mosaic_width = (mosaic_control & 0xF); + u16 mosaic_height = ((mosaic_control>>4) & 0xF); + + //mosaic test hacks + //mosaic_width = mosaic_height = 3; + + GPU::mosaicLookup.widthValue = mosaic_width; + GPU::mosaicLookup.heightValue = mosaic_height; + GPU::mosaicLookup.width = &GPU::mosaicLookup.table[mosaic_width][0]; + GPU::mosaicLookup.height = &GPU::mosaicLookup.table[mosaic_height][0]; + + if(gpu->need_update_winh[0]) gpu->update_winh(0); + if(gpu->need_update_winh[1]) gpu->update_winh(1); + + gpu->setup_windows<0>(); + gpu->setup_windows<1>(); + + //generate the 2d engine output + if(gpu->dispMode == 1) { + //optimization: render straight to the output buffer when thats what we are going to end up displaying anyway + gpu->tempScanline = screen->gpu->currDst = (u8 *)(GPU_screen) + (screen->offset + l) * 512; + } else { + //otherwise, we need to go to a temp buffer + gpu->tempScanline = screen->gpu->currDst = (u8 *)gpu->tempScanlineBuffer; + } + + GPU_RenderLine_layer(screen, l); + + switch (gpu->dispMode) + { + case 0: // Display Off(Display white) + { + u8 * dst = GPU_screen + (screen->offset + l) * 512; + + for (int i=0; i<256; i++) + HostWriteWord(dst, i << 1, 0x7FFF); + } + break; + + case 1: // Display BG and OBJ layers + //do nothing: it has already been generated into the right place + break; + + case 2: // Display vram framebuffer + { + u8 * dst = GPU_screen + (screen->offset + l) * 512; + u8 * src = gpu->VRAMaddr + (l*512); + memcpy (dst, src, 512); + } + break; + case 3: // Display memory FIFO + { + //this has not been tested since the dma timing for dispfifo was changed around the time of + //newemuloop. it may not work. + u8 * dst = GPU_screen + (screen->offset + l) * 512; + for (int i=0; i < 128; i++) + T1WriteLong(dst, i << 2, DISP_FIFOrecv() & 0x7FFF7FFF); + } + break; + } + + //capture after displaying so that we can safely display vram before overwriting it here + if (gpu->core == GPU_MAIN) + { + //BUG!!! if someone is capturing and displaying both from the fifo, then it will have been + //consumed above by the display before we get here + //(is that even legal? i think so) + GPU_RenderLine_DispCapture(l); + if (l == 191) { disp_fifo.head = disp_fifo.tail = 0; } + } + + + GPU_RenderLine_MasterBrightness(screen, l); +} + +void gpu_savestate(EMUFILE* os) +{ + //version + write32le(1,os); + + os->fwrite((char*)GPU_screen,sizeof(GPU_screen)); + + write32le(MainScreen.gpu->affineInfo[0].x,os); + write32le(MainScreen.gpu->affineInfo[0].y,os); + write32le(MainScreen.gpu->affineInfo[1].x,os); + write32le(MainScreen.gpu->affineInfo[1].y,os); + write32le(SubScreen.gpu->affineInfo[0].x,os); + write32le(SubScreen.gpu->affineInfo[0].y,os); + write32le(SubScreen.gpu->affineInfo[1].x,os); + write32le(SubScreen.gpu->affineInfo[1].y,os); +} + +bool gpu_loadstate(EMUFILE* is, int size) +{ + //read version + u32 version; + + //sigh.. shouldve used a new version number + if(size == 256*192*2*2) + version = 0; + else if(size== 0x30024) + { + read32le(&version,is); + version = 1; + } + else + if(read32le(&version,is) != 1) return false; + + + if(version<0||version>1) return false; + + is->fread((char*)GPU_screen,sizeof(GPU_screen)); + + if(version==1) + { + read32le(&MainScreen.gpu->affineInfo[0].x,is); + read32le(&MainScreen.gpu->affineInfo[0].y,is); + read32le(&MainScreen.gpu->affineInfo[1].x,is); + read32le(&MainScreen.gpu->affineInfo[1].y,is); + read32le(&SubScreen.gpu->affineInfo[0].x,is); + read32le(&SubScreen.gpu->affineInfo[0].y,is); + read32le(&SubScreen.gpu->affineInfo[1].x,is); + read32le(&SubScreen.gpu->affineInfo[1].y,is); + //removed per nitsuja feedback. anyway, this same thing will happen almost immediately in gpu line=0 + //MainScreen.gpu->refreshAffineStartRegs(-1,-1); + //SubScreen.gpu->refreshAffineStartRegs(-1,-1); + } + + MainScreen.gpu->updateBLDALPHA(); + SubScreen.gpu->updateBLDALPHA(); + return !is->fail(); +} + +u32 GPU::getAffineStart(int layer, int xy) +{ + if(xy==0) return affineInfo[layer-2].x; + else return affineInfo[layer-2].y; +} + +void GPU::setAffineStartWord(int layer, int xy, u16 val, int word) +{ + u32 curr = getAffineStart(layer,xy); + if(word==0) curr = (curr&0xFFFF0000)|val; + else curr = (curr&0x0000FFFF)|(((u32)val)<<16); + setAffineStart(layer,xy,curr); +} + +void GPU::setAffineStart(int layer, int xy, u32 val) +{ + if(xy==0) affineInfo[layer-2].x = val; + else affineInfo[layer-2].y = val; + refreshAffineStartRegs(layer,xy); +} + +void GPU::refreshAffineStartRegs(const int num, const int xy) +{ + if(num==-1) + { + refreshAffineStartRegs(2,xy); + refreshAffineStartRegs(3,xy); + return; + } + + if(xy==-1) + { + refreshAffineStartRegs(num,0); + refreshAffineStartRegs(num,1); + return; + } + + BGxPARMS * parms; + if (num==2) + parms = &(dispx_st)->dispx_BG2PARMS; + else + parms = &(dispx_st)->dispx_BG3PARMS; + + if(xy==0) + parms->BGxX = affineInfo[num-2].x; + else + parms->BGxY = affineInfo[num-2].y; +} + +template void GPU::modeRender(int layer) +{ + switch(GPU_mode2type[dispCnt().BG_Mode][layer]) + { + case BGType_Text: lineText(this); break; + case BGType_Affine: lineRot(this); break; + case BGType_AffineExt: lineExtRot(this); break; + case BGType_Large8bpp: lineExtRot(this); break; + case BGType_Invalid: + PROGINFO("Attempting to render an invalid BG type\n"); + break; + default: + break; + } +} + +void gpu_SetRotateScreen(u16 angle) +{ + gpu_angle = angle; +} diff --git a/jni/desmume/src/GPU.h b/jni/desmume/src/GPU.h new file mode 100755 index 0000000..11638df --- /dev/null +++ b/jni/desmume/src/GPU.h @@ -0,0 +1,996 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2006-2007 Theo Berkau + Copyright (C) 2007 shash + Copyright (C) 2009-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ + +#ifndef GPU_H +#define GPU_H + +#include +#include "mem.h" +#include "common.h" +#include "registers.h" +#include "FIFO.h" +#include "MMU.h" +#include + +//#undef FORCEINLINE +//#define FORCEINLINE + +void gpu_savestate(EMUFILE* os); +bool gpu_loadstate(EMUFILE* is, int size); + +/******************************************************************************* + this structure is for display control, + it holds flags for general display +*******************************************************************************/ + +#ifdef WORDS_BIGENDIAN +struct _DISPCNT +{ +/* 7*/ u8 ForceBlank:1; // A+B: +/* 6*/ u8 OBJ_BMP_mapping:1; // A+B: 0=2D (128KB), 1=1D (128..256KB) +/* 5*/ u8 OBJ_BMP_2D_dim:1; // A+B: 0=128x512, 1=256x256 pixels +/* 4*/ u8 OBJ_Tile_mapping:1;// A+B: 0=2D (32KB), 1=1D (32..256KB) +/* 3*/ u8 BG0_3D:1; // A : 0=2D, 1=3D +/* 0*/ u8 BG_Mode:3; // A+B: +/*15*/ u8 WinOBJ_Enable:1; // A+B: 0=disable, 1=Enable +/*14*/ u8 Win1_Enable:1; // A+B: 0=disable, 1=Enable +/*13*/ u8 Win0_Enable:1; // A+B: 0=disable, 1=Enable +/*12*/ u8 OBJ_Enable:1; // A+B: 0=disable, 1=Enable +/*11*/ u8 BG3_Enable:1; // A+B: 0=disable, 1=Enable +/*10*/ u8 BG2_Enable:1; // A+B: 0=disable, 1=Enable +/* 9*/ u8 BG1_Enable:1; // A+B: 0=disable, 1=Enable +/* 8*/ u8 BG0_Enable:1; // A+B: 0=disable, 1=Enable +/*23*/ u8 OBJ_HBlank_process:1; // A+B: OBJ processed during HBlank (GBA bit5) +/*22*/ u8 OBJ_BMP_1D_Bound:1; // A : +/*20*/ u8 OBJ_Tile_1D_Bound:2; // A+B: +/*18*/ u8 VRAM_Block:2; // A : VRAM block (0..3=A..D) + +/*16*/ u8 DisplayMode:2; // A+B: coreA(0..3) coreB(0..1) GBA(Green Swap) + // 0=off (white screen) + // 1=on (normal BG & OBJ layers) + // 2=VRAM display (coreA only) + // 3=RAM display (coreA only, DMA transfers) + +/*31*/ u8 ExOBJPalette_Enable:1; // A+B: 0=disable, 1=Enable OBJ extended Palette +/*30*/ u8 ExBGxPalette_Enable:1; // A+B: 0=disable, 1=Enable BG extended Palette +/*27*/ u8 ScreenBase_Block:3; // A : Screen Base (64K step) +/*24*/ u8 CharacBase_Block:3; // A : Character Base (64K step) +}; +#else +struct _DISPCNT +{ +/* 0*/ u8 BG_Mode:3; // A+B: +/* 3*/ u8 BG0_3D:1; // A : 0=2D, 1=3D +/* 4*/ u8 OBJ_Tile_mapping:1; // A+B: 0=2D (32KB), 1=1D (32..256KB) +/* 5*/ u8 OBJ_BMP_2D_dim:1; // A+B: 0=128x512, 1=256x256 pixels +/* 6*/ u8 OBJ_BMP_mapping:1; // A+B: 0=2D (128KB), 1=1D (128..256KB) + + // 7-15 same as GBA +/* 7*/ u8 ForceBlank:1; // A+B: +/* 8*/ u8 BG0_Enable:1; // A+B: 0=disable, 1=Enable +/* 9*/ u8 BG1_Enable:1; // A+B: 0=disable, 1=Enable +/*10*/ u8 BG2_Enable:1; // A+B: 0=disable, 1=Enable +/*11*/ u8 BG3_Enable:1; // A+B: 0=disable, 1=Enable +/*12*/ u8 OBJ_Enable:1; // A+B: 0=disable, 1=Enable +/*13*/ u8 Win0_Enable:1; // A+B: 0=disable, 1=Enable +/*14*/ u8 Win1_Enable:1; // A+B: 0=disable, 1=Enable +/*15*/ u8 WinOBJ_Enable:1; // A+B: 0=disable, 1=Enable + +/*16*/ u8 DisplayMode:2; // A+B: coreA(0..3) coreB(0..1) GBA(Green Swap) + // 0=off (white screen) + // 1=on (normal BG & OBJ layers) + // 2=VRAM display (coreA only) + // 3=RAM display (coreA only, DMA transfers) + +/*18*/ u8 VRAM_Block:2; // A : VRAM block (0..3=A..D) +/*20*/ u8 OBJ_Tile_1D_Bound:2; // A+B: +/*22*/ u8 OBJ_BMP_1D_Bound:1; // A : +/*23*/ u8 OBJ_HBlank_process:1; // A+B: OBJ processed during HBlank (GBA bit5) +/*24*/ u8 CharacBase_Block:3; // A : Character Base (64K step) +/*27*/ u8 ScreenBase_Block:3; // A : Screen Base (64K step) +/*30*/ u8 ExBGxPalette_Enable:1; // A+B: 0=disable, 1=Enable BG extended Palette +/*31*/ u8 ExOBJPalette_Enable:1; // A+B: 0=disable, 1=Enable OBJ extended Palette +}; +#endif + +typedef union +{ + struct _DISPCNT bits; + u32 val; +} DISPCNT; +#define BGxENABLED(cnt,num) ((num<8)? ((cnt.val>>8) & num):0) + + +enum BlendFunc +{ + None, Blend, Increase, Decrease +}; + + +/******************************************************************************* + this structure is for display control of a specific layer, + there are 4 background layers + their priority indicate which one to draw on top of the other + some flags indicate special drawing mode, size, FX +*******************************************************************************/ + +#ifdef WORDS_BIGENDIAN +struct _BGxCNT +{ +/* 7*/ u8 Palette_256:1; // 0=16x16, 1=1*256 palette +/* 6*/ u8 Mosaic_Enable:1; // 0=disable, 1=Enable mosaic +/* 2*/ u8 CharacBase_Block:4; // individual character base offset (n*16KB) +/* 0*/ u8 Priority:2; // 0..3=high..low +/*14*/ u8 ScreenSize:2; // text : 256x256 512x256 256x512 512x512 + // x/rot/s : 128x128 256x256 512x512 1024x1024 + // bmp : 128x128 256x256 512x256 512x512 + // large : 512x1024 1024x512 - - +/*13*/ u8 PaletteSet_Wrap:1; // BG0 extended palette set 0=set0, 1=set2 + // BG1 extended palette set 0=set1, 1=set3 + // BG2 overflow area wraparound 0=off, 1=wrap + // BG3 overflow area wraparound 0=off, 1=wrap +/* 8*/ u8 ScreenBase_Block:5; // individual screen base offset (text n*2KB, BMP n*16KB) +}; +#else +struct _BGxCNT +{ +/* 0*/ u8 Priority:2; // 0..3=high..low +/* 2*/ u8 CharacBase_Block:4; // individual character base offset (n*16KB) +/* 6*/ u8 Mosaic_Enable:1; // 0=disable, 1=Enable mosaic +/* 7*/ u8 Palette_256:1; // 0=16x16, 1=1*256 palette +/* 8*/ u8 ScreenBase_Block:5; // individual screen base offset (text n*2KB, BMP n*16KB) +/*13*/ u8 PaletteSet_Wrap:1; // BG0 extended palette set 0=set0, 1=set2 + // BG1 extended palette set 0=set1, 1=set3 + // BG2 overflow area wraparound 0=off, 1=wrap + // BG3 overflow area wraparound 0=off, 1=wrap +/*14*/ u8 ScreenSize:2; // text : 256x256 512x256 256x512 512x512 + // x/rot/s : 128x128 256x256 512x512 1024x1024 + // bmp : 128x128 256x256 512x256 512x512 + // large : 512x1024 1024x512 - - +}; +#endif + + +typedef union +{ + struct _BGxCNT bits; + u16 val; +} BGxCNT; + +/******************************************************************************* + this structure is for background offset +*******************************************************************************/ + +typedef struct { + u16 BGxHOFS; + u16 BGxVOFS; +} BGxOFS; + +/******************************************************************************* + this structure is for rotoscale parameters +*******************************************************************************/ + +typedef struct { + s16 BGxPA; + s16 BGxPB; + s16 BGxPC; + s16 BGxPD; + s32 BGxX; + s32 BGxY; +} BGxPARMS; + + +/******************************************************************************* + these structures are for window description, + windows are square regions and can "subclass" + background layers or object layers (i.e window controls the layers) + + screen + | + +-- Window0/Window1/OBJwindow/OutOfWindows + | + +-- BG0/BG1/BG2/BG3/OBJ +*******************************************************************************/ + +typedef union { + struct { + u8 end:8; + u8 start:8; + } bits ; + u16 val; +} WINxDIM; + +#ifdef WORDS_BIGENDIAN +typedef struct { +/* 6*/ u8 :2; +/* 5*/ u8 WINx_Effect_Enable:1; +/* 4*/ u8 WINx_OBJ_Enable:1; +/* 3*/ u8 WINx_BG3_Enable:1; +/* 2*/ u8 WINx_BG2_Enable:1; +/* 1*/ u8 WINx_BG1_Enable:1; +/* 0*/ u8 WINx_BG0_Enable:1; +} WINxBIT; +#else +typedef struct { +/* 0*/ u8 WINx_BG0_Enable:1; +/* 1*/ u8 WINx_BG1_Enable:1; +/* 2*/ u8 WINx_BG2_Enable:1; +/* 3*/ u8 WINx_BG3_Enable:1; +/* 4*/ u8 WINx_OBJ_Enable:1; +/* 5*/ u8 WINx_Effect_Enable:1; +/* 6*/ u8 :2; +} WINxBIT; +#endif + +#ifdef WORDS_BIGENDIAN +typedef union { + struct { + WINxBIT win0; + WINxBIT win1; + } bits; + struct { + u8 :3; + u8 win0_en:5; + u8 :3; + u8 win1_en:5; + } packed_bits; + struct { + u8 low; + u8 high; + } bytes; + u16 val ; +} WINxCNT ; +#else +typedef union { + struct { + WINxBIT win0; + WINxBIT win1; + } bits; + struct { + u8 win0_en:5; + u8 :3; + u8 win1_en:5; + u8 :3; + } packed_bits; + struct { + u8 low; + u8 high; + } bytes; + u16 val ; +} WINxCNT ; +#endif + +/* +typedef struct { + WINxDIM WIN0H; + WINxDIM WIN1H; + WINxDIM WIN0V; + WINxDIM WIN1V; + WINxCNT WININ; + WINxCNT WINOUT; +} WINCNT; +*/ + +/******************************************************************************* + this structure is for miscellanous settings + //TODO: needs further description +*******************************************************************************/ + +typedef struct { + u16 MOSAIC; + u16 unused1; + u16 unused2;//BLDCNT; + u16 unused3;//BLDALPHA; + u16 unused4;//BLDY; + u16 unused5; + /* + u16 unused6; + u16 unused7; + u16 unused8; + u16 unused9; + */ +} MISCCNT; + + +/******************************************************************************* + this structure is for 3D settings +*******************************************************************************/ + +struct _DISP3DCNT +{ +/* 0*/ u8 EnableTexMapping:1; // +/* 1*/ u8 PolygonShading:1; // 0=Toon Shading, 1=Highlight Shading +/* 2*/ u8 EnableAlphaTest:1; // see ALPHA_TEST_REF +/* 3*/ u8 EnableAlphaBlending:1; // see various Alpha values +/* 4*/ u8 EnableAntiAliasing:1; // +/* 5*/ u8 EnableEdgeMarking:1; // see EDGE_COLOR +/* 6*/ u8 FogOnlyAlpha:1; // 0=Alpha and Color, 1=Only Alpha (see FOG_COLOR) +/* 7*/ u8 EnableFog:1; // Fog Master Enable +/* 8*/ u8 FogShiftSHR:4; // 0..10 SHR-Divider (see FOG_OFFSET) +/*12*/ u8 AckColorBufferUnderflow:1; // Color Buffer RDLINES Underflow (0=None, 1=Underflow/Acknowledge) +/*13*/ u8 AckVertexRAMOverflow:1; // Polygon/Vertex RAM Overflow (0=None, 1=Overflow/Acknowledge) +/*14*/ u8 RearPlaneMode:1; // 0=Blank, 1=Bitmap +/*15*/ u8 :1; +/*16*/ u16 :16; +}; + +typedef union +{ + struct _DISP3DCNT bits; + u32 val; +} DISP3DCNT; + +/******************************************************************************* + this structure is for capture control (core A only) + + source: + http://nocash.emubase.de/gbatek.htm#dsvideocaptureandmainmemorydisplaymode +*******************************************************************************/ +struct DISPCAPCNT +{ + enum CAPX { + _128, _256 + } capx; + u32 val; + BOOL enabled; + u8 EVA; + u8 EVB; + u8 writeBlock; + u8 writeOffset; + u16 capy; + u8 srcA; + u8 srcB; + u8 readBlock; + u8 readOffset; + u8 capSrc; +} ; + +/******************************************************************************* + this structure holds everything and should be mapped to + * core A : 0x04000000 + * core B : 0x04001000 +*******************************************************************************/ + +typedef struct _reg_dispx { + DISPCNT dispx_DISPCNT; // 0x0400x000 + u16 dispA_DISPSTAT; // 0x04000004 + u16 dispx_VCOUNT; // 0x0400x006 + BGxCNT dispx_BGxCNT[4]; // 0x0400x008 + BGxOFS dispx_BGxOFS[4]; // 0x0400x010 + BGxPARMS dispx_BG2PARMS; // 0x0400x020 + BGxPARMS dispx_BG3PARMS; // 0x0400x030 + u8 filler[12]; // 0x0400x040 + MISCCNT dispx_MISC; // 0x0400x04C + DISP3DCNT dispA_DISP3DCNT; // 0x04000060 + DISPCAPCNT dispA_DISPCAPCNT; // 0x04000064 + u32 dispA_DISPMMEMFIFO; // 0x04000068 +} REG_DISPx ; + + +typedef BOOL (*fun_gl_Begin) (int screen); +typedef void (*fun_gl_End) (int screen); +// the GUI should use this function prior to all gl calls +// if call to beg succeeds opengl draw +void register_gl_fun(fun_gl_Begin beg,fun_gl_End end); + +#define GPU_MAIN 0 +#define GPU_SUB 1 + +/* human readable bitmask names */ +#define ADDRESS_STEP_512B 0x00200 +#define ADDRESS_STEP_1KB 0x00400 +#define ADDRESS_STEP_2KB 0x00800 +#define ADDRESS_STEP_4KB 0x01000 +#define ADDRESS_STEP_8KB 0x02000 +#define ADDRESS_STEP_16KB 0x04000 +#define ADDRESS_STEP_32KB 0x08000 +#define ADDRESS_STEP_64KB 0x10000 +#define ADDRESS_STEP_128KB 0x20000 +#define ADDRESS_STEP_256KB 0x40000 +#define ADDRESS_STEP_512KB 0x80000 +#define ADDRESS_MASK_256KB (ADDRESS_STEP_256KB-1) + +#ifdef WORDS_BIGENDIAN +struct _TILEENTRY +{ +/*14*/ unsigned Palette:4; +/*13*/ unsigned VFlip:1; // VERTICAL FLIP (top<-->bottom) +/*12*/ unsigned HFlip:1; // HORIZONTAL FLIP (left<-->right) +/* 0*/ unsigned TileNum:10; +}; +#else +struct _TILEENTRY +{ +/* 0*/ unsigned TileNum:10; +/*12*/ unsigned HFlip:1; // HORIZONTAL FLIP (left<-->right) +/*13*/ unsigned VFlip:1; // VERTICAL FLIP (top<-->bottom) +/*14*/ unsigned Palette:4; +}; +#endif +typedef union +{ + struct _TILEENTRY bits; + u16 val; +} TILEENTRY; + +struct _ROTOCOORD +{ + u32 Fraction:8; + s32 Integer:20; + u32 pad:4; +}; +typedef union +{ + struct _ROTOCOORD bits; + s32 val; +} ROTOCOORD; + + +/* + this structure is for color representation, + it holds 5 meaningful bits per color channel (red,green,blue) + and 1 meaningful bit for alpha representation + this bit can be unused or used for special FX +*/ + +struct _COLOR { // abgr x555 +#ifdef WORDS_BIGENDIAN + unsigned alpha:1; // sometimes it is unused (pad) + unsigned blue:5; + unsigned green:5; + unsigned red:5; +#else + unsigned red:5; + unsigned green:5; + unsigned blue:5; + unsigned alpha:1; // sometimes it is unused (pad) +#endif +}; +struct _COLORx { // abgr x555 + unsigned bgr:15; + unsigned alpha:1; // sometimes it is unused (pad) +}; + +typedef union +{ + struct _COLOR bits; + struct _COLORx bitx; + u16 val; +} COLOR; + +struct _COLOR32 { // ARGB + unsigned :3; + unsigned blue:5; + unsigned :3; + unsigned green:5; + unsigned :3; + unsigned red:5; + unsigned :7; + unsigned alpha:1; // sometimes it is unused (pad) +}; + +typedef union +{ + struct _COLOR32 bits; + u32 val; +} COLOR32; + +#define COLOR_16_32(w,i) \ + /* doesnt matter who's 16bit who's 32bit */ \ + i.bits.red = w.bits.red; \ + i.bits.green = w.bits.green; \ + i.bits.blue = w.bits.blue; \ + i.bits.alpha = w.bits.alpha; + + + + // (00: Normal, 01: Transparent, 10: Object window, 11: Bitmap) +enum GPU_OBJ_MODE +{ + GPU_OBJ_MODE_Normal = 0, + GPU_OBJ_MODE_Transparent = 1, + GPU_OBJ_MODE_Window = 2, + GPU_OBJ_MODE_Bitmap = 3 +}; + +/* + this structure is for Sprite description, + it holds flags & transformations for 1 sprite + (max 128 OBJs / screen) +ref: http://www.bottledlight.com/ds/index.php/Video/Sprites +*/ + +struct _OAM_ +{ +#ifdef WORDS_BIGENDIAN +// attr0 +/* 0*/ unsigned Y:8; +/*14*/ unsigned Shape:2; // (00: Square, 01: Wide, 10: Tall, 11: Illegal) +/*13*/ unsigned Depth:1; // (0: 16, 1: 256) +/*12*/ unsigned Mosaic:1; // (1: Enabled) +/*10*/ unsigned Mode:2; // (00: Normal, 01: Transparent, 10: Object window, 11: Bitmap) +/* 8*/ unsigned RotScale:2; // (00: Normal, 01: Rot/scale, 10: Disabled, 11: Double-size rot/scale) +// attr1 +/* 0*/ signed X:9; +/*14*/ unsigned Size:2; +/*13*/ unsigned VFlip:1; +/*12*/ unsigned HFlip:1; +/* 9*/ unsigned RotScalIndex:3; // Rot/scale matrix index +// attr2 +/* 0*/ unsigned TileIndex:10; +/*12*/ unsigned PaletteIndex:4; +/*10*/ unsigned Priority:2; +// attr3 + unsigned attr3:16; +#else +// attr0 +/* 0*/ unsigned Y:8; +/* 8*/ unsigned RotScale:2; // (00: Normal, 01: Rot/scale, 10: Disabled, 11: Double-size rot/scale) +/*10*/ unsigned Mode:2; // (00: Normal, 01: Transparent, 10: Object window, 11: Bitmap) +/*12*/ unsigned Mosaic:1; // (1: Enabled) +/*13*/ unsigned Depth:1; // (0: 16, 1: 256) +/*14*/ unsigned Shape:2; // (00: Square, 01: Wide, 10: Tall, 11: Illegal) +// attr1 +/* 0*/ signed X:9; +/* 9*/ unsigned RotScalIndex:3; // Rot/scale matrix index +/*12*/ unsigned HFlip:1; +/*13*/ unsigned VFlip:1; +/*14*/ unsigned Size:2; +// attr2 +/* 0*/ unsigned TileIndex:10; +/*10*/ unsigned Priority:2; +/*12*/ unsigned PaletteIndex:4; +// attr3 + unsigned attr3:16; +#endif +}; + +typedef struct +{ +#ifdef WORDS_BIGENDIAN + u8 attr00; + u8 attr01; + u8 attr10; + u8 attr11; + u8 attr20; + u8 attr21; + u8 attr30; + u8 attr31; +#else + u16 attr0; + u16 attr1; + u16 attr2; + u16 attr3; +#endif +} OAM; + + +typedef struct +{ + s16 x; + s16 y; +} size; + + + + +/* + this structure holds information + for rendering. +*/ + +#define NB_PRIORITIES 4 +#define NB_BG 4 +typedef struct +{ + u8 PixelsX[256]; + u8 BGs[NB_BG], nbBGs; + u8 pad[1]; + u16 nbPixelsX; + //256+8: + u8 pad2[248]; + + //things were slower when i organized this struct this way. whatever. + //u8 PixelsX[256]; + //int BGs[NB_BG], nbBGs; + //int nbPixelsX; + ////<-- 256 + 24 + //u8 pad2[256-24]; +} itemsForPriority_t; +#define MMU_ABG 0x06000000 +#define MMU_BBG 0x06200000 +#define MMU_AOBJ 0x06400000 +#define MMU_BOBJ 0x06600000 +#define MMU_LCDC 0x06800000 + +extern CACHE_ALIGN u8 gpuBlendTable555[17][17][32][32]; + +enum BGType { + BGType_Invalid=0, BGType_Text=1, BGType_Affine=2, BGType_Large8bpp=3, + BGType_AffineExt=4, BGType_AffineExt_256x16=5, BGType_AffineExt_256x1=6, BGType_AffineExt_Direct=7 +}; + +extern const BGType GPU_mode2type[8][4]; + +struct GPU +{ + GPU() + : debug(false) + {} + + // some structs are becoming redundant + // some functions too (no need to recopy some vars as it is done by MMU) + REG_DISPx * dispx_st; + + //this indicates whether this gpu is handling debug tools + bool debug; + + _BGxCNT & bgcnt(int num) { return (dispx_st)->dispx_BGxCNT[num].bits; } + _DISPCNT & dispCnt() { return dispx_st->dispx_DISPCNT.bits; } + template void modeRender(int layer); + + DISPCAPCNT dispCapCnt; + BOOL LayersEnable[5]; + itemsForPriority_t itemsForPriority[NB_PRIORITIES]; + +#define BGBmpBB BG_bmp_ram +#define BGChBB BG_tile_ram + + u32 BG_bmp_large_ram[4]; + u32 BG_bmp_ram[4]; + u32 BG_tile_ram[4]; + u32 BG_map_ram[4]; + + u8 BGExtPalSlot[4]; + u32 BGSize[4][2]; + BGType BGTypes[4]; + + struct MosaicColor { + u16 bg[4][256]; + struct Obj { + u16 color; + u8 alpha, opaque; + } obj[256]; + } mosaicColors; + + u8 sprNum[256]; + u8 h_win[2][256]; + const u8 *curr_win[2]; + void update_winh(int WIN_NUM); + bool need_update_winh[2]; + + template void setup_windows(); + + u8 core; + + u8 dispMode; + u8 vramBlock; + u8 *VRAMaddr; + + //FIFO fifo; + + u8 bgPrio[5]; + + BOOL bg0HasHighestPrio; + + OAM * oam; + u32 sprMem; + u8 sprBoundary; + u8 sprBMPBoundary; + u8 sprBMPMode; + u32 sprEnable; + + u8 WIN0H0; + u8 WIN0H1; + u8 WIN0V0; + u8 WIN0V1; + + u8 WIN1H0; + u8 WIN1H1; + u8 WIN1V0; + u8 WIN1V1; + + u8 WININ0; + bool WININ0_SPECIAL; + u8 WININ1; + bool WININ1_SPECIAL; + + u8 WINOUT; + bool WINOUT_SPECIAL; + u8 WINOBJ; + bool WINOBJ_SPECIAL; + + u8 WIN0_ENABLED; + u8 WIN1_ENABLED; + u8 WINOBJ_ENABLED; + + u16 BLDCNT; + u8 BLDALPHA_EVA; + u8 BLDALPHA_EVB; + u8 BLDY_EVY; + u16 *currentFadeInColors, *currentFadeOutColors; + bool blend2[8]; + + CACHE_ALIGN u16 tempScanlineBuffer[256]; + u8 *tempScanline; + + u8 MasterBrightMode; + u32 MasterBrightFactor; + + CACHE_ALIGN u8 bgPixels[1024]; //yes indeed, this is oversized. map debug tools try to write to it + + u32 currLine; + u8 currBgNum; + bool blend1; + u8* currDst; + + u8* _3dColorLine; + + + static struct MosaicLookup { + + struct TableEntry { + u8 begin, trunc; + } table[16][256]; + + MosaicLookup() { + for(int m=0;m<16;m++) + for(int i=0;i<256;i++) { + int mosaic = m+1; + TableEntry &te = table[m][i]; + te.begin = (i%mosaic==0); + te.trunc = i/mosaic*mosaic; + } + } + + TableEntry *width, *height; + int widthValue, heightValue; + + } mosaicLookup; + bool curr_mosaic_enabled; + + u16 blend(u16 colA, u16 colB); + + template + FORCEINLINE FASTCALL bool _master_setFinalBGColor(u16 &color, const u32 x); + + template + FORCEINLINE FASTCALL void _master_setFinal3dColor(int dstX, int srcX); + + int setFinalColorBck_funcNum; + int bgFunc; + int setFinalColor3d_funcNum; + int setFinalColorSpr_funcNum; + //Final3DColFunct setFinalColor3D; + enum SpriteRenderMode { + SPRITE_1D, SPRITE_2D + } spriteRenderMode; + + template + void _spriteRender(u8 * dst, u8 * dst_alpha, u8 * typeTab, u8 * prioTab); + + inline void spriteRender(u8 * dst, u8 * dst_alpha, u8 * typeTab, u8 * prioTab) + { + if(spriteRenderMode == SPRITE_1D) + _spriteRender(dst,dst_alpha,typeTab, prioTab); + else + _spriteRender(dst,dst_alpha,typeTab, prioTab); + } + + + void setFinalColor3d(int dstX, int srcX); + + template void setFinalColorBG(u16 color, const u32 x); + template FORCEINLINE void __setFinalColorBck(u16 color, const u32 x, const int opaque); + template FORCEINLINE void ___setFinalColorBck(u16 color, const u32 x, const int opaque); + + void setAffineStart(int layer, int xy, u32 val); + void setAffineStartWord(int layer, int xy, u16 val, int word); + u32 getAffineStart(int layer, int xy); + void refreshAffineStartRegs(const int num, const int xy); + + struct AffineInfo { + AffineInfo() : x(0), y(0) {} + u32 x, y; + } affineInfo[2]; + + void renderline_checkWindows(u16 x, bool &draw, bool &effect) const; + + // check whether (x,y) is within the rectangle (including wraparounds) + template + u8 withinRect(u16 x) const; + + void setBLDALPHA(u16 val) + { + BLDALPHA_EVA = (val&0x1f) > 16 ? 16 : (val&0x1f); + BLDALPHA_EVB = ((val>>8)&0x1f) > 16 ? 16 : ((val>>8)&0x1f); + updateBLDALPHA(); + } + + void setBLDALPHA_EVA(u8 val) + { + BLDALPHA_EVA = (val&0x1f) > 16 ? 16 : (val&0x1f); + updateBLDALPHA(); + } + + void setBLDALPHA_EVB(u8 val) + { + BLDALPHA_EVB = (val&0x1f) > 16 ? 16 : (val&0x1f); + updateBLDALPHA(); + } + + u32 getHOFS(int bg) { return T1ReadWord(&dispx_st->dispx_BGxOFS[bg].BGxHOFS,0) & 0x1FF; } + u32 getVOFS(int bg) { return T1ReadWord(&dispx_st->dispx_BGxOFS[bg].BGxVOFS,0) & 0x1FF; } + + typedef u8 TBlendTable[32][32]; + TBlendTable *blendTable; + + void updateBLDALPHA() + { + blendTable = (TBlendTable*)&gpuBlendTable555[BLDALPHA_EVA][BLDALPHA_EVB][0][0]; + } + +}; +#if 0 +// normally should have same addresses +static void REG_DISPx_pack_test(GPU * gpu) +{ + REG_DISPx * r = gpu->dispx_st; + printf ("%08x %02x\n", (u32)r, (u32)(&r->dispx_DISPCNT) - (u32)r); + printf ("\t%02x\n", (u32)(&r->dispA_DISPSTAT) - (u32)r); + printf ("\t%02x\n", (u32)(&r->dispx_VCOUNT) - (u32)r); + printf ("\t%02x\n", (u32)(&r->dispx_BGxCNT[0]) - (u32)r); + printf ("\t%02x\n", (u32)(&r->dispx_BGxOFS[0]) - (u32)r); + printf ("\t%02x\n", (u32)(&r->dispx_BG2PARMS) - (u32)r); + printf ("\t%02x\n", (u32)(&r->dispx_BG3PARMS) - (u32)r); +// printf ("\t%02x\n", (u32)(&r->dispx_WINCNT) - (u32)r); + printf ("\t%02x\n", (u32)(&r->dispx_MISC) - (u32)r); + printf ("\t%02x\n", (u32)(&r->dispA_DISP3DCNT) - (u32)r); + printf ("\t%02x\n", (u32)(&r->dispA_DISPCAPCNT) - (u32)r); + printf ("\t%02x\n", (u32)(&r->dispA_DISPMMEMFIFO) - (u32)r); +} +#endif + +CACHE_ALIGN extern u8 GPU_screen[4*256*192]; + + +GPU * GPU_Init(u8 l); +void GPU_Reset(GPU *g, u8 l); +void GPU_DeInit(GPU *); + +//these are functions used by debug tools which want to render layers etc outside the context of the emulation +namespace GPU_EXT +{ + void textBG(GPU * gpu, u8 num, u8 * DST); //Draw text based background + void rotBG(GPU * gpu, u8 num, u8 * DST); + void extRotBG(GPU * gpu, u8 num, u8 * DST); +}; +void sprite1D(GPU * gpu, u16 l, u8 * dst, u8 * dst_alpha, u8 * typeTab, u8 * prioTab); +void sprite2D(GPU * gpu, u16 l, u8 * dst, u8 * dst_alpha, u8 * typeTab, u8 * prioTab); + +extern const size sprSizeTab[4][4]; + +typedef struct { + GPU * gpu; + u16 offset; +} NDS_Screen; + +extern NDS_Screen MainScreen; +extern NDS_Screen SubScreen; + +int Screen_Init(int coreid); +void Screen_Reset(void); +void Screen_DeInit(void); + +extern MMU_struct MMU; + + + +#define GFXCORE_DEFAULT -1 +#define GFXCORE_DUMMY 0 + +#define GFXCORE_FULLSCREEN (1 << 0) + +struct GraphicsInterface_struct +{ + int id; // ID number for core(see above defines) + const char *Name; // Name of core + int flags; // What features the core supports(full screen, etc.) + int (*Init)(); // Initializes stuff related to core + void (*DeInit)(); // Deinitializes stuff related to core + void (*Resize)(int width, int height, BOOL fullscreen); // Resizes window or fullscreen + void (*OnScreenText)(char *string, ...); // For handling save state messages, etc. +} ; + +extern GraphicsInterface_struct GFXDummy; + +void GPU_setVideoProp(GPU *, u32 p); +void GPU_setBGProp(GPU *, u16 num, u16 p); + +void GPU_setBLDCNT(GPU *gpu, u16 v) ; +void GPU_setBLDY(GPU *gpu, u16 v) ; +void GPU_setMOSAIC(GPU *gpu, u16 v) ; + + +void GPU_remove(GPU *, u8 num); +void GPU_addBack(GPU *, u8 num); + +int GPU_ChangeGraphicsCore(int coreid); + +void GPU_set_DISPCAPCNT(u32 val) ; +void GPU_RenderLine(NDS_Screen * screen, u16 l, bool skip = false) ; +void GPU_setMasterBrightness (GPU *gpu, u16 val); + +inline void GPU_setWIN0_H(GPU* gpu, u16 val) { gpu->WIN0H0 = val >> 8; gpu->WIN0H1 = val&0xFF; gpu->need_update_winh[0] = true; } +inline void GPU_setWIN0_H0(GPU* gpu, u8 val) { gpu->WIN0H0 = val; gpu->need_update_winh[0] = true; } +inline void GPU_setWIN0_H1(GPU* gpu, u8 val) { gpu->WIN0H1 = val; gpu->need_update_winh[0] = true; } + +inline void GPU_setWIN0_V(GPU* gpu, u16 val) { gpu->WIN0V0 = val >> 8; gpu->WIN0V1 = val&0xFF;} +inline void GPU_setWIN0_V0(GPU* gpu, u8 val) { gpu->WIN0V0 = val; } +inline void GPU_setWIN0_V1(GPU* gpu, u8 val) { gpu->WIN0V1 = val; } + +inline void GPU_setWIN1_H(GPU* gpu, u16 val) {gpu->WIN1H0 = val >> 8; gpu->WIN1H1 = val&0xFF; gpu->need_update_winh[1] = true; } +inline void GPU_setWIN1_H0(GPU* gpu, u8 val) { gpu->WIN1H0 = val; gpu->need_update_winh[1] = true; } +inline void GPU_setWIN1_H1(GPU* gpu, u8 val) { gpu->WIN1H1 = val; gpu->need_update_winh[1] = true; } + +inline void GPU_setWIN1_V(GPU* gpu, u16 val) { gpu->WIN1V0 = val >> 8; gpu->WIN1V1 = val&0xFF; } +inline void GPU_setWIN1_V0(GPU* gpu, u8 val) { gpu->WIN1V0 = val; } +inline void GPU_setWIN1_V1(GPU* gpu, u8 val) { gpu->WIN1V1 = val; } + +inline void GPU_setWININ(GPU* gpu, u16 val) { + gpu->WININ0=val&0x1F; + gpu->WININ0_SPECIAL=((val>>5)&1)!=0; + gpu->WININ1=(val>>8)&0x1F; + gpu->WININ1_SPECIAL=((val>>13)&1)!=0; +} + +inline void GPU_setWININ0(GPU* gpu, u8 val) { gpu->WININ0 = val&0x1F; gpu->WININ0_SPECIAL = (val>>5)&1; } +inline void GPU_setWININ1(GPU* gpu, u8 val) { gpu->WININ1 = val&0x1F; gpu->WININ1_SPECIAL = (val>>5)&1; } + +inline void GPU_setWINOUT16(GPU* gpu, u16 val) { + gpu->WINOUT=val&0x1F; + gpu->WINOUT_SPECIAL=((val>>5)&1)!=0; + gpu->WINOBJ=(val>>8)&0x1F; + gpu->WINOBJ_SPECIAL=((val>>13)&1)!=0; +} +inline void GPU_setWINOUT(GPU* gpu, u8 val) { gpu->WINOUT = val&0x1F; gpu->WINOUT_SPECIAL = (val>>5)&1; } +inline void GPU_setWINOBJ(GPU* gpu, u8 val) { gpu->WINOBJ = val&0x1F; gpu->WINOBJ_SPECIAL = (val>>5)&1; } + +// Blending +void SetupFinalPixelBlitter (GPU *gpu); +#define GPU_setBLDCNT_LOW(gpu, val) {gpu->BLDCNT = (gpu->BLDCNT&0xFF00) | (val); SetupFinalPixelBlitter (gpu);} +#define GPU_setBLDCNT_HIGH(gpu, val) {gpu->BLDCNT = (gpu->BLDCNT&0xFF) | (val<<8); SetupFinalPixelBlitter (gpu);} +#define GPU_setBLDCNT(gpu, val) {gpu->BLDCNT = (val); SetupFinalPixelBlitter (gpu);} + + + +#define GPU_setBLDY_EVY(gpu, val) {gpu->BLDY_EVY = ((val)&0x1f) > 16 ? 16 : ((val)&0x1f);} + +//these arent needed right now since the values get poked into memory via default mmu handling and dispx_st +//#define GPU_setBGxHOFS(bg, gpu, val) gpu->dispx_st->dispx_BGxOFS[bg].BGxHOFS = ((val) & 0x1FF) +//#define GPU_setBGxVOFS(bg, gpu, val) gpu->dispx_st->dispx_BGxOFS[bg].BGxVOFS = ((val) & 0x1FF) + +void gpu_SetRotateScreen(u16 angle); + +//#undef FORCEINLINE +//#define FORCEINLINE __forceinline + +#endif + diff --git a/jni/desmume/src/GPU_osd.cpp b/jni/desmume/src/GPU_osd.cpp new file mode 100755 index 0000000..201b180 --- /dev/null +++ b/jni/desmume/src/GPU_osd.cpp @@ -0,0 +1,757 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2006-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ + +#include "GPU_osd.h" +#include "GPU.h" +#include "mem.h" +#include //mem funcs +#include //va_start, etc +#include +#include +#include +#ifndef ANDROID +#include +#else +#include +#endif +#include "debug.h" + +#include "aggdraw.h" +#include "movie.h" +#include "rtc.h" +#include "NDSSystem.h" +#include "mic.h" +#include "saves.h" + +bool HudEditorMode = false; +OSDCLASS *osd = NULL; +HudStruct Hud; + +//contains a timer to be used for well-timed hud components +static s64 hudTimer; + +static void SetHudDummy (HudCoordinates *hud) +{ + hud->x=666; + hud->y=666; +} + +static bool IsHudDummy (HudCoordinates *hud) +{ + return (hud->x == 666 && hud->y == 666); +} + +template +static T calcY(T y) // alters a GUI element y coordinate as necessary to obey swapScreens and singleScreen settings +{ + if(osd->singleScreen) + { + if(y >= 192) + y -= 192; + if(osd->swapScreens) + y += 192; + } + else if(osd->swapScreens) + { + if(y >= 192) + y -= 192; + else + y += 192; + } + return y; +} + +void EditHud(s32 x, s32 y, HudStruct *hudstruct) { + + u32 i = 0; + + while (!IsHudDummy(&hudstruct->hud(i))) { + HudCoordinates &hud = hudstruct->hud(i); + + //reset + if(!hud.clicked) { + hud.storedx=0; + hud.storedy=0; + } + + if((x >= hud.x && x <= hud.x + hud.xsize) && + (calcY(y) >= calcY(hud.y) && calcY(y) <= calcY(hud.y) + hud.ysize) && !hudstruct->clicked ) { + + hud.clicked=1; + hud.storedx = x - hud.x; + hud.storedy = y - hud.y; + } + + if(hud.clicked) { + hud.x = x - hud.storedx; + hud.y = y - hud.storedy; + } + + //sanity checks + if(hud.x < 0) hud.x = 0; + if(hud.y < 0) hud.y = 0; + if(hud.x > 245)hud.x = 245; //margins + if(hud.y > 384-16)hud.y = 384-16; + + if(hud.clicked) + { + hudstruct->clicked = true; + break;//prevent items from grouping together + } + + i++; + } +} + +void HudClickRelease(HudStruct *hudstruct) { + + u32 i = 0; + + while (!IsHudDummy(&hudstruct->hud(i))) { + HudCoordinates &hud = hudstruct->hud(i); + hud.clicked=0; + i++; + } + + hudstruct->clicked = false; +} + +void HudStruct::reset() +{ + FpsDisplay.x=0; + FpsDisplay.y=5; + FpsDisplay.xsize=166; + FpsDisplay.ysize=10; + + FrameCounter.x=0; + FrameCounter.y=25; + FrameCounter.xsize=60; + FrameCounter.ysize=10; + + InputDisplay.x=0; + InputDisplay.y=45; + InputDisplay.xsize=220; + InputDisplay.ysize=10; + + GraphicalInputDisplay.x=8; + GraphicalInputDisplay.y=328; + GraphicalInputDisplay.xsize=102; + GraphicalInputDisplay.ysize=50; + + LagFrameCounter.x=0; + LagFrameCounter.y=65; + LagFrameCounter.xsize=30; + LagFrameCounter.ysize=10; + + Microphone.x=0; + Microphone.y=85; + Microphone.xsize=20; + Microphone.ysize=10; + + RTCDisplay.x=0; + RTCDisplay.y=105; + RTCDisplay.xsize=220; + RTCDisplay.ysize=10; + + SavestateSlots.x = 8; + SavestateSlots.y = 160; + SavestateSlots.xsize = 240; + SavestateSlots.ysize = 24; + + SetHudDummy(&Dummy); + clicked = false; +} + +static void joyFill(int n) { + + bool pressedForGame = NDS_getFinalUserInput().buttons.array[n]; + bool physicallyPressed = NDS_getRawUserInput().buttons.array[n]; + if(pressedForGame && physicallyPressed) + aggDraw.hud->fillColor(0,0,0,255); + else if(pressedForGame) + aggDraw.hud->fillColor(255,0,0,255); + else if(physicallyPressed) + aggDraw.hud->fillColor(0,255,0,255); + else + aggDraw.hud->fillColor(255,255,255,255); +} + +static void joyEllipse(double ex, double ey, int xc, int yc, int x, int y, double ratio, double rad, int button) { + + joyFill(button); + aggDraw.hud->lineWidth(rad); + aggDraw.hud->ellipse(x+((xc*ex)*ratio), y+((yc*ey)*ratio), rad*ratio, rad*ratio); +} + +static void joyRoundedRect(double x1, double y1, int x2, int y2, int alpha1, int alpha2, int button) +{ + bool pressedForGame = NDS_getFinalUserInput().buttons.array[button]; + bool physicallyPressed = NDS_getRawUserInput().buttons.array[button]; + if(pressedForGame && physicallyPressed) + aggDraw.hud->fillLinearGradient(x1,y1,x2,y2,agg::rgba8(0,0,0,alpha1), agg::rgba8(0,0,0,alpha2)); + else if(pressedForGame) + aggDraw.hud->fillLinearGradient(x1,y1,x2,y2,agg::rgba8(255,0,0,alpha1), agg::rgba8(255,0,0,alpha2)); + else if(physicallyPressed) + aggDraw.hud->fillLinearGradient(x1,y1,x2,y2,agg::rgba8(0,255,0,alpha1), agg::rgba8(0,255,0,alpha2)); + else + return; //aggDraw.hud->fillLinearGradient(x1,y1,x2,y2,agg::rgba8(255,255,255,alpha1), agg::rgba8(255,255,255,alpha2)); + + aggDraw.hud->roundedRect(x1,y1,x2,y2,1); +} + + +static void drawPad(double x, double y, double ratio) { + + // you might notice black/red/green colors used to show what buttons are pressed. + // the logic is roughly: + // RED == PAST (the button was held last frame) + // GREEN == FUTURE (the button is physically held now) + // BLACK == PRESENT (the button was held last frame and is still physically held now) + + // aligning to odd half-pixel boundaries prevents agg2d from blurring thin straight lines + x = floor(x) + 0.5; + y = floor(calcY(y)) + 0.5; + double xc = 41 - 0.5; + double yc = 20 - 0.5; + + aggDraw.hud->lineColor(128,128,128,255); + + aggDraw.hud->fillLinearGradient(x, y, x+(xc*ratio), y+(yc*ratio), agg::rgba8(222,222,222,128), agg::rgba8(255,255,255,255)); + + aggDraw.hud->roundedRect (x, y, floor(x+(xc*ratio))+0.5, floor(y+(yc*ratio))+0.5, 1); + + double screenLeft = x+(xc*.25*ratio); + double screenTop = y+(yc*.1*ratio); + double screenRight = x+(xc*.745*ratio); + double screenBottom = y+(yc*.845*ratio); + aggDraw.hud->fillLinearGradient(screenLeft, screenTop, screenRight, screenBottom, agg::rgba8(128,128,128,128), agg::rgba8(255,255,255,255)); + aggDraw.hud->roundedRect (screenLeft, screenTop, screenRight, screenBottom, 1); + + + joyEllipse(.89,.45,xc,yc,x,y,ratio,1,6);//B + joyEllipse(.89,.22,xc,yc,x,y,ratio,1,3);//X + joyEllipse(.83,.34,xc,yc,x,y,ratio,1,4);//Y + joyEllipse(.95,.34,xc,yc,x,y,ratio,1,5);//A + joyEllipse(.82,.716,xc,yc,x,y,ratio,.5,7);//Start + joyEllipse(.82,.842,xc,yc,x,y,ratio,.5,8);//Select + + + double dpadPoints [][2] = { + {.04,.33}, // top-left corner of left button + {.08,.33}, + {.08,.24}, // top-left corner of up button + {.13,.24}, // top-right corner of up button + {.13,.33}, + {.17,.33}, // top-right corner of right button + {.17,.43}, // bottom-right corner of right button + {.13,.43}, + {.13,.516}, // bottom-right corner of down button + {.08,.516}, // bottom-left corner of down button + {.08,.43}, + {.04,.43}, // bottom-left corner of left button + }; + static const int numdpadPoints = sizeof(dpadPoints)/sizeof(dpadPoints[0]); + for(int i = 0; i < numdpadPoints; i++) + { + dpadPoints[i][0] = x+(xc*(dpadPoints[i][0]+.01)*ratio); + dpadPoints[i][1] = y+(yc*(dpadPoints[i][1]+.00)*ratio); + } + + // dpad outline + aggDraw.hud->fillColor(255,255,255,200); + aggDraw.hud->polygon((double*)dpadPoints, numdpadPoints); + + aggDraw.hud->noLine(); + + // left + joyRoundedRect(dpadPoints[0][0], dpadPoints[0][1], dpadPoints[7][0], dpadPoints[7][1], 255, 0, 11); + + // right + joyRoundedRect(dpadPoints[1][0], dpadPoints[1][1], dpadPoints[6][0], dpadPoints[6][1], 0, 255, 12); + + // up + joyRoundedRect(dpadPoints[2][0], dpadPoints[2][1], dpadPoints[7][0], dpadPoints[7][1], 255, 0, 9); + + // right + joyRoundedRect(dpadPoints[1][0], dpadPoints[1][1], dpadPoints[8][0], dpadPoints[8][1], 0, 255, 10); + + // left shoulder + joyRoundedRect(x+(xc*.00*ratio), y+(yc*.00*ratio), x+(xc*.15*ratio), y+(yc*.07*ratio), 255, 200, 2); + + // right shoulder + joyRoundedRect(x+(xc*.85*ratio), y+(yc*.00*ratio), x+(xc*1.0*ratio), y+(yc*.07*ratio), 200, 255, 1); + + // lid... + joyRoundedRect(x+(xc*.4*ratio), y+(yc*.96*ratio), x+(xc*0.6*ratio), y+(yc*1.0*ratio), 200, 200, 13); + + // touch pad + { + BOOL gameTouchOn = nds.isTouch; + double gameTouchX = screenLeft+1 + (nds.scr_touchX * 0.0625) * (screenRight - screenLeft - 2) / 256.0; + double gameTouchY = screenTop+1 + (nds.scr_touchY * 0.0625) * (screenBottom - screenTop - 2) / 192.0; + bool physicalTouchOn = NDS_getRawUserInput().touch.isTouch; + double physicalTouchX = screenLeft+1 + (NDS_getRawUserInput().touch.touchX * 0.0625) * (screenRight - screenLeft - 2) / 256.0; + double physicalTouchY = screenTop+1 + (NDS_getRawUserInput().touch.touchY * 0.0625) * (screenBottom - screenTop - 2) / 192.0; + if(gameTouchOn && physicalTouchOn && gameTouchX == physicalTouchX && gameTouchY == physicalTouchY) + { + aggDraw.hud->fillColor(0,0,0,255); + aggDraw.hud->ellipse(gameTouchX, gameTouchY, ratio*0.37, ratio*0.37); + } + else + { + if(physicalTouchOn) + { + aggDraw.hud->fillColor(0,0,0,128); + aggDraw.hud->ellipse(physicalTouchX, physicalTouchY, ratio*0.5, ratio*0.5); + aggDraw.hud->fillColor(0,255,0,255); + aggDraw.hud->ellipse(physicalTouchX, physicalTouchY, ratio*0.37, ratio*0.37); + } + if(gameTouchOn) + { + aggDraw.hud->fillColor(255,0,0,255); + aggDraw.hud->ellipse(gameTouchX, gameTouchY, ratio*0.37, ratio*0.37); + } + } + } +} + + +struct TouchInfo{ + u16 X; + u16 Y; +}; +static int touchalpha[8]= {31, 63, 95, 127, 159, 191, 223, 255}; +static TouchInfo temptouch; +static const bool touchshadow = false;//true; // sorry, it's cool but also distracting and looks cleaner with it off. maybe if it drew line segments between touch points instead of isolated crosses... +static std::vector touch (8); + +static void TextualInputDisplay() { + + // drawing the whole string at once looks ugly + // (because of variable width font and the "shadow" appearing over blank space) + // and can't give us the color-coded effects we want anyway (see drawPad for info) + + const UserButtons& gameButtons = NDS_getFinalUserInput().buttons; + const UserButtons& physicalButtons = NDS_getRawUserInput().buttons; + + double x = Hud.InputDisplay.x; + + // from order FRLDUTSBAYXWEG where G is 0 + static const char* buttonChars = "<^>vABXYLRSsgf"; + static const int buttonIndex [14] = {11,9,12,10,5,6,3,4,2,1,7,8,0,13}; + for(int i = 0; i < 14; i++, x+=11.0) + { + bool pressedForGame = gameButtons.array[buttonIndex[i]]; + bool physicallyPressed = physicalButtons.array[buttonIndex[i]]; + if(pressedForGame && physicallyPressed) + aggDraw.hud->lineColor(255,255,255,255); + else if(pressedForGame) + aggDraw.hud->lineColor(255,48,48,255); + else if(physicallyPressed) + aggDraw.hud->lineColor(0,192,0,255); + else + continue; + + // cast from char to std::string is a bit awkward + std::string str(buttonChars+i, 2); + str[1] = '\0'; + + aggDraw.hud->renderTextDropshadowed(x, calcY(Hud.InputDisplay.y), str); + } + + // touch pad + { + char str [32]; + BOOL gameTouchOn = nds.isTouch; + int gameTouchX = nds.adc_touchX >> 4; + int gameTouchY = nds.adc_touchY >> 4; + bool physicalTouchOn = NDS_getRawUserInput().touch.isTouch; + int physicalTouchX = NDS_getRawUserInput().touch.touchX >> 4; + int physicalTouchY = NDS_getRawUserInput().touch.touchY >> 4; + if(gameTouchOn && physicalTouchOn && gameTouchX == physicalTouchX && gameTouchY == physicalTouchY) + { + sprintf(str, "%d,%d", gameTouchX, gameTouchY); + aggDraw.hud->lineColor(255,255,255,255); + aggDraw.hud->renderTextDropshadowed(x, calcY(Hud.InputDisplay.y), str); + } + else + { + if(gameTouchOn) + { + sprintf(str, "%d,%d", gameTouchX, gameTouchY); + aggDraw.hud->lineColor(255,48,48,255); + aggDraw.hud->renderTextDropshadowed(x, calcY(Hud.InputDisplay.y)-(physicalTouchOn?8:0), str); + } + if(physicalTouchOn) + { + sprintf(str, "%d,%d", physicalTouchX, physicalTouchY); + aggDraw.hud->lineColor(0,192,0,255); + aggDraw.hud->renderTextDropshadowed(x, calcY(Hud.InputDisplay.y)+(gameTouchOn?8:0), str); + } + } + } +} + +static void TouchDisplay() { + // note: calcY should not be used in this function. + aggDraw.hud->lineWidth(1.0); + + temptouch.X = NDS_getRawUserInput().touch.touchX >> 4; + temptouch.Y = NDS_getRawUserInput().touch.touchY >> 4; + + if(touchshadow) { + + touch.push_back(temptouch); + if(touch.size() > 8) touch.erase(touch.begin()); + + for (int i = 0; i < 8; i++) { + temptouch = touch[i]; + if(temptouch.X != 0 || temptouch.Y != 0) { + aggDraw.hud->lineColor(0, 255, 0, touchalpha[i]); + aggDraw.hud->line(temptouch.X - 256, temptouch.Y + 192, temptouch.X + 256, temptouch.Y + 192); //horiz + aggDraw.hud->line(temptouch.X, temptouch.Y - 256, temptouch.X, temptouch.Y + 384); //vert + aggDraw.hud->fillColor(0, 0, 0, touchalpha[i]); + aggDraw.hud->rectangle(temptouch.X-1, temptouch.Y + 192-1, temptouch.X+1, temptouch.Y + 192+1); + } + } + } + else + if(NDS_getRawUserInput().touch.isTouch) { + aggDraw.hud->lineColor(0, 255, 0, 128); + aggDraw.hud->line(temptouch.X - 256, temptouch.Y + 192, temptouch.X + 256, temptouch.Y + 192); //horiz + aggDraw.hud->line(temptouch.X, temptouch.Y - 256, temptouch.X, temptouch.Y + 384); //vert + } + + if(nds.isTouch) { + temptouch.X = nds.scr_touchX; + temptouch.Y = nds.scr_touchY; + aggDraw.hud->lineColor(255, 0, 0, 128); + aggDraw.hud->line(temptouch.X - 256, temptouch.Y + 192, temptouch.X + 256, temptouch.Y + 192); //horiz + aggDraw.hud->line(temptouch.X, temptouch.Y - 256, temptouch.X, temptouch.Y + 384); //vert + } + +} + +static int previousslot = 0; +static char number[10]; +static s64 slotTimer=0; + +static void DrawStateSlots(){ + + const int yloc = calcY(Hud.SavestateSlots.y); //160 + const int xloc = Hud.SavestateSlots.x; //8 + + s64 fadecounter = 512 - (hudTimer-slotTimer)/4; //change constant to alter fade speed + if(fadecounter < 1) fadecounter = 0; + if(fadecounter>255) fadecounter = 255; + + int alpha = (int)fadecounter; + if(HudEditorMode) + alpha = 255; + + if(alpha!=0) + { + aggDraw.hud->lineWidth(1.0); + aggDraw.hud->lineColor(0, 0, 0, alpha); + aggDraw.hud->fillColor(255, 255, 255, alpha); + + for ( int i = 0, xpos=0; i < 10; xpos=xpos+24) { + + int yheight=0; + + aggDraw.hud->fillLinearGradient(xloc + xpos, yloc - yheight, xloc + 22 + xpos, yloc + 20 + yheight+20, agg::rgba8(100,200,255,alpha), agg::rgba8(255,255,255,0)); + + if(lastSaveState == i) { + yheight = 5; + aggDraw.hud->fillLinearGradient(xloc + xpos, yloc - yheight, 22 + xloc + xpos, yloc + 20 + yheight+20, agg::rgba8(100,255,255,alpha), agg::rgba8(255,255,255,0)); + } + + aggDraw.hud->rectangle(xloc + xpos , yloc - yheight, xloc + 22 + xpos , yloc + 20 + yheight); + snprintf(number, 10, "%d", i); + aggDraw.hud->renderText(xloc + 1 + xpos + 4, yloc+4, std::string(number)); + i++; + } + } + + if(lastSaveState != previousslot) + slotTimer = hudTimer; + + previousslot = lastSaveState; +} + +static void DrawEditableElementIndicators() +{ + u32 i = 0; + while (!IsHudDummy(&Hud.hud(i))) { + HudCoordinates &hud = Hud.hud(i); + aggDraw.hud->fillColor(0,0,0,0); + aggDraw.hud->lineColor(0,0,0,64); + aggDraw.hud->lineWidth(2.0); + aggDraw.hud->rectangle(hud.x,calcY(hud.y),hud.x+hud.xsize+1.0,calcY(hud.y)+hud.ysize+1.0); + aggDraw.hud->lineColor(255,hud.clicked?127:255,0,255); + aggDraw.hud->lineWidth(1.0); + aggDraw.hud->rectangle(hud.x-0.5,calcY(hud.y)-0.5,hud.x+hud.xsize+0.5,calcY(hud.y)+hud.ysize+0.5); + i++; + } +} + + +void DrawHUD() +{ +#ifdef ANDROID + struct timeval time; + gettimeofday(&time, NULL); +#else + GTimeVal time; + g_get_current_time(&time); +#endif + hudTimer = ((s64)time.tv_sec * 1000) + ((s64)time.tv_usec/1000); + + if (HudEditorMode) + { + DrawEditableElementIndicators(); + } + + if (CommonSettings.hud.ShowInputDisplay) + { + TextualInputDisplay(); + TouchDisplay(); + } + + if (CommonSettings.hud.FpsDisplay) + { + osd->addFixed(Hud.FpsDisplay.x, Hud.FpsDisplay.y, "Fps:%02d/%02d (%02d%%/%02d%%)%s", Hud.fps, Hud.fps3d, Hud.cpuload[0], Hud.cpuload[1], driver->EMU_IsEmulationPaused() ? " (paused)" : ""); + } + + if (CommonSettings.hud.FrameCounterDisplay) + { + if(movieMode == MOVIEMODE_RECORD) + osd->addFixed(Hud.FrameCounter.x, Hud.FrameCounter.y, "%d",currFrameCounter); + else if (movieMode == MOVIEMODE_PLAY) + osd->addFixed(Hud.FrameCounter.x, Hud.FrameCounter.y, "%d/%d",currFrameCounter,currMovieData.records.size()); + else if (movieMode == MOVIEMODE_FINISHED) + osd->addFixed(Hud.FrameCounter.x, Hud.FrameCounter.y, "%d/%d (finished)",currFrameCounter,currMovieData.records.size()); + else + osd->addFixed(Hud.FrameCounter.x, Hud.FrameCounter.y, "%d (no movie)",currFrameCounter); + } + + if (CommonSettings.hud.ShowLagFrameCounter) + { + osd->addFixed(Hud.LagFrameCounter.x, Hud.LagFrameCounter.y, "%d",TotalLagFrames); + } + + if (CommonSettings.hud.ShowGraphicalInputDisplay) + { + drawPad(Hud.GraphicalInputDisplay.x, Hud.GraphicalInputDisplay.y, 2.5); + } + + #if defined(WIN32) && !defined(WXPORT) + if (CommonSettings.hud.ShowMicrophone) + { + osd->addFixed(Hud.Microphone.x, Hud.Microphone.y, "%03d [%07d]",MicDisplay, Hud.cpuloopIterationCount); + } + #endif + + if (CommonSettings.hud.ShowRTC) + { + DateTime tm = rtcGetTime(); + static const char *wday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; + osd->addFixed(Hud.RTCDisplay.x, Hud.RTCDisplay.y, "%04d-%03s-%02d %s %02d:%02d:%02d", tm.get_Year(), DateTime::GetNameOfMonth(tm.get_Month()), tm.get_Day(), wday[tm.get_DayOfWeek()%7], tm.get_Hour(), tm.get_Minute(), tm.get_Second()); + } + + DrawStateSlots(); +} + + + +OSDCLASS::OSDCLASS(u8 core) +{ + memset(name,0,7); + + mode=core; + offset=0; + + lastLineText=0; + lineText_x = 5; + lineText_y = 120; + lineText_color = AggColor(255, 255, 255); + for (int i=0; i < OSD_MAX_LINES+1; i++) + { + lineText[i] = new char[1024]; + memset(lineText[i], 0, 1024); + lineTimer[i] = 0; + lineColor[i] = lineText_color; + } + + rotAngle = 0; + + singleScreen = false; + swapScreens = false; + + needUpdate = false; + + if (core==0) + strcpy(name,"Core A"); + else + if (core==1) + strcpy(name,"Core B"); + else + { + strcpy(name,"Main"); + mode=255; + } + + //border(false); + + LOG("OSD_Init (%s)\n",name); +} + +OSDCLASS::~OSDCLASS() +{ + LOG("OSD_Deinit (%s)\n",name); + + for (int i=0; i < OSD_MAX_LINES+1; i++) + { + if (lineText[i]) + delete [] lineText[i]; + lineText[i] = NULL; + } +} + +void OSDCLASS::setOffset(u16 ofs) +{ + offset=ofs; +} + +void OSDCLASS::setRotate(u16 angle) +{ + rotAngle = angle; +} + +void OSDCLASS::clear() +{ + needUpdate=false; +} + +bool OSDCLASS::checkTimers() +{ + if (lastLineText == 0) return false; + + time_t tmp_time = time(NULL); + + for (int i=0; i < lastLineText; i++) + { + if (tmp_time > (lineTimer[i] + OSD_TIMER_SECS) ) + { + if (i < lastLineText) + { + for (int j=i; j < lastLineText; j++) + { + strcpy(lineText[j], lineText[j+1]); + lineTimer[j] = lineTimer[j+1]; + lineColor[j] = lineColor[j+1]; + } + } + lineTimer[lastLineText] = 0; + lastLineText--; + if (lastLineText == 0) return false; + } + } + return true; +} + +void OSDCLASS::update() +{ + if ( (!needUpdate) && (!lastLineText) ) return; // don't update if buffer empty (speed up) + if (lastLineText) + { + if (checkTimers()) + { + for (int i=0; i < lastLineText; i++) + { + aggDraw.hud->lineColor(lineColor[i]); + aggDraw.hud->renderTextDropshadowed(lineText_x,lineText_y+(i*16),lineText[i]); + } + } + else + { + if (!needUpdate) return; + } + } +} + +void OSDCLASS::setListCoord(u16 x, u16 y) +{ + lineText_x = x; + lineText_y = y; +} + +void OSDCLASS::setLineColor(u8 r=255, u8 g=255, u8 b=255) +{ + lineText_color = AggColor(r,g,b); +} + +void OSDCLASS::addLine(const char *fmt, ...) +{ + va_list list; + + if (lastLineText > OSD_MAX_LINES) lastLineText = OSD_MAX_LINES; + if (lastLineText == OSD_MAX_LINES) // full + { + lastLineText--; + for (int j=0; j < lastLineText; j++) + { + strcpy(lineText[j], lineText[j+1]); + lineTimer[j] = lineTimer[j+1]; + lineColor[j] = lineColor[j+1]; + } + } + + va_start(list,fmt); +#if defined(_MSC_VER) || defined(__INTEL_COMPILER) + _vsnprintf(lineText[lastLineText],1023,fmt,list); +#else + vsnprintf(lineText[lastLineText],1023,fmt,list); +#endif + va_end(list); + lineColor[lastLineText] = lineText_color; + lineTimer[lastLineText] = time(NULL); + needUpdate = true; + + lastLineText++; +} + +void OSDCLASS::addFixed(u16 x, u16 y, const char *fmt, ...) +{ + va_list list; + char msg[1024]; + + va_start(list,fmt); + vsnprintf(msg,1023,fmt,list); + va_end(list); + + aggDraw.hud->lineColor(255,255,255); + aggDraw.hud->renderTextDropshadowed(x,calcY(y),msg); + + needUpdate = true; +} + +void OSDCLASS::border(bool enabled) +{ + //render51.setTextBoxBorder(enabled); +} diff --git a/jni/desmume/src/GPU_osd.h b/jni/desmume/src/GPU_osd.h new file mode 100755 index 0000000..6a63dfa --- /dev/null +++ b/jni/desmume/src/GPU_osd.h @@ -0,0 +1,141 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2008-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ + +#ifndef __GPU_OSD_ +#define __GPU_OSD_ + +#include "types.h" + +#ifdef HAVE_LIBAGG +#include +#include + +#include "aggdraw.h" + +#define OSD_MAX_LINES 4 +#define OSD_TIMER_SECS 2 + + +struct HudCoordinates{ + int x; + int y; + int xsize; + int ysize; + int storedx; + int storedy; + int clicked; +}; + +struct HudStruct +{ +public: + HudStruct() + { + resetTransient(); + } + + void resetTransient() + { + fps = 0; + fps3d = 0; + cpuload[0] = cpuload[1] = 0; + cpuloopIterationCount = 0; + clicked = false; + } + + HudCoordinates SavestateSlots; + HudCoordinates FpsDisplay; + HudCoordinates FrameCounter; + HudCoordinates InputDisplay; + HudCoordinates GraphicalInputDisplay; + HudCoordinates LagFrameCounter; + HudCoordinates Microphone; + HudCoordinates RTCDisplay; + HudCoordinates Dummy; + + HudCoordinates &hud(int i) { return ((HudCoordinates*)this)[i]; } + void reset(); + + int fps, fps3d, cpuload[2], cpuloopIterationCount; + bool clicked; +}; + +void EditHud(s32 x, s32 y, HudStruct *hudstruct); +void HudClickRelease(HudStruct *hudstruct); + +void DrawHUD(); + +extern HudStruct Hud; +extern bool HudEditorMode; + +class OSDCLASS +{ +private: + u64 offset; + u8 mode; + + u16 rotAngle; + + u16 lineText_x; + u16 lineText_y; + AggColor lineText_color; + u8 lastLineText; + char *lineText[OSD_MAX_LINES+1]; + time_t lineTimer[OSD_MAX_LINES+1]; + AggColor lineColor[OSD_MAX_LINES+1]; + + bool needUpdate; + + bool checkTimers(); + +public: + char name[7]; // for debuging + bool singleScreen; + bool swapScreens; + + OSDCLASS(u8 core); + ~OSDCLASS(); + + void setOffset(u16 ofs); + void setRotate(u16 angle); + void update(); + void clear(); + void setListCoord(u16 x, u16 y); + void setLineColor(u8 r, u8 b, u8 g); + void addLine(const char *fmt, ...); + void addFixed(u16 x, u16 y, const char *fmt, ...); + void border(bool enabled); +}; + +extern OSDCLASS *osd; +#else /* HAVE_LIBAGG */ +void DrawHUD(); + +class OSDCLASS { +public: + OSDCLASS(u8 core); + ~OSDCLASS(); + void update(); + void clear(); + void setLineColor(u8 r, u8 b, u8 g); + void addLine(const char *fmt, ...); +}; + +extern OSDCLASS *osd; +#endif +#endif diff --git a/jni/desmume/src/GPU_osd_stub.cpp b/jni/desmume/src/GPU_osd_stub.cpp new file mode 100755 index 0000000..b50e211 --- /dev/null +++ b/jni/desmume/src/GPU_osd_stub.cpp @@ -0,0 +1,30 @@ +/* + Copyright (C) 2010 DeSmumE team + + This file 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 file 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 the this software. If not, see . +*/ + +#include "types.h" +#include "GPU_osd.h" + +OSDCLASS *osd; + +OSDCLASS::OSDCLASS(u8 core) {} +OSDCLASS::~OSDCLASS() {} +void OSDCLASS::update() {} +void OSDCLASS::clear() {} +void OSDCLASS::setLineColor(u8 r, u8 b, u8 g) {} +void OSDCLASS::addLine(const char *fmt, ...) {} + +void DrawHUD() {} diff --git a/jni/desmume/src/MMU.cpp b/jni/desmume/src/MMU.cpp new file mode 100755 index 0000000..db3a131 --- /dev/null +++ b/jni/desmume/src/MMU.cpp @@ -0,0 +1,4863 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2007 shash + Copyright (C) 2007-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ + +#include +#include +#include +#include +#include + +#include "common.h" +#include "debug.h" +#include "NDSSystem.h" +#include "cp15.h" +#include "wifi.h" +#include "registers.h" +#include "render3D.h" +#include "gfx3d.h" +#include "rtc.h" +#include "mc.h" +#include "addons.h" +#include "slot1.h" +#include "mic.h" +#include "movie.h" +#include "readwrite.h" +#include "MMU_timing.h" + +#ifdef DO_ASSERT_UNALIGNED +#define ASSERT_UNALIGNED(x) assert(x) +#else +#define ASSERT_UNALIGNED(x) +#endif + +//http://home.utah.edu/~nahaj/factoring/isqrt.c.html +static u64 isqrt (u64 x) { + u64 squaredbit, remainder, root; + + if (x<1) return 0; + + /* Load the binary constant 01 00 00 ... 00, where the number + * of zero bits to the right of the single one bit + * is even, and the one bit is as far left as is consistant + * with that condition.) + */ + squaredbit = (u64) ((((u64) ~0LL) >> 1) & + ~(((u64) ~0LL) >> 2)); + /* This portable load replaces the loop that used to be + * here, and was donated by legalize@xmission.com + */ + + /* Form bits of the answer. */ + remainder = x; root = 0; + while (squaredbit > 0) { + if (remainder >= (squaredbit | root)) { + remainder -= (squaredbit | root); + root >>= 1; root |= squaredbit; + } else { + root >>= 1; + } + squaredbit >>= 2; + } + + return root; +} + +u32 partie = 1; +u32 _MMU_MAIN_MEM_MASK = 0x3FFFFF; +u32 _MMU_MAIN_MEM_MASK16 = 0x3FFFFF & ~1; +u32 _MMU_MAIN_MEM_MASK32 = 0x3FFFFF & ~3; + +//#define _MMU_DEBUG + +#ifdef _MMU_DEBUG + +#include +void mmu_log_debug_ARM9(u32 adr, const char *fmt, ...) +{ + if (adr < 0x4000000) return; +// if (adr > 0x4100014) return; +//#if 1 + if (adr >= 0x4000000 && adr <= 0x400006E) return; // Display Engine A + if (adr >= 0x40000B0 && adr <= 0x4000134) return; // DMA, Timers and Keypad + if (adr >= 0x4000180 && adr <= 0x40001BC) return; // IPC/ROM + if (adr >= 0x4000204 && adr <= 0x400024A) return; // Memory & IRQ control + if (adr >= 0x4000280 && adr <= 0x4000306) return; // Maths + if (adr >= 0x4000320 && adr <= 0x40006A3) return; // 3D dispaly engine + if (adr >= 0x4001000 && adr <= 0x400106E) return; // Display Engine B + if (adr >= 0x4100000 && adr <= 0x4100014) return; // IPC/ROM +//#endif + va_list list; + char msg[512]; + + memset(msg,0,512); + + va_start(list,fmt); + _vsnprintf(msg,511,fmt,list); + va_end(list); + + INFO("MMU ARM9 0x%08X: %s\n", adr, msg); +} + +void mmu_log_debug_ARM7(u32 adr, const char *fmt, ...) +{ + if (adr < 0x4000004) return; + if (adr > 0x4808FFF) return; +#if 1 + if (adr >= 0x4000004 && adr < 0x4000180) return; // ARM7 I/O Map + if (adr >= 0x4000180 && adr <= 0x40001C4) return; // IPC/ROM + if (adr >= 0x4000204 && adr <= 0x400030C) return; // Memory and IRQ Control + if (adr >= 0x4000400 && adr <= 0x400051E) return; // Sound Registers + if (adr >= 0x4100000 && adr <= 0x4100014) return; // IPC/ROM + if (adr >= 0x4800000 && adr <= 0x4808FFF) return; // WLAN Registers +#endif + va_list list; + char msg[512]; + + memset(msg,0,512); + + va_start(list,fmt); + _vsnprintf(msg,511,fmt,list); + va_end(list); + + INFO("MMU ARM7 0x%08X: %s\n", adr, msg); + +} +#else +#define mmu_log_debug_ARM9(...) +#define mmu_log_debug_ARM7(...) +#endif + + +//#define LOG_CARD +//#define LOG_GPU +//#define LOG_DMA +//#define LOG_DMA2 +//#define LOG_DIV + +#define DUP2(x) x, x +#define DUP4(x) x, x, x, x +#define DUP8(x) x, x, x, x, x, x, x, x +#define DUP16(x) x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x + +MMU_struct MMU; +MMU_struct_new MMU_new; +MMU_struct_timing MMU_timing; + +u8 * MMU_struct::MMU_MEM[2][256] = { + //arm9 + { + /* 0X*/ DUP16(MMU.ARM9_ITCM), + /* 1X*/ //DUP16(MMU.ARM9_ITCM) + /* 1X*/ DUP16(MMU.UNUSED_RAM), + /* 2X*/ DUP16(MMU.MAIN_MEM), + /* 3X*/ DUP16(MMU.SWIRAM), + /* 4X*/ DUP16(MMU.ARM9_REG), + /* 5X*/ DUP16(MMU.ARM9_VMEM), + /* 6X*/ DUP16(MMU.ARM9_LCD), + /* 7X*/ DUP16(MMU.ARM9_OAM), + /* 8X*/ DUP16(NULL), + /* 9X*/ DUP16(NULL), + /* AX*/ DUP16(MMU.UNUSED_RAM), + /* BX*/ DUP16(MMU.UNUSED_RAM), + /* CX*/ DUP16(MMU.UNUSED_RAM), + /* DX*/ DUP16(MMU.UNUSED_RAM), + /* EX*/ DUP16(MMU.UNUSED_RAM), + /* FX*/ DUP16(MMU.ARM9_BIOS) + }, + //arm7 + { + /* 0X*/ DUP16(MMU.ARM7_BIOS), + /* 1X*/ DUP16(MMU.UNUSED_RAM), + /* 2X*/ DUP16(MMU.MAIN_MEM), + /* 3X*/ DUP8(MMU.SWIRAM), + DUP8(MMU.ARM7_ERAM), + /* 4X*/ DUP8(MMU.ARM7_REG), + DUP8(MMU.ARM7_WIRAM), + /* 5X*/ DUP16(MMU.UNUSED_RAM), + /* 6X*/ DUP16(MMU.ARM9_LCD), + /* 7X*/ DUP16(MMU.UNUSED_RAM), + /* 8X*/ DUP16(NULL), + /* 9X*/ DUP16(NULL), + /* AX*/ DUP16(MMU.UNUSED_RAM), + /* BX*/ DUP16(MMU.UNUSED_RAM), + /* CX*/ DUP16(MMU.UNUSED_RAM), + /* DX*/ DUP16(MMU.UNUSED_RAM), + /* EX*/ DUP16(MMU.UNUSED_RAM), + /* FX*/ DUP16(MMU.UNUSED_RAM) + } +}; + +u32 MMU_struct::MMU_MASK[2][256] = { + //arm9 + { + /* 0X*/ DUP16(0x00007FFF), + /* 1X*/ //DUP16(0x00007FFF) + /* 1X*/ DUP16(0x00000003), + /* 2X*/ DUP16(0x003FFFFF), + /* 3X*/ DUP16(0x00007FFF), + /* 4X*/ DUP16(0x00FFFFFF), + /* 5X*/ DUP16(0x000007FF), + /* 6X*/ DUP16(0x00FFFFFF), + /* 7X*/ DUP16(0x000007FF), + /* 8X*/ DUP16(0x00000003), + /* 9X*/ DUP16(0x00000003), + /* AX*/ DUP16(0x00000003), + /* BX*/ DUP16(0x00000003), + /* CX*/ DUP16(0x00000003), + /* DX*/ DUP16(0x00000003), + /* EX*/ DUP16(0x00000003), + /* FX*/ DUP16(0x00007FFF) + }, + //arm7 + { + /* 0X*/ DUP16(0x00003FFF), + /* 1X*/ DUP16(0x00000003), + /* 2X*/ DUP16(0x003FFFFF), + /* 3X*/ DUP8(0x00007FFF), + DUP8(0x0000FFFF), + /* 4X*/ DUP8(0x00FFFFFF), + DUP8(0x0000FFFF), + /* 5X*/ DUP16(0x00000003), + /* 6X*/ DUP16(0x00FFFFFF), + /* 7X*/ DUP16(0x00000003), + /* 8X*/ DUP16(0x00000003), + /* 9X*/ DUP16(0x00000003), + /* AX*/ DUP16(0x00000003), + /* BX*/ DUP16(0x00000003), + /* CX*/ DUP16(0x00000003), + /* DX*/ DUP16(0x00000003), + /* EX*/ DUP16(0x00000003), + /* FX*/ DUP16(0x00000003) + } +}; + +// this logic was moved to MMU_timing.h +//CACHE_ALIGN +//TWaitState MMU_struct::MMU_WAIT16[2][16] = { +// { 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 1, 1, 1, 1, 1 }, //arm9 +// { 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 1, 1, 1, 1, 1 }, //arm7 +//}; +// +//CACHE_ALIGN +//TWaitState MMU_struct::MMU_WAIT32[2][16] = { +// { 1, 1, 1, 1, 1, 2, 2, 1, 8, 8, 5, 1, 1, 1, 1, 1 }, //arm9 +// { 1, 1, 1, 1, 1, 1, 1, 1, 8, 8, 5, 1, 1, 1, 1, 1 }, //arm7 +//}; + +////////////////////////////////////////////////////////////// + +//------------- +//VRAM MEMORY MAPPING +//------------- +//(Everything is mapped through to ARM9_LCD in blocks of 16KB) + +//for all of the below, values = 41 indicate unmapped memory +#define VRAM_PAGE_UNMAPPED 41 + +#define VRAM_LCDC_PAGES 41 +u8 vram_lcdc_map[VRAM_LCDC_PAGES]; + +//in the range of 0x06000000 - 0x06800000 in 16KB pages (the ARM9 vram mappable area) +//this maps to 16KB pages in the LCDC buffer which is what will actually contain the data +u8 vram_arm9_map[VRAM_ARM9_PAGES]; + +//this chooses which banks are mapped in the 128K banks starting at 0x06000000 in ARM7 +u8 vram_arm7_map[2]; + +//-----> +//consider these later, for better recordkeeping, instead of using the u8* in MMU + +////for each 128KB texture slot, this maps to a 16KB starting page in the LCDC buffer +//#define VRAM_TEX_SLOTS 4 +//u8 vram_tex_map[VRAM_TEX_SLOTS]; +// +////for each 16KB tex palette slot, this maps to a 16KB starting page in the LCDC buffer +//#define VRAM_TEX_PALETTE_SLOTS 6 +//u8 vram_tex_palette_map[VRAM_TEX_PALETTE_SLOTS]; + +//<--------- + + +void MMU_VRAM_unmap_all(); + +struct TVramBankInfo { + u8 page_addr, num_pages; +}; + +static const TVramBankInfo vram_bank_info[VRAM_BANKS] = { + {0,8}, + {8,8}, + {16,8}, + {24,8}, + {32,4}, + {36,1}, + {37,1}, + {38,2}, + {40,1} +}; + +//this is to remind you that the LCDC mapping returns a strange value (not 0x06800000) as you would expect +//in order to play nicely with the MMU address and mask tables +#define LCDC_HACKY_LOCATION 0x06000000 + +//maps an ARM9 BG/OBJ or LCDC address into an LCDC address, and informs the caller of whether it isn't mapped +//TODO - in cases where this does some mapping work, we could bypass the logic at the end of the _read* and _write* routines +//this is a good optimization to consider +template +static FORCEINLINE u32 MMU_LCDmap(u32 addr, bool& unmapped, bool& restricted) +{ + unmapped = false; + restricted = false; //this will track whether 8bit writes are allowed + + //in case the address is entirely outside of the interesting ranges + if(addr < 0x06000000) return addr; + if(addr >= 0x07000000) return addr; + + //shared wram mapping for arm7 + if(PROCNUM==ARMCPU_ARM7) + { + //necessary? not sure + //addr &= 0x3FFFF; + //addr += 0x06000000; + u32 ofs = addr & 0x1FFFF; + u32 bank = (addr >> 17)&1; + if(vram_arm7_map[bank] == VRAM_PAGE_UNMAPPED) + { + unmapped = true; + return 0; + } + return LCDC_HACKY_LOCATION + (vram_arm7_map[bank]<<14) + ofs; + } + + restricted = true; + + //handle LCD memory mirroring + if(addr>=0x068A4000) + addr = 0x06800000 + + //(addr%0xA4000); //yuck!! is this even how it mirrors? but we have to keep from overrunning the buffer somehow + (addr&0x80000); //just as likely to be right (I have no clue how it should work) but faster. + + u32 vram_page; + u32 ofs = addr & 0x3FFF; + + //return addresses in LCDC range + if(addr>=0x06800000) + { + //already in LCDC range. just look it up to see whether it is unmapped + vram_page = (addr>>14)&63; + assert(vram_page>14)&(VRAM_ARM9_PAGES-1); + assert(vram_page= VRAM_BANK_H) block++; + + u8 VRAMBankCnt = T1ReadByte(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x240 + block); + + //do nothing if the bank isnt enabled + u8 en = VRAMBankCnt & 0x80; + if(!en) return; + + int mst,ofs=0; + switch(bank) { + case VRAM_BANK_A: + case VRAM_BANK_B: + mst = VRAMBankCnt & 3; + ofs = (VRAMBankCnt>>3) & 3; + switch(mst) + { + case 0: //LCDC + vramConfiguration.banks[bank].purpose = VramConfiguration::LCDC; + MMU_vram_lcdc(bank); + if(ofs != 0) PROGINFO("Bank %i: MST %i OFS %i\n", mst, ofs); + break; + case 1: //ABG + vramConfiguration.banks[bank].purpose = VramConfiguration::ABG; + MMU_vram_arm9(bank,VRAM_PAGE_ABG+ofs*8); + break; + case 2: //AOBJ + vramConfiguration.banks[bank].purpose = VramConfiguration::AOBJ; + switch(ofs) { + case 0: + case 1: + MMU_vram_arm9(bank,VRAM_PAGE_AOBJ+ofs*8); + break; + default: + PROGINFO("Unsupported ofs setting %d for engine A OBJ vram bank %c\n", ofs, 'A'+bank); + } + break; + case 3: //texture + vramConfiguration.banks[bank].purpose = VramConfiguration::TEX; + MMU.texInfo.textureSlotAddr[ofs] = MMU_vram_physical(vram_bank_info[bank].page_addr); + break; + default: goto unsupported_mst; + } + break; + + case VRAM_BANK_C: + case VRAM_BANK_D: + mst = VRAMBankCnt & 7; + ofs = (VRAMBankCnt>>3) & 3; + switch(mst) + { + case 0: //LCDC + vramConfiguration.banks[bank].purpose = VramConfiguration::LCDC; + MMU_vram_lcdc(bank); + if(ofs != 0) PROGINFO("Bank %i: MST %i OFS %i\n", mst, ofs); + break; + case 1: //ABG + vramConfiguration.banks[bank].purpose = VramConfiguration::ABG; + MMU_vram_arm9(bank,VRAM_PAGE_ABG+ofs*8); + break; + case 2: //arm7 + vramConfiguration.banks[bank].purpose = VramConfiguration::ARM7; + if(bank == 2) T1WriteByte(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x240, T1ReadByte(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x240) | 1); + if(bank == 3) T1WriteByte(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x240, T1ReadByte(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x240) | 2); + //printf("DING!\n"); + switch(ofs) { + case 0: + case 1: + vram_arm7_map[ofs] = vram_bank_info[bank].page_addr; + break; + default: + PROGINFO("Unsupported ofs setting %d for arm7 vram bank %c\n", ofs, 'A'+bank); + } + + break; + case 3: //texture + vramConfiguration.banks[bank].purpose = VramConfiguration::TEX; + MMU.texInfo.textureSlotAddr[ofs] = MMU_vram_physical(vram_bank_info[bank].page_addr); + break; + case 4: //BGB or BOBJ + if(bank == VRAM_BANK_C) { + vramConfiguration.banks[bank].purpose = VramConfiguration::BBG; + MMU_vram_arm9(bank,VRAM_PAGE_BBG); //BBG + } else { + vramConfiguration.banks[bank].purpose = VramConfiguration::BOBJ; + MMU_vram_arm9(bank,VRAM_PAGE_BOBJ); //BOBJ + } + if(ofs != 0) PROGINFO("Bank %i: MST %i OFS %i\n", mst, ofs); + break; + default: goto unsupported_mst; + } + break; + + case VRAM_BANK_E: + mst = VRAMBankCnt & 7; + if(((VRAMBankCnt>>3)&3) != 0) PROGINFO("Bank %i: MST %i OFS %i\n", mst, ofs); + switch(mst) { + case 0: //LCDC + vramConfiguration.banks[bank].purpose = VramConfiguration::LCDC; + MMU_vram_lcdc(bank); + break; + case 1: //ABG + vramConfiguration.banks[bank].purpose = VramConfiguration::ABG; + MMU_vram_arm9(bank,VRAM_PAGE_ABG); + break; + case 2: //AOBJ + vramConfiguration.banks[bank].purpose = VramConfiguration::AOBJ; + MMU_vram_arm9(bank,VRAM_PAGE_AOBJ); + break; + case 3: //texture palette + vramConfiguration.banks[bank].purpose = VramConfiguration::TEXPAL; + MMU.texInfo.texPalSlot[0] = MMU_vram_physical(vram_bank_info[bank].page_addr); + MMU.texInfo.texPalSlot[1] = MMU_vram_physical(vram_bank_info[bank].page_addr+1); + MMU.texInfo.texPalSlot[2] = MMU_vram_physical(vram_bank_info[bank].page_addr+2); + MMU.texInfo.texPalSlot[3] = MMU_vram_physical(vram_bank_info[bank].page_addr+3); + break; + case 4: //A BG extended palette + vramConfiguration.banks[bank].purpose = VramConfiguration::ABGEXTPAL; + MMU.ExtPal[0][0] = MMU_vram_physical(vram_bank_info[bank].page_addr); + MMU.ExtPal[0][1] = MMU.ExtPal[0][0] + ADDRESS_STEP_8KB; + MMU.ExtPal[0][2] = MMU.ExtPal[0][1] + ADDRESS_STEP_8KB; + MMU.ExtPal[0][3] = MMU.ExtPal[0][2] + ADDRESS_STEP_8KB; + break; + default: goto unsupported_mst; + } + break; + + case VRAM_BANK_F: + case VRAM_BANK_G: { + mst = VRAMBankCnt & 7; + ofs = (VRAMBankCnt>>3) & 3; + const int pageofslut[] = {0,1,4,5}; + const int pageofs = pageofslut[ofs]; + switch(mst) + { + case 0: //LCDC + vramConfiguration.banks[bank].purpose = VramConfiguration::LCDC; + MMU_vram_lcdc(bank); + if(ofs != 0) PROGINFO("Bank %i: MST %i OFS %i\n", mst, ofs); + break; + case 1: //ABG + vramConfiguration.banks[bank].purpose = VramConfiguration::ABG; + MMU_vram_arm9(bank,VRAM_PAGE_ABG+pageofs); + MMU_vram_arm9(bank,VRAM_PAGE_ABG+pageofs+2); //unexpected mirroring (required by spyro eternal night) + break; + case 2: //AOBJ + vramConfiguration.banks[bank].purpose = VramConfiguration::AOBJ; + MMU_vram_arm9(bank,VRAM_PAGE_AOBJ+pageofs); + MMU_vram_arm9(bank,VRAM_PAGE_AOBJ+pageofs+2); //unexpected mirroring - I have no proof, but it is inferred from the ABG above + break; + case 3: //texture palette + vramConfiguration.banks[bank].purpose = VramConfiguration::TEXPAL; + MMU.texInfo.texPalSlot[pageofs] = MMU_vram_physical(vram_bank_info[bank].page_addr); + break; + case 4: //A BG extended palette + switch(ofs) { + case 0: + case 1: + vramConfiguration.banks[bank].purpose = VramConfiguration::ABGEXTPAL; + MMU.ExtPal[0][ofs*2] = MMU_vram_physical(vram_bank_info[bank].page_addr); + MMU.ExtPal[0][ofs*2+1] = MMU.ExtPal[0][ofs*2] + ADDRESS_STEP_8KB; + break; + default: + vramConfiguration.banks[bank].purpose = VramConfiguration::INVALID; + PROGINFO("Unsupported ofs setting %d for engine A bgextpal vram bank %c\n", ofs, 'A'+bank); + break; + } + break; + case 5: //A OBJ extended palette + vramConfiguration.banks[bank].purpose = VramConfiguration::AOBJEXTPAL; + MMU.ObjExtPal[0][0] = MMU_vram_physical(vram_bank_info[bank].page_addr); + MMU.ObjExtPal[0][1] = MMU.ObjExtPal[0][1] + ADDRESS_STEP_8KB; + if(ofs != 0) PROGINFO("Bank %i: MST %i OFS %i\n", mst, ofs); + break; + default: goto unsupported_mst; + } + break; + } + + case VRAM_BANK_H: + mst = VRAMBankCnt & 3; + if(((VRAMBankCnt>>3)&3) != 0) PROGINFO("Bank %i: MST %i OFS %i\n", mst, ofs); + switch(mst) + { + case 0: //LCDC + vramConfiguration.banks[bank].purpose = VramConfiguration::LCDC; + MMU_vram_lcdc(bank); + break; + case 1: //BBG + vramConfiguration.banks[bank].purpose = VramConfiguration::BBG; + MMU_vram_arm9(bank,VRAM_PAGE_BBG); + MMU_vram_arm9(bank,VRAM_PAGE_BBG + 4); //unexpected mirroring + break; + case 2: //B BG extended palette + vramConfiguration.banks[bank].purpose = VramConfiguration::BBGEXTPAL; + MMU.ExtPal[1][0] = MMU_vram_physical(vram_bank_info[bank].page_addr); + MMU.ExtPal[1][1] = MMU.ExtPal[1][0] + ADDRESS_STEP_8KB; + MMU.ExtPal[1][2] = MMU.ExtPal[1][1] + ADDRESS_STEP_8KB; + MMU.ExtPal[1][3] = MMU.ExtPal[1][2] + ADDRESS_STEP_8KB; + break; + default: goto unsupported_mst; + } + break; + + case VRAM_BANK_I: + mst = VRAMBankCnt & 3; + if(((VRAMBankCnt>>3)&3) != 0) PROGINFO("Bank %i: MST %i OFS %i\n", mst, ofs); + switch(mst) + { + case 0: //LCDC + vramConfiguration.banks[bank].purpose = VramConfiguration::LCDC; + MMU_vram_lcdc(bank); + break; + case 1: //BBG + vramConfiguration.banks[bank].purpose = VramConfiguration::BBG; + MMU_vram_arm9(bank,VRAM_PAGE_BBG+2); + MMU_vram_arm9(bank,VRAM_PAGE_BBG+3); //unexpected mirroring + break; + case 2: //BOBJ + vramConfiguration.banks[bank].purpose = VramConfiguration::BOBJ; + MMU_vram_arm9(bank,VRAM_PAGE_BOBJ); + MMU_vram_arm9(bank,VRAM_PAGE_BOBJ+1); //FF3 end scene (lens flare sprite) needs this as it renders a sprite off the end of the 16KB and back around + break; + case 3: //B OBJ extended palette + vramConfiguration.banks[bank].purpose = VramConfiguration::BOBJEXTPAL; + MMU.ObjExtPal[1][0] = MMU_vram_physical(vram_bank_info[bank].page_addr); + MMU.ObjExtPal[1][1] = MMU.ObjExtPal[1][1] + ADDRESS_STEP_8KB; + break; + default: goto unsupported_mst; + } + break; + + + } //switch(bank) + + vramConfiguration.banks[bank].ofs = ofs; + + return; + +unsupported_mst: + vramConfiguration.banks[bank].purpose = VramConfiguration::INVALID; + PROGINFO("Unsupported mst setting %d for vram bank %c\n", mst, 'A'+bank); +} + +void MMU_VRAM_unmap_all() +{ + vramConfiguration.clear(); + + vram_arm7_map[0] = VRAM_PAGE_UNMAPPED; + vram_arm7_map[1] = VRAM_PAGE_UNMAPPED; + + for(int i=0;iNDS_3D_VramReconfigureSignal(); + } + + //------------------------------- + //set up arm9 mirrorings + //these are probably not entirely accurate. more study will be necessary. + //in general, we find that it is not uncommon at all for games to accidentally do this. + // + //being able to easily do these experiments was one of the primary motivations for this remake of the vram mapping system + + //see the "unexpected mirroring" comments above for some more mirroring + //so far "unexpected mirrorings" are tested by combining these games: + //despereaux - storybook subtitles + //NSMB - world map sub screen + //drill spirits EU - mission select (just for control purposes, as it doesnt use H or I) + //... + //note that the "unexpected mirroring" items above may at some point rely on being executed in a certain order. + //(sequentially A..I) + + const int types[] = {VRAM_PAGE_ABG,VRAM_PAGE_BBG,VRAM_PAGE_AOBJ,VRAM_PAGE_BOBJ}; + const int sizes[] = {32,8,16,8}; + for(int t=0;t<4;t++) + { + //the idea here is to pad out the mirrored space with copies of the mappable area, + //without respect to what is mapped within that mappable area. + //we hope that this is correct in all cases + //required for driller spirits in mission select (mapping is simple A,B,C,D to each purpose) + const int size = sizes[t]; + const int mask = size-1; + const int type = types[t]; + for(int i=size;i<128;i++) + { + const int page = type + i; + vram_arm9_map[page] = vram_arm9_map[type+(i&mask)]; + } + + //attempt #1: screen corruption in drill spirits EU + //it seems like these shouldnt pad out 128K banks (space beyond those should have remained unmapped) + //int mirrorMask = -1; + //int type = types[t]; + ////if(type==VRAM_PAGE_BOBJ) continue; + //if(type==VRAM_PAGE_AOBJ) continue; + //for(int i=0;i<128;i++) + //{ + // int page = type + i; + // if(vram_arm9_map[page] == VRAM_PAGE_UNMAPPED) + // { + // if(i==0) break; //can't mirror anything if theres nothing mapped! + // if(mirrorMask == -1) + // mirrorMask = i-1; + // vram_arm9_map[page] = vram_arm9_map[type+(i&mirrorMask)]; + // } + //} + } + + //------------------------------- +} + +////////////////////////////////////////////////////////////// +//end vram +////////////////////////////////////////////////////////////// + + + +void MMU_Init(void) { + LOG("MMU init\n"); + + memset(&MMU, 0, sizeof(MMU_struct)); + + MMU.CART_ROM = MMU.UNUSED_RAM; + + //MMU.DTCMRegion = 0x027C0000; + //even though apps may change dtcm immediately upon startup, this is the correct hardware starting value: + MMU.DTCMRegion = 0x08000000; + MMU.ITCMRegion = 0x00000000; + + IPC_FIFOinit(ARMCPU_ARM9); + IPC_FIFOinit(ARMCPU_ARM7); + GFX_PIPEclear(); + GFX_FIFOclear(); + DISP_FIFOinit(); + new(&MMU_new) MMU_struct_new; + + mc_init(&MMU.fw, MC_TYPE_FLASH); /* init fw device */ + mc_alloc(&MMU.fw, NDS_FW_SIZE_V1); + MMU.fw.fp = NULL; + MMU.fw.isFirmware = true; + + // Init Backup Memory device, this should really be done when the rom is loaded + //mc_init(&MMU.bupmem, MC_TYPE_AUTODETECT); + //mc_alloc(&MMU.bupmem, 1); + //MMU.bupmem.fp = NULL; + rtcInit(); + addonsInit(); + slot1Init(); + if(Mic_Init() == FALSE) + INFO("Microphone init failed.\n"); + else + INFO("Microphone successfully inited.\n"); +} + +void MMU_DeInit(void) { + LOG("MMU deinit\n"); + if (MMU.fw.fp) + fclose(MMU.fw.fp); + mc_free(&MMU.fw); + //if (MMU.bupmem.fp) + // fclose(MMU.bupmem.fp); + //mc_free(&MMU.bupmem); + addonsClose(); + slot1Close(); + Mic_DeInit(); +} + +void MMU_Reset() +{ + memset(MMU.ARM9_DTCM, 0, sizeof(MMU.ARM9_DTCM)); + memset(MMU.ARM9_ITCM, 0, sizeof(MMU.ARM9_ITCM)); + memset(MMU.ARM9_LCD, 0, sizeof(MMU.ARM9_LCD)); + memset(MMU.ARM9_OAM, 0, sizeof(MMU.ARM9_OAM)); + memset(MMU.ARM9_REG, 0, sizeof(MMU.ARM9_REG)); + memset(MMU.ARM9_VMEM, 0, sizeof(MMU.ARM9_VMEM)); + memset(MMU.MAIN_MEM, 0, sizeof(MMU.MAIN_MEM)); + + memset(MMU.blank_memory, 0, sizeof(MMU.blank_memory)); + memset(MMU.UNUSED_RAM, 0, sizeof(MMU.UNUSED_RAM)); + memset(MMU.MORE_UNUSED_RAM, 0, sizeof(MMU.UNUSED_RAM)); + + memset(MMU.ARM7_ERAM, 0, sizeof(MMU.ARM7_ERAM)); + memset(MMU.ARM7_REG, 0, sizeof(MMU.ARM7_REG)); + memset(MMU.ARM7_WIRAM, 0, sizeof(MMU.ARM7_WIRAM)); + memset(MMU.SWIRAM, 0, sizeof(MMU.SWIRAM)); + + IPC_FIFOinit(ARMCPU_ARM9); + IPC_FIFOinit(ARMCPU_ARM7); + GFX_PIPEclear(); + GFX_FIFOclear(); + DISP_FIFOinit(); + + MMU.DTCMRegion = 0x027C0000; + MMU.ITCMRegion = 0x00000000; + + memset(MMU.timer, 0, sizeof(u16) * 2 * 4); + memset(MMU.timerMODE, 0, sizeof(s32) * 2 * 4); + memset(MMU.timerON, 0, sizeof(u32) * 2 * 4); + memset(MMU.timerRUN, 0, sizeof(u32) * 2 * 4); + memset(MMU.timerReload, 0, sizeof(u16) * 2 * 4); + + memset(MMU.reg_IME, 0, sizeof(u32) * 2); + memset(MMU.reg_IE, 0, sizeof(u32) * 2); + memset(MMU.reg_IF_bits, 0, sizeof(u32) * 2); + memset(MMU.reg_IF_pending, 0, sizeof(u32) * 2); + + memset(MMU.dscard, 0, sizeof(nds_dscard) * 2); + + MMU.divRunning = 0; + MMU.divResult = 0; + MMU.divMod = 0; + MMU.divCycles = 0; + + MMU.sqrtRunning = 0; + MMU.sqrtResult = 0; + MMU.sqrtCycles = 0; + + MMU.SPI_CNT = 0; + MMU.AUX_SPI_CNT = 0; + + // Enable the sound speakers + T1WriteWord(MMU.ARM7_REG, 0x304, 0x0001); + + MainScreen.offset = 0; + SubScreen.offset = 192; + + MMU_VRAM_unmap_all(); + + MMU.powerMan_CntReg = 0x00; + MMU.powerMan_CntRegWritten = FALSE; + MMU.powerMan_Reg[0] = 0x0B; + MMU.powerMan_Reg[1] = 0x00; + MMU.powerMan_Reg[2] = 0x01; + MMU.powerMan_Reg[3] = 0x00; + + rtcInit(); + partie = 1; + addonsReset(); + slot1Reset(); + Mic_Reset(); + MMU.gfx3dCycles = 0; + + memset(MMU.dscard[ARMCPU_ARM9].command, 0, 8); + MMU.dscard[ARMCPU_ARM9].address = 0; + MMU.dscard[ARMCPU_ARM9].transfer_count = 0; + MMU.dscard[ARMCPU_ARM9].mode = CardMode_Normal; + + memset(MMU.dscard[ARMCPU_ARM7].command, 0, 8); + MMU.dscard[ARMCPU_ARM7].address = 0; + MMU.dscard[ARMCPU_ARM7].transfer_count = 0; + MMU.dscard[ARMCPU_ARM7].mode = CardMode_Normal; + + //HACK!!! + //until we improve all our session tracking stuff, we need to save the backup memory filename + std::string bleh = MMU_new.backupDevice.getFilename(); + BackupDevice tempBackupDevice; + bool bleh2 = MMU_new.backupDevice.isMovieMode; + if(bleh2) tempBackupDevice = MMU_new.backupDevice; + reconstruct(&MMU_new); + if(bleh2) { + MMU_new.backupDevice = tempBackupDevice; + MMU_new.backupDevice.reset_hardware(); + } + else MMU_new.backupDevice.load_rom(bleh.c_str()); + + MMU_timing.arm7codeFetch.Reset(); + MMU_timing.arm7dataFetch.Reset(); + MMU_timing.arm9codeFetch.Reset(); + MMU_timing.arm9dataFetch.Reset(); + MMU_timing.arm9codeCache.Reset(); + MMU_timing.arm9dataCache.Reset(); +} + +void SetupMMU(bool debugConsole, bool dsi) { + if(debugConsole) _MMU_MAIN_MEM_MASK = 0x7FFFFF; + else _MMU_MAIN_MEM_MASK = 0x3FFFFF; + if(dsi) _MMU_MAIN_MEM_MASK = 0xFFFFFF; + _MMU_MAIN_MEM_MASK16 = _MMU_MAIN_MEM_MASK & ~1; + _MMU_MAIN_MEM_MASK32 = _MMU_MAIN_MEM_MASK & ~3; +} + +void MMU_setRom(u8 * rom, u32 mask) +{ + MMU.CART_ROM = rom; +} + +void MMU_unsetRom() +{ + MMU.CART_ROM=MMU.UNUSED_RAM; +} + +static void execsqrt() { + u32 ret; + u8 mode = MMU_new.sqrt.mode; + MMU_new.sqrt.busy = 1; + + if (mode) { + u64 v = T1ReadQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2B8); + ret = (u32)isqrt(v); + } else { + u32 v = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2B8); + ret = (u32)isqrt(v); + } + + //clear the result while the sqrt unit is busy + //todo - is this right? is it reasonable? + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2B4, 0); + + MMU.sqrtCycles = nds_timer + 26; + MMU.sqrtResult = ret; + MMU.sqrtRunning = TRUE; + NDS_Reschedule(); +} + +static void execdiv() { + + s64 num,den; + s64 res,mod; + u8 mode = MMU_new.div.mode; + MMU_new.div.busy = 1; + MMU_new.div.div0 = 0; + + switch(mode) + { + case 0: // 32/32 + num = (s64) (s32) T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x290); + den = (s64) (s32) T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x298); + MMU.divCycles = nds_timer + 36; + break; + case 1: // 64/32 + case 3: //gbatek says this is same as mode 1 + num = (s64) T1ReadQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x290); + den = (s64) (s32) T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x298); + MMU.divCycles = nds_timer + 68; + break; + case 2: // 64/64 + default: + num = (s64) T1ReadQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x290); + den = (s64) T1ReadQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x298); + MMU.divCycles = nds_timer + 68; + break; + } + + if(den==0) + { + res = ((num < 0) ? 1 : -1); + mod = num; + + // the DIV0 flag in DIVCNT is set only if the full 64bit DIV_DENOM value is zero, even in 32bit mode + if ((u64)T1ReadQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x298) == 0) + MMU_new.div.div0 = 1; + } + else + { + res = num / den; + mod = num % den; + } + + DIVLOG("DIV %08X%08X / %08X%08X = %08X%08X\r\n", (u32)(num>>32), (u32)num, + (u32)(den>>32), (u32)den, + (u32)(res>>32), (u32)res); + + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A0, 0); + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A4, 0); + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A8, 0); + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2AC, 0); + + MMU.divResult = res; + MMU.divMod = mod; + MMU.divRunning = TRUE; + NDS_Reschedule(); +} + +DSI_TSC::DSI_TSC() +{ + for(int i=0;i>1)&0x7F; + read_flag = val&1; + state = 1; + return read16(); + case 1: + if(read_flag) + { } + else + { + registers[reg_selection] = (u8)val; + } + ret = read16(); + reg_selection++; + reg_selection &= 0x7F; + return ret; + } + return 0; +} + +u16 DSI_TSC::read16() +{ + u8 page = registers[0]; + switch(page) + { + case 3: //page 3 + switch(reg_selection) + { + case 9: + if(nds.isTouch) + return 0; + else return 0x40; + break; + case 14: + if(nds.isTouch) + return 0; + else return 0x02; + break; + } + break; + + case 252: //page 252 + switch(reg_selection) + { + //high byte of X: + case 1: case 3: case 5: case 7: case 9: + return (nds.scr_touchX>>8)&0xFF; + + //low byte of X: + case 2: case 4: case 6: case 8: case 10: + return nds.scr_touchX&0xFF; + + //high byte of Y: + case 11: case 13: case 15: case 17: case 19: + return (nds.scr_touchY>>8)&0xFF; + + //low byte of Y: + case 12: case 14: case 16: case 18: case 20: + return nds.scr_touchY&0xFF; + + default: + return 0xFF; + } + break; + } //switch(page) + + //unknown page or register + return 0xFF; +} + +bool DSI_TSC::save_state(EMUFILE* os) +{ + u32 version = 0; + write32le(version,os); + + write8le(reg_selection,os); + write8le(read_flag,os); + write32le(state,os); + write32le(readcount,os); + for(int i=0;i +void FASTCALL MMU_writeToGCControl(u32 val) +{ + const int TEST_PROCNUM = PROCNUM; + nds_dscard& card = MMU.dscard[TEST_PROCNUM]; + + memcpy(&card.command[0], &MMU.MMU_MEM[TEST_PROCNUM][0x40][0x1A8], 8); + + card.blocklen = 0; + slot1_device.write32(PROCNUM,0xFFFFFFFF,val); //Special case for some flashcarts + if(card.blocklen==0x01020304) return; + + if(!(val & 0x80000000)) + { + card.address = 0; + card.transfer_count = 0; + + val &= 0x7F7FFFFF; + T1WriteLong(MMU.MMU_MEM[TEST_PROCNUM][0x40], 0x1A4, val); + return; + } + + u32 shift = (val>>24&7); + if(shift == 7) + card.transfer_count = 1; + else if(shift == 0) + card.transfer_count = 0; + else + card.transfer_count = (0x100< +u32 MMU_readFromGC() +{ + const int TEST_PROCNUM = PROCNUM; + + nds_dscard& card = MMU.dscard[TEST_PROCNUM]; + u32 val = 0; + + if(card.transfer_count == 0) + return 0; + + switch(card.command[0]) + { + case 0x9F: //Dummy + val = 0xFFFFFFFF; + break; + + case 0x3C: //Switch to KEY1 mode + val = 0xFFFFFFFF; + break; + + default: + val = slot1_device.read32(TEST_PROCNUM, REG_GCDATAIN); + break; + } + + card.address += 4; // increment address + + card.transfer_count--; // update transfer counter + if(card.transfer_count) // if transfer is not ended + return val; // return data + + // transfer is done + T1WriteLong(MMU.MMU_MEM[TEST_PROCNUM][0x40], 0x1A4, + T1ReadLong(MMU.MMU_MEM[TEST_PROCNUM][0x40], 0x1A4) & 0x7F7FFFFF); + + // if needed, throw irq for the end of transfer + if(MMU.AUX_SPI_CNT & 0x4000) + NDS_makeIrq(TEST_PROCNUM, IRQ_BIT_GC_TRANSFER_COMPLETE); + + return val; +} + + + +//does some validation on the game's choice of IF value, correcting it if necessary +static void validateIF_arm9() +{ +} + +template static void REG_IF_WriteByte(u32 addr, u8 val) +{ + //the following bits are generated from logic and should not be affected here + //Bit 21 NDS9 only: Geometry Command FIFO + //arm9: IF &= ~0x00200000; + //arm7: IF &= ~0x00000000; + //UPDATE IN setIF() ALSO!!!!!!!!!!!!!!!! + //UPDATE IN mmu_loadstate ALSO!!!!!!!!!!!! + if (addr==2) { + if(PROCNUM==ARMCPU_ARM9) + val &= ~0x20; + else + val &= ~0x00; + } + + //ZERO 01-dec-2010 : I am no longer sure this approach is correct.. it proved to be wrong for IPC fifo....... + //it seems as if IF bits should always be cached (only the user can clear them) + + MMU.reg_IF_bits[PROCNUM] &= (~(((u32)val)<<(addr<<3))); + NDS_Reschedule(); +} + +template static void REG_IF_WriteWord(u32 addr,u16 val) +{ + REG_IF_WriteByte(addr,val&0xFF); + REG_IF_WriteByte(addr+1,(val>>8)&0xFF); +} + +template static void REG_IF_WriteLong(u32 val) +{ + REG_IF_WriteByte(0,val&0xFF); + REG_IF_WriteByte(1,(val>>8)&0xFF); + REG_IF_WriteByte(2,(val>>16)&0xFF); + REG_IF_WriteByte(3,(val>>24)&0xFF); +} + +template +u32 MMU_struct::gen_IF() +{ + u32 IF = reg_IF_bits[PROCNUM]; + + if(PROCNUM==ARMCPU_ARM9) + { + //according to gbatek, these flags are forced on until the condition is removed. + //no proof of this though... + switch(MMU_new.gxstat.gxfifo_irq) + { + case 0: //never + break; + case 1: //less than half full + if(MMU_new.gxstat.fifo_low) + IF |= IRQ_MASK_ARM9_GXFIFO; + break; + case 2: //empty + if(MMU_new.gxstat.fifo_empty) + IF |= IRQ_MASK_ARM9_GXFIFO; + break; + case 3: //reserved/unknown + break; + } + } + + return IF; +} + +static void writereg_DISP3DCNT(const int size, const u32 adr, const u32 val) +{ + //UGH. rewrite this shite to use individual values and reconstruct the return value instead of packing things in this !@#)ing register + + //nanostray2 cutscene will test this vs old desmumes by using some kind of 32bit access for setting up this reg for cutscenes + switch(size) + { + case 8: + switch(adr) + { + case REG_DISPA_DISP3DCNT: + MMU.reg_DISP3DCNT_bits &= 0xFFFFFF00; + MMU.reg_DISP3DCNT_bits |= val; + gfx3d_Control(MMU.reg_DISP3DCNT_bits); + break; + case REG_DISPA_DISP3DCNT+1: + { + u32 myval = (val & ~0x30) | (~val & ((MMU.reg_DISP3DCNT_bits>>8) & 0x30)); // bits 12,13 are ack bits + myval &= 0x7F; //top bit isnt connected + MMU.reg_DISP3DCNT_bits = MMU.reg_DISP3DCNT_bits&0xFFFF00FF; + MMU.reg_DISP3DCNT_bits |= (myval<<8); + gfx3d_Control(MMU.reg_DISP3DCNT_bits); + } + break; + } + break; + case 16: + case 32: + writereg_DISP3DCNT(8,adr,val&0xFF); + writereg_DISP3DCNT(8,adr+1,(val>>8)&0xFF); + break; + } +} + +static u32 readreg_DISP3DCNT(const int size, const u32 adr) +{ + //UGH. rewrite this shite to use individual values and reconstruct the return value instead of packing things in this !@#)ing register + switch(size) + { + case 8: + switch(adr) + { + case REG_DISPA_DISP3DCNT: + return MMU.reg_DISP3DCNT_bits & 0xFF; + case REG_DISPA_DISP3DCNT+1: + return ((MMU.reg_DISP3DCNT_bits)>>8)& 0xFF; + } + break; + case 16: + case 32: + return readreg_DISP3DCNT(8,adr)|(readreg_DISP3DCNT(8,adr+1)<<8); + } + assert(false); + return 0; +} + + +static u32 readreg_POWCNT1(const int size, const u32 adr) { + switch(size) + { + case 8: + switch(adr) + { + case REG_POWCNT1: { + u8 ret = 0; + ret |= nds.power1.lcd?BIT(0):0; + ret |= nds.power1.gpuMain?BIT(1):0; + ret |= nds.power1.gfx3d_render?BIT(2):0; + ret |= nds.power1.gfx3d_geometry?BIT(3):0; + return ret; + } + case REG_POWCNT1+1: { + u8 ret = 0; + ret |= nds.power1.gpuSub?BIT(1):0; + ret |= nds.power1.dispswap?BIT(7):0; + return ret; + } + default: + return 0; } + case 16: + case 32: + return readreg_POWCNT1(8,adr)|(readreg_POWCNT1(8,adr+1)<<8); + } + assert(false); + return 0; +} +static void writereg_POWCNT1(const int size, const u32 adr, const u32 val) { + switch(size) + { + case 8: + switch(adr) + { + case REG_POWCNT1: + nds.power1.lcd = BIT0(val); + nds.power1.gpuMain = BIT1(val); + nds.power1.gfx3d_render = BIT2(val); + nds.power1.gfx3d_geometry = BIT3(val); + break; + case REG_POWCNT1+1: + nds.power1.gpuSub = BIT1(val); + nds.power1.dispswap = BIT7(val); + if(nds.power1.dispswap) + { + //printf("Main core on top (vcount=%d)\n",nds.VCount); + MainScreen.offset = 0; + SubScreen.offset = 192; + } + else + { + //printf("Main core on bottom (vcount=%d)\n",nds.VCount); + MainScreen.offset = 192; + SubScreen.offset = 0; + } + break; + } + break; + case 16: + case 32: + writereg_POWCNT1(8,adr,val&0xFF); + writereg_POWCNT1(8,adr+1,(val>>8)&0xFF); + break; + } +} + +static INLINE void MMU_IPCSync(u8 proc, u32 val) +{ + //INFO("IPC%s sync 0x%04X (0x%02X|%02X)\n", proc?"7":"9", val, val >> 8, val & 0xFF); + u32 sync_l = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x180) & 0xFFFF; + u32 sync_r = T1ReadLong(MMU.MMU_MEM[proc^1][0x40], 0x180) & 0xFFFF; + + sync_l = ( sync_l & 0x000F ) | ( val & 0x0F00 ); + sync_r = ( sync_r & 0x6F00 ) | ( (val >> 8) & 0x000F ); + + sync_l |= val & 0x6000; + + if(nds.ensataEmulation && proc==1 && nds.ensataIpcSyncCounter<9) { + u32 iteration = (val&0x0F00)>>8; + + if(iteration==8-nds.ensataIpcSyncCounter) + nds.ensataIpcSyncCounter++; + else printf("ERROR: ENSATA IPC SYNC HACK FAILED; BAD THINGS MAY HAPPEN\n"); + + //for some reason, the arm9 doesn't handshake when ensata is detected. + //so we complete the protocol here, which is to mirror the values 8..0 back to + //the arm7 as they are written by the arm7 + sync_r &= 0xF0FF; + sync_r |= (iteration<<8); + sync_l &= 0xFFF0; + sync_l |= iteration; + } + + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x180, sync_l); + T1WriteLong(MMU.MMU_MEM[proc^1][0x40], 0x180, sync_r); + + if ((sync_l & IPCSYNC_IRQ_SEND) && (sync_r & IPCSYNC_IRQ_RECV)) + NDS_makeIrq(proc^1, IRQ_BIT_IPCSYNC); + + NDS_Reschedule(); +} + +static INLINE u16 read_timer(int proc, int timerIndex) +{ + //chained timers are always up to date + if(MMU.timerMODE[proc][timerIndex] == 0xFFFF) + return MMU.timer[proc][timerIndex]; + + //sometimes a timer will be read when it is not enabled. + //we should have the value cached + if(!MMU.timerON[proc][timerIndex]) + return MMU.timer[proc][timerIndex]; + + //for unchained timers, we do not keep the timer up to date. its value will need to be calculated here + s32 diff = (s32)(nds.timerCycle[proc][timerIndex] - nds_timer); + assert(diff>=0); + if(diff<0) + printf("NEW EMULOOP BAD NEWS PLEASE REPORT: TIME READ DIFF < 0 (%d) (%d) (%d)\n",diff,timerIndex,MMU.timerMODE[proc][timerIndex]); + + s32 units = diff / (1<65536) { + printf("NEW EMULOOP BAD NEWS PLEASE REPORT: UNITS %d:%d = %d\n",proc,timerIndex,units); + ret = 0; + } + else ret = 65535 - units; + + return ret; +} + +static INLINE void write_timer(int proc, int timerIndex, u16 val) +{ +#if 0 + int mask = ((val&0x80)>>7) << timerIndex; + MMU.CheckTimers = (MMU.CheckTimers & (~mask)) | mask; +#endif + + if(val&0x80) + MMU.timer[proc][timerIndex] = MMU.timerReload[proc][timerIndex]; + else + { + if(MMU.timerON[proc][timerIndex]) + //read the timer value one last time + MMU.timer[proc][timerIndex] = read_timer(proc,timerIndex); + } + + MMU.timerON[proc][timerIndex] = val & 0x80; + + switch(val&7) + { + case 0 : + MMU.timerMODE[proc][timerIndex] = 0+1; + break; + case 1 : + MMU.timerMODE[proc][timerIndex] = 6+1; + break; + case 2 : + MMU.timerMODE[proc][timerIndex] = 8+1; + break; + case 3 : + MMU.timerMODE[proc][timerIndex] = 10+1; + break; + default : + MMU.timerMODE[proc][timerIndex] = 0xFFFF; + break; + } + + int remain = 65536 - MMU.timerReload[proc][timerIndex]; + nds.timerCycle[proc][timerIndex] = nds_timer + (remain<=255) ret |= BIT(24); //fifo full + if(gxFIFO.size<128) ret |= BIT(25); //fifo half + if(gxFIFO.size==0) ret |= BIT(26); //fifo empty + //determine busy flag. + //if we're waiting for a flush, we're busy + if(isSwapBuffers) ret |= BIT(27); + //if fifo is nonempty, we're busy + if(gxFIFO.size!=0) ret |= BIT(27); + + //printf("[%d] %d %d %d\n",currFrameCounter,se,sb,gxFIFO.size!=0); + + + ret |= ((gxfifo_irq & 0x3) << 30); //user's irq flags + + //printf("vc=%03d Returning gxstat read: %08X (isSwapBuffers=%d)\n",nds.VCount,ret,isSwapBuffers); + + //ret = (2 << 8); + //INFO("gxSTAT 0x%08X (proj %i, pos %i)\n", ret, _hack_getMatrixStackLevel(1), _hack_getMatrixStackLevel(2)); + return ret; +} + +void TGXSTAT::write32(const u32 val) +{ + gxfifo_irq = (val>>30)&3; + if(BIT15(val)) + { + // Writing "1" to Bit15 does reset the Error Flag (Bit15), + // and additionally resets the Projection Stack Pointer (Bit13) + mtxStack[0].position = 0; + se = 0; //clear stack error flag + } + //printf("gxstat write: %08X while gxfifo.size=%d\n",val,gxFIFO.size); + + //if (val & (1<<29)) // clear? (only in homebrew?) + //{ + // GFX_PIPEclear(); + // GFX_FIFOclear(); + // return; + //} +} + +void TGXSTAT::savestate(EMUFILE *f) +{ + write32le(1,f); //version + write8le(tb,f); write8le(tr,f); write8le(se,f); write8le(gxfifo_irq,f); write8le(sb,f); +} +bool TGXSTAT::loadstate(EMUFILE *f) +{ + u32 version; + if(read32le(&version,f) != 1) return false; + if(version > 1) return false; + + read8le(&tb,f); read8le(&tr,f); read8le(&se,f); read8le(&gxfifo_irq,f); + if (version >= 1) + read8le(&sb,f); + + return true; +} + +//this could be inlined... +void MMU_struct_new::write_dma(const int proc, const int size, const u32 _adr, const u32 val) +{ + //printf("%08lld -- write_dma: %d %d %08X %08X\n",nds_timer,proc,size,_adr,val); + const u32 adr = _adr - _REG_DMA_CONTROL_MIN; + const u32 chan = adr/12; + const u32 regnum = (adr - chan*12)>>2; + + if(proc==0&&chan==0) + { + int zzz=9; + } + + if(proc==1) { + int zzz=9; + } + + MMU_new.dma[proc][chan].regs[regnum]->write(size,adr,val); +} + + +//this could be inlined... +u32 MMU_struct_new::read_dma(const int proc, const int size, const u32 _adr) +{ + const u32 adr = _adr - _REG_DMA_CONTROL_MIN; + const u32 chan = adr/12; + const u32 regnum = (adr - chan*12)>>2; + + const u32 temp = MMU_new.dma[proc][chan].regs[regnum]->read(size,adr); + //printf("%08lld -- read_dma: %d %d %08X = %08X\n",nds_timer,proc,size,_adr,temp); + + + + if(temp == 0xAF00 && size == 16) + { + int zzz=9; + } + + return temp; +} + +MMU_struct_new::MMU_struct_new() +{ + for(int i=0;i<2;i++) + for(int j=0;j<4;j++) { + dma[i][j].procnum = i; + dma[i][j].chan = j; + } +} + +bool DmaController::loadstate(EMUFILE* f) +{ + u32 version; + if(read32le(&version,f) != 1) return false; + if(version >1) return false; + + read8le(&enable,f); read8le(&irq,f); read8le(&repeatMode,f); read8le(&_startmode,f); + read8le(&userEnable,f); + read32le(&wordcount,f); + u8 temp; + read8le(&temp,f); startmode = (EDMAMode)temp; + read8le(&temp,f); bitWidth = (EDMABitWidth)temp; + read8le(&temp,f); sar = (EDMASourceUpdate)temp; + read8le(&temp,f); dar = (EDMADestinationUpdate)temp; + read32le(&saddr,f); read32le(&daddr,f); + read32le(&dmaCheck,f); read32le(&running,f); read32le(&paused,f); read32le(&triggered,f); + read64le(&nextEvent,f); + + if(version==1) + { + read32le(&saddr_user,f); + read32le(&daddr_user,f); + } + + return true; +} + +void DmaController::savestate(EMUFILE *f) +{ + write32le(1,f); //version + write8le(enable,f); write8le(irq,f); write8le(repeatMode,f); write8le(_startmode,f); + write8le(userEnable,f); + write32le(wordcount,f); + write8le(startmode,f); + write8le(bitWidth,f); + write8le(sar,f); + write8le(dar,f); + write32le(saddr,f); write32le(daddr,f); + write32le(dmaCheck,f); write32le(running,f); write32le(paused,f); write32le(triggered,f); + write64le(nextEvent,f); + write32le(saddr_user,f); + write32le(daddr_user,f); +} + +void DmaController::write32(const u32 val) +{ + if(this->chan==0 && this->procnum==0) + { + int zzz=9; + } + if(running) + { + //desp triggers this a lot. figure out whats going on + //printf("thats weird..user edited dma control while it was running\n"); + } + //printf("dma %d,%d WRITE %08X\n",procnum,chan,val); + wordcount = val&0x1FFFFF; + if(wordcount==0x9FbFC || wordcount == 0x1FFFFC || wordcount == 0x1EFFFC || wordcount == 0x1FFFFF) { + int zzz=9; + } + u8 wasRepeatMode = repeatMode; + u8 wasEnable = enable; + u32 valhi = val>>16; + dar = (EDMADestinationUpdate)((valhi>>5)&3); + sar = (EDMASourceUpdate)((valhi>>7)&3); + repeatMode = BIT9(valhi); + bitWidth = (EDMABitWidth)BIT10(valhi); + _startmode = (valhi>>11)&7; + if(procnum==ARMCPU_ARM7) _startmode &= 6; + irq = BIT14(valhi); + enable = BIT15(valhi); + + if(val==0x84400076 && saddr ==0x023BCEC4) + { + int zzz=9; + } + + //if(irq) printf("!!!!!!!!!!!!IRQ!!!!!!!!!!!!!\n"); + + //make sure we don't get any old triggers + if(!wasEnable && enable) + triggered = FALSE; + + if(enable) + { + //address registers are reloaded from user's settings whenever dma is enabled + //this is tested well by contra4 classic games, which use this to hdma scroll registers + //specifically in the fit-screen mode. + saddr = saddr_user; + daddr = daddr_user; + } + + //printf("dma %d,%d set to startmode %d with wordcount set to: %08X\n",procnum,chan,_startmode,wordcount); +if(_startmode==0 && wordcount==1) { + int zzz=9; +} + if(enable) + { + int zzz=9; + } + + if (enable && procnum==1 && (!(chan&1)) && _startmode==6) + printf("!!!---!!! WIFI DMA: %08X TO %08X, %i WORDS !!!---!!!\n", saddr, daddr, wordcount); + + //analyze enabling and startmode. + //note that we only do this if the dma was freshly enabled. + //we should probably also only be latching these other regs in that case too.. + //but for now just this one will do (otherwise the dma repeat stop procedure (in this case the ff4 title menu load with gamecard dma) will fail) + //if(!running) enable = userEnable; + + //if we were previously in a triggered mode, and were already enabled, + //then don't re-trigger now. this is rather confusing.. + //we really only want to auto-trigger gxfifo and immediate modes. + //but we don't know what mode we're in yet. + //so this is our workaround + //(otherwise the dma repeat stop procedure (in this case the ff4 title menu load with gamecard dma) will fail) + bool doNotStart = false; + if(startmode != EDMAMode_Immediate && startmode != EDMAMode_GXFifo && wasEnable) doNotStart = true; + + //this dma may need to trigger now, so give it a chance + //if(!(wasRepeatMode && !repeatMode)) //this was an older test + if(!doNotStart) + doSchedule(); + + driver->DEBUG_UpdateIORegView(BaseDriver::EDEBUG_IOREG_DMA); +} + +void DmaController::exec() +{ + //this function runs when the DMA ends. the dma start actually queues this event after some kind of guess as to how long the DMA should take + + //we'll need to unfreeze the arm9 bus now + if(procnum==ARMCPU_ARM9) nds.freezeBus &= ~(1<<(chan+1)); + + dmaCheck = FALSE; + + if(running) + { + switch(startmode) { + case EDMAMode_GXFifo: + //this dma mode won't finish always its job when it gets signalled + //sometimes it will have words left to transfer. + //if(!paused) printf("gxfifo dma ended with %d remaining\n",wordcount); //only print this once + if(wordcount>0) { + doPause(); + break; + } + default: + doStop(); + driver->DEBUG_UpdateIORegView(BaseDriver::EDEBUG_IOREG_DMA); + return; + } + } + + if(enable) + { + //analyze startmode (this only gets latched when a dma begins) + if(procnum==ARMCPU_ARM9) startmode = (EDMAMode)_startmode; + else { + //arm7 startmode analysis: + static const EDMAMode lookup[] = {EDMAMode_Immediate,EDMAMode_VBlank,EDMAMode_Card,EDMAMode7_Wifi}; + //arm7 has a slightly different startmode encoding + startmode = lookup[_startmode>>1]; + if(startmode == EDMAMode7_Wifi && (chan==1 || chan==3)) + startmode = EDMAMode7_GBASlot; + } + + //make it run, if it is triggered + //but first, scan for triggering conditions + switch(startmode) { + case EDMAMode_Immediate: + triggered = TRUE; + break; + case EDMAMode_GXFifo: + if(gxFIFO.size<=127) + triggered = TRUE; + break; + default: + break; + } + + if(triggered) + { + //if(procnum==0) printf("vc=%03d %08lld trig type %d dma#%d w/words %d at src:%08X dst:%08X gxf:%d",nds.VCount,nds_timer,startmode,chan,wordcount,saddr,daddr,gxFIFO.size); + if(saddr ==0x023BCCEC && wordcount==118) { + int zzz=9; + } + if(startmode==0 && daddr == 0x4000400) { + int zzz=9; + } + running = TRUE; + paused = FALSE; + if(procnum == ARMCPU_ARM9) doCopy(); + else doCopy(); + //printf(";%d\n",gxFIFO.size); + } + } + + driver->DEBUG_UpdateIORegView(BaseDriver::EDEBUG_IOREG_DMA); +} + +template +void DmaController::doCopy() +{ + //generate a copy count depending on various copy mode's behavior + u32 todo = wordcount; + if(todo == 0) todo = 0x200000; //according to gbatek.. //TODO - this should not work this way for arm7 according to gbatek + if(startmode == EDMAMode_MemDisplay) + { + todo = 128; //this is a hack. maybe an alright one though. it should be 4 words at a time. this is a whole scanline + + //apparently this dma turns off after it finishes a frame + if(nds.VCount==191) enable = 0; + } + if(startmode == EDMAMode_Card) todo *= 0x80; + if(startmode == EDMAMode_GXFifo) todo = std::min(todo,(u32)112); + + //determine how we're going to copy + bool bogarted = false; + u32 sz = (bitWidth==EDMABitWidth_16)?2:4; + u32 dstinc,srcinc; + switch(dar) { + case EDMADestinationUpdate_Increment : dstinc = sz; break; + case EDMADestinationUpdate_Decrement : dstinc = (u32)-(s32)sz; break; + case EDMADestinationUpdate_Fixed : dstinc = 0; break; + case EDMADestinationUpdate_IncrementReload : dstinc = sz; break; + default: bogarted = true; break; + } + switch(sar) { + case EDMASourceUpdate_Increment : srcinc = sz; break; + case EDMASourceUpdate_Decrement : srcinc = (u32)-(s32)sz; break; + case EDMASourceUpdate_Fixed : srcinc = 0; break; + case EDMASourceUpdate_Invalid : bogarted = true; break; + default: bogarted = true; break; + } + + //need to figure out what to do about this + if(bogarted) + { + printf("YOUR GAME IS BOGARTED!!! PLEASE REPORT!!!\n"); + assert(false); + return; + } + + u32 src = saddr; + u32 dst = daddr; + + + //if these do not use MMU_AT_DMA and the corresponding code in the read/write routines, + //then danny phantom title screen will be filled with a garbage char which is made by + //dmaing from 0x00000000 to 0x06000000 + //TODO - these might be losing out a lot by not going through the templated version anymore. + //we might make another function to do just the raw copy op which can use them with checks + //outside the loop + int time_elapsed = 0; + if(sz==4) { + for(s32 i=(s32)todo; i>0; i--) + { + time_elapsed += _MMU_accesstime(src,true); + time_elapsed += _MMU_accesstime(dst,true); + u32 temp = _MMU_read32(procnum,MMU_AT_DMA,src); + _MMU_write32(procnum,MMU_AT_DMA,dst, temp); + dst += dstinc; + src += srcinc; + } + } else { + for(s32 i=(s32)todo; i>0; i--) + { + time_elapsed += _MMU_accesstime(src,true); + time_elapsed += _MMU_accesstime(dst,true); + u16 temp = _MMU_read16(procnum,MMU_AT_DMA,src); + _MMU_write16(procnum,MMU_AT_DMA,dst, temp); + dst += dstinc; + src += srcinc; + } + } + + //printf("dma of size %d took %d cycles\n",todo*sz,time_elapsed); + + //reschedule an event for the end of this dma, and figure out how much it cost us + doSchedule(); + nextEvent += time_elapsed; + + //freeze the ARM9 bus for the duration of this DMA + //thats not entirely accurate + if(procnum==ARMCPU_ARM9) + nds.freezeBus |= (1<<(chan+1)); + + //write back the addresses + saddr = src; + if(dar != EDMADestinationUpdate_IncrementReload) //but dont write back dst if we were supposed to reload + daddr = dst; + + //do wordcount accounting + if(startmode == EDMAMode_Card) + todo /= 0x80; //divide this funky one back down before subtracting it + + if(!repeatMode) + wordcount -= todo; +} + +void triggerDma(EDMAMode mode) +{ + MACRODO2(0, { + const int i=X; + MACRODO4(0, { + const int j=X; + MMU_new.dma[i][j].tryTrigger(mode); + }); + }); +} + +void DmaController::tryTrigger(EDMAMode mode) +{ + if(startmode != mode) return; + if(!enable) return; + + //hmm dont trigger it if its already running! + //but paused things need triggers to continue + if(running && !paused) return; + triggered = TRUE; + doSchedule(); +} + +void DmaController::doSchedule() +{ + dmaCheck = TRUE; + nextEvent = nds_timer; + NDS_RescheduleDMA(); +} + + +void DmaController::doPause() +{ + triggered = FALSE; + paused = TRUE; +} + +void DmaController::doStop() +{ + //if(procnum==0) printf("%08lld stop type %d dma#%d\n",nds_timer,startmode,chan); + running = FALSE; + if(!repeatMode) enable = FALSE; + if(irq) { + NDS_makeIrq(procnum,IRQ_BIT_DMA_0+chan); + } +} + + + +u32 DmaController::read32() +{ + u32 ret = 0; + ret |= enable<<31; + ret |= irq<<30; + ret |= _startmode<<27; + ret |= bitWidth<<26; + ret |= repeatMode<<25; + ret |= sar<<23; + ret |= dar<<21; + ret |= wordcount; + //printf("dma %d,%d READ %08X\n",procnum,chan,ret); + if(ret == 0xAF000001) { + int zzz=9; + } + return ret; +} + +static INLINE void write_auxspicnt(const int proc, const int size, const int adr, const int val) +{ + //why val==0 to reset? is it a particular bit? its not bit 6... + switch(size) { + case 16: + MMU.AUX_SPI_CNT = val; + if (val == 0) MMU_new.backupDevice.reset_command(); + break; + case 8: + switch(adr) { + case 0: + T1WriteByte((u8*)&MMU.AUX_SPI_CNT,0,val); + if (val == 0) MMU_new.backupDevice.reset_command(); + break; + case 1: + T1WriteByte((u8*)&MMU.AUX_SPI_CNT,1,val); + break; + } + } +} + + +//================================================================================================== ARM9 * +//========================================================================================================= +//========================================================================================================= +//================================================= MMU write 08 +void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val) +{ + adr &= 0x0FFFFFFF; + + mmu_log_debug_ARM9(adr, "(write08) 0x%02X", val); + + if(adr < 0x02000000) + { + T1WriteByte(MMU.ARM9_ITCM, adr&0x7FFF, val); + return; + } + + if ( (adr >= 0x08000000) && (adr < 0x0A010000) ) + { + u16 exmemcnt = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x204); + if(exmemcnt & EXMEMCNT_MASK_SLOT2_ARM7) + {} //prohibited + else addon.write08(ARMCPU_ARM9, adr, val); + return; + } + + //block 8bit writes to OAM and palette memory + if((adr&0x0F000000)==0x07000000) return; + if((adr&0x0F000000)==0x05000000) return; + + if (adr >> 24 == 4) + { + + // TODO: add pal reg + if (nds.power1.gpuMain == 0) + if ((adr >= 0x04000008) && (adr<=0x0400005F)) return; + if (nds.power1.gpuSub == 0) + if ((adr >= 0x04001008) && (adr<=0x0400105F)) return; + if (nds.power1.gfx3d_geometry == 0) + if ((adr >= 0x04000400) && (adr<=0x040006FF)) return; + if (nds.power1.gfx3d_render == 0) + if ((adr >= 0x04000320) && (adr<=0x040003FF)) return; + + if(MMU_new.is_dma(adr)) { + MMU_new.write_dma(ARMCPU_ARM9,8,adr,val); + return; + } + + switch(adr) + { + case REG_SQRTCNT: printf("ERROR 8bit SQRTCNT WRITE\n"); return; + case REG_SQRTCNT+1: printf("ERROR 8bit SQRTCNT1 WRITE\n"); return; + case REG_SQRTCNT+2: printf("ERROR 8bit SQRTCNT2 WRITE\n"); return; + case REG_SQRTCNT+3: printf("ERROR 8bit SQRTCNT3 WRITE\n"); return; + +#if 1 + case REG_DIVCNT: printf("ERROR 8bit DIVCNT WRITE\n"); return; + case REG_DIVCNT+1: printf("ERROR 8bit DIVCNT1 WRITE\n"); return; + case REG_DIVCNT+2: printf("ERROR 8bit DIVCNT2 WRITE\n"); return; + case REG_DIVCNT+3: printf("ERROR 8bit DIVCNT3 WRITE\n"); return; +#endif + + //fog table: only write bottom 7 bits + case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x01: case eng_3D_FOG_TABLE+0x02: case eng_3D_FOG_TABLE+0x03: + case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x05: case eng_3D_FOG_TABLE+0x06: case eng_3D_FOG_TABLE+0x07: + case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x09: case eng_3D_FOG_TABLE+0x0A: case eng_3D_FOG_TABLE+0x0B: + case eng_3D_FOG_TABLE+0x0C: case eng_3D_FOG_TABLE+0x0D: case eng_3D_FOG_TABLE+0x0E: case eng_3D_FOG_TABLE+0x0F: + case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x11: case eng_3D_FOG_TABLE+0x12: case eng_3D_FOG_TABLE+0x13: + case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x15: case eng_3D_FOG_TABLE+0x16: case eng_3D_FOG_TABLE+0x17: + case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x19: case eng_3D_FOG_TABLE+0x1A: case eng_3D_FOG_TABLE+0x1B: + case eng_3D_FOG_TABLE+0x1C: case eng_3D_FOG_TABLE+0x1D: case eng_3D_FOG_TABLE+0x1E: case eng_3D_FOG_TABLE+0x1F: + val &= 0x7F; + break; + + //ensata putchar port + case 0x04FFF000: + if(nds.ensataEmulation) + { + printf("%c",val); + fflush(stdout); + } + break; + + case eng_3D_GXSTAT: + MMU_new.gxstat.write(8,adr,val); + break; + + case REG_DISPA_WIN0H: + GPU_setWIN0_H1(MainScreen.gpu, val); + break ; + case REG_DISPA_WIN0H+1: + GPU_setWIN0_H0 (MainScreen.gpu, val); + break ; + case REG_DISPA_WIN1H: + GPU_setWIN1_H1 (MainScreen.gpu,val); + break ; + case REG_DISPA_WIN1H+1: + GPU_setWIN1_H0 (MainScreen.gpu,val); + break ; + + case REG_DISPB_WIN0H: + GPU_setWIN0_H1(SubScreen.gpu,val); + break ; + case REG_DISPB_WIN0H+1: + GPU_setWIN0_H0(SubScreen.gpu,val); + break ; + case REG_DISPB_WIN1H: + GPU_setWIN1_H1(SubScreen.gpu,val); + break ; + case REG_DISPB_WIN1H+1: + GPU_setWIN1_H0(SubScreen.gpu,val); + break ; + + case REG_DISPA_WIN0V: + GPU_setWIN0_V1(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WIN0V+1: + GPU_setWIN0_V0(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WIN1V: + GPU_setWIN1_V1(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WIN1V+1: + GPU_setWIN1_V0(MainScreen.gpu,val) ; + break ; + + case REG_DISPB_WIN0V: + GPU_setWIN0_V1(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WIN0V+1: + GPU_setWIN0_V0(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WIN1V: + GPU_setWIN1_V1(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WIN1V+1: + GPU_setWIN1_V0(SubScreen.gpu,val) ; + break ; + + case REG_DISPA_WININ: + GPU_setWININ0(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WININ+1: + GPU_setWININ1(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WINOUT: + GPU_setWINOUT(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WINOUT+1: + GPU_setWINOBJ(MainScreen.gpu,val); + break ; + + case REG_DISPB_WININ: + GPU_setWININ0(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WININ+1: + GPU_setWININ1(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WINOUT: + GPU_setWINOUT(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WINOUT+1: + GPU_setWINOBJ(SubScreen.gpu,val) ; + break ; + + case REG_DISPA_BLDCNT: + GPU_setBLDCNT_HIGH(MainScreen.gpu,val); + break; + case REG_DISPA_BLDCNT+1: + GPU_setBLDCNT_LOW (MainScreen.gpu,val); + break; + + case REG_DISPB_BLDCNT: + GPU_setBLDCNT_HIGH (SubScreen.gpu,val); + break; + case REG_DISPB_BLDCNT+1: + GPU_setBLDCNT_LOW (SubScreen.gpu,val); + break; + + case REG_DISPA_BLDALPHA: + MainScreen.gpu->setBLDALPHA_EVA(val); + break; + case REG_DISPA_BLDALPHA+1: + MainScreen.gpu->setBLDALPHA_EVB(val); + break; + + case REG_DISPB_BLDALPHA: + SubScreen.gpu->setBLDALPHA_EVA(val); + break; + case REG_DISPB_BLDALPHA+1: + SubScreen.gpu->setBLDALPHA_EVB(val); + break; + + case REG_DISPA_BLDY: + GPU_setBLDY_EVY(MainScreen.gpu,val) ; + break ; + case REG_DISPB_BLDY: + GPU_setBLDY_EVY(SubScreen.gpu,val) ; + break; + + case REG_AUXSPICNT: + write_auxspicnt(9,8,0,val); + return; + case REG_AUXSPICNT+1: + write_auxspicnt(9,8,1,val); + return; + + case REG_AUXSPIDATA: + if(val!=0) MMU.AUX_SPI_CMD = val & 0xFF; + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, MMU_new.backupDevice.data_command((u8)val,ARMCPU_ARM9)); + MMU.AUX_SPI_CNT &= ~0x80; //remove busy flag + return; + + case REG_WRAMCNT: + /* Update WRAMSTAT at the ARM7 side */ + T1WriteByte(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x241, val); + break; + + case REG_POWCNT1: writereg_POWCNT1(8,adr,val); break; + + case REG_DISPA_DISP3DCNT: writereg_DISP3DCNT(8,adr,val); return; + case REG_DISPA_DISP3DCNT+1: writereg_DISP3DCNT(8,adr,val); return; + + case REG_IF: REG_IF_WriteByte(0,val); break; + case REG_IF+1: REG_IF_WriteByte(1,val); break; + case REG_IF+2: REG_IF_WriteByte(2,val); break; + case REG_IF+3: REG_IF_WriteByte(3,val); break; + + case eng_3D_CLEAR_COLOR+0: case eng_3D_CLEAR_COLOR+1: + case eng_3D_CLEAR_COLOR+2: case eng_3D_CLEAR_COLOR+3: + T1WriteByte((u8*)&gfx3d.state.clearColor,adr-eng_3D_CLEAR_COLOR,val); + break; + + case REG_VRAMCNTA: + case REG_VRAMCNTB: + case REG_VRAMCNTC: + case REG_VRAMCNTD: + case REG_VRAMCNTE: + case REG_VRAMCNTF: + case REG_VRAMCNTG: + case REG_VRAMCNTH: + case REG_VRAMCNTI: + MMU_VRAMmapControl(adr-REG_VRAMCNTA, val); + break; + case REG_DISPA_DISPMMEMFIFO: + { + DISP_FIFOsend(val); + return; + } + #ifdef LOG_CARD + case 0x040001A0 : /* TODO (clear): ??? */ + case 0x040001A1 : + case 0x040001A2 : + case 0x040001A8 : + case 0x040001A9 : + case 0x040001AA : + case 0x040001AB : + case 0x040001AC : + case 0x040001AD : + case 0x040001AE : + case 0x040001AF : + LOG("%08X : %02X\r\n", adr, val); + #endif + + } + + MMU.MMU_MEM[ARMCPU_ARM9][adr>>20][adr&MMU.MMU_MASK[ARMCPU_ARM9][adr>>20]]=val; + return; + } + + bool unmapped, restricted; + adr = MMU_LCDmap(adr, unmapped, restricted); + if(unmapped) return; + if(restricted) return; //block 8bit vram writes + + // Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [shash] + MMU.MMU_MEM[ARMCPU_ARM9][adr>>20][adr&MMU.MMU_MASK[ARMCPU_ARM9][adr>>20]]=val; +} + +//================================================= MMU ARM9 write 16 +void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val) +{ + adr &= 0x0FFFFFFE; + + mmu_log_debug_ARM9(adr, "(write16) 0x%04X", val); + + if (adr < 0x02000000) + { + T1WriteWord(MMU.ARM9_ITCM, adr&0x7FFF, val); + return; + } + + if ( (adr >= 0x08000000) && (adr < 0x0A010000) ) + { + u16 exmemcnt = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x204); + if(exmemcnt & EXMEMCNT_MASK_SLOT2_ARM7) + {} //prohibited + else addon.write16(ARMCPU_ARM9, adr, val); + return; + } + + if((adr >> 24) == 4) + { + // TODO: add pal reg + if (nds.power1.gpuMain == 0) + if ((adr >= 0x04000008) && (adr<=0x0400005F)) return; + if (nds.power1.gpuSub == 0) + if ((adr >= 0x04001008) && (adr<=0x0400105F)) return; + if (nds.power1.gfx3d_geometry == 0) + if ((adr >= 0x04000400) && (adr<=0x040006FF)) return; + if (nds.power1.gfx3d_render == 0) + if ((adr >= 0x04000320) && (adr<=0x040003FF)) return; + + if(MMU_new.is_dma(adr)) { + if(val==0x02e9) { + int zzz=9; + } + MMU_new.write_dma(ARMCPU_ARM9,16,adr,val); + return; + } + + switch (adr >> 4) + { + //toon table + case 0x0400038: + case 0x0400039: + case 0x040003A: + case 0x040003B: + ((u16 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[(adr & 0xFFF)>>1] = val; + gfx3d_UpdateToonTable((adr & 0x3F) >> 1, val); + return; + } + // Address is an IO register + switch(adr) + { + case eng_3D_GXSTAT: + MMU_new.gxstat.write(16,adr,val); + break; + + //fog table: only write bottom 7 bits + case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x02: case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x06: + case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x0A: case eng_3D_FOG_TABLE+0x0C: case eng_3D_FOG_TABLE+0x0E: + case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x12: case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x16: + case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x1A: case eng_3D_FOG_TABLE+0x1C: case eng_3D_FOG_TABLE+0x1E: + val &= 0x7F7F; + break; + + case REG_DISPA_BG2XL: MainScreen.gpu->setAffineStartWord(2,0,val,0); break; + case REG_DISPA_BG2XH: MainScreen.gpu->setAffineStartWord(2,0,val,1); break; + case REG_DISPA_BG2YL: MainScreen.gpu->setAffineStartWord(2,1,val,0); break; + case REG_DISPA_BG2YH: MainScreen.gpu->setAffineStartWord(2,1,val,1); break; + case REG_DISPA_BG3XL: MainScreen.gpu->setAffineStartWord(3,0,val,0); break; + case REG_DISPA_BG3XH: MainScreen.gpu->setAffineStartWord(3,0,val,1); break; + case REG_DISPA_BG3YL: MainScreen.gpu->setAffineStartWord(3,1,val,0); break; + case REG_DISPA_BG3YH: MainScreen.gpu->setAffineStartWord(3,1,val,1); break; + case REG_DISPB_BG2XL: SubScreen.gpu->setAffineStartWord(2,0,val,0); break; + case REG_DISPB_BG2XH: SubScreen.gpu->setAffineStartWord(2,0,val,1); break; + case REG_DISPB_BG2YL: SubScreen.gpu->setAffineStartWord(2,1,val,0); break; + case REG_DISPB_BG2YH: SubScreen.gpu->setAffineStartWord(2,1,val,1); break; + case REG_DISPB_BG3XL: SubScreen.gpu->setAffineStartWord(3,0,val,0); break; + case REG_DISPB_BG3XH: SubScreen.gpu->setAffineStartWord(3,0,val,1); break; + case REG_DISPB_BG3YL: SubScreen.gpu->setAffineStartWord(3,1,val,0); break; + case REG_DISPB_BG3YH: SubScreen.gpu->setAffineStartWord(3,1,val,1); break; + + case REG_DISPA_DISP3DCNT: writereg_DISP3DCNT(16,adr,val); return; + + // Alpha test reference value - Parameters:1 + case eng_3D_ALPHA_TEST_REF: + { + ((u16 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x340>>1] = val; + gfx3d_glAlphaFunc(val); + return; + } + + case eng_3D_CLEAR_COLOR: + case eng_3D_CLEAR_COLOR+2: + { + T1WriteWord((u8*)&gfx3d.state.clearColor,adr-eng_3D_CLEAR_COLOR,val); + break; + } + + // Clear background depth setup - Parameters:2 + case eng_3D_CLEAR_DEPTH: + { + ((u16 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x354>>1] = val; + gfx3d_glClearDepth(val); + return; + } + // Fog Color - Parameters:4b + case eng_3D_FOG_COLOR: + { + ((u16 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x358>>1] = val; + gfx3d_glFogColor(val); + return; + } + case eng_3D_FOG_OFFSET: + { + ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x35C>>1] = val; + gfx3d_glFogOffset(val); + return; + } + + case REG_DIVCNT: + MMU_new.div.write16(val); + execdiv(); + return; +#if 1 + case REG_DIVNUMER: + case REG_DIVNUMER+2: + case REG_DIVNUMER+4: + printf("DIV: 16 write NUMER %08X. PLEASE REPORT! \n", val); + break; + case REG_DIVDENOM: + case REG_DIVDENOM+2: + case REG_DIVDENOM+4: + printf("DIV: 16 write DENOM %08X. PLEASE REPORT! \n", val); + break; +#endif + case REG_SQRTCNT: + MMU_new.sqrt.write16(val); + execsqrt(); + return; + + case REG_DISPA_BLDCNT: + GPU_setBLDCNT(MainScreen.gpu,val) ; + break ; + case REG_DISPB_BLDCNT: + GPU_setBLDCNT(SubScreen.gpu,val) ; + break ; + case REG_DISPA_BLDALPHA: + MainScreen.gpu->setBLDALPHA(val); + break ; + case REG_DISPB_BLDALPHA: + SubScreen.gpu->setBLDALPHA(val); + break ; + case REG_DISPA_BLDY: + GPU_setBLDY_EVY(MainScreen.gpu,val) ; + break ; + case REG_DISPB_BLDY: + GPU_setBLDY_EVY(SubScreen.gpu,val) ; + break; + case REG_DISPA_MASTERBRIGHT: + GPU_setMasterBrightness (MainScreen.gpu, val); + break; + /* + case REG_DISPA_MOSAIC: + GPU_setMOSAIC(MainScreen.gpu,val) ; + break ; + case REG_DISPB_MOSAIC: + GPU_setMOSAIC(SubScreen.gpu,val) ; + break ; + */ + //case REG_DISPA_BG0HOFS: + // GPU_setBGxHOFS(0, MainScreen.gpu, val); + // break; + //case REG_DISPA_BG0VOFS: + // GPU_setBGxVOFS(0, MainScreen.gpu, val); + // break; + //case REG_DISPA_BG1HOFS: + // GPU_setBGxHOFS(1, MainScreen.gpu, val); + // break; + //case REG_DISPA_BG1VOFS: + // GPU_setBGxVOFS(1, MainScreen.gpu, val); + // break; + //case REG_DISPA_BG2HOFS: + // GPU_setBGxHOFS(2, MainScreen.gpu, val); + // break; + //case REG_DISPA_BG2VOFS: + // GPU_setBGxVOFS(2, MainScreen.gpu, val); + // break; + //case REG_DISPA_BG3HOFS: + // GPU_setBGxHOFS(3, MainScreen.gpu, val); + // break; + //case REG_DISPA_BG3VOFS: + // GPU_setBGxVOFS(3, MainScreen.gpu, val); + // break; + + case REG_DISPA_WIN0H: + GPU_setWIN0_H (MainScreen.gpu,val) ; + break ; + case REG_DISPA_WIN1H: + GPU_setWIN1_H(MainScreen.gpu,val) ; + break ; + case REG_DISPB_WIN0H: + GPU_setWIN0_H(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WIN1H: + GPU_setWIN1_H(SubScreen.gpu,val) ; + break ; + case REG_DISPA_WIN0V: + GPU_setWIN0_V(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WIN1V: + GPU_setWIN1_V(MainScreen.gpu,val) ; + break ; + case REG_DISPB_WIN0V: + GPU_setWIN0_V(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WIN1V: + GPU_setWIN1_V(SubScreen.gpu,val) ; + break ; + case REG_DISPA_WININ: + GPU_setWININ(MainScreen.gpu, val) ; + break ; + case REG_DISPA_WINOUT: + GPU_setWINOUT16(MainScreen.gpu, val) ; + break ; + + /* case REG_DISPB_BG0HOFS: + GPU_setBGxHOFS(0, SubScreen.gpu, val); + break; + case REG_DISPB_BG0VOFS: + GPU_setBGxVOFS(0, SubScreen.gpu, val); + break; + case REG_DISPB_BG1HOFS: + GPU_setBGxHOFS(1, SubScreen.gpu, val); + break; + case REG_DISPB_BG1VOFS: + GPU_setBGxVOFS(1, SubScreen.gpu, val); + break; + case REG_DISPB_BG2HOFS: + GPU_setBGxHOFS(2, SubScreen.gpu, val); + break; + case REG_DISPB_BG2VOFS: + GPU_setBGxVOFS(2, SubScreen.gpu, val); + break; + case REG_DISPB_BG3HOFS: + GPU_setBGxHOFS(3, SubScreen.gpu, val); + break; + case REG_DISPB_BG3VOFS: + GPU_setBGxVOFS(3, SubScreen.gpu, val); + break;*/ + + case REG_DISPB_WININ: + GPU_setWININ(SubScreen.gpu, val) ; + break ; + case REG_DISPB_WINOUT: + GPU_setWINOUT16(SubScreen.gpu, val) ; + break ; + + case REG_DISPB_MASTERBRIGHT: + GPU_setMasterBrightness (SubScreen.gpu, val); + break; + + case REG_POWCNT1: + writereg_POWCNT1(16,adr,val); + return; + + case REG_EXMEMCNT: + { + u16 remote_proc = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204); + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x204, val); + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204, (val & 0xFF80) | (remote_proc & 0x7F)); + return; + } + + case REG_AUXSPICNT: + write_auxspicnt(9,16,0,val); + return; + + case REG_AUXSPIDATA: + if(val!=0) + MMU.AUX_SPI_CMD = val & 0xFF; + + //T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, bm_transfer(&MMU.bupmem, val)); + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, MMU_new.backupDevice.data_command((u8)val,ARMCPU_ARM9)); + MMU.AUX_SPI_CNT &= ~0x80; //remove busy flag + return; + + case REG_DISPA_BG0CNT : + //GPULOG("MAIN BG0 SETPROP 16B %08X\r\n", val); + GPU_setBGProp(MainScreen.gpu, 0, val); + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x8, val); + return; + case REG_DISPA_BG1CNT : + //GPULOG("MAIN BG1 SETPROP 16B %08X\r\n", val); + GPU_setBGProp(MainScreen.gpu, 1, val); + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xA, val); + return; + case REG_DISPA_BG2CNT : + //GPULOG("MAIN BG2 SETPROP 16B %08X\r\n", val); + GPU_setBGProp(MainScreen.gpu, 2, val); + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xC, val); + return; + case REG_DISPA_BG3CNT : + //GPULOG("MAIN BG3 SETPROP 16B %08X\r\n", val); + GPU_setBGProp(MainScreen.gpu, 3, val); + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xE, val); + return; + case REG_DISPB_BG0CNT : + //GPULOG("SUB BG0 SETPROP 16B %08X\r\n", val); + GPU_setBGProp(SubScreen.gpu, 0, val); + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1008, val); + return; + case REG_DISPB_BG1CNT : + //GPULOG("SUB BG1 SETPROP 16B %08X\r\n", val); + GPU_setBGProp(SubScreen.gpu, 1, val); + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x100A, val); + return; + case REG_DISPB_BG2CNT : + //GPULOG("SUB BG2 SETPROP 16B %08X\r\n", val); + GPU_setBGProp(SubScreen.gpu, 2, val); + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x100C, val); + return; + case REG_DISPB_BG3CNT : + //GPULOG("SUB BG3 SETPROP 16B %08X\r\n", val); + GPU_setBGProp(SubScreen.gpu, 3, val); + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x100E, val); + return; + + case REG_VRAMCNTA: + case REG_VRAMCNTC: + case REG_VRAMCNTE: + MMU_VRAMmapControl(adr-REG_VRAMCNTA, val & 0xFF); + MMU_VRAMmapControl(adr-REG_VRAMCNTA+1, val >> 8); + break; + case REG_VRAMCNTG: + MMU_VRAMmapControl(adr-REG_VRAMCNTA, val & 0xFF); + /* Update WRAMSTAT at the ARM7 side */ + T1WriteByte(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x241, val >> 8); + break; + case REG_VRAMCNTH: + MMU_VRAMmapControl(adr-REG_VRAMCNTA, val & 0xFF); + MMU_VRAMmapControl(adr-REG_VRAMCNTA+1, val >> 8); + break; + + case REG_IME: + NDS_Reschedule(); + MMU.reg_IME[ARMCPU_ARM9] = val & 0x01; + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x208, val); + return; + case REG_IE : + NDS_Reschedule(); + MMU.reg_IE[ARMCPU_ARM9] = (MMU.reg_IE[ARMCPU_ARM9]&0xFFFF0000) | val; + return; + case REG_IE + 2 : + NDS_Reschedule(); + MMU.reg_IE[ARMCPU_ARM9] = (MMU.reg_IE[ARMCPU_ARM9]&0xFFFF) | (((u32)val)<<16); + return; + case REG_IF: REG_IF_WriteWord(0,val); return; + case REG_IF+2: REG_IF_WriteWord(2,val); return; + + case REG_IPCSYNC: + MMU_IPCSync(ARMCPU_ARM9, val); + return; + case REG_IPCFIFOCNT: + IPC_FIFOcnt(ARMCPU_ARM9, val); + return; + + case REG_TM0CNTL : + case REG_TM1CNTL : + case REG_TM2CNTL : + case REG_TM3CNTL : + MMU.timerReload[ARMCPU_ARM9][(adr>>2)&3] = val; + return; + case REG_TM0CNTH : + case REG_TM1CNTH : + case REG_TM2CNTH : + case REG_TM3CNTH : + { + int timerIndex = ((adr-2)>>2)&0x3; + write_timer(ARMCPU_ARM9, timerIndex, val); + return; + } + + case REG_DISPA_DISPCNT : + { + u32 v = (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0) & 0xFFFF0000) | val; + GPU_setVideoProp(MainScreen.gpu, v); + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0, v); + return; + } + case REG_DISPA_DISPCNT+2 : + { + u32 v = (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0) & 0xFFFF) | ((u32) val << 16); + GPU_setVideoProp(MainScreen.gpu, v); + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0, v); + } + return; + case REG_DISPA_DISPCAPCNT : + { + u32 v = (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x64) & 0xFFFF0000) | val; + GPU_set_DISPCAPCNT(v); + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x64, v); + return; + } + case REG_DISPA_DISPCAPCNT + 2: + { + u32 v = (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x64) & 0xFFFF) | ((u32)val << 16); + GPU_set_DISPCAPCNT(v); + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x64, v); + return; + } + + case REG_DISPB_DISPCNT : + { + u32 v = (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1000) & 0xFFFF0000) | val; + GPU_setVideoProp(SubScreen.gpu, v); + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1000, v); + return; + } + case REG_DISPB_DISPCNT+2 : + { + //emu_halt(); + u32 v = (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1000) & 0xFFFF) | ((u32) val << 16); + GPU_setVideoProp(SubScreen.gpu, v); + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1000, v); + return; + } + + case REG_DISPA_DISPMMEMFIFO: + { + DISP_FIFOsend(val); + return; + } + + case REG_GCROMCTRL : + MMU_writeToGCControl( (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1A4) & 0xFFFF0000) | val); + return; + case REG_GCROMCTRL+2 : + MMU_writeToGCControl( (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1A4) & 0xFFFF) | ((u32) val << 16)); + return; + } + + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr&MMU.MMU_MASK[ARMCPU_ARM9][adr>>20], val); + return; + } + + + bool unmapped, restricted; + adr = MMU_LCDmap(adr, unmapped, restricted); + if(unmapped) return; + + // Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [shash] + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr&MMU.MMU_MASK[ARMCPU_ARM9][adr>>20], val); +} + +//================================================= MMU ARM9 write 32 +void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val) +{ + adr &= 0x0FFFFFFC; + + mmu_log_debug_ARM9(adr, "(write32) 0x%08X", val); + + if(adr<0x02000000) + { + T1WriteLong(MMU.ARM9_ITCM, adr&0x7FFF, val); + return ; + } + + if ( (adr >= 0x08000000) && (adr < 0x0A010000) ) + { + u16 exmemcnt = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x204); + if(exmemcnt & EXMEMCNT_MASK_SLOT2_ARM7) + {} //prohibited + else addon.write32(ARMCPU_ARM9, adr, val); + return; + } + + if((adr&0x0F000000)==0x05000000) + { + int zzz=9; + } + +#if 0 + if ((adr & 0xFF800000) == 0x04800000) { + // access to non regular hw registers + // return to not overwrite valid data + return ; + } +#endif + + if((adr>>24)==4) + { + // TODO: add pal reg + if (nds.power1.gpuMain == 0) + if ((adr >= 0x04000008) && (adr<=0x0400005F)) return; + if (nds.power1.gpuSub == 0) + if ((adr >= 0x04001008) && (adr<=0x0400105F)) return; + if (nds.power1.gfx3d_geometry == 0) + if ((adr >= 0x04000400) && (adr<=0x040006FF)) return; + if (nds.power1.gfx3d_render == 0) + if ((adr >= 0x04000320) && (adr<=0x040003FF)) return; + + // MightyMax: no need to do several ifs, when only one can happen + // switch/case instead + // both comparison >=,< per if can be replaced by one bit comparison since + // they are 2^4 aligned and 2^4n wide + // this looks ugly but should reduce load on register writes, they are done as + // lookups by the compiler + switch (adr >> 4) + { + case 0x400033: //edge color table + ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[(adr & 0xFFF) >> 2] = val; + return; + + case 0x400038: + case 0x400039: + case 0x40003A: + case 0x40003B: //toon table + ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[(adr & 0xFFF) >> 2] = val; + gfx3d_UpdateToonTable((adr & 0x3F) >> 1, val); + return; + + case 0x400040: + case 0x400041: + case 0x400042: + case 0x400043: // FIFO Commands + ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[(adr & 0xFFF) >> 2] = val; + gfx3d_sendCommandToFIFO(val); + return; + + case 0x400044: + case 0x400045: + case 0x400046: + case 0x400047: + case 0x400048: + case 0x400049: + case 0x40004A: + case 0x40004B: + case 0x40004C: + case 0x40004D: + case 0x40004E: + case 0x40004F: + case 0x400050: + case 0x400051: + case 0x400052: + case 0x400053: + case 0x400054: + case 0x400055: + case 0x400056: + case 0x400057: + case 0x400058: + case 0x400059: + case 0x40005A: + case 0x40005B: + case 0x40005C: // Individual Commands + if (gxFIFO.size > 254) + nds.freezeBus |= 1; + + ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[(adr & 0xFFF) >> 2] = val; + gfx3d_sendCommand(adr, val); + return; + + default: + break; + } + + if(MMU_new.is_dma(adr)) { + MMU_new.write_dma(ARMCPU_ARM9,32,adr,val); + return; + } + + switch(adr) + { + case REG_SQRTCNT: MMU_new.sqrt.write16((u16)val); return; + case REG_DIVCNT: MMU_new.div.write16((u16)val); return; + + case REG_POWCNT1: writereg_POWCNT1(32,adr,val); break; + + //fog table: only write bottom 7 bits + case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x0C: + case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x1C: + val &= 0x7F7F7F7F; + break; + + + //ensata handshaking port? + case 0x04FFF010: + if(nds.ensataEmulation && nds.ensataHandshake == ENSATA_HANDSHAKE_ack && val == 0x13579bdf) + nds.ensataHandshake = ENSATA_HANDSHAKE_confirm; + if(nds.ensataEmulation && nds.ensataHandshake == ENSATA_HANDSHAKE_confirm && val == 0xfdb97531) + { + printf("ENSATA HANDSHAKE COMPLETE\n"); + nds.ensataHandshake = ENSATA_HANDSHAKE_complete; + } + break; + + //todo - these are usually write only regs (these and 1000 more) + //shouldnt we block them from getting written? ugh + case eng_3D_CLIPMTX_RESULT: + if(nds.ensataEmulation && nds.ensataHandshake == ENSATA_HANDSHAKE_none && val==0x2468ace0) + { + printf("ENSATA HANDSHAKE BEGIN\n"); + nds.ensataHandshake = ENSATA_HANDSHAKE_query; + } + break; + + case eng_3D_GXSTAT: + MMU_new.gxstat.write32(val); + break; + case REG_DISPA_BG2XL: + MainScreen.gpu->setAffineStart(2,0,val); + return; + case REG_DISPA_BG2YL: + MainScreen.gpu->setAffineStart(2,1,val); + return; + case REG_DISPB_BG2XL: + SubScreen.gpu->setAffineStart(2,0,val); + return; + case REG_DISPB_BG2YL: + SubScreen.gpu->setAffineStart(2,1,val); + return; + case REG_DISPA_BG3XL: + MainScreen.gpu->setAffineStart(3,0,val); + return; + case REG_DISPA_BG3YL: + MainScreen.gpu->setAffineStart(3,1,val); + return; + case REG_DISPB_BG3XL: + SubScreen.gpu->setAffineStart(3,0,val); + return; + case REG_DISPB_BG3YL: + SubScreen.gpu->setAffineStart(3,1,val); + return; + + // Alpha test reference value - Parameters:1 + case eng_3D_ALPHA_TEST_REF: + { + ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x340>>2] = val; + gfx3d_glAlphaFunc(val); + return; + } + + case eng_3D_CLEAR_COLOR: + T1WriteLong((u8*)&gfx3d.state.clearColor,0,val); + break; + + // Clear background depth setup - Parameters:2 + case eng_3D_CLEAR_DEPTH: + { + ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x354>>2] = val; + gfx3d_glClearDepth(val); + return; + } + // Fog Color - Parameters:4b + case 0x04000358: + { + ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x358>>2] = val; + gfx3d_glFogColor(val); + return; + } + case 0x0400035C: + { + ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[0x35C>>2] = val; + gfx3d_glFogOffset(val); + return; + } + + //case REG_DISPA_BG0HOFS: + // GPU_setBGxHOFS(0, MainScreen.gpu, val&0xFFFF); + // GPU_setBGxVOFS(0, MainScreen.gpu, (val>>16)); + // break; + + case REG_DISPA_WININ: + { + GPU_setWININ(MainScreen.gpu, val & 0xFFFF) ; + GPU_setWINOUT16(MainScreen.gpu, (val >> 16) & 0xFFFF) ; + break; + } + case REG_DISPB_WININ: + { + GPU_setWININ(SubScreen.gpu, val & 0xFFFF) ; + GPU_setWINOUT16(SubScreen.gpu, (val >> 16) & 0xFFFF) ; + break; + } + + case REG_DISPA_WIN0H: + { + GPU_setWIN0_H(MainScreen.gpu, val&0xFFFF); + GPU_setWIN1_H(MainScreen.gpu, val>>16); + break; + } + case REG_DISPA_WIN0V: + { + GPU_setWIN0_V(MainScreen.gpu, val&0xFFFF); + GPU_setWIN1_V(MainScreen.gpu, val>>16); + break; + } + case REG_DISPB_WIN0H: + { + GPU_setWIN0_H(SubScreen.gpu, val&0xFFFF); + GPU_setWIN1_H(SubScreen.gpu, val>>16); + break; + } + case REG_DISPB_WIN0V: + { + GPU_setWIN0_V(SubScreen.gpu, val&0xFFFF); + GPU_setWIN1_V(SubScreen.gpu, val>>16); + break; + } + + case REG_DISPA_MASTERBRIGHT: + GPU_setMasterBrightness(MainScreen.gpu, val & 0xFFFF); + break; + case REG_DISPB_MASTERBRIGHT: + GPU_setMasterBrightness(SubScreen.gpu, val & 0xFFFF); + break; + + case REG_DISPA_BLDCNT: + { + GPU_setBLDCNT (MainScreen.gpu,val&0xffff); + MainScreen.gpu->setBLDALPHA(val>>16); + break; + } + case REG_DISPB_BLDCNT: + { + GPU_setBLDCNT (SubScreen.gpu,val&0xffff); + SubScreen.gpu->setBLDALPHA(val>>16); + break; + } + + case REG_DISPA_BLDY: + GPU_setBLDY_EVY(MainScreen.gpu,val&0xFFFF) ; + break ; + case REG_DISPB_BLDY: + GPU_setBLDY_EVY(SubScreen.gpu,val&0xFFFF); + break; + + case REG_DISPA_DISPCNT : + GPU_setVideoProp(MainScreen.gpu, val); + //GPULOG("MAIN INIT 32B %08X\r\n", val); + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0, val); + return; + + case REG_DISPB_DISPCNT : + GPU_setVideoProp(SubScreen.gpu, val); + //GPULOG("SUB INIT 32B %08X\r\n", val); + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1000, val); + return; + + case REG_VRAMCNTA: + MMU_VRAMmapControl(adr-REG_VRAMCNTA, val & 0xFF); + MMU_VRAMmapControl(adr-REG_VRAMCNTA+1, (val >> 8) & 0xFF); + MMU_VRAMmapControl(adr-REG_VRAMCNTA+2, (val >> 16) & 0xFF); + MMU_VRAMmapControl(adr-REG_VRAMCNTA+3, (val >> 24) & 0xFF); + break; + case REG_VRAMCNTE: + MMU_VRAMmapControl(adr-REG_VRAMCNTA, val & 0xFF); + MMU_VRAMmapControl(adr-REG_VRAMCNTA+1, (val >> 8) & 0xFF); + MMU_VRAMmapControl(adr-REG_VRAMCNTA+2, (val >> 16) & 0xFF); + /* Update WRAMSTAT at the ARM7 side */ + T1WriteByte(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x241, (val >> 24) & 0xFF); + break; + case REG_VRAMCNTH: + MMU_VRAMmapControl(adr-REG_VRAMCNTA, val & 0xFF); + MMU_VRAMmapControl(adr-REG_VRAMCNTA+1, (val >> 8) & 0xFF); + break; + + case REG_IME : + NDS_Reschedule(); + MMU.reg_IME[ARMCPU_ARM9] = val & 0x01; + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x208, val); + return; + + case REG_IE : + NDS_Reschedule(); + MMU.reg_IE[ARMCPU_ARM9] = val; + return; + + case REG_IF: REG_IF_WriteLong(val); return; + + case REG_TM0CNTL: + case REG_TM1CNTL: + case REG_TM2CNTL: + case REG_TM3CNTL: + { + int timerIndex = (adr>>2)&0x3; + MMU.timerReload[ARMCPU_ARM9][timerIndex] = (u16)val; + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], adr & 0xFFF, val); + write_timer(ARMCPU_ARM9, timerIndex, val>>16); + return; + } + + case REG_DIVNUMER: + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x290, val); + execdiv(); + return; + case REG_DIVNUMER+4: + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x294, val); + execdiv(); + return; + + case REG_DIVDENOM : + { + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x298, val); + execdiv(); + return; + } + case REG_DIVDENOM+4 : + { + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x29C, val); + execdiv(); + return; + } + + case REG_SQRTPARAM : + { + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2B8, val); + execsqrt(); + return; + } + case REG_SQRTPARAM+4 : + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2BC, val); + execsqrt(); + return; + + case REG_IPCSYNC: + MMU_IPCSync(ARMCPU_ARM9, val); + return; + case REG_IPCFIFOCNT: + IPC_FIFOcnt(ARMCPU_ARM9, val); + return; + case REG_IPCFIFOSEND: + IPC_FIFOsend(ARMCPU_ARM9, val); + return; + + + case REG_GCROMCTRL : + MMU_writeToGCControl(val); + return; + case REG_DISPA_DISPCAPCNT : + //INFO("MMU write32: REG_DISPA_DISPCAPCNT 0x%X\n", val); + GPU_set_DISPCAPCNT(val); + T1WriteLong(MMU.ARM9_REG, 0x64, val); + return; + + case REG_DISPA_BG0CNT : + GPU_setBGProp(MainScreen.gpu, 0, (val&0xFFFF)); + GPU_setBGProp(MainScreen.gpu, 1, (val>>16)); + //if((val>>16)==0x400) emu_halt(); + T1WriteLong(MMU.ARM9_REG, 8, val); + return; + case REG_DISPA_BG2CNT : + GPU_setBGProp(MainScreen.gpu, 2, (val&0xFFFF)); + GPU_setBGProp(MainScreen.gpu, 3, (val>>16)); + T1WriteLong(MMU.ARM9_REG, 0xC, val); + return; + case REG_DISPB_BG0CNT : + GPU_setBGProp(SubScreen.gpu, 0, (val&0xFFFF)); + GPU_setBGProp(SubScreen.gpu, 1, (val>>16)); + T1WriteLong(MMU.ARM9_REG, 0x1008, val); + return; + case REG_DISPB_BG2CNT : + GPU_setBGProp(SubScreen.gpu, 2, (val&0xFFFF)); + GPU_setBGProp(SubScreen.gpu, 3, (val>>16)); + T1WriteLong(MMU.ARM9_REG, 0x100C, val); + return; + case REG_DISPA_DISPMMEMFIFO: + { + DISP_FIFOsend(val); + return; + } + + case REG_DISPA_DISP3DCNT: writereg_DISP3DCNT(32,adr,val); return; + + case REG_GCDATAIN: + slot1_device.write32(ARMCPU_ARM9, REG_GCDATAIN,val); + return; + } + + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr & MMU.MMU_MASK[ARMCPU_ARM9][adr>>20], val); + return; + } + + bool unmapped, restricted; + adr = MMU_LCDmap(adr, unmapped, restricted); + if(unmapped) return; + + // Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [shash] + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr&MMU.MMU_MASK[ARMCPU_ARM9][adr>>20], val); +} + +//================================================= MMU ARM9 read 08 +u8 FASTCALL _MMU_ARM9_read08(u32 adr) +{ + adr &= 0x0FFFFFFF; + + mmu_log_debug_ARM9(adr, "(read08) 0x%02X", MMU.MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF][adr&MMU.MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF]]); + + if(adr<0x02000000) + return T1ReadByte(MMU.ARM9_ITCM, adr&0x7FFF); + + if ( (adr >= 0x08000000) && (adr < 0x0A010000) ) + { + u16 exmemcnt = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x204); + if(exmemcnt & EXMEMCNT_MASK_SLOT2_ARM7) + return 0; //prohibited + else return addon.read08(ARMCPU_ARM9, adr); + } + + if (adr >> 24 == 4) + { //Address is an IO register + if(MMU_new.is_dma(adr)) return MMU_new.read_dma(ARMCPU_ARM9,8,adr); + + switch(adr) + { + case REG_IF: return MMU.gen_IF(); + case REG_IF+1: return (MMU.gen_IF()>>8); + case REG_IF+2: return (MMU.gen_IF()>>16); + case REG_IF+3: return (MMU.gen_IF()>>24); + + case REG_DISPA_DISPSTAT: + break; + case REG_DISPA_DISPSTAT+1: + break; + case REG_DISPx_VCOUNT: return nds.VCount & 0xFF; + case REG_DISPx_VCOUNT+1: return (nds.VCount>>8) & 0xFF; +#if 0 + case REG_SQRTCNT: printf("ERROR 8bit SQRTCNT READ\n"); return 0; + case REG_SQRTCNT+1: printf("ERROR 8bit SQRTCNT1 READ\n"); return 0;//(MMU_new.sqrt.read16() & 0xFF00)>>8; +#else + case REG_SQRTCNT: return (MMU_new.sqrt.read16() & 0xFF); + case REG_SQRTCNT+1: return ((MMU_new.sqrt.read16()>>8) & 0xFF); +#endif + case REG_SQRTCNT+2: printf("ERROR 8bit SQRTCNT2 READ\n"); return 0; + case REG_SQRTCNT+3: printf("ERROR 8bit SQRTCNT3 READ\n"); return 0; +#if 1 + case REG_DIVCNT: printf("ERROR 8bit DIVCNT READ\n"); return 0; + case REG_DIVCNT+1: printf("ERROR 8bit DIVCNT1 READ\n"); return 0; +#else + case REG_DIVCNT: return (MMU_new.div.read16() & 0xFF); + case REG_DIVCNT+1: return ((MMU_new.div.read16()>>8) & 0xFF); +#endif + case REG_DIVCNT+2: printf("ERROR 8bit DIVCNT2 READ\n"); return 0; + case REG_DIVCNT+3: printf("ERROR 8bit DIVCNT3 READ\n"); return 0; + + //fog table: write only + case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x01: case eng_3D_FOG_TABLE+0x02: case eng_3D_FOG_TABLE+0x03: + case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x05: case eng_3D_FOG_TABLE+0x06: case eng_3D_FOG_TABLE+0x07: + case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x09: case eng_3D_FOG_TABLE+0x0A: case eng_3D_FOG_TABLE+0x0B: + case eng_3D_FOG_TABLE+0x0C: case eng_3D_FOG_TABLE+0x0D: case eng_3D_FOG_TABLE+0x0E: case eng_3D_FOG_TABLE+0x0F: + case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x11: case eng_3D_FOG_TABLE+0x12: case eng_3D_FOG_TABLE+0x13: + case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x15: case eng_3D_FOG_TABLE+0x16: case eng_3D_FOG_TABLE+0x17: + case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x19: case eng_3D_FOG_TABLE+0x1A: case eng_3D_FOG_TABLE+0x1B: + case eng_3D_FOG_TABLE+0x1C: case eng_3D_FOG_TABLE+0x1D: case eng_3D_FOG_TABLE+0x1E: case eng_3D_FOG_TABLE+0x1F: + return 0; + + case REG_POWCNT1: + case REG_POWCNT1+1: + case REG_POWCNT1+2: + case REG_POWCNT1+3: + return readreg_POWCNT1(8,adr); + + case eng_3D_GXSTAT: + return MMU_new.gxstat.read(8,adr); + + case REG_DISPA_DISP3DCNT: return readreg_DISP3DCNT(8,adr); + case REG_DISPA_DISP3DCNT+1: return readreg_DISP3DCNT(8,adr); + case REG_DISPA_DISP3DCNT+2: return readreg_DISP3DCNT(8,adr); + case REG_DISPA_DISP3DCNT+3: return readreg_DISP3DCNT(8,adr); + + case REG_KEYINPUT: + LagFrameFlag=0; + break; + } + } + + bool unmapped, restricted; + adr = MMU_LCDmap(adr, unmapped, restricted); + if(unmapped) return 0; + + return MMU.MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF][adr&MMU.MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF]]; +} + +//================================================= MMU ARM9 read 16 +u16 FASTCALL _MMU_ARM9_read16(u32 adr) +{ + adr &= 0x0FFFFFFE; + + mmu_log_debug_ARM9(adr, "(read16) 0x%04X", T1ReadWord_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM9][adr >> 20], adr & MMU.MMU_MASK[ARMCPU_ARM9][adr >> 20])); + + if(adr<0x02000000) + return T1ReadWord_guaranteedAligned(MMU.ARM9_ITCM, adr & 0x7FFE); + + if ( (adr >= 0x08000000) && (adr < 0x0A010000) ) + { + u16 exmemcnt = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x204); + if(exmemcnt & EXMEMCNT_MASK_SLOT2_ARM7) + return 0; //prohibited + else return addon.read16(ARMCPU_ARM9, adr); + } + + if (adr >> 24 == 4) + { + if(MMU_new.is_dma(adr)) return MMU_new.read_dma(ARMCPU_ARM9,16,adr); + + // Address is an IO register + switch(adr) + { + case REG_DISPA_DISPSTAT: + break; + + case REG_SQRTCNT: return MMU_new.sqrt.read16(); + case REG_DIVCNT: return MMU_new.div.read16(); + case eng_3D_GXSTAT: return MMU_new.gxstat.read(16,adr); + + case REG_DISPA_VCOUNT: + if(nds.ensataEmulation && nds.ensataHandshake == ENSATA_HANDSHAKE_query) + { + nds.ensataHandshake = ENSATA_HANDSHAKE_ack; + return 270; + } + else + return nds.VCount; + + // ============================================= 3D + case eng_3D_RAM_COUNT: + return 0; + //almost worthless for now + //return (gfx3d_GetNumPolys()); + case eng_3D_RAM_COUNT+2: + return 0; + //almost worthless for now + //return (gfx3d_GetNumVertex()); + // ============================================= 3D end + case REG_IME : + return (u16)MMU.reg_IME[ARMCPU_ARM9]; + + case REG_IE : + return (u16)MMU.reg_IE[ARMCPU_ARM9]; + case REG_IE + 2 : + return (u16)(MMU.reg_IE[ARMCPU_ARM9]>>16); + + case REG_IF: return MMU.gen_IF(); + case REG_IF+2: return MMU.gen_IF()>>16; + + case REG_TM0CNTL : + case REG_TM1CNTL : + case REG_TM2CNTL : + case REG_TM3CNTL : + return read_timer(ARMCPU_ARM9,(adr&0xF)>>2); + + case REG_AUXSPICNT: + return MMU.AUX_SPI_CNT; + + case REG_POWCNT1: + case REG_POWCNT1+2: + return readreg_POWCNT1(16,adr); + + case REG_DISPA_DISP3DCNT: return readreg_DISP3DCNT(16,adr); + case REG_DISPA_DISP3DCNT+2: return readreg_DISP3DCNT(16,adr); + + case REG_KEYINPUT: + LagFrameFlag=0; + break; + + //fog table: write only + case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x02: case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x06: + case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x0A: case eng_3D_FOG_TABLE+0x0C: case eng_3D_FOG_TABLE+0x0E: + case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x12: case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x16: + case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x1A: case eng_3D_FOG_TABLE+0x1C: case eng_3D_FOG_TABLE+0x1E: + return 0; + } + + return T1ReadWord_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr & MMU.MMU_MASK[ARMCPU_ARM9][adr>>20]); + } + + bool unmapped, restricted; + adr = MMU_LCDmap(adr,unmapped, restricted); + if(unmapped) return 0; + + // Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF + return T1ReadWord_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM9][adr >> 20], adr & MMU.MMU_MASK[ARMCPU_ARM9][adr >> 20]); +} + +//================================================= MMU ARM9 read 32 +u32 FASTCALL _MMU_ARM9_read32(u32 adr) +{ + adr &= 0x0FFFFFFC; + + mmu_log_debug_ARM9(adr, "(read32) 0x%08X", T1ReadLong_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM9][adr >> 20], adr & MMU.MMU_MASK[ARMCPU_ARM9][adr>>20])); + + if(adr<0x02000000) + return T1ReadLong_guaranteedAligned(MMU.ARM9_ITCM, adr&0x7FFC); + + if ( (adr >= 0x08000000) && (adr < 0x0A010000) ) + { + u16 exmemcnt = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x204); + if(exmemcnt & EXMEMCNT_MASK_SLOT2_ARM7) + return 0; //prohibited + else return addon.read32(ARMCPU_ARM9, adr); + } + + // Address is an IO register + if((adr >> 24) == 4) + { + if(MMU_new.is_dma(adr)) return MMU_new.read_dma(ARMCPU_ARM9,32,adr); + + switch(adr) + { + case REG_DSIMODE: + if(!nds.Is_DSI()) break; + return 1; + case 0x04004008: + if(!nds.Is_DSI()) break; + return 0x8000; + + case REG_DISPA_DISPSTAT: + break; + + case REG_DISPx_VCOUNT: return nds.VCount; + + //Dolphin Island Underwater Adventures uses this amidst seemingly reasonable divs so we're going to emulate it. + case REG_DIVCNT: return MMU_new.div.read16(); + //I guess we'll do this also + case REG_SQRTCNT: return MMU_new.sqrt.read16(); + + //fog table: write only + case eng_3D_FOG_TABLE+0x00: case eng_3D_FOG_TABLE+0x04: case eng_3D_FOG_TABLE+0x08: case eng_3D_FOG_TABLE+0x0C: + case eng_3D_FOG_TABLE+0x10: case eng_3D_FOG_TABLE+0x14: case eng_3D_FOG_TABLE+0x18: case eng_3D_FOG_TABLE+0x1C: + return 0; + + case eng_3D_CLIPMTX_RESULT: + case eng_3D_CLIPMTX_RESULT+4: + case eng_3D_CLIPMTX_RESULT+8: + case eng_3D_CLIPMTX_RESULT+12: + case eng_3D_CLIPMTX_RESULT+16: + case eng_3D_CLIPMTX_RESULT+20: + case eng_3D_CLIPMTX_RESULT+24: + case eng_3D_CLIPMTX_RESULT+28: + case eng_3D_CLIPMTX_RESULT+32: + case eng_3D_CLIPMTX_RESULT+36: + case eng_3D_CLIPMTX_RESULT+40: + case eng_3D_CLIPMTX_RESULT+44: + case eng_3D_CLIPMTX_RESULT+48: + case eng_3D_CLIPMTX_RESULT+52: + case eng_3D_CLIPMTX_RESULT+56: + case eng_3D_CLIPMTX_RESULT+60: + { + //LOG("4000640h..67Fh - CLIPMTX_RESULT - Read Current Clip Coordinates Matrix (R)"); + return gfx3d_GetClipMatrix ((adr-0x04000640)/4); + } + case eng_3D_VECMTX_RESULT: + case eng_3D_VECMTX_RESULT+4: + case eng_3D_VECMTX_RESULT+8: + case eng_3D_VECMTX_RESULT+12: + case eng_3D_VECMTX_RESULT+16: + case eng_3D_VECMTX_RESULT+20: + case eng_3D_VECMTX_RESULT+24: + case eng_3D_VECMTX_RESULT+28: + case eng_3D_VECMTX_RESULT+32: + { + //LOG("4000680h..6A3h - VECMTX_RESULT - Read Current Directional Vector Matrix (R)"); + return gfx3d_GetDirectionalMatrix ((adr-0x04000680)/4); + } + + case eng_3D_RAM_COUNT: + { + return (gfx3d_GetNumPolys()) | ((gfx3d_GetNumVertex()) << 16); + //LOG ("read32 - RAM_COUNT -> 0x%X", ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF]))[(adr&MMU.MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF])>>2]); + } + + case eng_3D_POS_RESULT: + case eng_3D_POS_RESULT+4: + case eng_3D_POS_RESULT+8: + case eng_3D_POS_RESULT+12: + { + return gfx3d_glGetPosRes((adr & 0xF) >> 2); + } + case eng_3D_GXSTAT: + return MMU_new.gxstat.read(32,adr); + // ======================================== 3D end + + + case REG_IME : + return MMU.reg_IME[ARMCPU_ARM9]; + case REG_IE : + return MMU.reg_IE[ARMCPU_ARM9]; + + case REG_IF: return MMU.gen_IF(); + + case REG_IPCFIFORECV : + return IPC_FIFOrecv(ARMCPU_ARM9); + case REG_TM0CNTL : + case REG_TM1CNTL : + case REG_TM2CNTL : + case REG_TM3CNTL : + { + u32 val = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], (adr + 2) & 0xFFF); + return MMU.timer[ARMCPU_ARM9][(adr&0xF)>>2] | (val<<16); + } + + case REG_GCDATAIN: return MMU_readFromGC(); + case REG_POWCNT1: return readreg_POWCNT1(32,adr); + case REG_DISPA_DISP3DCNT: return readreg_DISP3DCNT(32,adr); + + case REG_KEYINPUT: + LagFrameFlag=0; + break; + } + return T1ReadLong_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM9][adr>>20], adr & MMU.MMU_MASK[ARMCPU_ARM9][adr>>20]); + } + + bool unmapped, restricted; + adr = MMU_LCDmap(adr,unmapped, restricted); + if(unmapped) return 0; + + // Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [zeromus, inspired by shash] + return T1ReadLong_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM9][adr >> 20], adr & MMU.MMU_MASK[ARMCPU_ARM9][adr>>20]); +} +//================================================================================================== ARM7 * +//========================================================================================================= +//========================================================================================================= +//================================================= MMU ARM7 write 08 +void FASTCALL _MMU_ARM7_write08(u32 adr, u8 val) +{ + adr &= 0x0FFFFFFF; + + mmu_log_debug_ARM7(adr, "(write08) 0x%02X", val); + + if (adr < 0x4000) return; // PU BIOS + + if ( (adr >= 0x08000000) && (adr < 0x0A010000) ) + { + u16 exmemcnt = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204); + if(!(exmemcnt & EXMEMCNT_MASK_SLOT2_ARM7)) + {} //prohibited + else addon.write08(ARMCPU_ARM7,adr, val); + return; + } + + if ((adr>=0x04000400)&&(adr<0x04000520)) + { + SPU_WriteByte(adr, val); + return; + } + + if ((adr & 0xFFFF0000) == 0x04800000) + { + /* is wifi hardware, dont intermix with regular hardware registers */ + // 8-bit writes to wifi I/O and RAM are ignored + // Reference: http://nocash.emubase.de/gbatek.htm#dswifiiomap + return; + } + + if (adr >> 24 == 4) + { + if(MMU_new.is_dma(adr)) { MMU_new.write_dma(ARMCPU_ARM7,8,adr,val); return; } + + switch(adr) + { + case REG_IF: REG_IF_WriteByte(0,val); break; + case REG_IF+1: REG_IF_WriteByte(1,val); break; + case REG_IF+2: REG_IF_WriteByte(2,val); break; + case REG_IF+3: REG_IF_WriteByte(3,val); break; + + case REG_POSTFLG: + // hack for patched firmwares + if (val == 1) + { + if (_MMU_ARM7_read08(REG_POSTFLG) != 0) + break; + _MMU_write32(0x27FFE24, gameInfo.header.ARM9exe); + _MMU_write32(0x27FFE34, gameInfo.header.ARM7exe); + } + break; + + case REG_HALTCNT: + //printf("halt 0x%02X\n", val); + switch(val) + { + case 0xC0: NDS_Sleep(); break; + case 0x80: armcpu_Wait4IRQ(&NDS_ARM7); break; + default: break; + } + break; + + case REG_RTC: + rtcWrite(val); + return; + + case REG_AUXSPICNT: + write_auxspicnt(9,8,0,val); + return; + case REG_AUXSPICNT+1: + write_auxspicnt(9,8,1,val); + return; + case REG_AUXSPIDATA: + if(val!=0) MMU.AUX_SPI_CMD = val & 0xFF; + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, MMU_new.backupDevice.data_command((u8)val,ARMCPU_ARM7)); + MMU.AUX_SPI_CNT &= ~0x80; //remove busy flag + return; + } + MMU.MMU_MEM[ARMCPU_ARM7][adr>>20][adr&MMU.MMU_MASK[ARMCPU_ARM7][adr>>20]]=val; + return; + } + + bool unmapped, restricted; + adr = MMU_LCDmap(adr,unmapped, restricted); + if(unmapped) return; + + // Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [shash] + MMU.MMU_MEM[ARMCPU_ARM7][adr>>20][adr&MMU.MMU_MASK[ARMCPU_ARM7][adr>>20]]=val; +} + +static void CalculateTouchPressure(int pressurePercent, u16 &z1, u16& z2) +{ + bool touch = nds.isTouch!=0; + if(!touch) + { + z1 = z2 = 0; + return; + } + int y = nds.scr_touchY; + int x = nds.scr_touchX; + float u = (x/256.0f); + float v = (y/192.0f); + + //these coefficients + + float fPressurePercent = pressurePercent/100.0f; + //z1 goes up as pressure goes up + { + float b0 = (96-80)*fPressurePercent + 80; + float b1 = (970-864)*fPressurePercent + 864; + float b2 = (192-136)*fPressurePercent + 136; + float b3 = (1560-1100)*fPressurePercent + 1100; + z1 = (u16)(int)(b0 + (b1-b0)*u + (b2-b0)*v + (b3-b2-b1+b0)*u*v); + } + + //z2 goes down as pressure goes up + { + float b0=(1976-2300)*fPressurePercent + 2300; + float b1=(2360-2600)*fPressurePercent + 2600; + float b2=(3840-3900)*fPressurePercent + 3900; + float b3=(3912-3950)*fPressurePercent + 3950; + z2 = (u16)(int)(b0 + (b1-b0)*u + (b2-b0)*v + (b3-b2-b1+b0)*u*v); + } + +} + +//================================================= MMU ARM7 write 16 +void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val) +{ + adr &= 0x0FFFFFFE; + + mmu_log_debug_ARM7(adr, "(write16) 0x%04X", val); + + if (adr < 0x4000) return; // PU BIOS + + if ( (adr >= 0x08000000) && (adr < 0x0A010000) ) + { + u16 exmemcnt = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204); + if(!(exmemcnt & EXMEMCNT_MASK_SLOT2_ARM7)) + {} //prohibited + else addon.write16(ARMCPU_ARM7,adr, val); + return; + } + + //wifi mac access + if ((adr & 0xFFFF0000) == 0x04800000) + { + WIFI_write16(adr,val); + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x48], adr&MMU.MMU_MASK[ARMCPU_ARM7][0x48], val); + return; + } + + if ((adr>=0x04000400)&&(adr<0x04000520)) + { + SPU_WriteWord(adr, val); + return; + } + + if((adr >> 24) == 4) + { + if(MMU_new.is_dma(adr)) { MMU_new.write_dma(ARMCPU_ARM7,16,adr,val); return; } + + //Address is an IO register + switch(adr) + { + case REG_DISPA_VCOUNT: + if (nds.VCount >= 202 && nds.VCount <= 212) + { + printf("VCOUNT set to %i (previous value %i)\n", val, nds.VCount); + nds.VCount = val; + } + else + printf("Attempt to set VCOUNT while not within 202-212 (%i), ignored\n", nds.VCount); + return; + + case REG_RTC: + rtcWrite(val); + break; + + case REG_EXMEMCNT: + { + u16 remote_proc = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x204); + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204, (val & 0x7F) | (remote_proc & 0xFF80)); + } + return; + + case REG_EXTKEYIN: //readonly + return; + + + case REG_POWCNT2: + { + nds.power2.speakers = BIT0(val); + nds.power2.wifi = BIT0(val); + } + return; + + + case REG_AUXSPICNT: + write_auxspicnt(7,16,0,val); + return; + + case REG_AUXSPIDATA: + if(val!=0) + MMU.AUX_SPI_CMD = val & 0xFF; + + //T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, bm_transfer(&MMU.bupmem, val)); + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, MMU_new.backupDevice.data_command((u8)val,ARMCPU_ARM7)); + MMU.AUX_SPI_CNT &= ~0x80; //remove busy flag + return; + + case REG_SPICNT : + { + int reset_firmware = 1; + + if ( ((MMU.SPI_CNT >> 8) & 0x3) == 1) + { + if ( ((val >> 8) & 0x3) == 1) + { + if ( BIT11(MMU.SPI_CNT)) + { + // select held + reset_firmware = 0; + } + } + } + + //MMU.fw.com == 0; // reset fw device communication + if ( reset_firmware) + { + // reset fw device communication + fw_reset_com(&MMU.fw); + } + MMU.SPI_CNT = val; + + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_SPICNT >> 20) & 0xff], REG_SPICNT & 0xfff, val); + } + return; + + case REG_SPIDATA : + { + u16 spicnt; + + if(val!=0) + MMU.SPI_CMD = val; + + spicnt = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_SPICNT >> 20) & 0xff], REG_SPICNT & 0xfff); + + switch((spicnt >> 8) & 0x3) + { + case 0 : + { + if(!MMU.powerMan_CntRegWritten) + { + MMU.powerMan_CntReg = (val & 0xFF); + MMU.powerMan_CntRegWritten = TRUE; + } + else + { + u16 reg = MMU.powerMan_CntReg&0x7F; + reg &= 0x7; + if(reg==5 || reg==6 || reg==7) reg = 4; + + //(let's start with emulating a DS lite, since it is the more complex case) + if(MMU.powerMan_CntReg & 0x80) + { + //read + val = MMU.powerMan_Reg[reg]; + } + else + { + //write + MMU.powerMan_Reg[reg] = (u8)val; + + enum PM_Bits //from libnds + { + PM_SOUND_AMP = BIT(0) , /*!< \brief Power the sound hardware (needed to hear stuff in GBA mode too) */ + PM_SOUND_MUTE = BIT(1), /*!< \brief Mute the main speakers, headphone output will still work. */ + PM_BACKLIGHT_BOTTOM = BIT(2), /*!< \brief Enable the top backlight if set */ + PM_BACKLIGHT_TOP = BIT(3) , /*!< \brief Enable the bottom backlight if set */ + PM_SYSTEM_PWR = BIT(6) , /*!< \brief Turn the power *off* if set */ + }; + + //our totally pathetic register handling, only the one thing we've wanted so far + if(MMU.powerMan_Reg[0]&PM_SYSTEM_PWR) { + printf("SYSTEM POWERED OFF VIA ARM7 SPI POWER DEVICE\n"); + printf("Did your main() return?\n"); + emu_halt(); + } + } + + MMU.powerMan_CntRegWritten = FALSE; + } + } + break; + + case 1 : /* firmware memory device */ + if((spicnt & 0x3) != 0) /* check SPI baudrate (must be 4mhz) */ + { + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, 0); + break; + } + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, fw_transfer(&MMU.fw, (u8)val)); + return; + + case 2: + { + if(nds.Is_DSI()) + { + //pass data to TSC + val = MMU_new.dsi_tsc.write16(val); + + //apply reset command if appropriate + if(!BIT11(MMU.SPI_CNT)) + MMU_new.dsi_tsc.reset_command(); + + break; + } + + int channel = (MMU.SPI_CMD&0x70)>>4; + //printf("%08X\n",channel); + switch(channel) + { + case TSC_MEASURE_TEMP1: + if(spicnt & 0x800) + { + if(partie) + { + val = ((716<<3)&0x7FF); + partie = 0; + break; + } + val = (716>>5); + partie = 1; + break; + } + val = ((716<<3)&0x7FF); + partie = 1; + break; + case TSC_MEASURE_TEMP2: + if(spicnt & 0x800) + { + if(partie) + { + val = ((865<<3)&0x7FF); + partie = 0; + break; + } + val = (865>>5); + partie = 1; + break; + } + val = ((865<<3)&0x7FF); + partie = 1; + break; + + case TSC_MEASURE_Y: + { + //counter the number of adc touch coord reads and jitter it after a while to simulate a shaky human hand or multiple reads + nds.adc_jitterctr++; + if(nds.adc_jitterctr == 25) + { + nds.adc_jitterctr = 0; + nds.adc_touchY ^= 16; + nds.adc_touchX ^= 16; + } + if(MMU.SPI_CNT&(1<<11)) + { + if(partie) + { + val = (nds.adc_touchY<<3) & 0xFF; + partie = 0; + break; + } + + val = (nds.adc_touchY>>5) & 0xFF; + partie = 1; + break; + } + val = (nds.adc_touchY<<3)&0xFF; + partie = 1; + break; + } + case TSC_MEASURE_Z1: //Z1 + //used for pressure calculation - must be nonzero or else some softwares will think the stylus is up. + //something is wrong in here and some of these LSB dont make it back to libnds... whatever. + { + u16 scratch; + CalculateTouchPressure(CommonSettings.StylusPressure,val,scratch); + } + if(spicnt & 0x800) + { + if(partie) + { + val = ((val<<3)&0x7FF); + partie = 0; + break; + } + val = (val>>5); + partie = 1; + break; + } + val = ((val<<3)&0x7FF); + partie = 1; + break; + case TSC_MEASURE_Z2: //Z2 + //used for pressure calculation - must be nonzero or else some softwares will think the stylus is up. + //something is wrong in here and some of these LSB dont make it back to libnds... whatever. + { + u16 scratch; + CalculateTouchPressure(CommonSettings.StylusPressure,scratch,val); + } + if(spicnt & 0x800) + { + if(partie) + { + val = ((val<<3)&0x7FF); + partie = 0; + break; + } + val = (val>>5); + partie = 1; + break; + } + val = ((val<<3)&0x7FF); + partie = 1; + break; + case TSC_MEASURE_X: + if(spicnt & 0x800) + { + if(partie) + { + val = (nds.adc_touchX << 3) & 0xFF; + partie = 0; + break; + } + val = (nds.adc_touchX>>5) & 0xFF; + partie = 1; + break; + } + val = (nds.adc_touchX<<3) & 0xFF; + partie = 1; + break; + case TSC_MEASURE_AUX: + if(!(val & 0x80)) + val = (Mic_ReadSample() & 0xFF); + else + val = 0; + break; + } + break; + } + + case 3 : + /* NOTICE: Device 3 of SPI is reserved (unused and unusable) */ + break; + } + } + + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, val); + return; + + /* NOTICE: Perhaps we have to use gbatek-like reg names instead of libnds-like ones ...*/ + + case REG_IME : + NDS_Reschedule(); + MMU.reg_IME[ARMCPU_ARM7] = val & 0x01; + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x208, val); + return; + case REG_IE : + NDS_Reschedule(); + MMU.reg_IE[ARMCPU_ARM7] = (MMU.reg_IE[ARMCPU_ARM7]&0xFFFF0000) | val; + return; + case REG_IE + 2 : + NDS_Reschedule(); + //emu_halt(); + MMU.reg_IE[ARMCPU_ARM7] = (MMU.reg_IE[ARMCPU_ARM7]&0xFFFF) | (((u32)val)<<16); + return; + + case REG_IF: REG_IF_WriteWord(0,val); return; + case REG_IF+2: REG_IF_WriteWord(2,val); return; + + case REG_IPCSYNC: + MMU_IPCSync(ARMCPU_ARM7, val); + return; + case REG_IPCFIFOCNT: + IPC_FIFOcnt(ARMCPU_ARM7, val); + return; + + case REG_TM0CNTL : + case REG_TM1CNTL : + case REG_TM2CNTL : + case REG_TM3CNTL : + MMU.timerReload[ARMCPU_ARM7][(adr>>2)&3] = val; + return; + case REG_TM0CNTH : + case REG_TM1CNTH : + case REG_TM2CNTH : + case REG_TM3CNTH : + { + int timerIndex = ((adr-2)>>2)&0x3; + write_timer(ARMCPU_ARM7, timerIndex, val); + return; + } + + case REG_GCROMCTRL : + MMU_writeToGCControl( (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x1A4) & 0xFFFF0000) | val); + return; + case REG_GCROMCTRL+2 : + MMU_writeToGCControl( (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x1A4) & 0xFFFF) | ((u32) val << 16)); + return; + } + + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][adr>>20], adr&MMU.MMU_MASK[ARMCPU_ARM7][adr>>20], val); + return; + } + + bool unmapped, restricted; + adr = MMU_LCDmap(adr,unmapped, restricted); + if(unmapped) return; + + // Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [shash] + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][adr>>20], adr&MMU.MMU_MASK[ARMCPU_ARM7][adr>>20], val); +} +//================================================= MMU ARM7 write 32 +void FASTCALL _MMU_ARM7_write32(u32 adr, u32 val) +{ + adr &= 0x0FFFFFFC; + + mmu_log_debug_ARM7(adr, "(write32) 0x%08X", val); + + if (adr < 0x4000) return; // PU BIOS + + if ( (adr >= 0x08000000) && (adr < 0x0A010000) ) + { + u16 exmemcnt = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204); + if(!(exmemcnt & EXMEMCNT_MASK_SLOT2_ARM7)) + {} //prohibited + else addon.write32(ARMCPU_ARM7,adr, val); + return; + } + + if ((adr & 0xFFFF0000) == 0x04800000) + { + WIFI_write16(adr, val & 0xFFFF); + WIFI_write16(adr+2, val >> 16); + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][0x48], adr&MMU.MMU_MASK[ARMCPU_ARM7][0x48], val); + return; + } + + if ((adr>=0x04000400)&&(adr<0x04000520)) + { + SPU_WriteLong(adr, val); + return; + } + + if((adr>>24)==4) + { + if(MMU_new.is_dma(adr)) { MMU_new.write_dma(ARMCPU_ARM7,32,adr,val); return; } + + switch(adr) + { + case REG_RTC: + rtcWrite((u16)val); + break; + + case REG_IME : + NDS_Reschedule(); + MMU.reg_IME[ARMCPU_ARM7] = val & 0x01; + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x208, val); + return; + + case REG_IE : + NDS_Reschedule(); + MMU.reg_IE[ARMCPU_ARM7] = val; + return; + + case REG_IF: REG_IF_WriteLong(val); return; + + case REG_TM0CNTL: + case REG_TM1CNTL: + case REG_TM2CNTL: + case REG_TM3CNTL: + { + int timerIndex = (adr>>2)&0x3; + MMU.timerReload[ARMCPU_ARM7][timerIndex] = (u16)val; + T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], adr & 0xFFF, val); + write_timer(ARMCPU_ARM7, timerIndex, val>>16); + return; + } + + + case REG_IPCSYNC: + MMU_IPCSync(ARMCPU_ARM7, val); + return; + case REG_IPCFIFOCNT: + IPC_FIFOcnt(ARMCPU_ARM7, val); + return; + case REG_IPCFIFOSEND: + IPC_FIFOsend(ARMCPU_ARM7, val); + return; + + case REG_GCROMCTRL : + MMU_writeToGCControl(val); + return; + + case REG_GCDATAIN: + slot1_device.write32(ARMCPU_ARM7, REG_GCDATAIN,val); + return; + } + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][adr>>20], adr & MMU.MMU_MASK[ARMCPU_ARM7][adr>>20], val); + return; + } + + bool unmapped, restricted; + adr = MMU_LCDmap(adr,unmapped, restricted); + if(unmapped) return; + + // Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [shash] + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][adr>>20], adr&MMU.MMU_MASK[ARMCPU_ARM7][adr>>20], val); +} + +//================================================= MMU ARM7 read 08 +u8 FASTCALL _MMU_ARM7_read08(u32 adr) +{ + adr &= 0x0FFFFFFF; + + mmu_log_debug_ARM7(adr, "(read08) 0x%02X", MMU.MMU_MEM[ARMCPU_ARM7][(adr>>20)&0xFF][adr&MMU.MMU_MASK[ARMCPU_ARM7][(adr>>20)&0xFF]]); + + if (adr < 0x4000) + { + //u32 prot = T1ReadLong_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x04000308 & MMU.MMU_MASK[ARMCPU_ARM7][0x40]); + //if (prot) INFO("MMU7 read 08 at 0x%08X (PC 0x%08X) BIOSPROT address 0x%08X\n", adr, NDS_ARM7.R[15], prot); + + //How accurate is this? our R[15] may not be exactly what the hardware uses (may use something less by up to 0x08) + //This may be inaccurate at the very edge cases. + if (NDS_ARM7.R[15] > 0x3FFF) + return 0xFF; + } + + // wifi mac access + if ((adr & 0xFFFF0000) == 0x04800000) + { + if (adr & 1) + return (WIFI_read16(adr-1) >> 8) & 0xFF; + else + return WIFI_read16(adr) & 0xFF; + } + + if ( (adr >= 0x08000000) && (adr < 0x0A010000) ) + { + u16 exmemcnt = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204); + if(!(exmemcnt & EXMEMCNT_MASK_SLOT2_ARM7)) + return 0; //prohibited + else return addon.read08(ARMCPU_ARM7,adr); + } + + if ((adr>=0x04000400)&&(adr<0x04000520)) + { + return SPU_ReadByte(adr); + } + + if (adr == REG_RTC) return (u8)rtcRead(); + + if (adr >> 24 == 4) + { + if(MMU_new.is_dma(adr)) return MMU_new.read_dma(ARMCPU_ARM7,8,adr); + + // Address is an IO register + + switch(adr) + { + case REG_IF: return MMU.gen_IF(); + case REG_IF+1: return (MMU.gen_IF()>>8); + case REG_IF+2: return (MMU.gen_IF()>>16); + case REG_IF+3: return (MMU.gen_IF()>>24); + + case REG_DISPx_VCOUNT: return nds.VCount&0xFF; + case REG_DISPx_VCOUNT+1: return (nds.VCount>>8)&0xFF; + } + + return MMU.MMU_MEM[ARMCPU_ARM7][adr>>20][adr&MMU.MMU_MASK[ARMCPU_ARM7][adr>>20]]; + } + + bool unmapped, restricted; + adr = MMU_LCDmap(adr,unmapped, restricted); + if(unmapped) return 0; + + return MMU.MMU_MEM[ARMCPU_ARM7][adr>>20][adr&MMU.MMU_MASK[ARMCPU_ARM7][adr>>20]]; +} +//================================================= MMU ARM7 read 16 +u16 FASTCALL _MMU_ARM7_read16(u32 adr) +{ + adr &= 0x0FFFFFFE; + + mmu_log_debug_ARM7(adr, "(read16) 0x%04X", T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][(adr>>20)&0xFF], adr & MMU.MMU_MASK[ARMCPU_ARM7][(adr>>20)&0xFF])); + + if (adr < 0x4000) + { + //u32 prot = T1ReadLong_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x04000308 & MMU.MMU_MASK[ARMCPU_ARM7][0x40]); + //if (prot) INFO("MMU7 read 16 at 0x%08X (PC 0x%08X) BIOSPROT address 0x%08X\n", adr, NDS_ARM7.R[15], prot); + if (NDS_ARM7.R[15] > 0x3FFF) + return 0xFFFF; + } + + //wifi mac access + if ((adr & 0xFFFF0000) == 0x04800000) + return WIFI_read16(adr) ; + + if ( (adr >= 0x08000000) && (adr < 0x0A010000) ) + { + u16 exmemcnt = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204); + if(!(exmemcnt & EXMEMCNT_MASK_SLOT2_ARM7)) + return 0; //prohibited + else return addon.read16(ARMCPU_ARM7,adr); + } + + if ((adr>=0x04000400)&&(adr<0x04000520)) + { + return SPU_ReadWord(adr); + } + + if(adr>>24==4) + { //Address is an IO register + + if(MMU_new.is_dma(adr)) return MMU_new.read_dma(ARMCPU_ARM7,16,adr); + + switch(adr) + { + case REG_POWCNT2: + { + u16 ret = 0; + ret |= nds.power2.speakers?BIT(0):0; + ret |= nds.power2.wifi?BIT(1):0; + return ret; + } + + case REG_DISPx_VCOUNT: return nds.VCount; + case REG_RTC: return rtcRead(); + case REG_IME: return (u16)MMU.reg_IME[ARMCPU_ARM7]; + + case REG_IE: + return (u16)MMU.reg_IE[ARMCPU_ARM7]; + case REG_IE + 2: + return (u16)(MMU.reg_IE[ARMCPU_ARM7]>>16); + + case REG_IF: return MMU.gen_IF(); + case REG_IF+2: return MMU.gen_IF()>>16; + + case REG_TM0CNTL : + case REG_TM1CNTL : + case REG_TM2CNTL : + case REG_TM3CNTL : + return read_timer(ARMCPU_ARM7,(adr&0xF)>>2); + + case REG_AUXSPICNT: + return MMU.AUX_SPI_CNT; + + case REG_KEYINPUT: + //here is an example of what not to do: + //since the arm7 polls this (and EXTKEYIN) every frame, we shouldnt count this as an input check + //LagFrameFlag=0; + break; + + case REG_EXTKEYIN: + { + //this is gross. we should generate this whole reg instead of poking it in ndssystem + u16 ret = MMU.ARM7_REG[0x136]; + if(nds.isTouch) + ret &= ~64; + else ret |= 64; + return ret; + } + } + return T1ReadWord_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM7][adr>>20], adr & MMU.MMU_MASK[ARMCPU_ARM7][adr>>20]); + } + + bool unmapped, restricted; + adr = MMU_LCDmap(adr,unmapped, restricted); + if(unmapped) return 0; + + /* Returns data from memory */ + // Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF + return T1ReadWord_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM7][adr >> 20], adr & MMU.MMU_MASK[ARMCPU_ARM7][adr >> 20]); +} +//================================================= MMU ARM7 read 32 +u32 FASTCALL _MMU_ARM7_read32(u32 adr) +{ + adr &= 0x0FFFFFFC; + + mmu_log_debug_ARM7(adr, "(read32) 0x%08X", T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][(adr>>20)&0xFF], adr & MMU.MMU_MASK[ARMCPU_ARM7][(adr>>20)&0xFF])); + + if (adr < 0x4000) + { + //u32 prot = T1ReadLong_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x04000308 & MMU.MMU_MASK[ARMCPU_ARM7][0x40]); + //if (prot) INFO("MMU7 read 32 at 0x%08X (PC 0x%08X) BIOSPROT address 0x%08X\n", adr, NDS_ARM7.R[15], prot); + if (NDS_ARM7.R[15] > 0x3FFF) + return 0xFFFFFFFF; + } + + //wifi mac access + if ((adr & 0xFFFF0000) == 0x04800000) + return (WIFI_read16(adr) | (WIFI_read16(adr+2) << 16)); + + if ( (adr >= 0x08000000) && (adr < 0x0A010000) ) + { + u16 exmemcnt = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x204); + if(!(exmemcnt & EXMEMCNT_MASK_SLOT2_ARM7)) + return 0; //prohibited + else return addon.read32(ARMCPU_ARM7,adr); + } + + if ((adr>=0x04000400)&&(adr<0x04000520)) + { + return SPU_ReadLong(adr); + } + + if((adr >> 24) == 4) + { //Address is an IO register + + if(MMU_new.is_dma(adr)) return MMU_new.read_dma(ARMCPU_ARM7,32,adr); + + switch(adr) + { + case REG_RTC: return (u32)rtcRead(); + case REG_DISPx_VCOUNT: return nds.VCount; + + case REG_IME : + return MMU.reg_IME[ARMCPU_ARM7]; + case REG_IE : + return MMU.reg_IE[ARMCPU_ARM7]; + case REG_IF: return MMU.gen_IF(); + case REG_IPCFIFORECV : + return IPC_FIFOrecv(ARMCPU_ARM7); + case REG_TM0CNTL : + case REG_TM1CNTL : + case REG_TM2CNTL : + case REG_TM3CNTL : + { + u32 val = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], (adr + 2) & 0xFFF); + return MMU.timer[ARMCPU_ARM7][(adr&0xF)>>2] | (val<<16); + } + case REG_GCROMCTRL: + { + //INFO("arm7 romctrl read\n"); + break; + } + case REG_GCDATAIN: + return MMU_readFromGC(); + + } + return T1ReadLong_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM7][adr>>20], adr & MMU.MMU_MASK[ARMCPU_ARM7][adr>>20]); + } + + bool unmapped, restricted; + adr = MMU_LCDmap(adr,unmapped, restricted); + if(unmapped) return 0; + + //Returns data from memory + // Removed the &0xFF as they are implicit with the adr&0x0FFFFFFF [zeromus, inspired by shash] + return T1ReadLong_guaranteedAligned(MMU.MMU_MEM[ARMCPU_ARM7][adr >> 20], adr & MMU.MMU_MASK[ARMCPU_ARM7][adr >> 20]); +} + +//========================================================================================================= + +u32 FASTCALL MMU_read32(u32 proc, u32 adr) +{ + ASSERT_UNALIGNED((adr&3)==0); + + if(proc==0) + return _MMU_ARM9_read32(adr); + else + return _MMU_ARM7_read32(adr); +} + +u16 FASTCALL MMU_read16(u32 proc, u32 adr) +{ + ASSERT_UNALIGNED((adr&1)==0); + + if(proc==0) + return _MMU_ARM9_read16(adr); + else + return _MMU_ARM7_read16(adr); +} + +u8 FASTCALL MMU_read8(u32 proc, u32 adr) +{ + if(proc==0) + return _MMU_ARM9_read08(adr); + else + return _MMU_ARM7_read08(adr); +} + +void FASTCALL MMU_write32(u32 proc, u32 adr, u32 val) +{ + ASSERT_UNALIGNED((adr&3)==0); + + if(proc==0) + _MMU_ARM9_write32(adr, val); + else + _MMU_ARM7_write32(adr,val); +} + +void FASTCALL MMU_write16(u32 proc, u32 adr, u16 val) +{ + ASSERT_UNALIGNED((adr&1)==0); + + if(proc==0) + _MMU_ARM9_write16(adr, val); + else + _MMU_ARM7_write16(adr,val); +} + +void FASTCALL MMU_write8(u32 proc, u32 adr, u8 val) +{ + if(proc==0) + _MMU_ARM9_write08(adr, val); + else + _MMU_ARM7_write08(adr,val); +} + +void FASTCALL MMU_DumpMemBlock(u8 proc, u32 address, u32 size, u8 *buffer) +{ + u32 i; + u32 curaddr; + + for(i = 0, curaddr = address; i < size; i++, curaddr++) + { + buffer[i] = _MMU_read08(proc,MMU_AT_DEBUG,curaddr); + } +} + + +//these templates needed to be instantiated manually +template u32 MMU_struct::gen_IF(); +template u32 MMU_struct::gen_IF(); + +//////////////////////////////////////////////////////////// +//function pointer handlers for gdb stub stuff + +static u16 FASTCALL arm9_prefetch16( void *data, u32 adr) { + return _MMU_read16(adr); +} + +static u32 FASTCALL arm9_prefetch32( void *data, u32 adr) { + return _MMU_read32(adr); +} + +static u8 FASTCALL arm9_read8( void *data, u32 adr) { + return _MMU_read08(adr); +} + +static u16 FASTCALL arm9_read16( void *data, u32 adr) { + return _MMU_read16(adr); +} + +static u32 FASTCALL arm9_read32( void *data, u32 adr) { + return _MMU_read32(adr); +} + +static void FASTCALL arm9_write8(void *data, u32 adr, u8 val) { + _MMU_write08(adr, val); +} + +static void FASTCALL arm9_write16(void *data, u32 adr, u16 val) { + _MMU_write16(adr, val); +} + +static void FASTCALL arm9_write32(void *data, u32 adr, u32 val) { + _MMU_write32(adr, val); +} + +static u16 FASTCALL arm7_prefetch16( void *data, u32 adr) { + return _MMU_read16(adr); +} + +static u32 FASTCALL arm7_prefetch32( void *data, u32 adr) { + return _MMU_read32(adr); +} + +static u8 FASTCALL arm7_read8( void *data, u32 adr) { + return _MMU_read08(adr); +} + +static u16 FASTCALL arm7_read16( void *data, u32 adr) { + return _MMU_read16(adr); +} + +static u32 FASTCALL arm7_read32( void *data, u32 adr) { + return _MMU_read32(adr); +} + +static void FASTCALL arm7_write8(void *data, u32 adr, u8 val) { + _MMU_write08(adr, val); +} + +static void FASTCALL arm7_write16(void *data, u32 adr, u16 val) { + _MMU_write16(adr, val); +} + +static void FASTCALL arm7_write32(void *data, u32 adr, u32 val) { + _MMU_write32(adr, val); +} + + + +/* + * the base memory interfaces + */ +struct armcpu_memory_iface arm9_base_memory_iface = { + arm9_prefetch32, + arm9_prefetch16, + + arm9_read8, + arm9_read16, + arm9_read32, + + arm9_write8, + arm9_write16, + arm9_write32 +}; + +struct armcpu_memory_iface arm7_base_memory_iface = { + arm7_prefetch32, + arm7_prefetch16, + + arm7_read8, + arm7_read16, + arm7_read32, + + arm7_write8, + arm7_write16, + arm7_write32 +}; + +/* + * The direct memory interface for the ARM9. + * This avoids the ARM9 protection unit when accessing + * memory. + */ +struct armcpu_memory_iface arm9_direct_memory_iface = { + NULL, + NULL, + + arm9_read8, + arm9_read16, + arm9_read32, + + arm9_write8, + arm9_write16, + arm9_write32 +}; + + +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// + +//#ifdef PROFILE_MEMORY_ACCESS +// +//#define PROFILE_PREFETCH 0 +//#define PROFILE_READ 1 +//#define PROFILE_WRITE 2 +// +//struct mem_access_profile { +// u64 num_accesses; +// u32 address_mask; +// u32 masked_value; +//}; +// +//#define PROFILE_NUM_MEM_ACCESS_PROFILES 4 +// +//static u64 profile_num_accesses[2][3]; +//static u64 profile_unknown_addresses[2][3]; +//static struct mem_access_profile +//profile_memory_accesses[2][3][PROFILE_NUM_MEM_ACCESS_PROFILES]; +// +//static void +//setup_profiling( void) { +// int i; +// +// for ( i = 0; i < 2; i++) { +// int access_type; +// +// for ( access_type = 0; access_type < 3; access_type++) { +// profile_num_accesses[i][access_type] = 0; +// profile_unknown_addresses[i][access_type] = 0; +// +// /* +// * Setup the access testing structures +// */ +// profile_memory_accesses[i][access_type][0].address_mask = 0x0e000000; +// profile_memory_accesses[i][access_type][0].masked_value = 0x00000000; +// profile_memory_accesses[i][access_type][0].num_accesses = 0; +// +// /* main memory */ +// profile_memory_accesses[i][access_type][1].address_mask = 0x0f000000; +// profile_memory_accesses[i][access_type][1].masked_value = 0x02000000; +// profile_memory_accesses[i][access_type][1].num_accesses = 0; +// +// /* shared memory */ +// profile_memory_accesses[i][access_type][2].address_mask = 0x0f800000; +// profile_memory_accesses[i][access_type][2].masked_value = 0x03000000; +// profile_memory_accesses[i][access_type][2].num_accesses = 0; +// +// /* arm7 memory */ +// profile_memory_accesses[i][access_type][3].address_mask = 0x0f800000; +// profile_memory_accesses[i][access_type][3].masked_value = 0x03800000; +// profile_memory_accesses[i][access_type][3].num_accesses = 0; +// } +// } +//} +// +//static void +//profile_memory_access( int arm9, u32 adr, int access_type) { +// static int first = 1; +// int mem_profile; +// int address_found = 0; +// +// if ( first) { +// setup_profiling(); +// first = 0; +// } +// +// profile_num_accesses[arm9][access_type] += 1; +// +// for ( mem_profile = 0; +// mem_profile < PROFILE_NUM_MEM_ACCESS_PROFILES && +// !address_found; +// mem_profile++) { +// if ( (adr & profile_memory_accesses[arm9][access_type][mem_profile].address_mask) == +// profile_memory_accesses[arm9][access_type][mem_profile].masked_value) { +// /*printf( "adr %08x mask %08x res %08x expected %08x\n", +// adr, +// profile_memory_accesses[arm9][access_type][mem_profile].address_mask, +// adr & profile_memory_accesses[arm9][access_type][mem_profile].address_mask, +// profile_memory_accesses[arm9][access_type][mem_profile].masked_value);*/ +// address_found = 1; +// profile_memory_accesses[arm9][access_type][mem_profile].num_accesses += 1; +// } +// } +// +// if ( !address_found) { +// profile_unknown_addresses[arm9][access_type] += 1; +// } +//} +// +// +//static const char *access_type_strings[] = { +// "prefetch", +// "read ", +// "write " +//}; +// +//void +//print_memory_profiling( void) { +// int arm; +// +// printf("------ Memory access profile ------\n"); +// +// for ( arm = 0; arm < 2; arm++) { +// int access_type; +// +// for ( access_type = 0; access_type < 3; access_type++) { +// int mem_profile; +// printf("ARM%c: num of %s %lld\n", +// arm ? '9' : '7', +// access_type_strings[access_type], +// profile_num_accesses[arm][access_type]); +// +// for ( mem_profile = 0; +// mem_profile < PROFILE_NUM_MEM_ACCESS_PROFILES; +// mem_profile++) { +// printf( "address %08x: %lld\n", +// profile_memory_accesses[arm][access_type][mem_profile].masked_value, +// profile_memory_accesses[arm][access_type][mem_profile].num_accesses); +// } +// +// printf( "unknown addresses %lld\n", +// profile_unknown_addresses[arm][access_type]); +// +// printf( "\n"); +// } +// } +// +// printf("------ End of Memory access profile ------\n\n"); +//} +//#else +//void +//print_memory_profiling( void) { +//} +//#endif /* End of PROFILE_MEMORY_ACCESS area */ diff --git a/jni/desmume/src/MMU.h b/jni/desmume/src/MMU.h new file mode 100755 index 0000000..4fc2750 --- /dev/null +++ b/jni/desmume/src/MMU.h @@ -0,0 +1,938 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2007 shash + Copyright (C) 2007-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ + +#ifndef MMU_H +#define MMU_H + +#include "FIFO.h" +#include "mem.h" +#include "registers.h" +#include "mc.h" +#include "bits.h" +#include "readwrite.h" +#include "debug.h" + +#ifdef HAVE_LUA +#include "lua-engine.h" +#endif + +#define ARMCPU_ARM7 1 +#define ARMCPU_ARM9 0 +#define ARMPROC (PROCNUM ? NDS_ARM7:NDS_ARM9) + +typedef const u8 TWaitState; + + +enum EDMAMode +{ + EDMAMode_Immediate = 0, + EDMAMode_VBlank = 1, + EDMAMode_HBlank = 2, + EDMAMode_HStart = 3, + EDMAMode_MemDisplay = 4, + EDMAMode_Card = 5, + EDMAMode_GBASlot = 6, + EDMAMode_GXFifo = 7, + EDMAMode7_Wifi = 8, + EDMAMode7_GBASlot = 9, +}; + +enum EDMABitWidth +{ + EDMABitWidth_16 = 0, + EDMABitWidth_32 = 1 +}; + +enum EDMASourceUpdate +{ + EDMASourceUpdate_Increment = 0, + EDMASourceUpdate_Decrement = 1, + EDMASourceUpdate_Fixed = 2, + EDMASourceUpdate_Invalid = 3, +}; + +enum EDMADestinationUpdate +{ + EDMADestinationUpdate_Increment = 0, + EDMADestinationUpdate_Decrement = 1, + EDMADestinationUpdate_Fixed = 2, + EDMADestinationUpdate_IncrementReload = 3, +}; + +//TODO +//n.b. this may be a bad idea, for complex registers like the dma control register. +//we need to know exactly what part was written to, instead of assuming all 32bits were written. +class TRegister_32 +{ +public: + virtual u32 read32() = 0; + virtual void write32(const u32 val) = 0; + void write(const int size, const u32 adr, const u32 val) { + if(size==32) write32(val); + else { + const u32 offset = adr&3; + if(size==8) { + printf("WARNING! 8BIT DMA ACCESS\n"); + u32 mask = 0xFF<<(offset<<3); + write32((read32()&~mask)|(val<<(offset<<3))); + } + else if(size==16) { + u32 mask = 0xFFFF<<(offset<<3); + write32((read32()&~mask)|(val<<(offset<<3))); + } + } + } + + u32 read(const int size, const u32 adr) + { + if(size==32) return read32(); + else { + const u32 offset = adr&3; + if(size==8) { printf("WARNING! 8BIT DMA ACCESS\n"); return (read32()>>(offset<<3))&0xFF; } + else return (read32()>>(offset<<3))&0xFFFF; + } + } +}; + +struct TGXSTAT : public TRegister_32 +{ + TGXSTAT() { + gxfifo_irq = se = tr = tb = sb = 0; + fifo_empty = true; + fifo_low = false; + } + u8 tb; //test busy + u8 tr; //test result + u8 se; //stack error + u8 sb; //stack busy + u8 gxfifo_irq; //irq configuration + + bool fifo_empty, fifo_low; + + virtual u32 read32(); + virtual void write32(const u32 val); + + void savestate(EMUFILE *f); + bool loadstate(EMUFILE *f); +}; + +void triggerDma(EDMAMode mode); + +class DivController +{ +public: + DivController() + : mode(0), busy(0) + {} + void exec(); + u8 mode, busy, div0; + u16 read16() { return mode|(busy<<15)|(div0<<14); } + void write16(u16 val) { + mode = val&3; + //todo - do we clear the div0 flag here or is that strictly done by the divider unit? + } + void savestate(EMUFILE* os) + { + write8le(&mode,os); + write8le(&busy,os); + write8le(&div0,os); + } + bool loadstate(EMUFILE* is, int version) + { + int ret = 1; + ret &= read8le(&mode,is); + ret &= read8le(&busy,is); + ret &= read8le(&div0,is); + return ret==1; + } +}; + +class SqrtController +{ +public: + SqrtController() + : mode(0), busy(0) + {} + void exec(); + u8 mode, busy; + u16 read16() { return mode|(busy<<15); } + void write16(u16 val) { mode = val&1; } + void savestate(EMUFILE* os) + { + write8le(&mode,os); + write8le(&busy,os); + } + bool loadstate(EMUFILE* is, int version) + { + int ret=1; + ret &= read8le(&mode,is); + ret &= read8le(&busy,is); + return ret==1; + } +}; + + +class DmaController +{ +public: + u8 enable, irq, repeatMode, _startmode; + u8 userEnable; + u32 wordcount; + EDMAMode startmode; + EDMABitWidth bitWidth; + EDMASourceUpdate sar; + EDMADestinationUpdate dar; + u32 saddr, daddr; + u32 saddr_user, daddr_user; + + //indicates whether the dma needs to be checked for triggering + BOOL dmaCheck; + + //indicates whether the dma right now is logically running + //(though for now we copy all the data when it triggers) + BOOL running; + + BOOL paused; + + //this flag will sometimes be set when a start condition is triggered + //other conditions may be automatically triggered based on scanning conditions + BOOL triggered; + + u64 nextEvent; + + int procnum, chan; + + void savestate(EMUFILE *f); + bool loadstate(EMUFILE *f); + + void exec(); + template void doCopy(); + void doPause(); + void doStop(); + void doSchedule(); + void tryTrigger(EDMAMode mode); + + DmaController() : + enable(0), irq(0), repeatMode(0), _startmode(0), + wordcount(0), startmode(EDMAMode_Immediate), + bitWidth(EDMABitWidth_16), + sar(EDMASourceUpdate_Increment), dar(EDMADestinationUpdate_Increment), + //if saddr isnt cleared then rings of fate will trigger copy protection + //by inspecting dma3 saddr when it boots + saddr(0), daddr(0), + saddr_user(0), daddr_user(0), + dmaCheck(FALSE), + running(FALSE), + paused(FALSE), + triggered(FALSE), + nextEvent(0), + sad(&saddr_user), + dad(&daddr_user) + { + sad.controller = this; + dad.controller = this; + ctrl.controller = this; + regs[0] = &sad; + regs[1] = &dad; + regs[2] = &ctrl; + } + + class AddressRegister : public TRegister_32 { + public: + //we pass in a pointer to the controller here so we can alert it if anything changes + DmaController* controller; + u32 * const ptr; + AddressRegister(u32* _ptr) + : ptr(_ptr) + {} + virtual u32 read32() { + return *ptr; + } + virtual void write32(const u32 val) { + *ptr = val; + } + }; + + class ControlRegister : public TRegister_32 { + public: + //we pass in a pointer to the controller here so we can alert it if anything changes + DmaController* controller; + ControlRegister() {} + virtual u32 read32() { + return controller->read32(); + } + virtual void write32(const u32 val) { + return controller->write32(val); + } + }; + + AddressRegister sad, dad; + ControlRegister ctrl; + TRegister_32* regs[3]; + + void write32(const u32 val); + u32 read32(); + +}; + +enum ECardMode +{ + CardMode_Normal = 0, + CardMode_KEY1, + CardMode_KEY2, +}; + +typedef struct +{ + + u8 command[8]; + + u32 address; + u32 transfer_count; + + ECardMode mode; + + // NJSD stuff + int blocklen; + +} nds_dscard; + +struct MMU_struct +{ + //ARM9 mem + u8 ARM9_ITCM[0x8000]; + u8 ARM9_DTCM[0x4000]; + + //u8 MAIN_MEM[4*1024*1024]; //expanded from 4MB to 8MB to support debug consoles + //u8 MAIN_MEM[8*1024*1024]; //expanded from 8MB to 16MB to support dsi + u8 MAIN_MEM[16*1024*1024]; //expanded from 8MB to 16MB to support dsi + u8 ARM9_REG[0x1000000]; //this variable is evil and should be removed by correctly emulating all registers. + u8 ARM9_BIOS[0x8000]; + u8 ARM9_VMEM[0x800]; + + #include "PACKED.h" + struct { + u8 ARM9_LCD[0xA4000]; + //an extra 128KB for blank memory, directly after arm9_lcd, so that + //we can easily map things to the end of arm9_lcd to represent + //an unmapped state + u8 blank_memory[0x20000]; + }; + #include "PACKED_END.h" + + u8 ARM9_OAM[0x800]; + + u8* ExtPal[2][4]; + u8* ObjExtPal[2][2]; + + struct TextureInfo { + u8* texPalSlot[6]; + u8* textureSlotAddr[4]; + } texInfo; + + //ARM7 mem + u8 ARM7_BIOS[0x4000]; + u8 ARM7_ERAM[0x10000]; + u8 ARM7_REG[0x10000]; + u8 ARM7_WIRAM[0x10000]; + + // VRAM mapping + u8 VRAM_MAP[4][32]; + u32 LCD_VRAM_ADDR[10]; + u8 LCDCenable[10]; + + //Shared ram + u8 SWIRAM[0x8000]; + + //Card rom & ram + u8 * CART_ROM; + + //Unused ram + u8 UNUSED_RAM[4]; + + //this is here so that we can trap glitchy emulator code + //which is accessing offsets 5,6,7 of unused ram due to unaligned accesses + //(also since the emulator doesn't prevent unaligned accesses) + u8 MORE_UNUSED_RAM[4]; + + static u8 * MMU_MEM[2][256]; + static u32 MMU_MASK[2][256]; + + u8 ARM9_RW_MODE; + + u32 DTCMRegion; + u32 ITCMRegion; + + u16 timer[2][4]; + s32 timerMODE[2][4]; + u32 timerON[2][4]; + u32 timerRUN[2][4]; + u16 timerReload[2][4]; + + u32 reg_IME[2]; + u32 reg_IE[2]; + + //these are the user-controlled IF bits. some IF bits are generated as necessary from hardware conditions + u32 reg_IF_bits[2]; + //these flags are set occasionally to indicate that an irq should have entered the pipeline, and processing will be deferred a tiny bit to help emulate things + u32 reg_IF_pending[2]; + + u32 reg_DISP3DCNT_bits; + + template u32 gen_IF(); + + BOOL divRunning; + s64 divResult; + s64 divMod; + u64 divCycles; + + BOOL sqrtRunning; + u32 sqrtResult; + u64 sqrtCycles; + + u16 SPI_CNT; + u16 SPI_CMD; + u16 AUX_SPI_CNT; + u16 AUX_SPI_CMD; + + u64 gfx3dCycles; + + u8 powerMan_CntReg; + BOOL powerMan_CntRegWritten; + u8 powerMan_Reg[5]; + + memory_chip_t fw; + + nds_dscard dscard[2]; +}; + + +//everything in here is derived from libnds behaviours. no hardware tests yet +class DSI_TSC +{ +public: + DSI_TSC(); + void reset_command(); + u16 write16(u16 val); + bool save_state(EMUFILE* os); + bool load_state(EMUFILE* is); + +private: + u16 read16(); + u8 reg_selection; + u8 read_flag; + s32 state; + s32 readcount; + + //registers[0] contains the current page. + //we are going to go ahead and save these out in case we want to change the way this is emulated in the future.. + //we may want to poke registers in here at more convenient times and have the TSC dumbly pluck them out, + //rather than generate the values on the fly + u8 registers[0x80]; +}; + + +//this contains things which can't be memzeroed because they are smarter classes +struct MMU_struct_new +{ + MMU_struct_new() ; + BackupDevice backupDevice; + DmaController dma[2][4]; + TGXSTAT gxstat; + SqrtController sqrt; + DivController div; + DSI_TSC dsi_tsc; + + void write_dma(const int proc, const int size, const u32 adr, const u32 val); + u32 read_dma(const int proc, const int size, const u32 adr); + bool is_dma(const u32 adr) { return adr >= _REG_DMA_CONTROL_MIN && adr <= _REG_DMA_CONTROL_MAX; } +}; + +extern MMU_struct MMU; +extern MMU_struct_new MMU_new; + + +struct armcpu_memory_iface { + /** the 32 bit instruction prefetch */ + u32 FASTCALL (*prefetch32)( void *data, u32 adr); + + /** the 16 bit instruction prefetch */ + u16 FASTCALL (*prefetch16)( void *data, u32 adr); + + /** read 8 bit data value */ + u8 FASTCALL (*read8)( void *data, u32 adr); + /** read 16 bit data value */ + u16 FASTCALL (*read16)( void *data, u32 adr); + /** read 32 bit data value */ + u32 FASTCALL (*read32)( void *data, u32 adr); + + /** write 8 bit data value */ + void FASTCALL (*write8)( void *data, u32 adr, u8 val); + /** write 16 bit data value */ + void FASTCALL (*write16)( void *data, u32 adr, u16 val); + /** write 32 bit data value */ + void FASTCALL (*write32)( void *data, u32 adr, u32 val); + + void *data; +}; + + +void MMU_Init(void); +void MMU_DeInit(void); + +void MMU_Reset( void); + +void MMU_setRom(u8 * rom, u32 mask); +void MMU_unsetRom( void); + +void print_memory_profiling( void); + +// Memory reading/writing (old) +u8 FASTCALL MMU_read8(u32 proc, u32 adr); +u16 FASTCALL MMU_read16(u32 proc, u32 adr); +u32 FASTCALL MMU_read32(u32 proc, u32 adr); +void FASTCALL MMU_write8(u32 proc, u32 adr, u8 val); +void FASTCALL MMU_write16(u32 proc, u32 adr, u16 val); +void FASTCALL MMU_write32(u32 proc, u32 adr, u32 val); + +//template void FASTCALL MMU_doDMA(u32 num); + +//The base ARM memory interfaces +extern struct armcpu_memory_iface arm9_base_memory_iface; +extern struct armcpu_memory_iface arm7_base_memory_iface; +extern struct armcpu_memory_iface arm9_direct_memory_iface; + +#define VRAM_BANKS 9 +#define VRAM_BANK_A 0 +#define VRAM_BANK_B 1 +#define VRAM_BANK_C 2 +#define VRAM_BANK_D 3 +#define VRAM_BANK_E 4 +#define VRAM_BANK_F 5 +#define VRAM_BANK_G 6 +#define VRAM_BANK_H 7 +#define VRAM_BANK_I 8 + +#define VRAM_PAGE_ABG 0 +#define VRAM_PAGE_BBG 128 +#define VRAM_PAGE_AOBJ 256 +#define VRAM_PAGE_BOBJ 384 + + +struct VramConfiguration { + + enum Purpose { + OFF, INVALID, ABG, BBG, AOBJ, BOBJ, LCDC, ARM7, TEX, TEXPAL, ABGEXTPAL, BBGEXTPAL, AOBJEXTPAL, BOBJEXTPAL + }; + + struct BankInfo { + Purpose purpose; + int ofs; + } banks[VRAM_BANKS]; + + inline void clear() { + for(int i=0;i>14)&(VRAM_ARM9_PAGES-1); + u32 ofs = vram_addr & 0x3FFF; + vram_page = vram_arm9_map[vram_page]; + //blank pages are handled by the extra 16KB of blank memory at the end of ARM9_LCD + //and the fact that blank pages are mapped to appear at that location + return MMU.ARM9_LCD + (vram_page<<14) + ofs; +} + + +template u8 _MMU_read08(u32 addr); +template u16 _MMU_read16(u32 addr); +template u32 _MMU_read32(u32 addr); +template void _MMU_write08(u32 addr, u8 val); +template void _MMU_write16(u32 addr, u16 val); +template void _MMU_write32(u32 addr, u32 val); + +template FORCEINLINE u8 _MMU_read08(u32 addr) { return _MMU_read08(addr); } +template FORCEINLINE u16 _MMU_read16(u32 addr) { return _MMU_read16(addr); } +template FORCEINLINE u32 _MMU_read32(u32 addr) { return _MMU_read32(addr); } +template FORCEINLINE void _MMU_write08(u32 addr, u8 val) { _MMU_write08(addr,val); } +template FORCEINLINE void _MMU_write16(u32 addr, u16 val) { _MMU_write16(addr,val); } +template FORCEINLINE void _MMU_write32(u32 addr, u32 val) { _MMU_write32(addr,val); } + +void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val); +void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val); +void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val); +u8 FASTCALL _MMU_ARM9_read08(u32 adr); +u16 FASTCALL _MMU_ARM9_read16(u32 adr); +u32 FASTCALL _MMU_ARM9_read32(u32 adr); + +void FASTCALL _MMU_ARM7_write08(u32 adr, u8 val); +void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val); +void FASTCALL _MMU_ARM7_write32(u32 adr, u32 val); +u8 FASTCALL _MMU_ARM7_read08(u32 adr); +u16 FASTCALL _MMU_ARM7_read16(u32 adr); +u32 FASTCALL _MMU_ARM7_read32(u32 adr); + +extern u32 partie; + +extern u32 _MMU_MAIN_MEM_MASK; +extern u32 _MMU_MAIN_MEM_MASK16; +extern u32 _MMU_MAIN_MEM_MASK32; +void SetupMMU(bool debugConsole, bool dsi); + +FORCEINLINE void CheckMemoryDebugEvent(EDEBUG_EVENT event, const MMU_ACCESS_TYPE type, const u32 procnum, const u32 addr, const u32 size, const u32 val) +{ + //TODO - ugh work out a better prefetch event system + if(type == MMU_AT_CODE && event == DEBUG_EVENT_READ) + event = DEBUG_EVENT_EXECUTE; + if(CheckDebugEvent(event)) + { + DebugEventData.memAccessType = type; + DebugEventData.procnum = procnum; + DebugEventData.addr = addr; + DebugEventData.size = size; + DebugEventData.val = val; + HandleDebugEvent(event); + } +} + + +//ALERT!!!!!!!!!!!!!! +//the following inline functions dont do the 0x0FFFFFFF mask. +//this may result in some unexpected behavior + +FORCEINLINE u8 _MMU_read08(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr) +{ + CheckMemoryDebugEvent(DEBUG_EVENT_READ,AT,PROCNUM,addr,8,0); + + //special handling for DMA: read 0 from TCM + if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA) + { + if(addr<0x02000000) return 0; //itcm + if((addr&(~0x3FFF)) == MMU.DTCMRegion) return 0; //dtcm + } + +#ifdef HAVE_LUA + CallRegisteredLuaMemHook(addr, 1, /*FIXME*/ 0, LUAMEMHOOK_READ); +#endif + + if(PROCNUM==ARMCPU_ARM9) + if((addr&(~0x3FFF)) == MMU.DTCMRegion) + { + //Returns data from DTCM (ARM9 only) + return T1ReadByte(MMU.ARM9_DTCM, addr & 0x3FFF); + } + + if ( (addr & 0x0F000000) == 0x02000000) + return T1ReadByte( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK); + + if(PROCNUM==ARMCPU_ARM9) return _MMU_ARM9_read08(addr); + else return _MMU_ARM7_read08(addr); +} + +FORCEINLINE u16 _MMU_read16(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr) +{ + CheckMemoryDebugEvent(DEBUG_EVENT_READ,AT,PROCNUM,addr,16,0); + + //special handling for DMA: read 0 from TCM + if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA) + { + if(addr<0x02000000) return 0; //itcm + if((addr&(~0x3FFF)) == MMU.DTCMRegion) return 0; //dtcm + } + +#ifdef HAVE_LUA + CallRegisteredLuaMemHook(addr, 2, /*FIXME*/ 0, LUAMEMHOOK_READ); +#endif + + //special handling for execution from arm9, since we spend so much time in there + if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_CODE) + { + if ((addr & 0x0F000000) == 0x02000000) + return T1ReadWord_guaranteedAligned( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK16); + + if(addr<0x02000000) + return T1ReadWord_guaranteedAligned(MMU.ARM9_ITCM, addr&0x7FFE); + + goto dunno; + } + + if(PROCNUM==ARMCPU_ARM9) + if((addr&(~0x3FFF)) == MMU.DTCMRegion) + { + //Returns data from DTCM (ARM9 only) + return T1ReadWord_guaranteedAligned(MMU.ARM9_DTCM, addr & 0x3FFE); + } + + if ( (addr & 0x0F000000) == 0x02000000) + return T1ReadWord_guaranteedAligned( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK16); + +dunno: + if(PROCNUM==ARMCPU_ARM9) return _MMU_ARM9_read16(addr); + else return _MMU_ARM7_read16(addr); +} + +FORCEINLINE u32 _MMU_read32(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr) +{ + CheckMemoryDebugEvent(DEBUG_EVENT_READ,AT,PROCNUM,addr,32,0); + + //special handling for DMA: read 0 from TCM + if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA) + { + if(addr<0x02000000) return 0; //itcm + if((addr&(~0x3FFF)) == MMU.DTCMRegion) return 0; //dtcm + } + +#ifdef HAVE_LUA + CallRegisteredLuaMemHook(addr, 4, /*FIXME*/ 0, LUAMEMHOOK_READ); +#endif + + //special handling for execution from arm9, since we spend so much time in there + if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_CODE) + { + if ( (addr & 0x0F000000) == 0x02000000) + return T1ReadLong_guaranteedAligned( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK32); + + if(addr<0x02000000) + return T1ReadLong_guaranteedAligned(MMU.ARM9_ITCM, addr&0x7FFC); + + //what happens when we execute from DTCM? nocash makes it look like we get 0xFFFFFFFF but i can't seem to verify it + //historically, desmume would fall through to its old memory map struct + //which would return unused memory (0) + //it seems the hardware returns 0 or something benign because in actuality 0xFFFFFFFF is an undefined opcode + //and we know our handling for that is solid + + goto dunno; + } + + //special handling for execution from arm7. try reading from main memory first + if(PROCNUM==ARMCPU_ARM7) + { + if ( (addr & 0x0F000000) == 0x02000000) + return T1ReadLong_guaranteedAligned( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK32); + else if((addr & 0xFF800000) == 0x03800000) + return T1ReadLong_guaranteedAligned(MMU.ARM7_ERAM, addr&0xFFFC); + else if((addr & 0xFF800000) == 0x03000000) + return T1ReadLong_guaranteedAligned(MMU.SWIRAM, addr&0x7FFC); + } + + + //for other arm9 cases, we have to check from dtcm first because it is patched on top of the main memory range + if(PROCNUM==ARMCPU_ARM9) + { + if((addr&(~0x3FFF)) == MMU.DTCMRegion) + { + //Returns data from DTCM (ARM9 only) + return T1ReadLong_guaranteedAligned(MMU.ARM9_DTCM, addr & 0x3FFC); + } + + if ( (addr & 0x0F000000) == 0x02000000) + return T1ReadLong_guaranteedAligned( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK32); + } + +dunno: + if(PROCNUM==ARMCPU_ARM9) return _MMU_ARM9_read32(addr); + else return _MMU_ARM7_read32(addr); +} + +FORCEINLINE void _MMU_write08(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr, u8 val) +{ + CheckMemoryDebugEvent(DEBUG_EVENT_WRITE,AT,PROCNUM,addr,8,val); + + //special handling for DMA: discard writes to TCM + if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA) + { + if(addr<0x02000000) return; //itcm + if((addr&(~0x3FFF)) == MMU.DTCMRegion) return; //dtcm + } + + if(PROCNUM==ARMCPU_ARM9) + if((addr&(~0x3FFF)) == MMU.DTCMRegion) + { + T1WriteByte(MMU.ARM9_DTCM, addr & 0x3FFF, val); +#ifdef HAVE_LUA + CallRegisteredLuaMemHook(addr, 1, val, LUAMEMHOOK_WRITE); +#endif + return; + } + + if ( (addr & 0x0F000000) == 0x02000000) { + T1WriteByte( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK, val); +#ifdef HAVE_LUA + CallRegisteredLuaMemHook(addr, 1, val, LUAMEMHOOK_WRITE); +#endif + return; + } + + if(PROCNUM==ARMCPU_ARM9) _MMU_ARM9_write08(addr,val); + else _MMU_ARM7_write08(addr,val); +#ifdef HAVE_LUA + CallRegisteredLuaMemHook(addr, 1, val, LUAMEMHOOK_WRITE); +#endif +} + +FORCEINLINE void _MMU_write16(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr, u16 val) +{ + CheckMemoryDebugEvent(DEBUG_EVENT_WRITE,AT,PROCNUM,addr,16,val); + + //special handling for DMA: discard writes to TCM + if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA) + { + if(addr<0x02000000) return; //itcm + if((addr&(~0x3FFF)) == MMU.DTCMRegion) return; //dtcm + } + + if(PROCNUM==ARMCPU_ARM9) + if((addr&(~0x3FFF)) == MMU.DTCMRegion) + { + T1WriteWord(MMU.ARM9_DTCM, addr & 0x3FFE, val); +#ifdef HAVE_LUA + CallRegisteredLuaMemHook(addr, 2, val, LUAMEMHOOK_WRITE); +#endif + return; + } + + if ( (addr & 0x0F000000) == 0x02000000) { + T1WriteWord( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK16, val); +#ifdef HAVE_LUA + CallRegisteredLuaMemHook(addr, 2, val, LUAMEMHOOK_WRITE); +#endif + return; + } + + if(PROCNUM==ARMCPU_ARM9) _MMU_ARM9_write16(addr,val); + else _MMU_ARM7_write16(addr,val); +#ifdef HAVE_LUA + CallRegisteredLuaMemHook(addr, 2, val, LUAMEMHOOK_WRITE); +#endif +} + +FORCEINLINE void _MMU_write32(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr, u32 val) +{ + CheckMemoryDebugEvent(DEBUG_EVENT_WRITE,AT,PROCNUM,addr,32,val); + + //special handling for DMA: discard writes to TCM + if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA) + { + if(addr<0x02000000) return; //itcm + if((addr&(~0x3FFF)) == MMU.DTCMRegion) return; //dtcm + } + + if(PROCNUM==ARMCPU_ARM9) + if((addr&(~0x3FFF)) == MMU.DTCMRegion) + { + T1WriteLong(MMU.ARM9_DTCM, addr & 0x3FFC, val); +#ifdef HAVE_LUA + CallRegisteredLuaMemHook(addr, 4, val, LUAMEMHOOK_WRITE); +#endif + return; + } + + if ( (addr & 0x0F000000) == 0x02000000) { + T1WriteLong( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK32, val); +#ifdef HAVE_LUA + CallRegisteredLuaMemHook(addr, 4, val, LUAMEMHOOK_WRITE); +#endif + return; + } + + if(PROCNUM==ARMCPU_ARM9) _MMU_ARM9_write32(addr,val); + else _MMU_ARM7_write32(addr,val); +#ifdef HAVE_LUA + CallRegisteredLuaMemHook(addr, 4, val, LUAMEMHOOK_WRITE); +#endif +} + + +//#ifdef MMU_ENABLE_ACL +// void FASTCALL MMU_write8_acl(u32 proc, u32 adr, u8 val); +// void FASTCALL MMU_write16_acl(u32 proc, u32 adr, u16 val); +// void FASTCALL MMU_write32_acl(u32 proc, u32 adr, u32 val); +// u8 FASTCALL MMU_read8_acl(u32 proc, u32 adr, u32 access); +// u16 FASTCALL MMU_read16_acl(u32 proc, u32 adr, u32 access); +// u32 FASTCALL MMU_read32_acl(u32 proc, u32 adr, u32 access); +//#else +// #define MMU_write8_acl(proc, adr, val) _MMU_write08(adr, val) +// #define MMU_write16_acl(proc, adr, val) _MMU_write16(adr, val) +// #define MMU_write32_acl(proc, adr, val) _MMU_write32(adr, val) +// #define MMU_read8_acl(proc,adr,access) _MMU_read08(adr) +// #define MMU_read16_acl(proc,adr,access) ((access==CP15_ACCESS_EXECUTE)?_MMU_read16(adr):_MMU_read16(adr)) +// #define MMU_read32_acl(proc,adr,access) ((access==CP15_ACCESS_EXECUTE)?_MMU_read32(adr):_MMU_read32(adr)) +//#endif + +// Use this macros for reading/writing, so the GDB stub isn't broken +#ifdef GDB_STUB + #define READ32(a,b) cpu->mem_if->read32(a,(b) & 0xFFFFFFFC) + #define WRITE32(a,b,c) cpu->mem_if->write32(a,(b) & 0xFFFFFFFC,c) + #define READ16(a,b) cpu->mem_if->read16(a,(b) & 0xFFFFFFFE) + #define WRITE16(a,b,c) cpu->mem_if->write16(a,(b) & 0xFFFFFFFE,c) + #define READ8(a,b) cpu->mem_if->read8(a,b) + #define WRITE8(a,b,c) cpu->mem_if->write8(a,b,c) +#else + #define READ32(a,b) _MMU_read32((b) & 0xFFFFFFFC) + #define WRITE32(a,b,c) _MMU_write32((b) & 0xFFFFFFFC,c) + #define READ16(a,b) _MMU_read16((b) & 0xFFFFFFFE) + #define WRITE16(a,b,c) _MMU_write16((b) & 0xFFFFFFFE,c) + #define READ8(a,b) _MMU_read08(b) + #define WRITE8(a,b,c) _MMU_write08(b, c) +#endif + +template +FORCEINLINE u8 _MMU_read08(u32 addr) { return _MMU_read08(PROCNUM, AT, addr); } + +template +FORCEINLINE u16 _MMU_read16(u32 addr) { return _MMU_read16(PROCNUM, AT, addr); } + +template +FORCEINLINE u32 _MMU_read32(u32 addr) { return _MMU_read32(PROCNUM, AT, addr); } + +template +FORCEINLINE void _MMU_write08(u32 addr, u8 val) { _MMU_write08(PROCNUM, AT, addr, val); } + +template +FORCEINLINE void _MMU_write16(u32 addr, u16 val) { _MMU_write16(PROCNUM, AT, addr, val); } + +template +FORCEINLINE void _MMU_write32(u32 addr, u32 val) { _MMU_write32(PROCNUM, AT, addr, val); } + +void FASTCALL MMU_DumpMemBlock(u8 proc, u32 address, u32 size, u8 *buffer); + +#endif diff --git a/jni/desmume/src/MMU_timing.h b/jni/desmume/src/MMU_timing.h new file mode 100755 index 0000000..9da0a09 --- /dev/null +++ b/jni/desmume/src/MMU_timing.h @@ -0,0 +1,459 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2007 shash + Copyright (C) 2007-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ + +// this file is split from MMU.h for the purpose of avoiding ridiculous recompile times +// when changing it, because practically everything includes MMU.h. +#ifndef MMUTIMING_H +#define MMUTIMING_H + +#include +#include "MMU.h" +#include "cp15.h" +#include "readwrite.h" +#include "debug.h" +#include "NDSSystem.h" + +//////////////////////////////////////////////////////////////// +// MEMORY TIMING ACCURACY CONFIGURATION +// +// the more of these are enabled, +// the more accurate memory access timing _should_ become. +// they should be listed roughly in order of most to least important. +// it's reasonable to disable some of these as a speed hack. +// obviously, these defines don't cover all the variables or features needed, +// and in particular, DMA or code+data access bus contention is still missing. + + //disable this to prevent the advanced timing logic from ever running at all +#define ENABLE_ADVANCED_TIMING + +#ifdef ENABLE_ADVANCED_TIMING + // makes non-sequential accesses slower than sequential ones. +#define ACCOUNT_FOR_NON_SEQUENTIAL_ACCESS + //(SOMETIMES THIS IS A BIG SPEED HIT!) + + // enables emulation of code fetch waits. +#define ACCOUNT_FOR_CODE_FETCH_CYCLES + + // makes access to DTCM (arm9 only) fast. +#define ACCOUNT_FOR_DATA_TCM_SPEED + + // enables simulation of cache hits and cache misses. +#define ENABLE_CACHE_CONTROLLER_EMULATION + +#endif //ENABLE_ADVANCED_TIMING + +// +//////////////////////////////////////////////////////////////// + +FORCEINLINE bool USE_TIMING() { +#ifdef ENABLE_ADVANCED_TIMING + return CommonSettings.advanced_timing; +#else + return false; +#endif +} + + +enum MMU_ACCESS_DIRECTION +{ + MMU_AD_READ, MMU_AD_WRITE +}; + + +// note that we don't actually emulate the cache contents here, +// only enough to guess what would be a cache hit or a cache miss. +// this doesn't really get used unless ENABLE_CACHE_CONTROLLER_EMULATION is defined. +template +class CacheController +{ +public: + template + FORCEINLINE bool Cached(u32 addr) + { + u32 blockMasked = addr & BLOCKMASK; + if(blockMasked == m_cacheCache) + return true; + else + return this->CachedInternal(addr, blockMasked); + } + + void Reset() + { + for(int blockIndex = 0; blockIndex < NUMBLOCKS; blockIndex++) + m_blocks[blockIndex].Reset(); + m_cacheCache = ~0; + } + CacheController() + { + Reset(); + } + + void savestate(EMUFILE* os, int version) + { + write32le(m_cacheCache, os); + for(int i = 0; i < NUMBLOCKS; i++) + { + for(int j = 0; j < ASSOCIATIVITY; j++) + write32le(m_blocks[i].tag[j],os); + write32le(m_blocks[i].nextWay,os); + } + } + bool loadstate(EMUFILE* is, int version) + { + read32le(&m_cacheCache, is); + for(int i = 0; i < NUMBLOCKS; i++) + { + for(int j = 0; j < ASSOCIATIVITY; j++) + read32le(&m_blocks[i].tag[j],is); + read32le(&m_blocks[i].nextWay,is); + } + return true; + } + +private: + template + bool CachedInternal(u32 addr, u32 blockMasked) + { + u32 blockIndex = blockMasked >> BLOCKSIZESHIFT; + CacheBlock& block = m_blocks[blockIndex]; + addr &= TAGMASK; + + for(int way = 0; way < ASSOCIATIVITY; way++) + if(addr == block.tag[way]) + { + // found it, already allocated + m_cacheCache = blockMasked; + return true; + } + if(DIR == MMU_AD_READ) + { + // TODO: support other allocation orders? + block.tag[block.nextWay++] = addr; + block.nextWay %= ASSOCIATIVITY; + m_cacheCache = blockMasked; + } + return false; + } + + enum { SIZE = 1 << SIZESHIFT }; + enum { ASSOCIATIVITY = 1 << ASSOCIATIVESHIFT }; + enum { BLOCKSIZE = 1 << BLOCKSIZESHIFT }; + enum { TAGSHIFT = SIZESHIFT - ASSOCIATIVESHIFT }; + enum { TAGMASK = (u32)(~0 << TAGSHIFT) }; + enum { BLOCKMASK = ((u32)~0 >> (32 - TAGSHIFT)) & (u32)(~0 << BLOCKSIZESHIFT) }; + enum { WORDSIZE = sizeof(u32) }; + enum { WORDSPERBLOCK = (1 << BLOCKSIZESHIFT) / WORDSIZE }; + enum { DATAPERWORD = WORDSIZE * ASSOCIATIVITY }; + enum { DATAPERBLOCK = DATAPERWORD * WORDSPERBLOCK }; + enum { NUMBLOCKS = SIZE / DATAPERBLOCK }; + + struct CacheBlock + { + u32 tag [ASSOCIATIVITY]; + u32 nextWay; + + void Reset() + { + nextWay = 0; + for(int way = 0; way < ASSOCIATIVITY; way++) + tag[way] = 0; + } + }; + + u32 m_cacheCache; // optimization + + CacheBlock m_blocks [NUMBLOCKS]; +}; + + +template +FORCEINLINE u32 _MMU_accesstime(u32 addr, bool sequential); + + +template +class FetchAccessUnit +{ +public: + template + FORCEINLINE u32 Fetch(u32 address) + { + #ifdef ACCOUNT_FOR_CODE_FETCH_CYCLES + const bool prohibit = TIMING; + #else + const bool prohibit = false; + #endif + + if(AT == MMU_AT_CODE && !prohibit) + { + return 1; + } + + u32 time = _MMU_accesstime(address, +#ifdef ACCOUNT_FOR_NON_SEQUENTIAL_ACCESS + (TIMING? + (address == (m_lastAddress + (READSIZE>>3))) + :true + ) +#else + true +#endif + ); + +#ifdef ACCOUNT_FOR_NON_SEQUENTIAL_ACCESS + m_lastAddress = address; +#endif + + return time; + } + + void Reset() + { + m_lastAddress = ~0; + } + FetchAccessUnit() { this->Reset(); } + + void savestate(EMUFILE* os, int version) + { + write32le(m_lastAddress,os); + } + bool loadstate(EMUFILE* is, int version) + { + read32le(&m_lastAddress,is); + return true; + } + +private: + u32 m_lastAddress; +}; + + + + + +struct MMU_struct_timing +{ + // technically part of the cp15, but I didn't want the dereferencing penalty. + // these template values correspond with the value of armcp15->cacheType. + CacheController<13,2,5> arm9codeCache; // 8192 bytes, 4-way associative, 32-byte blocks + CacheController<12,2,5> arm9dataCache; // 4096 bytes, 4-way associative, 32-byte blocks + + // technically part of armcpu_t, but that struct isn't templated on PROCNUM + FetchAccessUnit<0,MMU_AT_CODE> arm9codeFetch; + FetchAccessUnit<0,MMU_AT_DATA> arm9dataFetch; + FetchAccessUnit<1,MMU_AT_CODE> arm7codeFetch; + FetchAccessUnit<1,MMU_AT_DATA> arm7dataFetch; + + template FORCEINLINE FetchAccessUnit& armCodeFetch(); + template FORCEINLINE FetchAccessUnit& armDataFetch(); +}; +template<> FORCEINLINE FetchAccessUnit<0,MMU_AT_CODE>& MMU_struct_timing::armCodeFetch<0>() { return this->arm9codeFetch; } +template<> FORCEINLINE FetchAccessUnit<1,MMU_AT_CODE>& MMU_struct_timing::armCodeFetch<1>() { return this->arm7codeFetch; } +template<> FORCEINLINE FetchAccessUnit<0,MMU_AT_DATA>& MMU_struct_timing::armDataFetch<0>() { return this->arm9dataFetch; } +template<> FORCEINLINE FetchAccessUnit<1,MMU_AT_DATA>& MMU_struct_timing::armDataFetch<1>() { return this->arm7dataFetch; } + + +extern MMU_struct_timing MMU_timing; + + + +// calculates the time a single memory access takes, +// in units of cycles of the current processor. +// this function replaces what used to be MMU_WAIT16 and MMU_WAIT32. +// this may have side effects, so don't call it more than necessary. +template +FORCEINLINE u32 _MMU_accesstime(u32 addr, bool sequential) +{ + static const int MC = 1; // cached or tcm memory speed + static const int M32 = (PROCNUM==ARMCPU_ARM9) ? 2 : 1; // access through 32-bit bus + static const int M16 = M32 * ((READSIZE>16) ? 2 : 1); // access through 16-bit bus + static const int MSLW = M16 * 8; // this needs tuning + + if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_CODE && addr < 0x02000000) + return MC; // ITCM + +#ifdef ACCOUNT_FOR_DATA_TCM_SPEED + if(TIMING && PROCNUM==ARMCPU_ARM9 && AT==MMU_AT_DATA && (addr&(~0x3FFF)) == MMU.DTCMRegion) + return MC; // DTCM +#endif + + // for now, assume the cache is always enabled for all of main memory + if(AT != MMU_AT_DMA && TIMING && PROCNUM==ARMCPU_ARM9 && (addr & 0x0F000000) == 0x02000000) + { +#ifdef ENABLE_CACHE_CONTROLLER_EMULATION + bool cached = false; + if(AT==MMU_AT_CODE) + cached = MMU_timing.arm9codeCache.Cached(addr); + if(AT==MMU_AT_DATA) + cached = MMU_timing.arm9dataCache.Cached(addr); + if(cached) + return MC; + u32 c; + if(sequential && AT==MMU_AT_DATA) + c = M16; // bonus for sequential data access + else if(DIRECTION == MMU_AD_READ) + c = M16 * 5; + else + c = M16 * 2; // should be 4, but write buffer isn't emulated yet. + if(DIRECTION == MMU_AD_READ) + { + // cache miss while reading means it has to fill a whole cache line + // by reading 32 bytes... + c += 8 * M32*2; + } + + if(CheckDebugEvent(DEBUG_EVENT_CACHE_MISS)) + { + DebugEventData.addr = addr; + DebugEventData.size = READSIZE; + HandleDebugEvent(DEBUG_EVENT_CACHE_MISS); + } + + return c; +#elif defined(ACCOUNT_FOR_NON_SEQUENTIAL_ACCESS) + // this is the closest approximation I could find + // to the with-cache-controller timing + // that doesn't do any actual caching logic. + return sequential ? MC : M16; +#endif + } + + static const TWaitState MMU_WAIT[16*16] = { + // ITCM, ITCM, MAIN, SWI, REG, VMEM, LCD, OAM, ROM, ROM, RAM, U, U, U, U, BIOS +#define X MC, MC, M16, M32, M32, M16, M16, M32, MSLW, MSLW, MSLW, M32,M32,M32,M32, M32, + // duplicate it 16 times (this was somehow faster than using a mask of 0xF) + X X X X X X X X X X X X X X X X +#undef X + }; + + u32 c = MMU_WAIT[(addr >> 24)]; + +#ifdef ACCOUNT_FOR_NON_SEQUENTIAL_ACCESS + if(TIMING && !sequential) + { + //if(c != MC || PROCNUM==ARMCPU_ARM7) // check not needed anymore because ITCM/DTCM return earlier + { + c += (PROCNUM==ARMCPU_ARM9) ? 3*2 : 1; + } + } +#endif + + return c; +} + + + + + +// calculates the cycle time of a single memory access in the MEM stage. +// to be used to calculate the memCycles argument for MMU_aluMemCycles. +// this may have side effects, so don't call it more than necessary. +template +FORCEINLINE u32 MMU_memAccessCycles(u32 addr) +{ + if(TIMING) + return MMU_timing.armDataFetch().template Fetch((addr)&(~((READSIZE>>3)-1))); + else + return MMU_timing.armDataFetch().template Fetch((addr)&(~((READSIZE>>3)-1))); +} + +template +FORCEINLINE u32 MMU_memAccessCycles(u32 addr) +{ + if(USE_TIMING()) + return MMU_memAccessCycles(addr); + else + return MMU_memAccessCycles(addr); +} + +// calculates the cycle time of a single code fetch in the FETCH stage +// to be used to calculate the fetchCycles argument for MMU_fetchExecuteCycles. +// this may have side effects, so don't call it more than necessary. +template +FORCEINLINE u32 MMU_codeFetchCycles(u32 addr) +{ + if(USE_TIMING()) + return MMU_timing.armCodeFetch().template Fetch((addr)&(~((READSIZE>>3)-1))); + else + return MMU_timing.armCodeFetch().template Fetch((addr)&(~((READSIZE>>3)-1))); +} + +// calculates the cycle contribution of ALU + MEM stages (= EXECUTE) +// given ALU cycle time and the summation of multiple memory access cycle times. +// this function might belong more in armcpu, but I don't think it matters. +template +FORCEINLINE u32 MMU_aluMemCycles(u32 aluCycles, u32 memCycles) +{ + if(PROCNUM==ARMCPU_ARM9) + { + // ALU and MEM are different stages of the 5-stage pipeline. + // we approximate the pipeline throughput using max, + // since simply adding the cycles of each instruction together + // fails to take into account the parallelism of the arm pipeline + // and would make the emulated system unnaturally slow. + return std::max(aluCycles, memCycles); + } + else + { + // ALU and MEM are part of the same stage of the 3-stage pipeline, + // thus they occur in sequence and we can simply add the counts together. + return aluCycles + memCycles; + } +} + +// calculates the cycle contribution of ALU + MEM stages (= EXECUTE) +// given ALU cycle time and the description of a single memory access. +// this may have side effects, so don't call it more than necessary. +template +FORCEINLINE u32 MMU_aluMemAccessCycles(u32 aluCycles, u32 addr) +{ + u32 memCycles; + if(USE_TIMING()) + memCycles = MMU_memAccessCycles(addr); + else memCycles = MMU_memAccessCycles(addr); + return MMU_aluMemCycles(aluCycles, memCycles); +} + +// calculates the cycle contribution of FETCH + EXECUTE stages +// given executeCycles = the combined ALU+MEM cycles +// and fetchCycles = the cycle time of the FETCH stage +// this function might belong more in armcpu, but I don't think it matters. +template +FORCEINLINE u32 MMU_fetchExecuteCycles(u32 executeCycles, u32 fetchCycles) +{ + #ifdef ACCOUNT_FOR_CODE_FETCH_CYCLES + const bool allow = true; + #else + const bool allow = false; + #endif + + if(USE_TIMING() && allow) + { + // execute and fetch are different stages of the pipeline for both arm7 and arm9. + // again, we approximate the pipeline throughput using max. + return std::max(executeCycles, fetchCycles); + // TODO: add an option to support conflict between MEM and FETCH cycles + // if they're both using the same data bus. + // in the case of a conflict this should be: + // return std::max(aluCycles, memCycles + fetchCycles); + } + return executeCycles; +} + + +#endif //MMUTIMING_H diff --git a/jni/desmume/src/Makefile.am b/jni/desmume/src/Makefile.am new file mode 100755 index 0000000..235b255 --- /dev/null +++ b/jni/desmume/src/Makefile.am @@ -0,0 +1,125 @@ +include $(top_srcdir)/src/desmume.mk + +AM_CPPFLAGS += $(SDL_CFLAGS) $(GTHREAD_CFLAGS) $(X_CFLAGS) $(ALSA_CFLAGS) $(LIBAGG_CFLAGS) $(LIBSOUNDTOUCH_CFLAGS) + +EXTRA_DIST = build.bat instruction_tabdef.inc thumb_tabdef.inc fs-linux.cpp fs-windows.cpp cocoa +if HAVE_GDB_STUB +SUBDIRS = . gdbstub $(UI_DIR) +else +SUBDIRS = . $(UI_DIR) +endif +DIST_SUBDIRS = . gdbstub cli gtk gtk-glade wx +noinst_LIBRARIES = libdesmume.a +libdesmume_a_SOURCES = \ + armcpu.cpp armcpu.h \ + arm_instructions.cpp arm_instructions.h \ + agg2d.h agg2d.inl \ + bios.cpp bios.h bits.h cp15.cpp cp15.h \ + commandline.h commandline.cpp \ + common.cpp common.h \ + debug.cpp debug.h \ + Disassembler.cpp Disassembler.h \ + emufile.h emufile.cpp emufile_types.h FIFO.cpp FIFO.h \ + firmware.cpp firmware.h GPU.cpp GPU.h \ + fs.h \ + GPU_osd.h \ + mem.h mc.cpp mc.h \ + path.cpp path.h \ + readwrite.cpp readwrite.h \ + wifi.cpp wifi.h \ + mic.h \ + MMU.cpp MMU.h MMU_timing.h NDSSystem.cpp NDSSystem.h registers.h \ + OGLRender.h \ + ROMReader.cpp ROMReader.h \ + render3D.cpp render3D.h \ + rtc.cpp rtc.h \ + saves.cpp saves.h \ + slot1.cpp slot1.h \ + SPU.cpp SPU.h \ + matrix.cpp matrix.h \ + gfx3d.cpp gfx3d.h \ + thumb_instructions.cpp thumb_instructions.h types.h \ + shaders.h \ + movie.cpp movie.h \ + PACKED.h PACKED_END.h \ + utils/datetime.cpp utils/datetime.h \ + utils/ConvertUTF.c utils/ConvertUTF.h utils/guid.cpp utils/guid.h \ + utils/emufat.cpp utils/emufat.h utils/emufat_types.h \ + utils/md5.cpp utils/md5.h utils/valuearray.h utils/xstring.cpp utils/xstring.h \ + utils/decrypt/crc.cpp utils/decrypt/crc.h utils/decrypt/decrypt.cpp \ + utils/decrypt/decrypt.h utils/decrypt/header.cpp utils/decrypt/header.h \ + utils/task.cpp utils/task.h \ + utils/vfat.h utils/vfat.cpp \ + utils/dlditool.cpp \ + utils/libfat/bit_ops.h \ + utils/libfat/cache.cpp \ + utils/libfat/cache.h \ + utils/libfat/common.h \ + utils/libfat/directory.cpp \ + utils/libfat/directory.h \ + utils/libfat/disc.cpp \ + utils/libfat/disc.h \ + utils/libfat/disc_io.h \ + utils/libfat/fat.h \ + utils/libfat/fatdir.cpp \ + utils/libfat/fatdir.h \ + utils/libfat/fatfile.cpp \ + utils/libfat/fatfile.h \ + utils/libfat/filetime.cpp \ + utils/libfat/filetime.h \ + utils/libfat/file_allocation_table.cpp \ + utils/libfat/file_allocation_table.h \ + utils/libfat/libfat.cpp \ + utils/libfat/libfat_pc.h \ + utils/libfat/libfat_public_api.cpp \ + utils/libfat/libfat_public_api.h \ + utils/libfat/lock.cpp \ + utils/libfat/lock.h \ + utils/libfat/mem_allocate.h \ + utils/libfat/partition.cpp \ + utils/libfat/partition.h \ + utils/tinyxml/tinystr.cpp \ + utils/tinyxml/tinystr.h \ + utils/tinyxml/tinyxml.cpp \ + utils/tinyxml/tinyxml.h \ + utils/tinyxml/tinyxmlerror.cpp \ + utils/tinyxml/tinyxmlparser.cpp \ + addons.cpp addons.h \ + addons/slot2_mpcf.cpp addons/slot2_paddle.cpp addons/slot2_gbagame.cpp addons/slot2_none.cpp addons/slot2_rumblepak.cpp addons/slot2_guitarGrip.cpp addons/slot2_expMemory.cpp addons/slot2_piano.cpp addons/slot1_none.cpp addons/slot1_r4.cpp addons/slot1_retail.cpp addons/slot1_retail_nand.cpp \ + cheatSystem.cpp cheatSystem.h \ + texcache.cpp texcache.h rasterize.cpp rasterize.h \ + metaspu/metaspu.cpp metaspu/metaspu.h \ + version.cpp version.h \ + desmume_config.cpp desmume_config.h + +if HAVE_GL +libdesmume_a_SOURCES += OGLRender.cpp +endif + +if HAVE_OPENAL +libdesmume_a_SOURCES += mic_openal.cpp +else +if HAVE_ALSA +libdesmume_a_SOURCES += mic_alsa.cpp +else +libdesmume_a_SOURCES += mic.cpp +endif +endif + +if HAVE_LIBSOUNDTOUCH +libdesmume_a_SOURCES += metaspu/SndOut.cpp metaspu/SndOut.h metaspu/Timestretcher.cpp +endif + +if HAVE_LIBAGG +libdesmume_a_SOURCES += aggdraw.cpp aggdraw.h GPU_osd.cpp +else +libdesmume_a_SOURCES += GPU_osd_stub.cpp +endif +if HAVE_LUA +AM_CPPFLAGS += $(LUA_CFLAGS) +libdesmume_a_SOURCES += lua-engine.cpp +endif +if HAVE_GDB_STUB +libdesmume_a_SOURCES += gdbstub.h +endif +libdesmume_a_LIBADD = fs-$(desmume_arch).$(OBJEXT) diff --git a/jni/desmume/src/Makefile.in b/jni/desmume/src/Makefile.in new file mode 100755 index 0000000..0cbc343 --- /dev/null +++ b/jni/desmume/src/Makefile.in @@ -0,0 +1,1536 @@ +# Makefile.in generated by automake 1.11.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/src/desmume.mk +@HAVE_GL_TRUE@am__append_1 = OGLRender.cpp +@HAVE_OPENAL_TRUE@am__append_2 = mic_openal.cpp +@HAVE_ALSA_TRUE@@HAVE_OPENAL_FALSE@am__append_3 = mic_alsa.cpp +@HAVE_ALSA_FALSE@@HAVE_OPENAL_FALSE@am__append_4 = mic.cpp +@HAVE_LIBSOUNDTOUCH_TRUE@am__append_5 = metaspu/SndOut.cpp metaspu/SndOut.h metaspu/Timestretcher.cpp +@HAVE_LIBAGG_TRUE@am__append_6 = aggdraw.cpp aggdraw.h GPU_osd.cpp +@HAVE_LIBAGG_FALSE@am__append_7 = GPU_osd_stub.cpp +@HAVE_LUA_TRUE@am__append_8 = $(LUA_CFLAGS) +@HAVE_LUA_TRUE@am__append_9 = lua-engine.cpp +@HAVE_GDB_STUB_TRUE@am__append_10 = gdbstub.h +subdir = src +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/wxwin.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +libdesmume_a_AR = $(AR) $(ARFLAGS) +libdesmume_a_DEPENDENCIES = fs-$(desmume_arch).$(OBJEXT) +am__libdesmume_a_SOURCES_DIST = armcpu.cpp armcpu.h \ + arm_instructions.cpp arm_instructions.h agg2d.h agg2d.inl \ + bios.cpp bios.h bits.h cp15.cpp cp15.h commandline.h \ + commandline.cpp common.cpp common.h debug.cpp debug.h \ + Disassembler.cpp Disassembler.h emufile.h emufile.cpp \ + emufile_types.h FIFO.cpp FIFO.h firmware.cpp firmware.h \ + GPU.cpp GPU.h fs.h GPU_osd.h mem.h mc.cpp mc.h path.cpp path.h \ + readwrite.cpp readwrite.h wifi.cpp wifi.h mic.h MMU.cpp MMU.h \ + MMU_timing.h NDSSystem.cpp NDSSystem.h registers.h OGLRender.h \ + ROMReader.cpp ROMReader.h render3D.cpp render3D.h rtc.cpp \ + rtc.h saves.cpp saves.h slot1.cpp slot1.h SPU.cpp SPU.h \ + matrix.cpp matrix.h gfx3d.cpp gfx3d.h thumb_instructions.cpp \ + thumb_instructions.h types.h shaders.h movie.cpp movie.h \ + PACKED.h PACKED_END.h utils/datetime.cpp utils/datetime.h \ + utils/ConvertUTF.c utils/ConvertUTF.h utils/guid.cpp \ + utils/guid.h utils/emufat.cpp utils/emufat.h \ + utils/emufat_types.h utils/md5.cpp utils/md5.h \ + utils/valuearray.h utils/xstring.cpp utils/xstring.h \ + utils/decrypt/crc.cpp utils/decrypt/crc.h \ + utils/decrypt/decrypt.cpp utils/decrypt/decrypt.h \ + utils/decrypt/header.cpp utils/decrypt/header.h utils/task.cpp \ + utils/task.h utils/vfat.h utils/vfat.cpp utils/dlditool.cpp \ + utils/libfat/bit_ops.h utils/libfat/cache.cpp \ + utils/libfat/cache.h utils/libfat/common.h \ + utils/libfat/directory.cpp utils/libfat/directory.h \ + utils/libfat/disc.cpp utils/libfat/disc.h \ + utils/libfat/disc_io.h utils/libfat/fat.h \ + utils/libfat/fatdir.cpp utils/libfat/fatdir.h \ + utils/libfat/fatfile.cpp utils/libfat/fatfile.h \ + utils/libfat/filetime.cpp utils/libfat/filetime.h \ + utils/libfat/file_allocation_table.cpp \ + utils/libfat/file_allocation_table.h utils/libfat/libfat.cpp \ + utils/libfat/libfat_pc.h utils/libfat/libfat_public_api.cpp \ + utils/libfat/libfat_public_api.h utils/libfat/lock.cpp \ + utils/libfat/lock.h utils/libfat/mem_allocate.h \ + utils/libfat/partition.cpp utils/libfat/partition.h \ + utils/tinyxml/tinystr.cpp utils/tinyxml/tinystr.h \ + utils/tinyxml/tinyxml.cpp utils/tinyxml/tinyxml.h \ + utils/tinyxml/tinyxmlerror.cpp utils/tinyxml/tinyxmlparser.cpp \ + addons.cpp addons.h addons/slot2_mpcf.cpp \ + addons/slot2_paddle.cpp addons/slot2_gbagame.cpp \ + addons/slot2_none.cpp addons/slot2_rumblepak.cpp \ + addons/slot2_guitarGrip.cpp addons/slot2_expMemory.cpp \ + addons/slot2_piano.cpp addons/slot1_none.cpp \ + addons/slot1_r4.cpp addons/slot1_retail.cpp \ + addons/slot1_retail_nand.cpp cheatSystem.cpp cheatSystem.h \ + texcache.cpp texcache.h rasterize.cpp rasterize.h \ + metaspu/metaspu.cpp metaspu/metaspu.h version.cpp version.h \ + desmume_config.cpp desmume_config.h OGLRender.cpp \ + mic_openal.cpp mic_alsa.cpp mic.cpp metaspu/SndOut.cpp \ + metaspu/SndOut.h metaspu/Timestretcher.cpp aggdraw.cpp \ + aggdraw.h GPU_osd.cpp GPU_osd_stub.cpp lua-engine.cpp \ + gdbstub.h +@HAVE_GL_TRUE@am__objects_1 = OGLRender.$(OBJEXT) +@HAVE_OPENAL_TRUE@am__objects_2 = mic_openal.$(OBJEXT) +@HAVE_ALSA_TRUE@@HAVE_OPENAL_FALSE@am__objects_3 = mic_alsa.$(OBJEXT) +@HAVE_ALSA_FALSE@@HAVE_OPENAL_FALSE@am__objects_4 = mic.$(OBJEXT) +@HAVE_LIBSOUNDTOUCH_TRUE@am__objects_5 = SndOut.$(OBJEXT) \ +@HAVE_LIBSOUNDTOUCH_TRUE@ Timestretcher.$(OBJEXT) +@HAVE_LIBAGG_TRUE@am__objects_6 = aggdraw.$(OBJEXT) GPU_osd.$(OBJEXT) +@HAVE_LIBAGG_FALSE@am__objects_7 = GPU_osd_stub.$(OBJEXT) +@HAVE_LUA_TRUE@am__objects_8 = lua-engine.$(OBJEXT) +am__objects_9 = +am_libdesmume_a_OBJECTS = armcpu.$(OBJEXT) arm_instructions.$(OBJEXT) \ + bios.$(OBJEXT) cp15.$(OBJEXT) commandline.$(OBJEXT) \ + common.$(OBJEXT) debug.$(OBJEXT) Disassembler.$(OBJEXT) \ + emufile.$(OBJEXT) FIFO.$(OBJEXT) firmware.$(OBJEXT) \ + GPU.$(OBJEXT) mc.$(OBJEXT) path.$(OBJEXT) readwrite.$(OBJEXT) \ + wifi.$(OBJEXT) MMU.$(OBJEXT) NDSSystem.$(OBJEXT) \ + ROMReader.$(OBJEXT) render3D.$(OBJEXT) rtc.$(OBJEXT) \ + saves.$(OBJEXT) slot1.$(OBJEXT) SPU.$(OBJEXT) matrix.$(OBJEXT) \ + gfx3d.$(OBJEXT) thumb_instructions.$(OBJEXT) movie.$(OBJEXT) \ + datetime.$(OBJEXT) ConvertUTF.$(OBJEXT) guid.$(OBJEXT) \ + emufat.$(OBJEXT) md5.$(OBJEXT) xstring.$(OBJEXT) crc.$(OBJEXT) \ + decrypt.$(OBJEXT) header.$(OBJEXT) task.$(OBJEXT) \ + vfat.$(OBJEXT) dlditool.$(OBJEXT) cache.$(OBJEXT) \ + directory.$(OBJEXT) disc.$(OBJEXT) fatdir.$(OBJEXT) \ + fatfile.$(OBJEXT) filetime.$(OBJEXT) \ + file_allocation_table.$(OBJEXT) libfat.$(OBJEXT) \ + libfat_public_api.$(OBJEXT) lock.$(OBJEXT) partition.$(OBJEXT) \ + tinystr.$(OBJEXT) tinyxml.$(OBJEXT) tinyxmlerror.$(OBJEXT) \ + tinyxmlparser.$(OBJEXT) addons.$(OBJEXT) slot2_mpcf.$(OBJEXT) \ + slot2_paddle.$(OBJEXT) slot2_gbagame.$(OBJEXT) \ + slot2_none.$(OBJEXT) slot2_rumblepak.$(OBJEXT) \ + slot2_guitarGrip.$(OBJEXT) slot2_expMemory.$(OBJEXT) \ + slot2_piano.$(OBJEXT) slot1_none.$(OBJEXT) slot1_r4.$(OBJEXT) \ + slot1_retail.$(OBJEXT) slot1_retail_nand.$(OBJEXT) \ + cheatSystem.$(OBJEXT) texcache.$(OBJEXT) rasterize.$(OBJEXT) \ + metaspu.$(OBJEXT) version.$(OBJEXT) desmume_config.$(OBJEXT) \ + $(am__objects_1) $(am__objects_2) $(am__objects_3) \ + $(am__objects_4) $(am__objects_5) $(am__objects_6) \ + $(am__objects_7) $(am__objects_8) $(am__objects_9) +libdesmume_a_OBJECTS = $(am_libdesmume_a_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(libdesmume_a_SOURCES) +DIST_SOURCES = $(am__libdesmume_a_SOURCES_DIST) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLADEUI_UNINSTALLED_DIR = @GLADEUI_UNINSTALLED_DIR@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_LIBS = @GLIB_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GREP = @GREP@ +GTHREAD_CFLAGS = @GTHREAD_CFLAGS@ +GTHREAD_LIBS = @GTHREAD_LIBS@ +GTKGLEXT_CFLAGS = @GTKGLEXT_CFLAGS@ +GTKGLEXT_LIBS = @GTKGLEXT_LIBS@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_PKG = @HAVE_PKG@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +LDFLAGS = @LDFLAGS@ +LIBAGG_CFLAGS = @LIBAGG_CFLAGS@ +LIBAGG_LIBS = @LIBAGG_LIBS@ +LIBGLADE_CFLAGS = @LIBGLADE_CFLAGS@ +LIBGLADE_LIBS = @LIBGLADE_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSOUNDTOUCH_CFLAGS = @LIBSOUNDTOUCH_CFLAGS@ +LIBSOUNDTOUCH_LIBS = @LIBSOUNDTOUCH_LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +LUA_CFLAGS = @LUA_CFLAGS@ +LUA_LIBS = @LUA_LIBS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +OBJEXT = @OBJEXT@ +OSMESA_LIBS = @OSMESA_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POFILES = @POFILES@ +POSUB = @POSUB@ +PO_DIR = @PO_DIR@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +RANLIB = @RANLIB@ +SDLCONFIG = @SDLCONFIG@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_LIBS = @SDL_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +UI_DIR = @UI_DIR@ +UPDATEDESKTOP = @UPDATEDESKTOP@ +USE_MAINTAINER_MODE = @USE_MAINTAINER_MODE@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WX_CFLAGS = @WX_CFLAGS@ +WX_CFLAGS_ONLY = @WX_CFLAGS_ONLY@ +WX_CONFIG_PATH = @WX_CONFIG_PATH@ +WX_CPPFLAGS = @WX_CPPFLAGS@ +WX_CXXFLAGS = @WX_CXXFLAGS@ +WX_CXXFLAGS_ONLY = @WX_CXXFLAGS_ONLY@ +WX_LIBS = @WX_LIBS@ +WX_LIBS_STATIC = @WX_LIBS_STATIC@ +WX_RESCOMP = @WX_RESCOMP@ +WX_VERSION = @WX_VERSION@ +XGETTEXT = @XGETTEXT@ +XMKMF = @XMKMF@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +desmume_arch = @desmume_arch@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CFLAGS = +AM_CPPFLAGS = -I$(top_srcdir)/src $(SDL_CFLAGS) $(GTHREAD_CFLAGS) \ + $(X_CFLAGS) $(ALSA_CFLAGS) $(LIBAGG_CFLAGS) \ + $(LIBSOUNDTOUCH_CFLAGS) $(am__append_8) +AM_LDFLAGS = +EXTRA_DIST = build.bat instruction_tabdef.inc thumb_tabdef.inc fs-linux.cpp fs-windows.cpp cocoa +@HAVE_GDB_STUB_FALSE@SUBDIRS = . $(UI_DIR) +@HAVE_GDB_STUB_TRUE@SUBDIRS = . gdbstub $(UI_DIR) +DIST_SUBDIRS = . gdbstub cli gtk gtk-glade wx +noinst_LIBRARIES = libdesmume.a +libdesmume_a_SOURCES = armcpu.cpp armcpu.h arm_instructions.cpp \ + arm_instructions.h agg2d.h agg2d.inl bios.cpp bios.h bits.h \ + cp15.cpp cp15.h commandline.h commandline.cpp common.cpp \ + common.h debug.cpp debug.h Disassembler.cpp Disassembler.h \ + emufile.h emufile.cpp emufile_types.h FIFO.cpp FIFO.h \ + firmware.cpp firmware.h GPU.cpp GPU.h fs.h GPU_osd.h mem.h \ + mc.cpp mc.h path.cpp path.h readwrite.cpp readwrite.h wifi.cpp \ + wifi.h mic.h MMU.cpp MMU.h MMU_timing.h NDSSystem.cpp \ + NDSSystem.h registers.h OGLRender.h ROMReader.cpp ROMReader.h \ + render3D.cpp render3D.h rtc.cpp rtc.h saves.cpp saves.h \ + slot1.cpp slot1.h SPU.cpp SPU.h matrix.cpp matrix.h gfx3d.cpp \ + gfx3d.h thumb_instructions.cpp thumb_instructions.h types.h \ + shaders.h movie.cpp movie.h PACKED.h PACKED_END.h \ + utils/datetime.cpp utils/datetime.h utils/ConvertUTF.c \ + utils/ConvertUTF.h utils/guid.cpp utils/guid.h \ + utils/emufat.cpp utils/emufat.h utils/emufat_types.h \ + utils/md5.cpp utils/md5.h utils/valuearray.h utils/xstring.cpp \ + utils/xstring.h utils/decrypt/crc.cpp utils/decrypt/crc.h \ + utils/decrypt/decrypt.cpp utils/decrypt/decrypt.h \ + utils/decrypt/header.cpp utils/decrypt/header.h utils/task.cpp \ + utils/task.h utils/vfat.h utils/vfat.cpp utils/dlditool.cpp \ + utils/libfat/bit_ops.h utils/libfat/cache.cpp \ + utils/libfat/cache.h utils/libfat/common.h \ + utils/libfat/directory.cpp utils/libfat/directory.h \ + utils/libfat/disc.cpp utils/libfat/disc.h \ + utils/libfat/disc_io.h utils/libfat/fat.h \ + utils/libfat/fatdir.cpp utils/libfat/fatdir.h \ + utils/libfat/fatfile.cpp utils/libfat/fatfile.h \ + utils/libfat/filetime.cpp utils/libfat/filetime.h \ + utils/libfat/file_allocation_table.cpp \ + utils/libfat/file_allocation_table.h utils/libfat/libfat.cpp \ + utils/libfat/libfat_pc.h utils/libfat/libfat_public_api.cpp \ + utils/libfat/libfat_public_api.h utils/libfat/lock.cpp \ + utils/libfat/lock.h utils/libfat/mem_allocate.h \ + utils/libfat/partition.cpp utils/libfat/partition.h \ + utils/tinyxml/tinystr.cpp utils/tinyxml/tinystr.h \ + utils/tinyxml/tinyxml.cpp utils/tinyxml/tinyxml.h \ + utils/tinyxml/tinyxmlerror.cpp utils/tinyxml/tinyxmlparser.cpp \ + addons.cpp addons.h addons/slot2_mpcf.cpp \ + addons/slot2_paddle.cpp addons/slot2_gbagame.cpp \ + addons/slot2_none.cpp addons/slot2_rumblepak.cpp \ + addons/slot2_guitarGrip.cpp addons/slot2_expMemory.cpp \ + addons/slot2_piano.cpp addons/slot1_none.cpp \ + addons/slot1_r4.cpp addons/slot1_retail.cpp \ + addons/slot1_retail_nand.cpp cheatSystem.cpp cheatSystem.h \ + texcache.cpp texcache.h rasterize.cpp rasterize.h \ + metaspu/metaspu.cpp metaspu/metaspu.h version.cpp version.h \ + desmume_config.cpp desmume_config.h $(am__append_1) \ + $(am__append_2) $(am__append_3) $(am__append_4) \ + $(am__append_5) $(am__append_6) $(am__append_7) \ + $(am__append_9) $(am__append_10) +libdesmume_a_LIBADD = fs-$(desmume_arch).$(OBJEXT) +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .cpp .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/src/desmume.mk $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/src/desmume.mk: + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libdesmume.a: $(libdesmume_a_OBJECTS) $(libdesmume_a_DEPENDENCIES) $(EXTRA_libdesmume_a_DEPENDENCIES) + -rm -f libdesmume.a + $(libdesmume_a_AR) libdesmume.a $(libdesmume_a_OBJECTS) $(libdesmume_a_LIBADD) + $(RANLIB) libdesmume.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ConvertUTF.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Disassembler.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FIFO.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GPU.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GPU_osd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GPU_osd_stub.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MMU.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NDSSystem.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OGLRender.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ROMReader.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SPU.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SndOut.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Timestretcher.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addons.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aggdraw.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm_instructions.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/armcpu.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bios.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cache.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cheatSystem.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/commandline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cp15.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/datetime.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decrypt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/desmume_config.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/directory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/disc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dlditool.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emufat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emufile.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fatdir.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fatfile.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_allocation_table.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filetime.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/firmware.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gfx3d.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/guid.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/header.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfat_public_api.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lua-engine.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/matrix.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/metaspu.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mic.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mic_alsa.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mic_openal.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/movie.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/partition.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/path.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rasterize.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readwrite.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/render3D.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rtc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/saves.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slot1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slot1_none.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slot1_r4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slot1_retail.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slot1_retail_nand.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slot2_expMemory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slot2_gbagame.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slot2_guitarGrip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slot2_mpcf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slot2_none.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slot2_paddle.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slot2_piano.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slot2_rumblepak.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/texcache.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thumb_instructions.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tinystr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tinyxml.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tinyxmlerror.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tinyxmlparser.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vfat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wifi.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xstring.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +ConvertUTF.o: utils/ConvertUTF.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ConvertUTF.o -MD -MP -MF $(DEPDIR)/ConvertUTF.Tpo -c -o ConvertUTF.o `test -f 'utils/ConvertUTF.c' || echo '$(srcdir)/'`utils/ConvertUTF.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ConvertUTF.Tpo $(DEPDIR)/ConvertUTF.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='utils/ConvertUTF.c' object='ConvertUTF.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ConvertUTF.o `test -f 'utils/ConvertUTF.c' || echo '$(srcdir)/'`utils/ConvertUTF.c + +ConvertUTF.obj: utils/ConvertUTF.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ConvertUTF.obj -MD -MP -MF $(DEPDIR)/ConvertUTF.Tpo -c -o ConvertUTF.obj `if test -f 'utils/ConvertUTF.c'; then $(CYGPATH_W) 'utils/ConvertUTF.c'; else $(CYGPATH_W) '$(srcdir)/utils/ConvertUTF.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ConvertUTF.Tpo $(DEPDIR)/ConvertUTF.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='utils/ConvertUTF.c' object='ConvertUTF.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ConvertUTF.obj `if test -f 'utils/ConvertUTF.c'; then $(CYGPATH_W) 'utils/ConvertUTF.c'; else $(CYGPATH_W) '$(srcdir)/utils/ConvertUTF.c'; fi` + +.cpp.o: +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +datetime.o: utils/datetime.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT datetime.o -MD -MP -MF $(DEPDIR)/datetime.Tpo -c -o datetime.o `test -f 'utils/datetime.cpp' || echo '$(srcdir)/'`utils/datetime.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/datetime.Tpo $(DEPDIR)/datetime.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/datetime.cpp' object='datetime.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o datetime.o `test -f 'utils/datetime.cpp' || echo '$(srcdir)/'`utils/datetime.cpp + +datetime.obj: utils/datetime.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT datetime.obj -MD -MP -MF $(DEPDIR)/datetime.Tpo -c -o datetime.obj `if test -f 'utils/datetime.cpp'; then $(CYGPATH_W) 'utils/datetime.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/datetime.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/datetime.Tpo $(DEPDIR)/datetime.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/datetime.cpp' object='datetime.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o datetime.obj `if test -f 'utils/datetime.cpp'; then $(CYGPATH_W) 'utils/datetime.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/datetime.cpp'; fi` + +guid.o: utils/guid.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT guid.o -MD -MP -MF $(DEPDIR)/guid.Tpo -c -o guid.o `test -f 'utils/guid.cpp' || echo '$(srcdir)/'`utils/guid.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/guid.Tpo $(DEPDIR)/guid.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/guid.cpp' object='guid.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o guid.o `test -f 'utils/guid.cpp' || echo '$(srcdir)/'`utils/guid.cpp + +guid.obj: utils/guid.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT guid.obj -MD -MP -MF $(DEPDIR)/guid.Tpo -c -o guid.obj `if test -f 'utils/guid.cpp'; then $(CYGPATH_W) 'utils/guid.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/guid.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/guid.Tpo $(DEPDIR)/guid.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/guid.cpp' object='guid.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o guid.obj `if test -f 'utils/guid.cpp'; then $(CYGPATH_W) 'utils/guid.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/guid.cpp'; fi` + +emufat.o: utils/emufat.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT emufat.o -MD -MP -MF $(DEPDIR)/emufat.Tpo -c -o emufat.o `test -f 'utils/emufat.cpp' || echo '$(srcdir)/'`utils/emufat.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/emufat.Tpo $(DEPDIR)/emufat.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/emufat.cpp' object='emufat.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o emufat.o `test -f 'utils/emufat.cpp' || echo '$(srcdir)/'`utils/emufat.cpp + +emufat.obj: utils/emufat.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT emufat.obj -MD -MP -MF $(DEPDIR)/emufat.Tpo -c -o emufat.obj `if test -f 'utils/emufat.cpp'; then $(CYGPATH_W) 'utils/emufat.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/emufat.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/emufat.Tpo $(DEPDIR)/emufat.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/emufat.cpp' object='emufat.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o emufat.obj `if test -f 'utils/emufat.cpp'; then $(CYGPATH_W) 'utils/emufat.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/emufat.cpp'; fi` + +md5.o: utils/md5.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT md5.o -MD -MP -MF $(DEPDIR)/md5.Tpo -c -o md5.o `test -f 'utils/md5.cpp' || echo '$(srcdir)/'`utils/md5.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/md5.Tpo $(DEPDIR)/md5.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/md5.cpp' object='md5.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o md5.o `test -f 'utils/md5.cpp' || echo '$(srcdir)/'`utils/md5.cpp + +md5.obj: utils/md5.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT md5.obj -MD -MP -MF $(DEPDIR)/md5.Tpo -c -o md5.obj `if test -f 'utils/md5.cpp'; then $(CYGPATH_W) 'utils/md5.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/md5.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/md5.Tpo $(DEPDIR)/md5.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/md5.cpp' object='md5.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o md5.obj `if test -f 'utils/md5.cpp'; then $(CYGPATH_W) 'utils/md5.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/md5.cpp'; fi` + +xstring.o: utils/xstring.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xstring.o -MD -MP -MF $(DEPDIR)/xstring.Tpo -c -o xstring.o `test -f 'utils/xstring.cpp' || echo '$(srcdir)/'`utils/xstring.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/xstring.Tpo $(DEPDIR)/xstring.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/xstring.cpp' object='xstring.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xstring.o `test -f 'utils/xstring.cpp' || echo '$(srcdir)/'`utils/xstring.cpp + +xstring.obj: utils/xstring.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xstring.obj -MD -MP -MF $(DEPDIR)/xstring.Tpo -c -o xstring.obj `if test -f 'utils/xstring.cpp'; then $(CYGPATH_W) 'utils/xstring.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/xstring.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/xstring.Tpo $(DEPDIR)/xstring.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/xstring.cpp' object='xstring.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xstring.obj `if test -f 'utils/xstring.cpp'; then $(CYGPATH_W) 'utils/xstring.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/xstring.cpp'; fi` + +crc.o: utils/decrypt/crc.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT crc.o -MD -MP -MF $(DEPDIR)/crc.Tpo -c -o crc.o `test -f 'utils/decrypt/crc.cpp' || echo '$(srcdir)/'`utils/decrypt/crc.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/crc.Tpo $(DEPDIR)/crc.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/decrypt/crc.cpp' object='crc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o crc.o `test -f 'utils/decrypt/crc.cpp' || echo '$(srcdir)/'`utils/decrypt/crc.cpp + +crc.obj: utils/decrypt/crc.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT crc.obj -MD -MP -MF $(DEPDIR)/crc.Tpo -c -o crc.obj `if test -f 'utils/decrypt/crc.cpp'; then $(CYGPATH_W) 'utils/decrypt/crc.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/decrypt/crc.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/crc.Tpo $(DEPDIR)/crc.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/decrypt/crc.cpp' object='crc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o crc.obj `if test -f 'utils/decrypt/crc.cpp'; then $(CYGPATH_W) 'utils/decrypt/crc.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/decrypt/crc.cpp'; fi` + +decrypt.o: utils/decrypt/decrypt.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT decrypt.o -MD -MP -MF $(DEPDIR)/decrypt.Tpo -c -o decrypt.o `test -f 'utils/decrypt/decrypt.cpp' || echo '$(srcdir)/'`utils/decrypt/decrypt.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/decrypt.Tpo $(DEPDIR)/decrypt.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/decrypt/decrypt.cpp' object='decrypt.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o decrypt.o `test -f 'utils/decrypt/decrypt.cpp' || echo '$(srcdir)/'`utils/decrypt/decrypt.cpp + +decrypt.obj: utils/decrypt/decrypt.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT decrypt.obj -MD -MP -MF $(DEPDIR)/decrypt.Tpo -c -o decrypt.obj `if test -f 'utils/decrypt/decrypt.cpp'; then $(CYGPATH_W) 'utils/decrypt/decrypt.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/decrypt/decrypt.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/decrypt.Tpo $(DEPDIR)/decrypt.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/decrypt/decrypt.cpp' object='decrypt.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o decrypt.obj `if test -f 'utils/decrypt/decrypt.cpp'; then $(CYGPATH_W) 'utils/decrypt/decrypt.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/decrypt/decrypt.cpp'; fi` + +header.o: utils/decrypt/header.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT header.o -MD -MP -MF $(DEPDIR)/header.Tpo -c -o header.o `test -f 'utils/decrypt/header.cpp' || echo '$(srcdir)/'`utils/decrypt/header.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/header.Tpo $(DEPDIR)/header.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/decrypt/header.cpp' object='header.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o header.o `test -f 'utils/decrypt/header.cpp' || echo '$(srcdir)/'`utils/decrypt/header.cpp + +header.obj: utils/decrypt/header.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT header.obj -MD -MP -MF $(DEPDIR)/header.Tpo -c -o header.obj `if test -f 'utils/decrypt/header.cpp'; then $(CYGPATH_W) 'utils/decrypt/header.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/decrypt/header.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/header.Tpo $(DEPDIR)/header.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/decrypt/header.cpp' object='header.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o header.obj `if test -f 'utils/decrypt/header.cpp'; then $(CYGPATH_W) 'utils/decrypt/header.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/decrypt/header.cpp'; fi` + +task.o: utils/task.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT task.o -MD -MP -MF $(DEPDIR)/task.Tpo -c -o task.o `test -f 'utils/task.cpp' || echo '$(srcdir)/'`utils/task.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/task.Tpo $(DEPDIR)/task.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/task.cpp' object='task.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o task.o `test -f 'utils/task.cpp' || echo '$(srcdir)/'`utils/task.cpp + +task.obj: utils/task.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT task.obj -MD -MP -MF $(DEPDIR)/task.Tpo -c -o task.obj `if test -f 'utils/task.cpp'; then $(CYGPATH_W) 'utils/task.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/task.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/task.Tpo $(DEPDIR)/task.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/task.cpp' object='task.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o task.obj `if test -f 'utils/task.cpp'; then $(CYGPATH_W) 'utils/task.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/task.cpp'; fi` + +vfat.o: utils/vfat.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT vfat.o -MD -MP -MF $(DEPDIR)/vfat.Tpo -c -o vfat.o `test -f 'utils/vfat.cpp' || echo '$(srcdir)/'`utils/vfat.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/vfat.Tpo $(DEPDIR)/vfat.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/vfat.cpp' object='vfat.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o vfat.o `test -f 'utils/vfat.cpp' || echo '$(srcdir)/'`utils/vfat.cpp + +vfat.obj: utils/vfat.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT vfat.obj -MD -MP -MF $(DEPDIR)/vfat.Tpo -c -o vfat.obj `if test -f 'utils/vfat.cpp'; then $(CYGPATH_W) 'utils/vfat.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/vfat.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/vfat.Tpo $(DEPDIR)/vfat.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/vfat.cpp' object='vfat.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o vfat.obj `if test -f 'utils/vfat.cpp'; then $(CYGPATH_W) 'utils/vfat.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/vfat.cpp'; fi` + +dlditool.o: utils/dlditool.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT dlditool.o -MD -MP -MF $(DEPDIR)/dlditool.Tpo -c -o dlditool.o `test -f 'utils/dlditool.cpp' || echo '$(srcdir)/'`utils/dlditool.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/dlditool.Tpo $(DEPDIR)/dlditool.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/dlditool.cpp' object='dlditool.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o dlditool.o `test -f 'utils/dlditool.cpp' || echo '$(srcdir)/'`utils/dlditool.cpp + +dlditool.obj: utils/dlditool.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT dlditool.obj -MD -MP -MF $(DEPDIR)/dlditool.Tpo -c -o dlditool.obj `if test -f 'utils/dlditool.cpp'; then $(CYGPATH_W) 'utils/dlditool.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/dlditool.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/dlditool.Tpo $(DEPDIR)/dlditool.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/dlditool.cpp' object='dlditool.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o dlditool.obj `if test -f 'utils/dlditool.cpp'; then $(CYGPATH_W) 'utils/dlditool.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/dlditool.cpp'; fi` + +cache.o: utils/libfat/cache.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cache.o -MD -MP -MF $(DEPDIR)/cache.Tpo -c -o cache.o `test -f 'utils/libfat/cache.cpp' || echo '$(srcdir)/'`utils/libfat/cache.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/cache.Tpo $(DEPDIR)/cache.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/cache.cpp' object='cache.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cache.o `test -f 'utils/libfat/cache.cpp' || echo '$(srcdir)/'`utils/libfat/cache.cpp + +cache.obj: utils/libfat/cache.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cache.obj -MD -MP -MF $(DEPDIR)/cache.Tpo -c -o cache.obj `if test -f 'utils/libfat/cache.cpp'; then $(CYGPATH_W) 'utils/libfat/cache.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/cache.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/cache.Tpo $(DEPDIR)/cache.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/cache.cpp' object='cache.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cache.obj `if test -f 'utils/libfat/cache.cpp'; then $(CYGPATH_W) 'utils/libfat/cache.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/cache.cpp'; fi` + +directory.o: utils/libfat/directory.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT directory.o -MD -MP -MF $(DEPDIR)/directory.Tpo -c -o directory.o `test -f 'utils/libfat/directory.cpp' || echo '$(srcdir)/'`utils/libfat/directory.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/directory.Tpo $(DEPDIR)/directory.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/directory.cpp' object='directory.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o directory.o `test -f 'utils/libfat/directory.cpp' || echo '$(srcdir)/'`utils/libfat/directory.cpp + +directory.obj: utils/libfat/directory.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT directory.obj -MD -MP -MF $(DEPDIR)/directory.Tpo -c -o directory.obj `if test -f 'utils/libfat/directory.cpp'; then $(CYGPATH_W) 'utils/libfat/directory.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/directory.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/directory.Tpo $(DEPDIR)/directory.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/directory.cpp' object='directory.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o directory.obj `if test -f 'utils/libfat/directory.cpp'; then $(CYGPATH_W) 'utils/libfat/directory.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/directory.cpp'; fi` + +disc.o: utils/libfat/disc.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT disc.o -MD -MP -MF $(DEPDIR)/disc.Tpo -c -o disc.o `test -f 'utils/libfat/disc.cpp' || echo '$(srcdir)/'`utils/libfat/disc.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/disc.Tpo $(DEPDIR)/disc.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/disc.cpp' object='disc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o disc.o `test -f 'utils/libfat/disc.cpp' || echo '$(srcdir)/'`utils/libfat/disc.cpp + +disc.obj: utils/libfat/disc.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT disc.obj -MD -MP -MF $(DEPDIR)/disc.Tpo -c -o disc.obj `if test -f 'utils/libfat/disc.cpp'; then $(CYGPATH_W) 'utils/libfat/disc.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/disc.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/disc.Tpo $(DEPDIR)/disc.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/disc.cpp' object='disc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o disc.obj `if test -f 'utils/libfat/disc.cpp'; then $(CYGPATH_W) 'utils/libfat/disc.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/disc.cpp'; fi` + +fatdir.o: utils/libfat/fatdir.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT fatdir.o -MD -MP -MF $(DEPDIR)/fatdir.Tpo -c -o fatdir.o `test -f 'utils/libfat/fatdir.cpp' || echo '$(srcdir)/'`utils/libfat/fatdir.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/fatdir.Tpo $(DEPDIR)/fatdir.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/fatdir.cpp' object='fatdir.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o fatdir.o `test -f 'utils/libfat/fatdir.cpp' || echo '$(srcdir)/'`utils/libfat/fatdir.cpp + +fatdir.obj: utils/libfat/fatdir.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT fatdir.obj -MD -MP -MF $(DEPDIR)/fatdir.Tpo -c -o fatdir.obj `if test -f 'utils/libfat/fatdir.cpp'; then $(CYGPATH_W) 'utils/libfat/fatdir.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/fatdir.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/fatdir.Tpo $(DEPDIR)/fatdir.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/fatdir.cpp' object='fatdir.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o fatdir.obj `if test -f 'utils/libfat/fatdir.cpp'; then $(CYGPATH_W) 'utils/libfat/fatdir.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/fatdir.cpp'; fi` + +fatfile.o: utils/libfat/fatfile.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT fatfile.o -MD -MP -MF $(DEPDIR)/fatfile.Tpo -c -o fatfile.o `test -f 'utils/libfat/fatfile.cpp' || echo '$(srcdir)/'`utils/libfat/fatfile.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/fatfile.Tpo $(DEPDIR)/fatfile.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/fatfile.cpp' object='fatfile.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o fatfile.o `test -f 'utils/libfat/fatfile.cpp' || echo '$(srcdir)/'`utils/libfat/fatfile.cpp + +fatfile.obj: utils/libfat/fatfile.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT fatfile.obj -MD -MP -MF $(DEPDIR)/fatfile.Tpo -c -o fatfile.obj `if test -f 'utils/libfat/fatfile.cpp'; then $(CYGPATH_W) 'utils/libfat/fatfile.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/fatfile.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/fatfile.Tpo $(DEPDIR)/fatfile.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/fatfile.cpp' object='fatfile.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o fatfile.obj `if test -f 'utils/libfat/fatfile.cpp'; then $(CYGPATH_W) 'utils/libfat/fatfile.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/fatfile.cpp'; fi` + +filetime.o: utils/libfat/filetime.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT filetime.o -MD -MP -MF $(DEPDIR)/filetime.Tpo -c -o filetime.o `test -f 'utils/libfat/filetime.cpp' || echo '$(srcdir)/'`utils/libfat/filetime.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/filetime.Tpo $(DEPDIR)/filetime.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/filetime.cpp' object='filetime.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o filetime.o `test -f 'utils/libfat/filetime.cpp' || echo '$(srcdir)/'`utils/libfat/filetime.cpp + +filetime.obj: utils/libfat/filetime.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT filetime.obj -MD -MP -MF $(DEPDIR)/filetime.Tpo -c -o filetime.obj `if test -f 'utils/libfat/filetime.cpp'; then $(CYGPATH_W) 'utils/libfat/filetime.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/filetime.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/filetime.Tpo $(DEPDIR)/filetime.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/filetime.cpp' object='filetime.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o filetime.obj `if test -f 'utils/libfat/filetime.cpp'; then $(CYGPATH_W) 'utils/libfat/filetime.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/filetime.cpp'; fi` + +file_allocation_table.o: utils/libfat/file_allocation_table.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT file_allocation_table.o -MD -MP -MF $(DEPDIR)/file_allocation_table.Tpo -c -o file_allocation_table.o `test -f 'utils/libfat/file_allocation_table.cpp' || echo '$(srcdir)/'`utils/libfat/file_allocation_table.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/file_allocation_table.Tpo $(DEPDIR)/file_allocation_table.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/file_allocation_table.cpp' object='file_allocation_table.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o file_allocation_table.o `test -f 'utils/libfat/file_allocation_table.cpp' || echo '$(srcdir)/'`utils/libfat/file_allocation_table.cpp + +file_allocation_table.obj: utils/libfat/file_allocation_table.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT file_allocation_table.obj -MD -MP -MF $(DEPDIR)/file_allocation_table.Tpo -c -o file_allocation_table.obj `if test -f 'utils/libfat/file_allocation_table.cpp'; then $(CYGPATH_W) 'utils/libfat/file_allocation_table.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/file_allocation_table.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/file_allocation_table.Tpo $(DEPDIR)/file_allocation_table.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/file_allocation_table.cpp' object='file_allocation_table.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o file_allocation_table.obj `if test -f 'utils/libfat/file_allocation_table.cpp'; then $(CYGPATH_W) 'utils/libfat/file_allocation_table.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/file_allocation_table.cpp'; fi` + +libfat.o: utils/libfat/libfat.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libfat.o -MD -MP -MF $(DEPDIR)/libfat.Tpo -c -o libfat.o `test -f 'utils/libfat/libfat.cpp' || echo '$(srcdir)/'`utils/libfat/libfat.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libfat.Tpo $(DEPDIR)/libfat.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/libfat.cpp' object='libfat.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libfat.o `test -f 'utils/libfat/libfat.cpp' || echo '$(srcdir)/'`utils/libfat/libfat.cpp + +libfat.obj: utils/libfat/libfat.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libfat.obj -MD -MP -MF $(DEPDIR)/libfat.Tpo -c -o libfat.obj `if test -f 'utils/libfat/libfat.cpp'; then $(CYGPATH_W) 'utils/libfat/libfat.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/libfat.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libfat.Tpo $(DEPDIR)/libfat.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/libfat.cpp' object='libfat.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libfat.obj `if test -f 'utils/libfat/libfat.cpp'; then $(CYGPATH_W) 'utils/libfat/libfat.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/libfat.cpp'; fi` + +libfat_public_api.o: utils/libfat/libfat_public_api.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libfat_public_api.o -MD -MP -MF $(DEPDIR)/libfat_public_api.Tpo -c -o libfat_public_api.o `test -f 'utils/libfat/libfat_public_api.cpp' || echo '$(srcdir)/'`utils/libfat/libfat_public_api.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libfat_public_api.Tpo $(DEPDIR)/libfat_public_api.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/libfat_public_api.cpp' object='libfat_public_api.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libfat_public_api.o `test -f 'utils/libfat/libfat_public_api.cpp' || echo '$(srcdir)/'`utils/libfat/libfat_public_api.cpp + +libfat_public_api.obj: utils/libfat/libfat_public_api.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libfat_public_api.obj -MD -MP -MF $(DEPDIR)/libfat_public_api.Tpo -c -o libfat_public_api.obj `if test -f 'utils/libfat/libfat_public_api.cpp'; then $(CYGPATH_W) 'utils/libfat/libfat_public_api.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/libfat_public_api.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/libfat_public_api.Tpo $(DEPDIR)/libfat_public_api.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/libfat_public_api.cpp' object='libfat_public_api.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libfat_public_api.obj `if test -f 'utils/libfat/libfat_public_api.cpp'; then $(CYGPATH_W) 'utils/libfat/libfat_public_api.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/libfat_public_api.cpp'; fi` + +lock.o: utils/libfat/lock.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT lock.o -MD -MP -MF $(DEPDIR)/lock.Tpo -c -o lock.o `test -f 'utils/libfat/lock.cpp' || echo '$(srcdir)/'`utils/libfat/lock.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/lock.Tpo $(DEPDIR)/lock.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/lock.cpp' object='lock.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o lock.o `test -f 'utils/libfat/lock.cpp' || echo '$(srcdir)/'`utils/libfat/lock.cpp + +lock.obj: utils/libfat/lock.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT lock.obj -MD -MP -MF $(DEPDIR)/lock.Tpo -c -o lock.obj `if test -f 'utils/libfat/lock.cpp'; then $(CYGPATH_W) 'utils/libfat/lock.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/lock.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/lock.Tpo $(DEPDIR)/lock.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/lock.cpp' object='lock.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o lock.obj `if test -f 'utils/libfat/lock.cpp'; then $(CYGPATH_W) 'utils/libfat/lock.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/lock.cpp'; fi` + +partition.o: utils/libfat/partition.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT partition.o -MD -MP -MF $(DEPDIR)/partition.Tpo -c -o partition.o `test -f 'utils/libfat/partition.cpp' || echo '$(srcdir)/'`utils/libfat/partition.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/partition.Tpo $(DEPDIR)/partition.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/partition.cpp' object='partition.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o partition.o `test -f 'utils/libfat/partition.cpp' || echo '$(srcdir)/'`utils/libfat/partition.cpp + +partition.obj: utils/libfat/partition.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT partition.obj -MD -MP -MF $(DEPDIR)/partition.Tpo -c -o partition.obj `if test -f 'utils/libfat/partition.cpp'; then $(CYGPATH_W) 'utils/libfat/partition.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/partition.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/partition.Tpo $(DEPDIR)/partition.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/libfat/partition.cpp' object='partition.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o partition.obj `if test -f 'utils/libfat/partition.cpp'; then $(CYGPATH_W) 'utils/libfat/partition.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/libfat/partition.cpp'; fi` + +tinystr.o: utils/tinyxml/tinystr.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT tinystr.o -MD -MP -MF $(DEPDIR)/tinystr.Tpo -c -o tinystr.o `test -f 'utils/tinyxml/tinystr.cpp' || echo '$(srcdir)/'`utils/tinyxml/tinystr.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/tinystr.Tpo $(DEPDIR)/tinystr.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/tinyxml/tinystr.cpp' object='tinystr.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o tinystr.o `test -f 'utils/tinyxml/tinystr.cpp' || echo '$(srcdir)/'`utils/tinyxml/tinystr.cpp + +tinystr.obj: utils/tinyxml/tinystr.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT tinystr.obj -MD -MP -MF $(DEPDIR)/tinystr.Tpo -c -o tinystr.obj `if test -f 'utils/tinyxml/tinystr.cpp'; then $(CYGPATH_W) 'utils/tinyxml/tinystr.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/tinyxml/tinystr.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/tinystr.Tpo $(DEPDIR)/tinystr.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/tinyxml/tinystr.cpp' object='tinystr.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o tinystr.obj `if test -f 'utils/tinyxml/tinystr.cpp'; then $(CYGPATH_W) 'utils/tinyxml/tinystr.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/tinyxml/tinystr.cpp'; fi` + +tinyxml.o: utils/tinyxml/tinyxml.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT tinyxml.o -MD -MP -MF $(DEPDIR)/tinyxml.Tpo -c -o tinyxml.o `test -f 'utils/tinyxml/tinyxml.cpp' || echo '$(srcdir)/'`utils/tinyxml/tinyxml.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/tinyxml.Tpo $(DEPDIR)/tinyxml.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/tinyxml/tinyxml.cpp' object='tinyxml.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o tinyxml.o `test -f 'utils/tinyxml/tinyxml.cpp' || echo '$(srcdir)/'`utils/tinyxml/tinyxml.cpp + +tinyxml.obj: utils/tinyxml/tinyxml.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT tinyxml.obj -MD -MP -MF $(DEPDIR)/tinyxml.Tpo -c -o tinyxml.obj `if test -f 'utils/tinyxml/tinyxml.cpp'; then $(CYGPATH_W) 'utils/tinyxml/tinyxml.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/tinyxml/tinyxml.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/tinyxml.Tpo $(DEPDIR)/tinyxml.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/tinyxml/tinyxml.cpp' object='tinyxml.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o tinyxml.obj `if test -f 'utils/tinyxml/tinyxml.cpp'; then $(CYGPATH_W) 'utils/tinyxml/tinyxml.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/tinyxml/tinyxml.cpp'; fi` + +tinyxmlerror.o: utils/tinyxml/tinyxmlerror.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT tinyxmlerror.o -MD -MP -MF $(DEPDIR)/tinyxmlerror.Tpo -c -o tinyxmlerror.o `test -f 'utils/tinyxml/tinyxmlerror.cpp' || echo '$(srcdir)/'`utils/tinyxml/tinyxmlerror.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/tinyxmlerror.Tpo $(DEPDIR)/tinyxmlerror.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/tinyxml/tinyxmlerror.cpp' object='tinyxmlerror.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o tinyxmlerror.o `test -f 'utils/tinyxml/tinyxmlerror.cpp' || echo '$(srcdir)/'`utils/tinyxml/tinyxmlerror.cpp + +tinyxmlerror.obj: utils/tinyxml/tinyxmlerror.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT tinyxmlerror.obj -MD -MP -MF $(DEPDIR)/tinyxmlerror.Tpo -c -o tinyxmlerror.obj `if test -f 'utils/tinyxml/tinyxmlerror.cpp'; then $(CYGPATH_W) 'utils/tinyxml/tinyxmlerror.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/tinyxml/tinyxmlerror.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/tinyxmlerror.Tpo $(DEPDIR)/tinyxmlerror.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/tinyxml/tinyxmlerror.cpp' object='tinyxmlerror.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o tinyxmlerror.obj `if test -f 'utils/tinyxml/tinyxmlerror.cpp'; then $(CYGPATH_W) 'utils/tinyxml/tinyxmlerror.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/tinyxml/tinyxmlerror.cpp'; fi` + +tinyxmlparser.o: utils/tinyxml/tinyxmlparser.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT tinyxmlparser.o -MD -MP -MF $(DEPDIR)/tinyxmlparser.Tpo -c -o tinyxmlparser.o `test -f 'utils/tinyxml/tinyxmlparser.cpp' || echo '$(srcdir)/'`utils/tinyxml/tinyxmlparser.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/tinyxmlparser.Tpo $(DEPDIR)/tinyxmlparser.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/tinyxml/tinyxmlparser.cpp' object='tinyxmlparser.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o tinyxmlparser.o `test -f 'utils/tinyxml/tinyxmlparser.cpp' || echo '$(srcdir)/'`utils/tinyxml/tinyxmlparser.cpp + +tinyxmlparser.obj: utils/tinyxml/tinyxmlparser.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT tinyxmlparser.obj -MD -MP -MF $(DEPDIR)/tinyxmlparser.Tpo -c -o tinyxmlparser.obj `if test -f 'utils/tinyxml/tinyxmlparser.cpp'; then $(CYGPATH_W) 'utils/tinyxml/tinyxmlparser.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/tinyxml/tinyxmlparser.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/tinyxmlparser.Tpo $(DEPDIR)/tinyxmlparser.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='utils/tinyxml/tinyxmlparser.cpp' object='tinyxmlparser.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o tinyxmlparser.obj `if test -f 'utils/tinyxml/tinyxmlparser.cpp'; then $(CYGPATH_W) 'utils/tinyxml/tinyxmlparser.cpp'; else $(CYGPATH_W) '$(srcdir)/utils/tinyxml/tinyxmlparser.cpp'; fi` + +slot2_mpcf.o: addons/slot2_mpcf.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot2_mpcf.o -MD -MP -MF $(DEPDIR)/slot2_mpcf.Tpo -c -o slot2_mpcf.o `test -f 'addons/slot2_mpcf.cpp' || echo '$(srcdir)/'`addons/slot2_mpcf.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot2_mpcf.Tpo $(DEPDIR)/slot2_mpcf.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot2_mpcf.cpp' object='slot2_mpcf.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot2_mpcf.o `test -f 'addons/slot2_mpcf.cpp' || echo '$(srcdir)/'`addons/slot2_mpcf.cpp + +slot2_mpcf.obj: addons/slot2_mpcf.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot2_mpcf.obj -MD -MP -MF $(DEPDIR)/slot2_mpcf.Tpo -c -o slot2_mpcf.obj `if test -f 'addons/slot2_mpcf.cpp'; then $(CYGPATH_W) 'addons/slot2_mpcf.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot2_mpcf.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot2_mpcf.Tpo $(DEPDIR)/slot2_mpcf.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot2_mpcf.cpp' object='slot2_mpcf.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot2_mpcf.obj `if test -f 'addons/slot2_mpcf.cpp'; then $(CYGPATH_W) 'addons/slot2_mpcf.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot2_mpcf.cpp'; fi` + +slot2_paddle.o: addons/slot2_paddle.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot2_paddle.o -MD -MP -MF $(DEPDIR)/slot2_paddle.Tpo -c -o slot2_paddle.o `test -f 'addons/slot2_paddle.cpp' || echo '$(srcdir)/'`addons/slot2_paddle.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot2_paddle.Tpo $(DEPDIR)/slot2_paddle.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot2_paddle.cpp' object='slot2_paddle.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot2_paddle.o `test -f 'addons/slot2_paddle.cpp' || echo '$(srcdir)/'`addons/slot2_paddle.cpp + +slot2_paddle.obj: addons/slot2_paddle.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot2_paddle.obj -MD -MP -MF $(DEPDIR)/slot2_paddle.Tpo -c -o slot2_paddle.obj `if test -f 'addons/slot2_paddle.cpp'; then $(CYGPATH_W) 'addons/slot2_paddle.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot2_paddle.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot2_paddle.Tpo $(DEPDIR)/slot2_paddle.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot2_paddle.cpp' object='slot2_paddle.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot2_paddle.obj `if test -f 'addons/slot2_paddle.cpp'; then $(CYGPATH_W) 'addons/slot2_paddle.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot2_paddle.cpp'; fi` + +slot2_gbagame.o: addons/slot2_gbagame.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot2_gbagame.o -MD -MP -MF $(DEPDIR)/slot2_gbagame.Tpo -c -o slot2_gbagame.o `test -f 'addons/slot2_gbagame.cpp' || echo '$(srcdir)/'`addons/slot2_gbagame.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot2_gbagame.Tpo $(DEPDIR)/slot2_gbagame.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot2_gbagame.cpp' object='slot2_gbagame.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot2_gbagame.o `test -f 'addons/slot2_gbagame.cpp' || echo '$(srcdir)/'`addons/slot2_gbagame.cpp + +slot2_gbagame.obj: addons/slot2_gbagame.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot2_gbagame.obj -MD -MP -MF $(DEPDIR)/slot2_gbagame.Tpo -c -o slot2_gbagame.obj `if test -f 'addons/slot2_gbagame.cpp'; then $(CYGPATH_W) 'addons/slot2_gbagame.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot2_gbagame.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot2_gbagame.Tpo $(DEPDIR)/slot2_gbagame.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot2_gbagame.cpp' object='slot2_gbagame.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot2_gbagame.obj `if test -f 'addons/slot2_gbagame.cpp'; then $(CYGPATH_W) 'addons/slot2_gbagame.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot2_gbagame.cpp'; fi` + +slot2_none.o: addons/slot2_none.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot2_none.o -MD -MP -MF $(DEPDIR)/slot2_none.Tpo -c -o slot2_none.o `test -f 'addons/slot2_none.cpp' || echo '$(srcdir)/'`addons/slot2_none.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot2_none.Tpo $(DEPDIR)/slot2_none.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot2_none.cpp' object='slot2_none.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot2_none.o `test -f 'addons/slot2_none.cpp' || echo '$(srcdir)/'`addons/slot2_none.cpp + +slot2_none.obj: addons/slot2_none.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot2_none.obj -MD -MP -MF $(DEPDIR)/slot2_none.Tpo -c -o slot2_none.obj `if test -f 'addons/slot2_none.cpp'; then $(CYGPATH_W) 'addons/slot2_none.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot2_none.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot2_none.Tpo $(DEPDIR)/slot2_none.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot2_none.cpp' object='slot2_none.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot2_none.obj `if test -f 'addons/slot2_none.cpp'; then $(CYGPATH_W) 'addons/slot2_none.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot2_none.cpp'; fi` + +slot2_rumblepak.o: addons/slot2_rumblepak.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot2_rumblepak.o -MD -MP -MF $(DEPDIR)/slot2_rumblepak.Tpo -c -o slot2_rumblepak.o `test -f 'addons/slot2_rumblepak.cpp' || echo '$(srcdir)/'`addons/slot2_rumblepak.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot2_rumblepak.Tpo $(DEPDIR)/slot2_rumblepak.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot2_rumblepak.cpp' object='slot2_rumblepak.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot2_rumblepak.o `test -f 'addons/slot2_rumblepak.cpp' || echo '$(srcdir)/'`addons/slot2_rumblepak.cpp + +slot2_rumblepak.obj: addons/slot2_rumblepak.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot2_rumblepak.obj -MD -MP -MF $(DEPDIR)/slot2_rumblepak.Tpo -c -o slot2_rumblepak.obj `if test -f 'addons/slot2_rumblepak.cpp'; then $(CYGPATH_W) 'addons/slot2_rumblepak.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot2_rumblepak.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot2_rumblepak.Tpo $(DEPDIR)/slot2_rumblepak.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot2_rumblepak.cpp' object='slot2_rumblepak.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot2_rumblepak.obj `if test -f 'addons/slot2_rumblepak.cpp'; then $(CYGPATH_W) 'addons/slot2_rumblepak.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot2_rumblepak.cpp'; fi` + +slot2_guitarGrip.o: addons/slot2_guitarGrip.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot2_guitarGrip.o -MD -MP -MF $(DEPDIR)/slot2_guitarGrip.Tpo -c -o slot2_guitarGrip.o `test -f 'addons/slot2_guitarGrip.cpp' || echo '$(srcdir)/'`addons/slot2_guitarGrip.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot2_guitarGrip.Tpo $(DEPDIR)/slot2_guitarGrip.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot2_guitarGrip.cpp' object='slot2_guitarGrip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot2_guitarGrip.o `test -f 'addons/slot2_guitarGrip.cpp' || echo '$(srcdir)/'`addons/slot2_guitarGrip.cpp + +slot2_guitarGrip.obj: addons/slot2_guitarGrip.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot2_guitarGrip.obj -MD -MP -MF $(DEPDIR)/slot2_guitarGrip.Tpo -c -o slot2_guitarGrip.obj `if test -f 'addons/slot2_guitarGrip.cpp'; then $(CYGPATH_W) 'addons/slot2_guitarGrip.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot2_guitarGrip.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot2_guitarGrip.Tpo $(DEPDIR)/slot2_guitarGrip.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot2_guitarGrip.cpp' object='slot2_guitarGrip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot2_guitarGrip.obj `if test -f 'addons/slot2_guitarGrip.cpp'; then $(CYGPATH_W) 'addons/slot2_guitarGrip.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot2_guitarGrip.cpp'; fi` + +slot2_expMemory.o: addons/slot2_expMemory.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot2_expMemory.o -MD -MP -MF $(DEPDIR)/slot2_expMemory.Tpo -c -o slot2_expMemory.o `test -f 'addons/slot2_expMemory.cpp' || echo '$(srcdir)/'`addons/slot2_expMemory.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot2_expMemory.Tpo $(DEPDIR)/slot2_expMemory.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot2_expMemory.cpp' object='slot2_expMemory.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot2_expMemory.o `test -f 'addons/slot2_expMemory.cpp' || echo '$(srcdir)/'`addons/slot2_expMemory.cpp + +slot2_expMemory.obj: addons/slot2_expMemory.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot2_expMemory.obj -MD -MP -MF $(DEPDIR)/slot2_expMemory.Tpo -c -o slot2_expMemory.obj `if test -f 'addons/slot2_expMemory.cpp'; then $(CYGPATH_W) 'addons/slot2_expMemory.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot2_expMemory.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot2_expMemory.Tpo $(DEPDIR)/slot2_expMemory.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot2_expMemory.cpp' object='slot2_expMemory.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot2_expMemory.obj `if test -f 'addons/slot2_expMemory.cpp'; then $(CYGPATH_W) 'addons/slot2_expMemory.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot2_expMemory.cpp'; fi` + +slot2_piano.o: addons/slot2_piano.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot2_piano.o -MD -MP -MF $(DEPDIR)/slot2_piano.Tpo -c -o slot2_piano.o `test -f 'addons/slot2_piano.cpp' || echo '$(srcdir)/'`addons/slot2_piano.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot2_piano.Tpo $(DEPDIR)/slot2_piano.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot2_piano.cpp' object='slot2_piano.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot2_piano.o `test -f 'addons/slot2_piano.cpp' || echo '$(srcdir)/'`addons/slot2_piano.cpp + +slot2_piano.obj: addons/slot2_piano.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot2_piano.obj -MD -MP -MF $(DEPDIR)/slot2_piano.Tpo -c -o slot2_piano.obj `if test -f 'addons/slot2_piano.cpp'; then $(CYGPATH_W) 'addons/slot2_piano.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot2_piano.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot2_piano.Tpo $(DEPDIR)/slot2_piano.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot2_piano.cpp' object='slot2_piano.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot2_piano.obj `if test -f 'addons/slot2_piano.cpp'; then $(CYGPATH_W) 'addons/slot2_piano.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot2_piano.cpp'; fi` + +slot1_none.o: addons/slot1_none.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot1_none.o -MD -MP -MF $(DEPDIR)/slot1_none.Tpo -c -o slot1_none.o `test -f 'addons/slot1_none.cpp' || echo '$(srcdir)/'`addons/slot1_none.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot1_none.Tpo $(DEPDIR)/slot1_none.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot1_none.cpp' object='slot1_none.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot1_none.o `test -f 'addons/slot1_none.cpp' || echo '$(srcdir)/'`addons/slot1_none.cpp + +slot1_none.obj: addons/slot1_none.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot1_none.obj -MD -MP -MF $(DEPDIR)/slot1_none.Tpo -c -o slot1_none.obj `if test -f 'addons/slot1_none.cpp'; then $(CYGPATH_W) 'addons/slot1_none.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot1_none.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot1_none.Tpo $(DEPDIR)/slot1_none.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot1_none.cpp' object='slot1_none.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot1_none.obj `if test -f 'addons/slot1_none.cpp'; then $(CYGPATH_W) 'addons/slot1_none.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot1_none.cpp'; fi` + +slot1_r4.o: addons/slot1_r4.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot1_r4.o -MD -MP -MF $(DEPDIR)/slot1_r4.Tpo -c -o slot1_r4.o `test -f 'addons/slot1_r4.cpp' || echo '$(srcdir)/'`addons/slot1_r4.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot1_r4.Tpo $(DEPDIR)/slot1_r4.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot1_r4.cpp' object='slot1_r4.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot1_r4.o `test -f 'addons/slot1_r4.cpp' || echo '$(srcdir)/'`addons/slot1_r4.cpp + +slot1_r4.obj: addons/slot1_r4.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot1_r4.obj -MD -MP -MF $(DEPDIR)/slot1_r4.Tpo -c -o slot1_r4.obj `if test -f 'addons/slot1_r4.cpp'; then $(CYGPATH_W) 'addons/slot1_r4.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot1_r4.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot1_r4.Tpo $(DEPDIR)/slot1_r4.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot1_r4.cpp' object='slot1_r4.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot1_r4.obj `if test -f 'addons/slot1_r4.cpp'; then $(CYGPATH_W) 'addons/slot1_r4.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot1_r4.cpp'; fi` + +slot1_retail.o: addons/slot1_retail.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot1_retail.o -MD -MP -MF $(DEPDIR)/slot1_retail.Tpo -c -o slot1_retail.o `test -f 'addons/slot1_retail.cpp' || echo '$(srcdir)/'`addons/slot1_retail.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot1_retail.Tpo $(DEPDIR)/slot1_retail.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot1_retail.cpp' object='slot1_retail.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot1_retail.o `test -f 'addons/slot1_retail.cpp' || echo '$(srcdir)/'`addons/slot1_retail.cpp + +slot1_retail.obj: addons/slot1_retail.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot1_retail.obj -MD -MP -MF $(DEPDIR)/slot1_retail.Tpo -c -o slot1_retail.obj `if test -f 'addons/slot1_retail.cpp'; then $(CYGPATH_W) 'addons/slot1_retail.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot1_retail.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot1_retail.Tpo $(DEPDIR)/slot1_retail.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot1_retail.cpp' object='slot1_retail.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot1_retail.obj `if test -f 'addons/slot1_retail.cpp'; then $(CYGPATH_W) 'addons/slot1_retail.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot1_retail.cpp'; fi` + +slot1_retail_nand.o: addons/slot1_retail_nand.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot1_retail_nand.o -MD -MP -MF $(DEPDIR)/slot1_retail_nand.Tpo -c -o slot1_retail_nand.o `test -f 'addons/slot1_retail_nand.cpp' || echo '$(srcdir)/'`addons/slot1_retail_nand.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot1_retail_nand.Tpo $(DEPDIR)/slot1_retail_nand.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot1_retail_nand.cpp' object='slot1_retail_nand.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot1_retail_nand.o `test -f 'addons/slot1_retail_nand.cpp' || echo '$(srcdir)/'`addons/slot1_retail_nand.cpp + +slot1_retail_nand.obj: addons/slot1_retail_nand.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT slot1_retail_nand.obj -MD -MP -MF $(DEPDIR)/slot1_retail_nand.Tpo -c -o slot1_retail_nand.obj `if test -f 'addons/slot1_retail_nand.cpp'; then $(CYGPATH_W) 'addons/slot1_retail_nand.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot1_retail_nand.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/slot1_retail_nand.Tpo $(DEPDIR)/slot1_retail_nand.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='addons/slot1_retail_nand.cpp' object='slot1_retail_nand.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o slot1_retail_nand.obj `if test -f 'addons/slot1_retail_nand.cpp'; then $(CYGPATH_W) 'addons/slot1_retail_nand.cpp'; else $(CYGPATH_W) '$(srcdir)/addons/slot1_retail_nand.cpp'; fi` + +metaspu.o: metaspu/metaspu.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT metaspu.o -MD -MP -MF $(DEPDIR)/metaspu.Tpo -c -o metaspu.o `test -f 'metaspu/metaspu.cpp' || echo '$(srcdir)/'`metaspu/metaspu.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/metaspu.Tpo $(DEPDIR)/metaspu.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='metaspu/metaspu.cpp' object='metaspu.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o metaspu.o `test -f 'metaspu/metaspu.cpp' || echo '$(srcdir)/'`metaspu/metaspu.cpp + +metaspu.obj: metaspu/metaspu.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT metaspu.obj -MD -MP -MF $(DEPDIR)/metaspu.Tpo -c -o metaspu.obj `if test -f 'metaspu/metaspu.cpp'; then $(CYGPATH_W) 'metaspu/metaspu.cpp'; else $(CYGPATH_W) '$(srcdir)/metaspu/metaspu.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/metaspu.Tpo $(DEPDIR)/metaspu.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='metaspu/metaspu.cpp' object='metaspu.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o metaspu.obj `if test -f 'metaspu/metaspu.cpp'; then $(CYGPATH_W) 'metaspu/metaspu.cpp'; else $(CYGPATH_W) '$(srcdir)/metaspu/metaspu.cpp'; fi` + +SndOut.o: metaspu/SndOut.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT SndOut.o -MD -MP -MF $(DEPDIR)/SndOut.Tpo -c -o SndOut.o `test -f 'metaspu/SndOut.cpp' || echo '$(srcdir)/'`metaspu/SndOut.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/SndOut.Tpo $(DEPDIR)/SndOut.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='metaspu/SndOut.cpp' object='SndOut.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o SndOut.o `test -f 'metaspu/SndOut.cpp' || echo '$(srcdir)/'`metaspu/SndOut.cpp + +SndOut.obj: metaspu/SndOut.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT SndOut.obj -MD -MP -MF $(DEPDIR)/SndOut.Tpo -c -o SndOut.obj `if test -f 'metaspu/SndOut.cpp'; then $(CYGPATH_W) 'metaspu/SndOut.cpp'; else $(CYGPATH_W) '$(srcdir)/metaspu/SndOut.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/SndOut.Tpo $(DEPDIR)/SndOut.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='metaspu/SndOut.cpp' object='SndOut.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o SndOut.obj `if test -f 'metaspu/SndOut.cpp'; then $(CYGPATH_W) 'metaspu/SndOut.cpp'; else $(CYGPATH_W) '$(srcdir)/metaspu/SndOut.cpp'; fi` + +Timestretcher.o: metaspu/Timestretcher.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT Timestretcher.o -MD -MP -MF $(DEPDIR)/Timestretcher.Tpo -c -o Timestretcher.o `test -f 'metaspu/Timestretcher.cpp' || echo '$(srcdir)/'`metaspu/Timestretcher.cpp +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/Timestretcher.Tpo $(DEPDIR)/Timestretcher.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='metaspu/Timestretcher.cpp' object='Timestretcher.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o Timestretcher.o `test -f 'metaspu/Timestretcher.cpp' || echo '$(srcdir)/'`metaspu/Timestretcher.cpp + +Timestretcher.obj: metaspu/Timestretcher.cpp +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT Timestretcher.obj -MD -MP -MF $(DEPDIR)/Timestretcher.Tpo -c -o Timestretcher.obj `if test -f 'metaspu/Timestretcher.cpp'; then $(CYGPATH_W) 'metaspu/Timestretcher.cpp'; else $(CYGPATH_W) '$(srcdir)/metaspu/Timestretcher.cpp'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/Timestretcher.Tpo $(DEPDIR)/Timestretcher.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='metaspu/Timestretcher.cpp' object='Timestretcher.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o Timestretcher.obj `if test -f 'metaspu/Timestretcher.cpp'; then $(CYGPATH_W) 'metaspu/Timestretcher.cpp'; else $(CYGPATH_W) '$(srcdir)/metaspu/Timestretcher.cpp'; fi` + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(LIBRARIES) +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags ctags-recursive distclean \ + distclean-compile distclean-generic distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ + tags tags-recursive uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/jni/desmume/src/NDSSystem.cpp b/jni/desmume/src/NDSSystem.cpp new file mode 100755 index 0000000..28e2725 --- /dev/null +++ b/jni/desmume/src/NDSSystem.cpp @@ -0,0 +1,3020 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2008-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ + +#include +#include +#include +#include +#include + +#include "common.h" +#include "NDSSystem.h" +#include "render3D.h" +#include "MMU.h" +#include "ROMReader.h" +#include "gfx3d.h" +#include "utils/decrypt/decrypt.h" +#include "utils/decrypt/crc.h" +#include "bios.h" +#include "debug.h" +#include "cheatSystem.h" +#include "movie.h" +#include "Disassembler.h" +#include "readwrite.h" +#include "debug.h" +#include "firmware.h" +#include "version.h" +#include "slot1.h" + +#include "path.h" + +//int xxctr=0; +//#define LOG_ARM9 +//#define LOG_ARM7 +//#define dolog (currFrameCounter>15) +//#define LOG_TO_FILE +//#define LOG_TO_FILE_REGS + +//=============================================================== +FILE *fp_dis7 = NULL; +FILE *fp_dis9 = NULL; + +PathInfo path; + +TCommonSettings CommonSettings; +static BaseDriver _stub_driver; +BaseDriver* driver = &_stub_driver; +std::string InputDisplayString; + +static BOOL LidClosed = FALSE; +static u8 countLid = 0; + +GameInfo gameInfo; +NDSSystem nds; +CFIRMWARE *firmware = NULL; +ADVANsCEne advsc; + +using std::min; +using std::max; + +bool singleStep; +bool nds_debug_continuing[2]; +int lagframecounter; +int LagFrameFlag; +int lastLag; +int TotalLagFrames; + +TSCalInfo TSCal; + +namespace DLDI +{ + bool tryPatch(void* data, size_t size); +} + +void Desmume_InitOnce() +{ + static bool initOnce = false; + if(initOnce) return; + initOnce = true; + +#ifdef HAVE_LIBAGG + extern void Agg_init(); //no need to include just for this + Agg_init(); +#endif +} + +#ifdef GDB_STUB +int NDS_Init( struct armcpu_memory_iface *arm9_mem_if, +struct armcpu_ctrl_iface **arm9_ctrl_iface, +struct armcpu_memory_iface *arm7_mem_if, +struct armcpu_ctrl_iface **arm7_ctrl_iface) { +#else +int NDS_Init( void) { +#endif + nds.idleFrameCounter = 0; + memset(nds.runCycleCollector,0,sizeof(nds.runCycleCollector)); + MMU_Init(); + nds.VCount = 0; + + //got to print this somewhere.. + printf("%s\n", EMU_DESMUME_NAME_AND_VERSION()); + + if (Screen_Init(GFXCORE_DUMMY) != 0) + return -1; + + gfx3d_init(); + +#ifdef GDB_STUB + armcpu_new(&NDS_ARM7,1, arm7_mem_if, arm7_ctrl_iface); + armcpu_new(&NDS_ARM9,0, arm9_mem_if, arm9_ctrl_iface); +#else + armcpu_new(&NDS_ARM7,1); + armcpu_new(&NDS_ARM9,0); +#endif + + if (SPU_Init(SNDCORE_DUMMY, 740) != 0) + return -1; + + WIFI_Init() ; + + // Init calibration info + TSCal.adc.x1 = 0x0200; + TSCal.adc.y1 = 0x0200; + TSCal.scr.x1 = 0x20 + 1; // calibration screen coords are 1-based, + TSCal.scr.y1 = 0x20 + 1; // either that or NDS_getADCTouchPosX/Y are wrong. + TSCal.adc.x2 = 0x0E00; + TSCal.adc.y2 = 0x0800; + TSCal.scr.x2 = 0xE0 + 1; + TSCal.scr.y2 = 0x80 + 1; + TSCal.adc.width = (TSCal.adc.x2 - TSCal.adc.x1); + TSCal.adc.height = (TSCal.adc.y2 - TSCal.adc.y1); + TSCal.scr.width = (TSCal.scr.x2 - TSCal.scr.x1); + TSCal.scr.height = (TSCal.scr.y2 - TSCal.scr.y1); + + cheats = new CHEATS(); + cheatSearch = new CHEATSEARCH(); + + return 0; +} + +void NDS_DeInit(void) { + if(MMU.CART_ROM != MMU.UNUSED_RAM) + NDS_FreeROM(); + + SPU_DeInit(); + Screen_DeInit(); + MMU_DeInit(); + gpu3D->NDS_3D_Close(); + + WIFI_DeInit(); + if (cheats) + delete cheats; + if (cheatSearch) + delete cheatSearch; + +#ifdef LOG_ARM7 + if (fp_dis7 != NULL) + { + fclose(fp_dis7); + fp_dis7 = NULL; + } +#endif + +#ifdef LOG_ARM9 + if (fp_dis9 != NULL) + { + fclose(fp_dis9); + fp_dis9 = NULL; + } +#endif +} + +BOOL NDS_SetROM(u8 * rom, u32 mask) +{ + MMU_setRom(rom, mask); + + return TRUE; +} + +NDS_header * NDS_getROMHeader(void) +{ + if(MMU.CART_ROM == MMU.UNUSED_RAM) return NULL; + NDS_header * header = new NDS_header; + + memcpy(header->gameTile, MMU.CART_ROM, 12); + memcpy(header->gameCode, MMU.CART_ROM + 12, 4); + header->makerCode = T1ReadWord(MMU.CART_ROM, 16); + header->unitCode = MMU.CART_ROM[18]; + header->deviceCode = MMU.CART_ROM[19]; + header->cardSize = MMU.CART_ROM[20]; + memcpy(header->cardInfo, MMU.CART_ROM + 21, 8); + header->flags = MMU.CART_ROM[29]; + header->romversion = MMU.CART_ROM[30]; + header->ARM9src = T1ReadLong(MMU.CART_ROM, 32); + header->ARM9exe = T1ReadLong(MMU.CART_ROM, 36); + header->ARM9cpy = T1ReadLong(MMU.CART_ROM, 40); + header->ARM9binSize = T1ReadLong(MMU.CART_ROM, 44); + header->ARM7src = T1ReadLong(MMU.CART_ROM, 48); + header->ARM7exe = T1ReadLong(MMU.CART_ROM, 52); + header->ARM7cpy = T1ReadLong(MMU.CART_ROM, 56); + header->ARM7binSize = T1ReadLong(MMU.CART_ROM, 60); + header->FNameTblOff = T1ReadLong(MMU.CART_ROM, 64); + header->FNameTblSize = T1ReadLong(MMU.CART_ROM, 68); + header->FATOff = T1ReadLong(MMU.CART_ROM, 72); + header->FATSize = T1ReadLong(MMU.CART_ROM, 76); + header->ARM9OverlayOff = T1ReadLong(MMU.CART_ROM, 80); + header->ARM9OverlaySize = T1ReadLong(MMU.CART_ROM, 84); + header->ARM7OverlayOff = T1ReadLong(MMU.CART_ROM, 88); + header->ARM7OverlaySize = T1ReadLong(MMU.CART_ROM, 92); + header->unknown2a = T1ReadLong(MMU.CART_ROM, 96); + header->unknown2b = T1ReadLong(MMU.CART_ROM, 100); + header->IconOff = T1ReadLong(MMU.CART_ROM, 104); + header->CRC16 = T1ReadWord(MMU.CART_ROM, 108); + header->ROMtimeout = T1ReadWord(MMU.CART_ROM, 110); + header->ARM9unk = T1ReadLong(MMU.CART_ROM, 112); + header->ARM7unk = T1ReadLong(MMU.CART_ROM, 116); + memcpy(header->unknown3c, MMU.CART_ROM + 120, 8); + header->ROMSize = T1ReadLong(MMU.CART_ROM, 128); + header->HeaderSize = T1ReadLong(MMU.CART_ROM, 132); + memcpy(header->unknown5, MMU.CART_ROM + 136, 56); + memcpy(header->logo, MMU.CART_ROM + 192, 156); + header->logoCRC16 = T1ReadWord(MMU.CART_ROM, 348); + header->headerCRC16 = T1ReadWord(MMU.CART_ROM, 350); + memcpy(header->reserved, MMU.CART_ROM + 352, min(160, (int)gameInfo.romsize - 352)); + + return header; +} + + + + +void debug() +{ + //if(NDS_ARM9.R[15]==0x020520DC) emu_halt(); + //DSLinux + //if(NDS_ARM9.CPSR.bits.mode == 0) emu_halt(); + //if((NDS_ARM9.R[15]&0xFFFFF000)==0) emu_halt(); + //if((NDS_ARM9.R[15]==0x0201B4F4)/*&&(NDS_ARM9.R[1]==0x0)*/) emu_halt(); + //AOE + //if((NDS_ARM9.R[15]==0x01FFE194)&&(NDS_ARM9.R[0]==0)) emu_halt(); + //if((NDS_ARM9.R[15]==0x01FFE134)&&(NDS_ARM9.R[0]==0)) emu_halt(); + + //BBMAN + //if(NDS_ARM9.R[15]==0x02098B4C) emu_halt(); + //if(NDS_ARM9.R[15]==0x02004924) emu_halt(); + //if(NDS_ARM9.R[15]==0x02004890) emu_halt(); + + //if(NDS_ARM9.R[15]==0x0202B800) emu_halt(); + //if(NDS_ARM9.R[15]==0x0202B3DC) emu_halt(); + //if((NDS_ARM9.R[1]==0x9AC29AC1)&&(!fait)) {emu_halt();fait = TRUE;} + //if(NDS_ARM9.R[1]==0x0400004A) {emu_halt();fait = TRUE;} + /*if(NDS_ARM9.R[4]==0x2E33373C) emu_halt(); + if(NDS_ARM9.R[15]==0x02036668) //emu_halt(); + { + nds.logcount++; + sprintf(logbuf, "%d %08X", nds.logcount, NDS_ARM9.R[13]); + log::ajouter(logbuf); + if(nds.logcount==89) execute=FALSE; + }*/ + //if(NDS_ARM9.instruction==0) emu_halt(); + //if((NDS_ARM9.R[15]>>28)) emu_halt(); +} + +#define DSGBA_LOADER_SIZE 512 +enum +{ + ROM_NDS = 0, + ROM_DSGBA +}; + +#if 0 /* not used */ +//http://www.aggregate.org/MAGIC/#Population%20Count%20(Ones%20Count) +static u32 ones32(u32 x) +{ + /* 32-bit recursive reduction using SWAR... + but first step is mapping 2-bit values + into sum of 2 1-bit values in sneaky way + */ + x -= ((x >> 1) & 0x55555555); + x = (((x >> 2) & 0x33333333) + (x & 0x33333333)); + x = (((x >> 4) + x) & 0x0f0f0f0f); + x += (x >> 8); + x += (x >> 16); + return(x & 0x0000003f); +} +#endif + +RomBanner::RomBanner(bool defaultInit) +{ + if(!defaultInit) return; + version = 1; //Version (0001h) + crc16 = 0; //CRC16 across entries 020h..83Fh + memset(reserved,0,sizeof(reserved)); + memset(bitmap,0,sizeof(bitmap)); + memset(palette,0,sizeof(palette)); + memset(titles,0,sizeof(titles)); + memset(end0xFF,0,sizeof(end0xFF)); +} + +bool GameInfo::hasRomBanner() +{ + if(header.IconOff + sizeof(RomBanner) > romsize) + return false; + else return true; +} + +const RomBanner& GameInfo::getRomBanner() +{ + //we may not have a valid banner. return a default one + if(!hasRomBanner()) + { + static RomBanner defaultBanner(true); + return defaultBanner; + } + + return *(RomBanner*)(romdata+header.IconOff); +} + +void GameInfo::populate() +{ + const char *regions[] = { "JPFSEDIRKH", + "JPN", + "EUR", + "FRA", + "ESP", + "USA", + "NOE", + "ITA", + "RUS", + "KOR", + "HOL", + + }; + + NDS_header * _header = NDS_getROMHeader(); + header = *_header; + delete _header; + + memset(ROMserial, 0, sizeof(ROMserial)); + memset(ROMname, 0, sizeof(ROMname)); + + if ( + //Option 1. - look for this instruction in the game title + //(did this ever work?) + //(header->gameTile[0] == 0x2E) && + //(header->gameTile[1] == 0x00) && + //(header->gameTile[2] == 0x00) && + //(header->gameTile[3] == 0xEA) + //) && + //option 2. - look for gamecode #### (default for ndstool) + //or an invalid gamecode + ( + ((header.gameCode[0] == 0x23) && + (header.gameCode[1] == 0x23) && + (header.gameCode[2] == 0x23) && + (header.gameCode[3] == 0x23) + ) || + (header.gameCode[0] == 0x00) + ) + && + header.makerCode == 0x0 + ) + { + //we can't really make a serial for a homebrew game that hasnt set a game code + strcpy(ROMserial, "Homebrew"); + } + else + { + strcpy(ROMserial,"NTR- -"); + memcpy(ROMserial+4, header.gameCode, 4); + + u32 region = (u32)(std::max(strchr(regions[0],header.gameCode[3]) - regions[0] + 1, 0)); + if (region != 0) + strcat(ROMserial, regions[region]); + else + strcat(ROMserial, "Unknown"); + } + + //rom name is probably set even in homebrew + memset(ROMname, 0, sizeof(ROMname)); + memcpy(ROMname, header.gameTile, 12); + trim(ROMname,20); + + /*if(header.IconOff < romsize) + { + u8 num = (T1ReadByte((u8*)romdata, header.IconOff) == 1)?6:7; + for (int i = 0; i < num; i++) + { + wcstombs(ROMfullName[i], (wchar_t *)(romdata+header.IconOff+0x240+(i*0x100)), 0x100); + trim(ROMfullName[i]); + } + }*/ + + //this may look like a poor heuristic for detecting homebrew, but it is actually pretty good. + //setting your own game code is stupid, so homebrew should just leave it. + //however, non-devkitARM-default makefiles may not have set this. + isHomebrew = !memcmp(header.gameCode,"####",4); +} + +#ifdef _WINDOWS + +static std::vector buffer; +static std::vector v; + +static void loadrom(std::string fname) { + + FILE* inf = fopen(fname.c_str(),"rb"); + if(!inf) return; + + fseek(inf,0,SEEK_END); + int size = ftell(inf); + fseek(inf,0,SEEK_SET); + + gameInfo.resize(size); + fread(gameInfo.romdata,1,size,inf); + gameInfo.fillGap(); + + fclose(inf); +} + +static int rom_init_path(const char *filename, const char *logicalFilename) +{ + int type = ROM_NDS; + + path.init(logicalFilename); + + if ( path.isdsgba(path.path)) { + type = ROM_DSGBA; + loadrom(path.path); + } + else if ( !strcasecmp(path.extension().c_str(), "nds")) { + type = ROM_NDS; + loadrom(path.path); //n.b. this does nothing if the file can't be found (i.e. if it was an extracted tempfile)... + //...but since the data was extracted to gameInfo then it is ok + } + //ds.gba in archives, it's already been loaded into memory at this point + else if (path.isdsgba(std::string(logicalFilename))) { + type = ROM_DSGBA; + } else { + //well, try to load it as an nds rom anyway + type = ROM_NDS; + loadrom(path.path); + } + + if(type == ROM_DSGBA) + { + std::vector v(gameInfo.romdata + DSGBA_LOADER_SIZE, gameInfo.romdata + gameInfo.romsize); + gameInfo.loadData(&v[0],gameInfo.romsize - DSGBA_LOADER_SIZE); + } + + //check that size is at least the size of the header + if (gameInfo.romsize < 352) { + return -1; + } + + return 1; +} +#else +static int rom_init_path(const char *filename, const char *logicalFilename) +{ + int ret; + int type; + ROMReader_struct *reader; + void *file; + u32 size; + char *noext; + + noext = strdup(filename); + reader = ROMReaderInit(&noext); + free(noext); + + if (logicalFilename) + path.init(logicalFilename); + else + path.init(filename); + + if (!strcasecmp(path.extension().c_str(), "zip")) + type = ROM_NDS; + else if (!strcasecmp(path.extension().c_str(), "nds")) + type = ROM_NDS; + else if (path.isdsgba(path.path)) + type = ROM_DSGBA; + else + type = ROM_NDS; + + file = reader->Init(filename); + if (!file) + { + reader->DeInit(file); + return -1; + } + + size = reader->Size(file); + + if(type == ROM_DSGBA) + { + reader->Seek(file, DSGBA_LOADER_SIZE, SEEK_SET); + size -= DSGBA_LOADER_SIZE; + } + + //check that size is at least the size of the header + if (size < 352) { + reader->DeInit(file); + return -1; + } + + // Make sure old ROM is freed first(at least this way we won't be eating + // up a ton of ram before the old ROM is freed) + if(MMU.CART_ROM != MMU.UNUSED_RAM) + NDS_FreeROM(); + + gameInfo.resize(size); + ret = reader->Read(file, gameInfo.romdata, size); + gameInfo.fillGap(); + reader->DeInit(file); + + return ret; +} +#endif + +int NDS_LoadROM(const char *filename, const char *logicalFilename) +{ + int ret; + char buf[MAX_PATH]; + + if (filename == NULL) + return -1; + + ret = rom_init_path(filename, logicalFilename); + if (ret < 1) + return ret; + + //decrypt if necessary.. + //but this is untested and suspected to fail on big endian, so lets not support this on big endian +#ifndef WORDS_BIGENDIAN + bool okRom = DecryptSecureArea((u8*)gameInfo.romdata,gameInfo.romsize); + + if(!okRom) { + printf("Specified file is not a valid rom\n"); + return -1; + } +#endif + + if (cheatSearch) + cheatSearch->close(); + FCEUI_StopMovie(); + + MMU_unsetRom(); + NDS_SetROM((u8*)gameInfo.romdata, gameInfo.mask); + + gameInfo.populate(); + gameInfo.crc = crc32(0,(u8*)gameInfo.romdata,gameInfo.romsize); + INFO("\nROM game code: %c%c%c%c\n", gameInfo.header.gameCode[0], gameInfo.header.gameCode[1], gameInfo.header.gameCode[2], gameInfo.header.gameCode[3]); + INFO("ROM crc: %08X\n", gameInfo.crc); + INFO("ROM serial: %s\n", gameInfo.ROMserial); + INFO("ROM internal name: %s\n", gameInfo.ROMname); + + memset(buf, 0, MAX_PATH); + strcpy(buf, path.pathToModule); + strcat(buf, "desmume.ddb"); // DeSmuME database :) + advsc.setDatabase(buf); + buf[0] = gameInfo.header.gameCode[0]; + buf[1] = gameInfo.header.gameCode[1]; + buf[2] = gameInfo.header.gameCode[2]; + buf[3] = gameInfo.header.gameCode[3]; + buf[4] = 0; + if (advsc.checkDB(buf)) + { + u8 sv = advsc.getSaveType(); + printf("ADVANsCEne database:\n"); + printf("\t* ROM save type: "); + if (sv == 0xFF) + printf("Unknown"); + else + if (sv == 0xFE) + printf("None"); + else + { + printf("%s", save_names[sv]); + if (CommonSettings.autodetectBackupMethod == 1) + backup_setManualBackupType(sv+1); + } + printf("\n\t* ROM crc: %08X\n", advsc.getCRC32()); + } + printf("\n"); + + //for homebrew, try auto-patching DLDI. should be benign if there is no DLDI or if it fails + if(gameInfo.isHomebrew) + DLDI::tryPatch((void*)gameInfo.romdata, gameInfo.romsize); + + memset(buf, 0, MAX_PATH); + path.getpathnoext(path.BATTERY, buf); + strcat(buf, ".dsv"); // DeSmuME memory card :) + MMU_new.backupDevice.load_rom(buf); + + memset(buf, 0, MAX_PATH); + path.getpathnoext(path.CHEATS, buf); + strcat(buf, ".dct"); // DeSmuME cheat :) + cheats->init(buf); + + NDS_Reset(); + + return ret; +} + +void NDS_FreeROM(void) +{ + FCEUI_StopMovie(); + if ((u8*)MMU.CART_ROM == (u8*)gameInfo.romdata) + gameInfo.romdata = NULL; + if (MMU.CART_ROM != MMU.UNUSED_RAM) + delete [] MMU.CART_ROM; + MMU_unsetRom(); +} + +u32 NDS_ImportSaveSize(const char *filename) +{ + u32 res = 0; + if (strlen(filename) < 4) return 0; + + if (memcmp(filename+strlen(filename)-4, ".duc", 4) == 0) + { + res = MMU_new.backupDevice.get_save_duc_size(filename); + if (res == 0xFFFFFFFF) return 0; + return res; + } + + res = MMU_new.backupDevice.get_save_nogba_size(filename); + if (res != 0xFFFFFFFF) return res; + + res = MMU_new.backupDevice.get_save_raw_size(filename); + if (res != 0xFFFFFFFF) return res; + + return 0; +} + +int NDS_ImportSave(const char *filename, u32 force_size) +{ + if (strlen(filename) < 4) return 0; + + if (memcmp(filename+strlen(filename)-4, ".duc", 4) == 0) + return MMU_new.backupDevice.load_duc(filename, force_size); + else + if (MMU_new.backupDevice.load_no_gba(filename, force_size)) + return 1; + else + return MMU_new.backupDevice.load_raw(filename, force_size); + + return 0; +} + +bool NDS_ExportSave(const char *filename) +{ + if (strlen(filename) < 4) + return false; + + if (memcmp(filename+strlen(filename)-5, ".sav*", 5) == 0) + { + char tmp[MAX_PATH]; + memset(tmp, 0, MAX_PATH); + strcpy(tmp, filename); + tmp[strlen(tmp)-1] = 0; + return MMU_new.backupDevice.save_no_gba(tmp); + } + + if (memcmp(filename+strlen(filename)-4, ".sav", 4) == 0) + return MMU_new.backupDevice.save_raw(filename); + + return false; +} + +static int WritePNGChunk(FILE *fp, uint32 size, const char *type, const uint8 *data) +{ + uint32 crc; + + uint8 tempo[4]; + + tempo[0]=size>>24; + tempo[1]=size>>16; + tempo[2]=size>>8; + tempo[3]=size; + + if(fwrite(tempo,4,1,fp)!=1) + return 0; + if(fwrite(type,4,1,fp)!=1) + return 0; + + if(size) + if(fwrite(data,1,size,fp)!=size) + return 0; + + crc = crc32(0,(uint8 *)type,4); + if(size) + crc = crc32(crc,data,size); + + tempo[0]=crc>>24; + tempo[1]=crc>>16; + tempo[2]=crc>>8; + tempo[3]=crc; + + if(fwrite(tempo,4,1,fp)!=1) + return 0; + return 1; +} +int NDS_WritePNG(const char *fname) +{ + int x, y; + int width=256; + int height=192*2; + u16 * bmp = (u16 *)GPU_screen; + FILE *pp=NULL; + uint8 *compmem = NULL; + uLongf compmemsize = (uLongf)( (height * (width + 1) * 3 * 1.001 + 1) + 12 ); + + if(!(compmem=(uint8 *)malloc(compmemsize))) + return 0; + + if(!(pp=fopen(fname, "wb"))) + { + goto PNGerr; + } + { + const uint8 header[8]={137,80,78,71,13,10,26,10}; + if(fwrite(header,8,1,pp)!=1) + goto PNGerr; + } + + { + uint8 chunko[13]; + + chunko[0] = width >> 24; // Width + chunko[1] = width >> 16; + chunko[2] = width >> 8; + chunko[3] = width; + + chunko[4] = height >> 24; // Height + chunko[5] = height >> 16; + chunko[6] = height >> 8; + chunko[7] = height; + + chunko[8]=8; // 8 bits per sample(24 bits per pixel) + chunko[9]=2; // Color type; RGB triplet + chunko[10]=0; // compression: deflate + chunko[11]=0; // Basic adapative filter set(though none are used). + chunko[12]=0; // No interlace. + + if(!WritePNGChunk(pp,13,"IHDR",chunko)) + goto PNGerr; + } + + { + uint8 *tmp_buffer; + uint8 *tmp_inc; + tmp_inc = tmp_buffer = (uint8 *)malloc((width * 3 + 1) * height); + + for(y=0;y>10; + pixel-=r<<10; + g = pixel>>5; + pixel-=g<<5; + b = pixel; + r*=255/31; + g*=255/31; + b*=255/31; + tmp_inc[0] = b; + tmp_inc[1] = g; + tmp_inc[2] = r; + tmp_inc += 3; + } + } + + if(compress(compmem, &compmemsize, tmp_buffer, height * (width * 3 + 1))!=Z_OK) + { + if(tmp_buffer) free(tmp_buffer); + goto PNGerr; + } + if(tmp_buffer) free(tmp_buffer); + if(!WritePNGChunk(pp,compmemsize,"IDAT",compmem)) + goto PNGerr; + } + if(!WritePNGChunk(pp,0,"IEND",0)) + goto PNGerr; + + free(compmem); + fclose(pp); + + return 1; + +PNGerr: + if(compmem) + free(compmem); + if(pp) + fclose(pp); + return(0); +} + +typedef struct +{ + u32 size; + s32 width; + s32 height; + u16 planes; + u16 bpp; + u32 cmptype; + u32 imgsize; + s32 hppm; + s32 vppm; + u32 numcol; + u32 numimpcol; +} bmpimgheader_struct; + +#include "PACKED.h" +typedef struct +{ + u16 id __PACKED; + u32 size __PACKED; + u16 reserved1 __PACKED; + u16 reserved2 __PACKED; + u32 imgoffset __PACKED; +} bmpfileheader_struct; +#include "PACKED_END.h" + +int NDS_WriteBMP(const char *filename) +{ + bmpfileheader_struct fileheader; + bmpimgheader_struct imageheader; + FILE *file; + int i,j; + u16 * bmp = (u16 *)GPU_screen; + size_t elems_written = 0; + + memset(&fileheader, 0, sizeof(fileheader)); + fileheader.size = sizeof(fileheader); + fileheader.id = 'B' | ('M' << 8); + fileheader.imgoffset = sizeof(fileheader)+sizeof(imageheader); + + memset(&imageheader, 0, sizeof(imageheader)); + imageheader.size = sizeof(imageheader); + imageheader.width = 256; + imageheader.height = 192*2; + imageheader.planes = 1; + imageheader.bpp = 24; + imageheader.cmptype = 0; // None + imageheader.imgsize = imageheader.width * imageheader.height * 3; + + if ((file = fopen(filename,"wb")) == NULL) + return 0; + + elems_written += fwrite(&fileheader, 1, sizeof(fileheader), file); + elems_written += fwrite(&imageheader, 1, sizeof(imageheader), file); + + for(j=0;j<192*2;j++) + { + for(i=0;i<256;i++) + { + u8 r,g,b; + u16 pixel = bmp[(192*2-j-1)*256+i]; + r = pixel>>10; + pixel-=r<<10; + g = pixel>>5; + pixel-=g<<5; + b = (u8)pixel; + r*=255/31; + g*=255/31; + b*=255/31; + elems_written += fwrite(&r, 1, sizeof(u8), file); + elems_written += fwrite(&g, 1, sizeof(u8), file); + elems_written += fwrite(&b, 1, sizeof(u8), file); + } + } + fclose(file); + + return 1; +} + +int NDS_WriteBMP_32bppBuffer(int width, int height, const void* buf, const char *filename) +{ + bmpfileheader_struct fileheader; + bmpimgheader_struct imageheader; + FILE *file; + size_t elems_written = 0; + memset(&fileheader, 0, sizeof(fileheader)); + fileheader.size = sizeof(fileheader); + fileheader.id = 'B' | ('M' << 8); + fileheader.imgoffset = sizeof(fileheader)+sizeof(imageheader); + + memset(&imageheader, 0, sizeof(imageheader)); + imageheader.size = sizeof(imageheader); + imageheader.width = width; + imageheader.height = height; + imageheader.planes = 1; + imageheader.bpp = 32; + imageheader.cmptype = 0; // None + imageheader.imgsize = imageheader.width * imageheader.height * 4; + + if ((file = fopen(filename,"wb")) == NULL) + return 0; + + elems_written += fwrite(&fileheader, 1, sizeof(fileheader), file); + elems_written += fwrite(&imageheader, 1, sizeof(imageheader), file); + + for(int i=0;i 30) || forceEvenIfCapturing) + { + SkipCur2DFrame = false; + SkipCur3DFrame = false; + SkipNext2DFrame = false; + if(forceEvenIfCapturing) + consecutiveNonCaptures = 0; + } + } + void Advance() + { + bool capturing = (MainScreen.gpu->dispCapCnt.enabled || (MainScreen.gpu->dispCapCnt.val & 0x80000000)); + + if(capturing && consecutiveNonCaptures > 30) + { + // the worst-looking graphics corruption problems from frameskip + // are the result of skipping the capture on first frame it turns on. + // so we do this to handle the capture immediately, + // despite the risk of 1 frame of 2d/3d mismatch or wrong screen display. + SkipNext2DFrame = false; + nextSkip = false; + } + else if(lastOffset != MainScreen.offset && lastSkip && !skipped) + { + // if we're switching from not skipping to skipping + // and the screens are also switching around this frame, + // go for 1 extra frame without skipping. + // this avoids the scenario where we only draw one of the two screens + // when a game is switching screens every frame. + nextSkip = false; + } + + if(capturing) + consecutiveNonCaptures = 0; + else if(!(consecutiveNonCaptures > 9000)) // arbitrary cap to avoid eventual wrap + consecutiveNonCaptures++; + lastLastOffset = lastOffset; + lastOffset = MainScreen.offset; + lastSkip = skipped; + skipped = nextSkip; + nextSkip = false; + + SkipCur2DFrame = SkipNext2DFrame; + SkipCur3DFrame = skipped; + SkipNext2DFrame = skipped; + } + FORCEINLINE bool ShouldSkip2D() + { + return SkipCur2DFrame; + } + FORCEINLINE bool ShouldSkip3D() + { + return SkipCur3DFrame; + } + FrameSkipper() + { + nextSkip = false; + skipped = false; + lastSkip = false; + lastOffset = 0; + SkipCur2DFrame = false; + SkipCur3DFrame = false; + SkipNext2DFrame = false; + consecutiveNonCaptures = 0; + } +private: + bool nextSkip; + bool skipped; + bool lastSkip; + int lastOffset; + int lastLastOffset; + int consecutiveNonCaptures; + bool SkipCur2DFrame; + bool SkipCur3DFrame; + bool SkipNext2DFrame; +}; +static FrameSkipper frameSkipper; + + +void NDS_SkipNextFrame() { + if (!driver->AVI_IsRecording()) { + frameSkipper.RequestSkip(); + } +} +void NDS_OmitFrameSkip(int force) { + frameSkipper.OmitSkip(force > 0, force > 1); +} + +#define INDEX(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF)) + + +enum ESI_DISPCNT +{ + ESI_DISPCNT_HStart, ESI_DISPCNT_HStartIRQ, ESI_DISPCNT_HDraw, ESI_DISPCNT_HBlank +}; + +u64 nds_timer; +u64 nds_arm9_timer, nds_arm7_timer; + +static const u64 kNever = 0xFFFFFFFFFFFFFFFFULL; + +struct TSequenceItem +{ + u64 timestamp; + u32 param; + bool enabled; + + virtual void save(EMUFILE* os) + { + write64le(timestamp,os); + write32le(param,os); + writebool(enabled,os); + } + + virtual bool load(EMUFILE* is) + { + if(read64le(×tamp,is) != 1) return false; + if(read32le(¶m,is) != 1) return false; + if(readbool(&enabled,is) != 1) return false; + return true; + } + + FORCEINLINE bool isTriggered() + { + return enabled && nds_timer >= timestamp; + } + + FORCEINLINE u64 next() + { + return timestamp; + } +}; + +struct TSequenceItem_GXFIFO : public TSequenceItem +{ + FORCEINLINE bool isTriggered() + { + return enabled && nds_timer >= MMU.gfx3dCycles; + } + + FORCEINLINE void exec() + { + IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[4]++); + while(isTriggered()) { + enabled = false; + gfx3d_execute3D(); + } + } + + FORCEINLINE u64 next() + { + if(enabled) return MMU.gfx3dCycles; + else return kNever; + } +}; + +template struct TSequenceItem_Timer : public TSequenceItem +{ + FORCEINLINE bool isTriggered() + { + return enabled && nds_timer >= nds.timerCycle[procnum][num]; + } + + FORCEINLINE void schedule() + { + enabled = MMU.timerON[procnum][num] && MMU.timerMODE[procnum][num] != 0xFFFF; + } + + FORCEINLINE u64 next() + { + return nds.timerCycle[procnum][num]; + } + + FORCEINLINE void exec() + { + IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[13+procnum*4+num]++); + u8* regs = procnum==0?MMU.ARM9_REG:MMU.ARM7_REG; + bool first = true, over; + //we'll need to check chained timers.. + for(int i=num;i<4;i++) + { + //maybe too many checks if this is here, but we need it here for now + if(!MMU.timerON[procnum][i]) return; + + if(MMU.timerMODE[procnum][i] == 0xFFFF) + { + ++(MMU.timer[procnum][i]); + over = !MMU.timer[procnum][i]; + } + else + { + if(!first) break; //this timer isn't chained. break the chain + first = false; + + over = true; + int remain = 65536 - MMU.timerReload[procnum][i]; + int ctr=0; + while(nds.timerCycle[procnum][i] <= nds_timer) { + nds.timerCycle[procnum][i] += (remain << MMU.timerMODE[procnum][i]); + ctr++; + } +#ifndef NDEBUG + if(ctr>1) { + printf("yikes!!!!! please report!\n"); + } +#endif + } + + if(over) + { + MMU.timer[procnum][i] = MMU.timerReload[procnum][i]; + if(T1ReadWord(regs, 0x102 + i*4) & 0x40) + { + NDS_makeIrq(procnum, IRQ_BIT_TIMER_0 + i); + } + } + else + break; //no more chained timers to trigger. we're done here + } + } +}; + +template struct TSequenceItem_DMA : public TSequenceItem +{ + DmaController* controller; + + FORCEINLINE bool isTriggered() + { + return (controller->dmaCheck && nds_timer>= controller->nextEvent); + } + + FORCEINLINE bool isEnabled() { + return controller->dmaCheck?TRUE:FALSE; + } + + FORCEINLINE u64 next() + { + return controller->nextEvent; + } + + FORCEINLINE void exec() + { + IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[5+procnum*4+chan]++); + + //if (nds.freezeBus) return; + + //printf("exec from TSequenceItem_DMA: %d %d\n",procnum,chan); + controller->exec(); +// //give gxfifo dmas a chance to re-trigger +// if(MMU.DMAStartTime[procnum][chan] == EDMAMode_GXFifo) { +// MMU.DMAing[procnum][chan] = FALSE; +// if (gxFIFO.size <= 127) +// { +// execHardware_doDma(procnum,chan,EDMAMode_GXFifo); +// if (MMU.DMACompleted[procnum][chan]) +// goto docomplete; +// else return; +// } +// } +// +//docomplete: +// if (MMU.DMACompleted[procnum][chan]) +// { +// u8* regs = procnum==0?MMU.ARM9_REG:MMU.ARM7_REG; +// +// //disable the channel +// if(MMU.DMAStartTime[procnum][chan] != EDMAMode_GXFifo) { +// T1WriteLong(regs, 0xB8 + (0xC*chan), T1ReadLong(regs, 0xB8 + (0xC*chan)) & 0x7FFFFFFF); +// MMU.DMACrt[procnum][chan] &= 0x7FFFFFFF; //blehhh i hate this shit being mirrored in memory +// } +// +// if((MMU.DMACrt[procnum][chan])&(1<<30)) { +// if(procnum==0) NDS_makeARM9Int(8+chan); +// else NDS_makeARM7Int(8+chan); +// } +// +// MMU.DMAing[procnum][chan] = FALSE; +// } + + } +}; + +struct TSequenceItem_divider : public TSequenceItem +{ + FORCEINLINE bool isTriggered() + { + return MMU.divRunning && nds_timer >= MMU.divCycles; + } + + bool isEnabled() { return MMU.divRunning!=0; } + + FORCEINLINE u64 next() + { + return MMU.divCycles; + } + + void exec() + { + IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[2]++); + MMU_new.div.busy = 0; +#ifdef _WIN64 + T1WriteQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A0, MMU.divResult); + T1WriteQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A8, MMU.divMod); +#else + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A0, (u32)MMU.divResult); + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A4, (u32)(MMU.divResult >> 32)); + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2A8, (u32)MMU.divMod); + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2AC, (u32)(MMU.divMod >> 32)); +#endif + MMU.divRunning = FALSE; + } + +}; + +struct TSequenceItem_sqrtunit : public TSequenceItem +{ + FORCEINLINE bool isTriggered() + { + return MMU.sqrtRunning && nds_timer >= MMU.sqrtCycles; + } + + bool isEnabled() { return MMU.sqrtRunning!=0; } + + FORCEINLINE u64 next() + { + return MMU.sqrtCycles; + } + + FORCEINLINE void exec() + { + IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[3]++); + MMU_new.sqrt.busy = 0; + T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2B4, MMU.sqrtResult); + MMU.sqrtRunning = FALSE; + } + +}; + +struct Sequencer +{ + bool nds_vblankEnded; + bool reschedule; + TSequenceItem dispcnt; + TSequenceItem wifi; + TSequenceItem_divider divider; + TSequenceItem_sqrtunit sqrtunit; + TSequenceItem_GXFIFO gxfifo; + TSequenceItem_DMA<0,0> dma_0_0; TSequenceItem_DMA<0,1> dma_0_1; + TSequenceItem_DMA<0,2> dma_0_2; TSequenceItem_DMA<0,3> dma_0_3; + TSequenceItem_DMA<1,0> dma_1_0; TSequenceItem_DMA<1,1> dma_1_1; + TSequenceItem_DMA<1,2> dma_1_2; TSequenceItem_DMA<1,3> dma_1_3; + TSequenceItem_Timer<0,0> timer_0_0; TSequenceItem_Timer<0,1> timer_0_1; + TSequenceItem_Timer<0,2> timer_0_2; TSequenceItem_Timer<0,3> timer_0_3; + TSequenceItem_Timer<1,0> timer_1_0; TSequenceItem_Timer<1,1> timer_1_1; + TSequenceItem_Timer<1,2> timer_1_2; TSequenceItem_Timer<1,3> timer_1_3; + + void init(); + + void execHardware(); + u64 findNext(); + + void save(EMUFILE* os) + { + write64le(nds_timer,os); + write64le(nds_arm9_timer,os); + write64le(nds_arm7_timer,os); + dispcnt.save(os); + divider.save(os); + sqrtunit.save(os); + gxfifo.save(os); + wifi.save(os); +#define SAVE(I,X,Y) I##_##X##_##Y .save(os); + SAVE(timer,0,0); SAVE(timer,0,1); SAVE(timer,0,2); SAVE(timer,0,3); + SAVE(timer,1,0); SAVE(timer,1,1); SAVE(timer,1,2); SAVE(timer,1,3); + SAVE(dma,0,0); SAVE(dma,0,1); SAVE(dma,0,2); SAVE(dma,0,3); + SAVE(dma,1,0); SAVE(dma,1,1); SAVE(dma,1,2); SAVE(dma,1,3); +#undef SAVE + } + + bool load(EMUFILE* is, int version) + { + if(read64le(&nds_timer,is) != 1) return false; + if(read64le(&nds_arm9_timer,is) != 1) return false; + if(read64le(&nds_arm7_timer,is) != 1) return false; + if(!dispcnt.load(is)) return false; + if(!divider.load(is)) return false; + if(!sqrtunit.load(is)) return false; + if(!gxfifo.load(is)) return false; + if(version >= 1) if(!wifi.load(is)) return false; +#define LOAD(I,X,Y) if(!I##_##X##_##Y .load(is)) return false; + LOAD(timer,0,0); LOAD(timer,0,1); LOAD(timer,0,2); LOAD(timer,0,3); + LOAD(timer,1,0); LOAD(timer,1,1); LOAD(timer,1,2); LOAD(timer,1,3); + LOAD(dma,0,0); LOAD(dma,0,1); LOAD(dma,0,2); LOAD(dma,0,3); + LOAD(dma,1,0); LOAD(dma,1,1); LOAD(dma,1,2); LOAD(dma,1,3); +#undef LOAD + + return true; + } + +} sequencer; + +void NDS_RescheduleGXFIFO(u32 cost) +{ + if(!sequencer.gxfifo.enabled) { + MMU.gfx3dCycles = nds_timer; + sequencer.gxfifo.enabled = true; + } + MMU.gfx3dCycles += cost; + NDS_Reschedule(); +} + +void NDS_RescheduleTimers() +{ +#define check(X,Y) sequencer.timer_##X##_##Y .schedule(); + check(0,0); check(0,1); check(0,2); check(0,3); + check(1,0); check(1,1); check(1,2); check(1,3); +#undef check + + NDS_Reschedule(); +} + +void NDS_RescheduleDMA() +{ + //TBD + NDS_Reschedule(); + +} + +static void initSchedule() +{ + sequencer.init(); + + //begin at the very end of the last scanline + //so that at t=0 we can increment to scanline=0 + nds.VCount = 262; + + sequencer.nds_vblankEnded = false; +} + + +// 2196372 ~= (ARM7_CLOCK << 16) / 1000000 +// This value makes more sense to me, because: +// ARM7_CLOCK = 33.51 mhz +// = 33513982 cycles per second +// = 33.513982 cycles per microsecond +const u64 kWifiCycles = 67;//34*2; +//(this isn't very precise. I don't think it needs to be) + +void Sequencer::init() +{ + NDS_RescheduleTimers(); + NDS_RescheduleDMA(); + + reschedule = false; + nds_timer = 0; + nds_arm9_timer = 0; + nds_arm7_timer = 0; + + dispcnt.enabled = true; + dispcnt.param = ESI_DISPCNT_HStart; + dispcnt.timestamp = 0; + + gxfifo.enabled = false; + + dma_0_0.controller = &MMU_new.dma[0][0]; + dma_0_1.controller = &MMU_new.dma[0][1]; + dma_0_2.controller = &MMU_new.dma[0][2]; + dma_0_3.controller = &MMU_new.dma[0][3]; + dma_1_0.controller = &MMU_new.dma[1][0]; + dma_1_1.controller = &MMU_new.dma[1][1]; + dma_1_2.controller = &MMU_new.dma[1][2]; + dma_1_3.controller = &MMU_new.dma[1][3]; + + + #ifdef EXPERIMENTAL_WIFI_COMM + wifi.enabled = true; + wifi.timestamp = kWifiCycles; + #else + wifi.enabled = false; + #endif +} + +//this isnt helping much right now. work on it later +//#include "utils/task.h" +//Task taskSubGpu(true); +//void* renderSubScreen(void*) +//{ +// GPU_RenderLine(&SubScreen, nds.VCount, SkipCur2DFrame); +// return NULL; +//} + +static void execHardware_hblank() +{ + //this logic keeps moving around. + //now, we try and give the game as much time as possible to finish doing its work for the scanline, + //by drawing scanline N at the end of drawing time (but before subsequent interrupt or hdma-driven events happen) + //don't try to do this at the end of the scanline, because some games (sonic classics) may use hblank IRQ to set + //scroll regs for the next scanline + if(nds.VCount<192) + { + //taskSubGpu.execute(renderSubScreen,NULL); + GPU_RenderLine(&MainScreen, nds.VCount, frameSkipper.ShouldSkip2D()); + GPU_RenderLine(&SubScreen, nds.VCount, frameSkipper.ShouldSkip2D()); + //taskSubGpu.finish(); + + //trigger hblank dmas + //but notice, we do that just after we finished drawing the line + //(values copied by this hdma should not be used until the next scanline) + triggerDma(EDMAMode_HBlank); + } + + if(nds.VCount==262) + { + //we need to trigger one last hblank dma since + //a. we're sort of lagged behind by one scanline + //b. i think that 193 hblanks actually fire (one for the hblank in scanline 262) + //this is demonstrated by NSMB splot-parallaxing clouds + //for some reason the game will setup two hdma scroll register buffers + //to be run consecutively, and unless we do this, the second buffer will be offset by one scanline + //causing a glitch in the 0th scanline + //triggerDma(EDMAMode_HBlank); + + //BUT! this was removed in order to make glitches in megaman zero collection (mmz 4 1st level) work. + //and, it seems that it is no longer necessary in nsmb. perhaps something else fixed it + } + + + //turn on hblank status bit + T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) | 2); + T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 2); + + //fire hblank interrupts if necessary + if(T1ReadWord(MMU.ARM9_REG, 4) & 0x10) NDS_makeIrq(ARMCPU_ARM9,IRQ_BIT_LCD_HBLANK); + if(T1ReadWord(MMU.ARM7_REG, 4) & 0x10) NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_LCD_HBLANK); + + //emulation housekeeping. for some reason we always do this at hblank, + //even though it sounds more reasonable to do it at hstart + SPU_Emulate_core(); + driver->AVI_SoundUpdate(SPU_core->outbuf,spu_core_samples); + WAV_WavSoundUpdate(SPU_core->outbuf,spu_core_samples); +} + +static void execHardware_hstart_vblankEnd() +{ + sequencer.nds_vblankEnded = true; + sequencer.reschedule = true; + + //turn off vblank status bit + T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) & ~1); + T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & ~1); + + //some emulation housekeeping + frameSkipper.Advance(); +} + +static void execHardware_hstart_vblankStart() +{ + //printf("--------VBLANK!!!--------\n"); + + //fire vblank interrupts if necessary + for(int i=0;i<2;i++) + if(MMU.reg_IF_pending[i] & (1<>8)|((vmatch<<1)&(1<<8))); + return vmatch; +} + +static void execHardware_hstart_vcount_irq() +{ + //trigger pending VMATCH irqs + if(MMU.reg_IF_pending[ARMCPU_ARM9] & (1<>8)|((vmatch<<1)&(1<<8))); + if(nds.VCount==vmatch) + { + //arm7 vmatch + T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 4); + if(T1ReadWord(MMU.ARM7_REG, 4) & 32) + MMU.reg_IF_pending[ARMCPU_ARM7] |= (1<> (32-1)) & (c^d)) ^ d); +} + +FORCEINLINE u64 _fast_min(u64 a, u64 b) +{ + //you might find that this is faster on a 64bit system; someone should try it + //http://aggregate.org/MAGIC/#Integer%20Selection + //u64 ret = (((((s64)(a-b)) >> (64-1)) & (a^b)) ^ b); + //assert(ret==min(a,b)); + //return ret; + + //but this ends up being the fastest on 32bits + return a>= 63; //no 64bit shra in sse2, what a disappointment + //temp = _mm_and_si128(temp,xorval); + //temp = _mm_xor_si128(temp,__b); + //return temp.m128i_u64[0]; +} + + + +u64 Sequencer::findNext() +{ + //this one is always enabled so dont bother to check it + u64 next = dispcnt.next(); + + if(divider.isEnabled()) next = _fast_min(next,divider.next()); + if(sqrtunit.isEnabled()) next = _fast_min(next,sqrtunit.next()); + if(gxfifo.enabled) next = _fast_min(next,gxfifo.next()); + +#ifdef EXPERIMENTAL_WIFI_COMM + next = _fast_min(next,wifi.next()); +#endif + +#define test(X,Y) if(dma_##X##_##Y .isEnabled()) next = _fast_min(next,dma_##X##_##Y .next()); + test(0,0); test(0,1); test(0,2); test(0,3); + test(1,0); test(1,1); test(1,2); test(1,3); +#undef test +#define test(X,Y) if(timer_##X##_##Y .enabled) next = _fast_min(next,timer_##X##_##Y .next()); + test(0,0); test(0,1); test(0,2); test(0,3); + test(1,0); test(1,1); test(1,2); test(1,3); +#undef test + + return next; +} + +void Sequencer::execHardware() +{ + if(dispcnt.isTriggered()) + { + + IF_DEVELOPER(DEBUG_statistics.sequencerExecutionCounters[1]++); + + switch(dispcnt.param) + { + case ESI_DISPCNT_HStart: + execHardware_hstart(); + //(used to be 3168) + //hstart is actually 8 dots before the visible drawing begins + //we're going to run 1 here and then run 7 in the next case + dispcnt.timestamp += 1*6*2; + dispcnt.param = ESI_DISPCNT_HStartIRQ; + break; + case ESI_DISPCNT_HStartIRQ: + execHardware_hstart_irq(); + dispcnt.timestamp += 7*6*2; + dispcnt.param = ESI_DISPCNT_HDraw; + break; + + case ESI_DISPCNT_HDraw: + execHardware_hdraw(); + //duration of non-blanking period is ~1606 clocks (gbatek agrees) [but says its different on arm7] + //im gonna call this 267 dots = 267*6=1602 + //so, this event lasts 267 dots minus the 8 dot preroll + dispcnt.timestamp += (267-8)*6*2; + dispcnt.param = ESI_DISPCNT_HBlank; + break; + + case ESI_DISPCNT_HBlank: + execHardware_hblank(); + //(once this was 1092 or 1092/12=91 dots.) + //there are surely 355 dots per scanline, less 267 for non-blanking period. the rest is hblank and then after that is hstart + dispcnt.timestamp += (355-267)*6*2; + dispcnt.param = ESI_DISPCNT_HStart; + break; + } + } + +#ifdef EXPERIMENTAL_WIFI_COMM + if(wifi.isTriggered()) + { + WIFI_usTrigger(); + wifi.timestamp += kWifiCycles; + } +#endif + + if(divider.isTriggered()) divider.exec(); + if(sqrtunit.isTriggered()) sqrtunit.exec(); + if(gxfifo.isTriggered()) gxfifo.exec(); + + +#define test(X,Y) if(dma_##X##_##Y .isTriggered()) dma_##X##_##Y .exec(); + test(0,0); test(0,1); test(0,2); test(0,3); + test(1,0); test(1,1); test(1,2); test(1,3); +#undef test +#define test(X,Y) if(timer_##X##_##Y .enabled) if(timer_##X##_##Y .isTriggered()) timer_##X##_##Y .exec(); + test(0,0); test(0,1); test(0,2); test(0,3); + test(1,0); test(1,1); test(1,2); test(1,3); +#undef test +} + +void execHardware_interrupts(); + +static void saveUserInput(EMUFILE* os); +static bool loadUserInput(EMUFILE* is, int version); + +void nds_savestate(EMUFILE* os) +{ + //version + write32le(3,os); + + sequencer.save(os); + + saveUserInput(os); + + write32le(LidClosed,os); + write8le(countLid,os); +} + +bool nds_loadstate(EMUFILE* is, int size) +{ + // this isn't part of the savestate loading logic, but + // don't skip the next frame after loading a savestate + frameSkipper.OmitSkip(true, true); + + //read version + u32 version; + if(read32le(&version,is) != 1) return false; + + if(version > 3) return false; + + bool temp = true; + temp &= sequencer.load(is, version); + if(version <= 1 || !temp) return temp; + temp &= loadUserInput(is, version); + + if(version < 3) return temp; + + read32le(&LidClosed,is); + read8le(&countLid,is); + + return temp; +} + +FORCEINLINE void arm9log() +{ +#ifdef LOG_ARM9 + if(dolog) + { + char dasmbuf[4096]; + if(NDS_ARM9.CPSR.bits.T) + des_thumb_instructions_set[((NDS_ARM9.instruction)>>6)&1023](NDS_ARM9.instruct_adr, NDS_ARM9.instruction, dasmbuf); + else + des_arm_instructions_set[INDEX(NDS_ARM9.instruction)](NDS_ARM9.instruct_adr, NDS_ARM9.instruction, dasmbuf); + +#ifdef LOG_TO_FILE + if (!fp_dis9) return; +#ifdef LOG_TO_FILE_REGS + fprintf(fp_dis9, "\t\t;R0:%08X R1:%08X R2:%08X R3:%08X R4:%08X R5:%08X R6:%08X R7:%08X R8:%08X R9:%08X\n\t\t;R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X| next %08X, N:%i Z:%i C:%i V:%i\n", + NDS_ARM9.R[0], NDS_ARM9.R[1], NDS_ARM9.R[2], NDS_ARM9.R[3], NDS_ARM9.R[4], NDS_ARM9.R[5], NDS_ARM9.R[6], NDS_ARM9.R[7], + NDS_ARM9.R[8], NDS_ARM9.R[9], NDS_ARM9.R[10], NDS_ARM9.R[11], NDS_ARM9.R[12], NDS_ARM9.R[13], NDS_ARM9.R[14], NDS_ARM9.R[15], + NDS_ARM9.next_instruction, NDS_ARM9.CPSR.bits.N, NDS_ARM9.CPSR.bits.Z, NDS_ARM9.CPSR.bits.C, NDS_ARM9.CPSR.bits.V); +#endif + fprintf(fp_dis9, "%s %08X\t%08X \t%s\n", NDS_ARM9.CPSR.bits.T?"THUMB":"ARM", NDS_ARM9.instruct_adr, NDS_ARM9.instruction, dasmbuf); + /*if (NDS_ARM9.instruction == 0) + { + dolog = false; + INFO("Disassembler is stopped\n"); + }*/ +#else + printf("%05d:%03d %12lld 9:%08X %08X %-30s R00:%08X R01:%08X R02:%08X R03:%08X R04:%08X R05:%08X R06:%08X R07:%08X R08:%08X R09:%08X R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X\n", + currFrameCounter, nds.VCount, nds_timer, + NDS_ARM9.instruct_adr,NDS_ARM9.instruction, dasmbuf, + NDS_ARM9.R[0], NDS_ARM9.R[1], NDS_ARM9.R[2], NDS_ARM9.R[3], NDS_ARM9.R[4], NDS_ARM9.R[5], NDS_ARM9.R[6], NDS_ARM9.R[7], + NDS_ARM9.R[8], NDS_ARM9.R[9], NDS_ARM9.R[10], NDS_ARM9.R[11], NDS_ARM9.R[12], NDS_ARM9.R[13], NDS_ARM9.R[14], NDS_ARM9.R[15]); +#endif + } +#endif +} + +FORCEINLINE void arm7log() +{ +#ifdef LOG_ARM7 + if(dolog) + { + char dasmbuf[4096]; + if(NDS_ARM7.CPSR.bits.T) + des_thumb_instructions_set[((NDS_ARM7.instruction)>>6)&1023](NDS_ARM7.instruct_adr, NDS_ARM7.instruction, dasmbuf); + else + des_arm_instructions_set[INDEX(NDS_ARM7.instruction)](NDS_ARM7.instruct_adr, NDS_ARM7.instruction, dasmbuf); +#ifdef LOG_TO_FILE + if (!fp_dis7) return; +#ifdef LOG_TO_FILE_REGS + fprintf(fp_dis7, "\t\t;R0:%08X R1:%08X R2:%08X R3:%08X R4:%08X R5:%08X R6:%08X R7:%08X R8:%08X R9:%08X\n\t\t;R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X| next %08X, N:%i Z:%i C:%i V:%i\n", + NDS_ARM7.R[0], NDS_ARM7.R[1], NDS_ARM7.R[2], NDS_ARM7.R[3], NDS_ARM7.R[4], NDS_ARM7.R[5], NDS_ARM7.R[6], NDS_ARM7.R[7], + NDS_ARM7.R[8], NDS_ARM7.R[9], NDS_ARM7.R[10], NDS_ARM7.R[11], NDS_ARM7.R[12], NDS_ARM7.R[13], NDS_ARM7.R[14], NDS_ARM7.R[15], + NDS_ARM7.next_instruction, NDS_ARM7.CPSR.bits.N, NDS_ARM7.CPSR.bits.Z, NDS_ARM7.CPSR.bits.C, NDS_ARM7.CPSR.bits.V); +#endif + fprintf(fp_dis7, "%s %08X\t%08X \t%s\n", NDS_ARM7.CPSR.bits.T?"THUMB":"ARM", NDS_ARM7.instruct_adr, NDS_ARM7.instruction, dasmbuf); + /*if (NDS_ARM7.instruction == 0) + { + dolog = false; + INFO("Disassembler is stopped\n"); + }*/ +#else + printf("%05d:%03d %12lld 7:%08X %08X %-30s R00:%08X R01:%08X R02:%08X R03:%08X R04:%08X R05:%08X R06:%08X R07:%08X R08:%08X R09:%08X R10:%08X R11:%08X R12:%08X R13:%08X R14:%08X R15:%08X\n", + currFrameCounter, nds.VCount, nds_timer, + NDS_ARM7.instruct_adr,NDS_ARM7.instruction, dasmbuf, + NDS_ARM7.R[0], NDS_ARM7.R[1], NDS_ARM7.R[2], NDS_ARM7.R[3], NDS_ARM7.R[4], NDS_ARM7.R[5], NDS_ARM7.R[6], NDS_ARM7.R[7], + NDS_ARM7.R[8], NDS_ARM7.R[9], NDS_ARM7.R[10], NDS_ARM7.R[11], NDS_ARM7.R[12], NDS_ARM7.R[13], NDS_ARM7.R[14], NDS_ARM7.R[15]); +#endif + } +#endif +} + +//these have not been tuned very well yet. +static const int kMaxWork = 4000; +static const int kIrqWait = 4000; + + +template +static FORCEINLINE s32 minarmtime(s32 arm9, s32 arm7) +{ + if(doarm9) + if(doarm7) + return min(arm9,arm7); + else + return arm9; + else + return arm7; +} + +template +static /*donotinline*/ std::pair armInnerLoop( + const u64 nds_timer_base, const s32 s32next, s32 arm9, s32 arm7) +{ + s32 timer = minarmtime(arm9,arm7); + while(timer < s32next && !sequencer.reschedule && execute) + { + if(doarm9 && (!doarm7 || arm9 <= timer)) + { + if(!NDS_ARM9.waitIRQ&&!nds.freezeBus) + { + arm9log(); + debug(); + arm9 += armcpu_exec(); + #ifdef DEVELOPER + nds_debug_continuing[0] = false; + #endif + } + else + { + s32 temp = arm9; + arm9 = min(s32next, arm9 + kIrqWait); + nds.idleCycles[0] += arm9-temp; + if (gxFIFO.size < 255) nds.freezeBus &= ~1; + } + } + if(doarm7 && (!doarm9 || arm7 <= timer)) + { + if(!NDS_ARM7.waitIRQ&&!nds.freezeBus) + { + arm7log(); + arm7 += (armcpu_exec()<<1); + #ifdef DEVELOPER + nds_debug_continuing[1] = false; + #endif + } + else + { + s32 temp = arm7; + arm7 = min(s32next, arm7 + kIrqWait); + nds.idleCycles[1] += arm7-temp; + if(arm7 == s32next) + { + nds_timer = nds_timer_base + minarmtime(arm9,arm7); + return armInnerLoop(nds_timer_base, s32next, arm9, arm7); + } + } + } + + timer = minarmtime(arm9,arm7); + nds_timer = nds_timer_base + timer; + } + + return std::make_pair(arm9, arm7); +} + +void NDS_debug_break() +{ + NDS_ARM9.stalled = NDS_ARM7.stalled = 1; + + //triggers an immediate exit from the cpu loop + NDS_Reschedule(); +} + +void NDS_debug_continue() +{ + NDS_ARM9.stalled = NDS_ARM7.stalled = 0; +} + +void NDS_debug_step() +{ + NDS_debug_continue(); + singleStep = true; +} + +template +void NDS_exec(s32 nb) +{ + LagFrameFlag=1; + + if((currFrameCounter&63) == 0) + MMU_new.backupDevice.lazy_flush(); + + sequencer.nds_vblankEnded = false; + + nds.cpuloopIterationCount = 0; + + IF_DEVELOPER(for(int i=0;i<32;i++) DEBUG_statistics.sequencerExecutionCounters[i] = 0); + + if(nds.sleeping) + { + //speculative code: if ANY irq happens, wake up the arm7. + //I think the arm7 program analyzes the system and may decide not to wake up + //if it is dissatisfied with the conditions + if((MMU.reg_IE[1] & MMU.gen_IF<1>())) + { + nds.sleeping = FALSE; + } + } + else + { + for(;;) + { + //trap the debug-stalled condition + #ifdef DEVELOPER + singleStep = false; + //(gdb stub doesnt yet know how to trigger these immediately by calling reschedule) + while((NDS_ARM9.stalled || NDS_ARM7.stalled) && execute) + { + driver->EMU_DebugIdleUpdate(); + nds_debug_continuing[0] = nds_debug_continuing[1] = true; + } + #endif + + nds.cpuloopIterationCount++; + sequencer.execHardware(); + + //break out once per frame + if(sequencer.nds_vblankEnded) break; + //it should be benign to execute execHardware in the next frame, + //since there won't be anything for it to do (everything should be scheduled in the future) + + //bail in case the system halted + if(!execute) break; + + execHardware_interrupts(); + + //find next work unit: + u64 next = sequencer.findNext(); + next = min(next,nds_timer+kMaxWork); //lets set an upper limit for now + + //printf("%d\n",(next-nds_timer)); + + sequencer.reschedule = false; + + //cast these down to 32bits so that things run faster on 32bit procs + u64 nds_timer_base = nds_timer; + s32 arm9 = (s32)(nds_arm9_timer-nds_timer); + s32 arm7 = (s32)(nds_arm7_timer-nds_timer); + s32 s32next = (s32)(next-nds_timer); + + #ifdef DEVELOPER + if(singleStep) + { + s32next = 1; + } + #endif + + std::pair arm9arm7 = armInnerLoop(nds_timer_base,s32next,arm9,arm7); + + #ifdef DEVELOPER + if(singleStep) + { + NDS_ARM9.stalled = NDS_ARM7.stalled = 1; + } + #endif + + arm9 = arm9arm7.first; + arm7 = arm9arm7.second; + nds_arm7_timer = nds_timer_base+arm7; + nds_arm9_timer = nds_timer_base+arm9; + +#ifndef NDEBUG + //what we find here is dependent on the timing constants above + //if(nds_timer>next && (nds_timer-next)>22) + // printf("curious. please report: over by %d\n",(int)(nds_timer-next)); +#endif + + //if we were waiting for an irq, don't wait too long: + //let's re-analyze it after this hardware event (this rolls back a big burst of irq waiting which may have been interrupted by a resynch) + if(NDS_ARM9.waitIRQ) + { + nds.idleCycles[0] -= (s32)(nds_arm9_timer-nds_timer); + nds_arm9_timer = nds_timer; + } + if(NDS_ARM7.waitIRQ) + { + nds.idleCycles[1] -= (s32)(nds_arm7_timer-nds_timer); + nds_arm7_timer = nds_timer; + } + } + } + + //DEBUG_statistics.printSequencerExecutionCounters(); + //DEBUG_statistics.print(); + + //end of frame emulation housekeeping + if(LagFrameFlag) + { + lagframecounter++; + TotalLagFrames++; + } + else + { + lastLag = lagframecounter; + lagframecounter = 0; + } + currFrameCounter++; + DEBUG_Notify.NextFrame(); + if (cheats) + cheats->process(); +} + +template static void execHardware_interrupts_core() +{ + u32 IF = MMU.gen_IF(); + u32 IE = MMU.reg_IE[PROCNUM]; + u32 masked = IF & IE; + if(ARMPROC.halt_IE_and_IF && masked) + { + ARMPROC.halt_IE_and_IF = FALSE; + ARMPROC.waitIRQ = FALSE; + } + + if(masked && MMU.reg_IME[PROCNUM] && !ARMPROC.CPSR.bits.I) + { + //printf("Executing IRQ on procnum %d with IF = %08X and IE = %08X\n",PROCNUM,IF,IE); + armcpu_irqException(&ARMPROC); + } +} + +void execHardware_interrupts() +{ + execHardware_interrupts_core(); + execHardware_interrupts_core(); +} + +static void resetUserInput(); + +bool _HACK_DONT_STOPMOVIE = false; +void NDS_Reset() +{ + singleStep = false; + nds_debug_continuing[0] = nds_debug_continuing[1] = false; + u32 src = 0; + u32 dst = 0; + bool fw_success = false; + FILE* inf = NULL; + NDS_header * header = NDS_getROMHeader(); + + DEBUG_reset(); + + if (!header) return ; + + nds.sleeping = FALSE; + nds.cardEjected = FALSE; + nds.freezeBus = 0; + nds.power1.lcd = nds.power1.gpuMain = nds.power1.gfx3d_render = nds.power1.gfx3d_geometry = nds.power1.gpuSub = nds.power1.dispswap = 1; + nds.power2.speakers = 1; + nds.power2.wifi = 0; + + nds_timer = 0; + nds_arm9_timer = 0; + nds_arm7_timer = 0; + + if(movieMode != MOVIEMODE_INACTIVE && !_HACK_DONT_STOPMOVIE) + movie_reset_command = true; + + if(movieMode == MOVIEMODE_INACTIVE) { + currFrameCounter = 0; + lagframecounter = 0; + LagFrameFlag = 0; + lastLag = 0; + TotalLagFrames = 0; + } + + SPU_DeInit(); + + MMU_Reset(); + + + //put random garbage in vram for homebrew games, to help mimic the situation where libnds does not clear out junk + //which the card's launcher may or may not have left behind + //1. retail games dont clear TCM, so why should we jumble it and expect homebrew to clear it? + //2. some retail games _dont boot_ if main memory is jumbled. wha...? + //3. clearing this is not as useful as tracking uninitialized reads in dev+ builds + //4. the vram clearing causes lots of graphical corruptions in badly coded homebrews. this reduces compatibility substantially + //conclusion: disable it for now and bring it back as an option + //if(gameInfo.isHomebrew) + //{ + // u32 w=100000,x=99,y=117,z=19382173; + // CTASSERT(sizeof(MMU.ARM9_LCD) < sizeof(MMU.MAIN_MEM)); + // CTASSERT(sizeof(MMU.ARM9_VMEM) < sizeof(MMU.MAIN_MEM)); + // CTASSERT(sizeof(MMU.ARM9_ITCM) < sizeof(MMU.MAIN_MEM)); + // CTASSERT(sizeof(MMU.ARM9_DTCM) < sizeof(MMU.MAIN_MEM)); + // for(int i=0;i>19))^(t^(t>>8))); + // //MMU.MAIN_MEM[i] = t; + // if (i(0x00002F08, 0x4770); + + INFO("ARM7 BIOS is %s.\n", NDS_ARM7.BIOS_loaded?"loaded":"failed"); + } + else + { + NDS_ARM7.swi_tab = ARM7_swi_tab; + +#if 0 + // TODO + T1WriteLong(MMU.ARM7_BIOS, 0x0000, 0xEAFFFFFE); // loop for Reset !!! + T1WriteLong(MMU.ARM7_BIOS, 0x0004, 0xEAFFFFFE); // loop for Undef instr expection + T1WriteLong(MMU.ARM7_BIOS, 0x0008, 0xEA00009C); // SWI + T1WriteLong(MMU.ARM7_BIOS, 0x000C, 0xEAFFFFFE); // loop for Prefetch Abort + T1WriteLong(MMU.ARM7_BIOS, 0x0010, 0xEAFFFFFE); // loop for Data Abort + T1WriteLong(MMU.ARM7_BIOS, 0x0014, 0x00000000); // Reserved + T1WriteLong(MMU.ARM7_BIOS, 0x001C, 0x00000000); // Fast IRQ +#endif + T1WriteLong(MMU.ARM7_BIOS, 0x0000, 0xE25EF002); + T1WriteLong(MMU.ARM7_BIOS, 0x0018, 0xEA000000); + T1WriteLong(MMU.ARM7_BIOS, 0x0020, 0xE92D500F); + T1WriteLong(MMU.ARM7_BIOS, 0x0024, 0xE3A00301); + T1WriteLong(MMU.ARM7_BIOS, 0x0028, 0xE28FE000); + T1WriteLong(MMU.ARM7_BIOS, 0x002C, 0xE510F004); + T1WriteLong(MMU.ARM7_BIOS, 0x0030, 0xE8BD500F); + T1WriteLong(MMU.ARM7_BIOS, 0x0034, 0xE25EF004); + } + + //ARM9 BIOS IRQ HANDLER + if(CommonSettings.UseExtBIOS == true) + inf = fopen(CommonSettings.ARM9BIOS,"rb"); + else + inf = NULL; + + if(inf) + { + if (fread(MMU.ARM9_BIOS,1,4096,inf) == 4096) NDS_ARM9.BIOS_loaded = true; + fclose(inf); + + if((CommonSettings.SWIFromBIOS) && (NDS_ARM9.BIOS_loaded)) NDS_ARM9.swi_tab = 0; + else NDS_ARM9.swi_tab = ARM9_swi_tab; + + if (CommonSettings.PatchSWI3) + _MMU_write16(0xFFFF07CC, 0x4770); + + INFO("ARM9 BIOS is %s.\n", NDS_ARM9.BIOS_loaded?"loaded":"failed"); + } + else + { + NDS_ARM9.swi_tab = ARM9_swi_tab; + + //bios chains data abort to fast irq + + //exception vectors: + T1WriteLong(MMU.ARM9_BIOS, 0x0000, 0xEAFFFFFE); // (infinite loop for) Reset !!! + //T1WriteLong(MMU.ARM9_BIOS, 0x0004, 0xEAFFFFFE); // (infinite loop for) Undefined instruction + T1WriteLong(MMU.ARM9_BIOS, 0x0004, 0xEA000004); // Undefined instruction -> Fast IRQ (just guessing) + T1WriteLong(MMU.ARM9_BIOS, 0x0008, 0xEA00009C); // SWI -> ????? + T1WriteLong(MMU.ARM9_BIOS, 0x000C, 0xEAFFFFFE); // (infinite loop for) Prefetch Abort + T1WriteLong(MMU.ARM9_BIOS, 0x0010, 0xEA000001); // Data Abort -> Fast IRQ + T1WriteLong(MMU.ARM9_BIOS, 0x0014, 0x00000000); // Reserved + T1WriteLong(MMU.ARM9_BIOS, 0x0018, 0xEA000095); // Normal IRQ -> 0x0274 + T1WriteLong(MMU.ARM9_BIOS, 0x001C, 0xEA00009D); // Fast IRQ -> 0x0298 + + // logo (do some games fail to boot without this? example?) + for (int t = 0; t < 0x9C; t++) + MMU.ARM9_BIOS[t + 0x20] = logo_data[t]; + + //...0xBC: + + //(now what goes in this gap??) + + //IRQ handler: get dtcm address and jump to a vector in it + T1WriteLong(MMU.ARM9_BIOS, 0x0274, 0xE92D500F); //STMDB SP!, {R0-R3,R12,LR} + T1WriteLong(MMU.ARM9_BIOS, 0x0278, 0xEE190F11); //MRC CP15, 0, R0, CR9, CR1, 0 + T1WriteLong(MMU.ARM9_BIOS, 0x027C, 0xE1A00620); //MOV R0, R0, LSR #C + T1WriteLong(MMU.ARM9_BIOS, 0x0280, 0xE1A00600); //MOV R0, R0, LSL #C + T1WriteLong(MMU.ARM9_BIOS, 0x0284, 0xE2800C40); //ADD R0, R0, #4000 + T1WriteLong(MMU.ARM9_BIOS, 0x0288, 0xE28FE000); //ADD LR, PC, #0 + T1WriteLong(MMU.ARM9_BIOS, 0x028C, 0xE510F004); //LDR PC, [R0, -#4] + + //???? + T1WriteLong(MMU.ARM9_BIOS, 0x0290, 0xE8BD500F); //LDMIA SP!, {R0-R3,R12,LR} + T1WriteLong(MMU.ARM9_BIOS, 0x0294, 0xE25EF004); //SUBS PC, LR, #4 + + //------- + //FIQ and abort exception handler + //TODO - this code is copied from the bios. refactor it + //friendly reminder: to calculate an immediate offset: encoded = (desired_address-cur_address-8) + + T1WriteLong(MMU.ARM9_BIOS, 0x0298, 0xE10FD000); //MRS SP, CPSR + T1WriteLong(MMU.ARM9_BIOS, 0x029C, 0xE38DD0C0); //ORR SP, SP, #C0 + + T1WriteLong(MMU.ARM9_BIOS, 0x02A0, 0xE12FF00D); //MSR CPSR_fsxc, SP + T1WriteLong(MMU.ARM9_BIOS, 0x02A4, 0xE59FD000 | (0x2D4-0x2A4-8)); //LDR SP, [FFFF02D4] + T1WriteLong(MMU.ARM9_BIOS, 0x02A8, 0xE28DD001); //ADD SP, SP, #1 + T1WriteLong(MMU.ARM9_BIOS, 0x02AC, 0xE92D5000); //STMDB SP!, {R12,LR} + + T1WriteLong(MMU.ARM9_BIOS, 0x02B0, 0xE14FE000); //MRS LR, SPSR + T1WriteLong(MMU.ARM9_BIOS, 0x02B4, 0xEE11CF10); //MRC CP15, 0, R12, CR1, CR0, 0 + T1WriteLong(MMU.ARM9_BIOS, 0x02B8, 0xE92D5000); //STMDB SP!, {R12,LR} + T1WriteLong(MMU.ARM9_BIOS, 0x02BC, 0xE3CCC001); //BIC R12, R12, #1 + + T1WriteLong(MMU.ARM9_BIOS, 0x02C0, 0xEE01CF10); //MCR CP15, 0, R12, CR1, CR0, 0 + T1WriteLong(MMU.ARM9_BIOS, 0x02C4, 0xE3CDC001); //BIC R12, SP, #1 + T1WriteLong(MMU.ARM9_BIOS, 0x02C8, 0xE59CC010); //LDR R12, [R12, #10] + T1WriteLong(MMU.ARM9_BIOS, 0x02CC, 0xE35C0000); //CMP R12, #0 + + T1WriteLong(MMU.ARM9_BIOS, 0x02D0, 0x112FFF3C); //BLXNE R12 + T1WriteLong(MMU.ARM9_BIOS, 0x02D4, 0x027FFD9C); //0x027FFD9C + //--------- + + } + +#ifdef LOG_ARM7 + if (fp_dis7 != NULL) + { + fclose(fp_dis7); + fp_dis7 = NULL; + } + fp_dis7 = fopen("D:\\desmume_dis7.asm", "w"); +#endif + +#ifdef LOG_ARM9 + if (fp_dis9 != NULL) + { + fclose(fp_dis9); + fp_dis9 = NULL; + } + fp_dis9 = fopen("D:\\desmume_dis9.asm", "w"); +#endif + + if (firmware) + { + delete firmware; + firmware = NULL; + } + firmware = new CFIRMWARE(); + fw_success = firmware->load(); + if (NDS_ARM7.BIOS_loaded && NDS_ARM9.BIOS_loaded && CommonSettings.BootFromFirmware && fw_success) + { + // Copy secure area to memory if needed + if ((header->ARM9src >= 0x4000) && (header->ARM9src < 0x8000)) + { + src = header->ARM9src; + dst = header->ARM9cpy; + + u32 size = (0x8000 - src) >> 2; + //INFO("Copy secure area from 0x%08X to 0x%08X (size %i/0x%08X)\n", src, dst, size, size); + for (u32 i = 0; i < size; i++) + { + _MMU_write32(dst, T1ReadLong(MMU.CART_ROM, src)); + src += 4; dst += 4; + } + } + + if (firmware->patched) + { + armcpu_init(&NDS_ARM7, 0x00000008); + armcpu_init(&NDS_ARM9, 0xFFFF0008); + } + else + { + //INFO("Booting at ARM9: 0x%08X, ARM7: 0x%08X\n", firmware->ARM9bootAddr, firmware->ARM7bootAddr); + // need for firmware + //armcpu_init(&NDS_ARM7, 0x00000008); + //armcpu_init(&NDS_ARM9, 0xFFFF0008); + armcpu_init(&NDS_ARM7, firmware->ARM7bootAddr); + armcpu_init(&NDS_ARM9, firmware->ARM9bootAddr); + } + + _MMU_write08(0x04000300, 0); + _MMU_write08(0x04000300, 0); + } + else + { + src = header->ARM9src; + dst = header->ARM9cpy; + + for(u32 i = 0; i < (header->ARM9binSize>>2); ++i) + { + _MMU_write32(dst, T1ReadLong(MMU.CART_ROM, src)); + dst += 4; + src += 4; + } + + src = header->ARM7src; + dst = header->ARM7cpy; + + for(u32 i = 0; i < (header->ARM7binSize>>2); ++i) + { + _MMU_write32(dst, T1ReadLong(MMU.CART_ROM, src)); + dst += 4; + src += 4; + } + + armcpu_init(&NDS_ARM7, header->ARM7exe); + armcpu_init(&NDS_ARM9, header->ARM9exe); + + _MMU_write08(REG_POSTFLG, 1); + _MMU_write08(REG_POSTFLG, 1); + } + //bitbox 4k demo is so stripped down it relies on default stack values + //otherwise the arm7 will crash before making a sound + //(these according to gbatek softreset bios docs) + NDS_ARM7.R13_svc = 0x0380FFDC; + NDS_ARM7.R13_irq = 0x0380FFB0; + NDS_ARM7.R13_usr = 0x0380FF00; + NDS_ARM7.R[13] = NDS_ARM7.R13_usr; + //and let's set these for the arm9 while we're at it, though we have no proof + NDS_ARM9.R13_svc = 0x00803FC0; + NDS_ARM9.R13_irq = 0x00803FA0; + NDS_ARM9.R13_usr = 0x00803EC0; + NDS_ARM9.R13_abt = NDS_ARM9.R13_usr; //????? + //I think it is wrong to take gbatek's "SYS" and put it in USR--maybe USR doesnt matter. + //i think SYS is all the misc modes. please verify by setting nonsensical stack values for USR here + NDS_ARM9.R[13] = NDS_ARM9.R13_usr; + //n.b.: im not sure about all these, I dont know enough about arm9 svc/irq/etc modes + //and how theyre named in desmume to match them up correctly. i just guessed. + + nds.wifiCycle = 0; + memset(nds.timerCycle, 0, sizeof(u64) * 2 * 4); + nds.old = 0; + nds.scr_touchX = nds.scr_touchY = nds.adc_touchX = nds.adc_touchY = 0; + nds.isTouch = 0; + nds.paddle = 0; + nds.ConsoleType = CommonSettings.ConsoleType; + nds._DebugConsole = CommonSettings.DebugConsole; + nds.ensataEmulation = CommonSettings.EnsataEmulation; + nds.ensataHandshake = ENSATA_HANDSHAKE_none; + nds.ensataIpcSyncCounter = 0; + SetupMMU(nds.Is_DebugConsole(),nds.Is_DSI()); + + _MMU_write16(REG_KEYINPUT, 0x3FF); + _MMU_write16(REG_KEYINPUT, 0x3FF); + _MMU_write08(REG_EXTKEYIN, 0x43); + + LidClosed = FALSE; + countLid = 0; + + resetUserInput(); + + //Setup a copy of the firmware user settings in memory. + //(this is what the DS firmware would do). + { + u8 temp_buffer[NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT]; + int fw_index; + + if ( copy_firmware_user_data( temp_buffer, MMU.fw.data)) { + for ( fw_index = 0; fw_index < NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT; fw_index++) + _MMU_write08(0x027FFC80 + fw_index, temp_buffer[fw_index]); + } + } + + // Copy the whole header to Main RAM 0x27FFE00 on startup. (http://nocash.emubase.de/gbatek.htm#dscartridgeheader) + //once upon a time this copied 0x90 more. this was thought to be wrong, and changed. + if(nds.Is_DSI()) + { + //dsi needs this copied later in memory. there are probably a number of things that get copied to a later location in memory.. thats where the NDS consoles tend to stash stuff. + for (int i = 0; i < ((0x170)/4); i++) + _MMU_write32(0x02FFFE00+i*4, LE_TO_LOCAL_32(((u32*)MMU.CART_ROM)[i])); + } + else + { + for (int i = 0; i < ((0x170)/4); i++) + _MMU_write32(0x027FFE00+i*4, LE_TO_LOCAL_32(((u32*)MMU.CART_ROM)[i])); + } + + + // Write the header checksum to memory (the firmware needs it to see the cart) + _MMU_write16(0x027FF808, T1ReadWord(MMU.CART_ROM, 0x15E)); + + //-------------------------------- + //setup the homebrew argv + //this is useful for nitrofs apps which are emulating themselves via cflash + //struct __argv { + // int argvMagic; //!< argv magic number, set to 0x5f617267 ('_arg') if valid + // char *commandLine; //!< base address of command line, set of null terminated strings + // int length; //!< total length of command line + // int argc; //!< internal use, number of arguments + // char **argv; //!< internal use, argv pointer + //}; + std::string rompath = "fat:/" + path.RomName; + const u32 kCommandline = 0x027E0000; + //const u32 kCommandline = 0x027FFF84; + + // + _MMU_write32(0x02FFFE70, 0x5f617267); + _MMU_write32(0x02FFFE74, kCommandline); //(commandline starts here) + _MMU_write32(0x02FFFE78, rompath.size()+1); + //0x027FFF7C (argc) + //0x027FFF80 (argv) + for(size_t i=0;i(kCommandline+i, rompath[i]); + _MMU_write08(kCommandline+rompath.size(), 0); + //-------------------------------- + + if ((firmware->patched) && (CommonSettings.UseExtBIOS == true) && (CommonSettings.BootFromFirmware == true) && (fw_success == TRUE)) + { + // HACK! for flashme + _MMU_write32(0x27FFE24, firmware->ARM9bootAddr); + _MMU_write32(0x27FFE34, firmware->ARM7bootAddr); + } + + // make system think it's booted from card -- EXTREMELY IMPORTANT!!! Thanks to cReDiAr + _MMU_write08(0x02FFFC40,0x1); + _MMU_write08(0x02FFFC40,0x1); + + // Save touchscreen calibration info in a structure + // so we can easily access it at any time + TSCal.adc.x1 = _MMU_read16(0x027FFC80 + 0x58); + TSCal.adc.y1 = _MMU_read16(0x027FFC80 + 0x5A); + TSCal.scr.x1 = _MMU_read08(0x027FFC80 + 0x5C); + TSCal.scr.y1 = _MMU_read08(0x027FFC80 + 0x5D); + TSCal.adc.x2 = _MMU_read16(0x027FFC80 + 0x5E); + TSCal.adc.y2 = _MMU_read16(0x027FFC80 + 0x60); + TSCal.scr.x2 = _MMU_read08(0x027FFC80 + 0x62); + TSCal.scr.y2 = _MMU_read08(0x027FFC80 + 0x63); + + TSCal.adc.width = (TSCal.adc.x2 - TSCal.adc.x1); + TSCal.adc.height = (TSCal.adc.y2 - TSCal.adc.y1); + TSCal.scr.width = (TSCal.scr.x2 - TSCal.scr.x1); + TSCal.scr.height = (TSCal.scr.y2 - TSCal.scr.y1); + + MainScreen.offset = 0; + SubScreen.offset = 192; + + //_MMU_write32[ARMCPU_ARM9](0x02007FFC, 0xE92D4030); + + delete header; + + Screen_Reset(); + gfx3d_reset(); + gpu3D->NDS_3D_Reset(); + slot1Reset(); + + WIFI_Reset(); + + memcpy(FW_Mac, (MMU.fw.data + 0x36), 6); + + initSchedule(); + + SPU_ReInit(); +} + +static std::string MakeInputDisplayString(u16 pad, const std::string* Buttons, int count) { + std::string s; + for (int x = 0; x < count; x++) { + if (pad & (1 << x)) + s.append(Buttons[x].size(), ' '); + else + s += Buttons[x]; + } + return s; +} + +static std::string MakeInputDisplayString(u16 pad, u16 padExt) { + const std::string Buttons[] = {"A", "B", "Sl", "St", "R", "L", "U", "D", "Rs", "Ls"}; + const std::string Ext[] = {"X", "Y"}; + + std::string s = MakeInputDisplayString(pad, Ext, ARRAY_SIZE(Ext)); + s += MakeInputDisplayString(padExt, Buttons, ARRAY_SIZE(Buttons)); + + return s; +} + + +buttonstruct Turbo; +buttonstruct TurboTime; +buttonstruct AutoHold; + +void ClearAutoHold(void) { + + for (u32 i=0; i < ARRAY_SIZE(AutoHold.array); i++) { + AutoHold.array[i]=false; + } +} + +//convert a 12.4 screen coordinate to an ADC value. +//the desmume host system will track the screen coordinate, but the hardware should be receiving the raw ADC values. +//so we'll need to use this to simulate the ADC values corresponding to the desired screen coords, based on the current TSC calibrations +u16 NDS_getADCTouchPosX(int scrX_lsl4) +{ + scrX_lsl4 >>= 4; + int rv = ((scrX_lsl4 - TSCal.scr.x1 + 1) * TSCal.adc.width) / TSCal.scr.width + TSCal.adc.x1; + rv = min(0xFFF, max(0, rv)); + return (u16)(rv); +} +u16 NDS_getADCTouchPosY(int scrY_lsl4) +{ + scrY_lsl4 >>= 4; + int rv = ((scrY_lsl4 - TSCal.scr.y1 + 1) * TSCal.adc.height) / TSCal.scr.height + TSCal.adc.y1; + rv = min(0xFFF, max(0, rv)); + return (u16)(rv); +} + +static UserInput rawUserInput = {}; // requested input, generally what the user is physically pressing +static UserInput intermediateUserInput = {}; // intermediate buffer for modifications (seperated from finalUserInput for safety reasons) +static UserInput finalUserInput = {}; // what gets sent to the game and possibly recorded +bool validToProcessInput = false; + +const UserInput& NDS_getRawUserInput() +{ + return rawUserInput; +} +UserInput& NDS_getProcessingUserInput() +{ + assert(validToProcessInput); + return intermediateUserInput; +} +bool NDS_isProcessingUserInput() +{ + return validToProcessInput; +} +const UserInput& NDS_getFinalUserInput() +{ + return finalUserInput; +} + + +static void saveUserInput(EMUFILE* os, UserInput& input) +{ + os->fwrite((const char*)input.buttons.array, 14); + writebool(input.touch.isTouch, os); + write16le(input.touch.touchX, os); + write16le(input.touch.touchY, os); + write32le(input.mic.micButtonPressed, os); +} +static bool loadUserInput(EMUFILE* is, UserInput& input, int version) +{ + is->fread((char*)input.buttons.array, 14); + readbool(&input.touch.isTouch, is); + read16le(&input.touch.touchX, is); + read16le(&input.touch.touchY, is); + read32le(&input.mic.micButtonPressed, is); + return true; +} +static void resetUserInput(UserInput& input) +{ + memset(&input, 0, sizeof(UserInput)); +} +// (userinput is kind of a misnomer, e.g. finalUserInput has to mirror nds.pad, nds.touchX, etc.) +static void saveUserInput(EMUFILE* os) +{ + saveUserInput(os, finalUserInput); + saveUserInput(os, intermediateUserInput); // saved in case a savestate is made during input processing (which Lua could do if nothing else) + writebool(validToProcessInput, os); + for(int i = 0; i < 14; i++) + write32le(TurboTime.array[i], os); // saved to make autofire more tolerable to use with re-recording +} +static bool loadUserInput(EMUFILE* is, int version) +{ + bool rv = true; + rv &= loadUserInput(is, finalUserInput, version); + rv &= loadUserInput(is, intermediateUserInput, version); + readbool(&validToProcessInput, is); + for(int i = 0; i < 14; i++) + read32le((u32*)&TurboTime.array[i], is); + return rv; +} +static void resetUserInput() +{ + resetUserInput(finalUserInput); + resetUserInput(intermediateUserInput); +} + +static inline void gotInputRequest() +{ + // nobody should set the raw input while we're processing the input. + // it might not screw anything up but it would be completely useless. + assert(!validToProcessInput); +} + +void NDS_setPad(bool R,bool L,bool D,bool U,bool T,bool S,bool B,bool A,bool Y,bool X,bool W,bool E,bool G, bool F) +{ + gotInputRequest(); + UserButtons& rawButtons = rawUserInput.buttons; + rawButtons.R = R; + rawButtons.L = L; + rawButtons.D = D; + rawButtons.U = U; + rawButtons.T = T; + rawButtons.S = S; + rawButtons.B = B; + rawButtons.A = A; + rawButtons.Y = Y; + rawButtons.X = X; + rawButtons.W = W; + rawButtons.E = E; + rawButtons.G = G; + rawButtons.F = F; +} +void NDS_setTouchPos(u16 x, u16 y) +{ + gotInputRequest(); + rawUserInput.touch.touchX = x<<4; + rawUserInput.touch.touchY = y<<4; + rawUserInput.touch.isTouch = true; + + if(movieMode != MOVIEMODE_INACTIVE && movieMode != MOVIEMODE_FINISHED) + { + // just in case, since the movie only stores 8 bits per touch coord +#ifdef WORDS_BIGENDIAN + rawUserInput.touch.touchX &= 0xF00F; + rawUserInput.touch.touchY &= 0xF00F; +#else + rawUserInput.touch.touchX &= 0x0FF0; + rawUserInput.touch.touchY &= 0x0FF0; +#endif + } +} +void NDS_releaseTouch(void) +{ + gotInputRequest(); + rawUserInput.touch.touchX = 0; + rawUserInput.touch.touchY = 0; + rawUserInput.touch.isTouch = false; +} +void NDS_setMic(bool pressed) +{ + gotInputRequest(); + rawUserInput.mic.micButtonPressed = (pressed ? TRUE : FALSE); +} + + +static void NDS_applyFinalInput(); + + +void NDS_beginProcessingInput() +{ + // start off from the raw input + intermediateUserInput = rawUserInput; + + // processing is valid now + validToProcessInput = true; +} + +void NDS_endProcessingInput() +{ + // transfer the processed input + finalUserInput = intermediateUserInput; + + // processing is invalid now + validToProcessInput = false; + + // use the final input for a few things right away + NDS_applyFinalInput(); +} + + + + + + + + +static void NDS_applyFinalInput() +{ + const UserInput& input = NDS_getFinalUserInput(); + + u16 pad = (0 | + ((input.buttons.A ? 0 : 0x80) >> 7) | + ((input.buttons.B ? 0 : 0x80) >> 6) | + ((input.buttons.T ? 0 : 0x80) >> 5) | + ((input.buttons.S ? 0 : 0x80) >> 4) | + ((input.buttons.R ? 0 : 0x80) >> 3) | + ((input.buttons.L ? 0 : 0x80) >> 2) | + ((input.buttons.U ? 0 : 0x80) >> 1) | + ((input.buttons.D ? 0 : 0x80) ) | + ((input.buttons.E ? 0 : 0x80) << 1) | + ((input.buttons.W ? 0 : 0x80) << 2)) ; + + pad = LOCAL_TO_LE_16(pad); + ((u16 *)MMU.ARM9_REG)[0x130>>1] = (u16)pad; + ((u16 *)MMU.ARM7_REG)[0x130>>1] = (u16)pad; + + u16 k_cnt = ((u16 *)MMU.ARM9_REG)[0x132>>1]; + if ( k_cnt & (1<<14)) + { + //INFO("ARM9: KeyPad IRQ (pad 0x%04X, cnt 0x%04X (condition %s))\n", pad, k_cnt, k_cnt&(1<<15)?"AND":"OR"); + u16 k_cnt_selected = (k_cnt & 0x3F); + if (k_cnt&(1<<15)) // AND + { + if ((~pad & k_cnt_selected) == k_cnt_selected) NDS_makeIrq(ARMCPU_ARM9,IRQ_BIT_KEYPAD); + } + else // OR + { + if (~pad & k_cnt_selected) NDS_makeIrq(ARMCPU_ARM9,IRQ_BIT_KEYPAD); + } + } + + k_cnt = ((u16 *)MMU.ARM7_REG)[0x132>>1]; + if ( k_cnt & (1<<14)) + { + //INFO("ARM7: KeyPad IRQ (pad 0x%04X, cnt 0x%04X (condition %s))\n", pad, k_cnt, k_cnt&(1<<15)?"AND":"OR"); + u16 k_cnt_selected = (k_cnt & 0x3F); + if (k_cnt&(1<<15)) // AND + { + if ((~pad & k_cnt_selected) == k_cnt_selected) NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_KEYPAD); + } + else // OR + { + if (~pad & k_cnt_selected) NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_KEYPAD); + } + } + + + if(input.touch.isTouch) + { + u16 adc_x = NDS_getADCTouchPosX(input.touch.touchX); + u16 adc_y = NDS_getADCTouchPosY(input.touch.touchY); + nds.adc_touchX = adc_x; + nds.adc_touchY = adc_y; + nds.adc_jitterctr = 0; + + nds.scr_touchX = input.touch.touchX; + nds.scr_touchY = input.touch.touchY; + nds.isTouch = 1; + } + else + { + nds.adc_touchX = 0; + nds.adc_touchY = 0; + nds.scr_touchX = 0; + nds.scr_touchY = 0; + nds.isTouch = 0; + } + + if (input.buttons.F && !countLid) + { + LidClosed = (!LidClosed) & 0x01; + if (!LidClosed) + { + NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_ARM7_FOLD); + } + + countLid = 30; + } + else + { + if (countLid > 0) + countLid--; + } + + u16 padExt = ((input.buttons.X ? 0 : 0x80) >> 7) | + ((input.buttons.Y ? 0 : 0x80) >> 6) | + ((input.buttons.G ? 0 : 0x80) >> 4) | + ((LidClosed) << 7) | + 0x0034; + + padExt = LOCAL_TO_LE_16(padExt); + padExt |= (((u16 *)MMU.ARM7_REG)[0x136>>1] & 0x0070); + + ((u16 *)MMU.ARM7_REG)[0x136>>1] = (u16)padExt; + + InputDisplayString=MakeInputDisplayString(padExt, pad); + + //put into the format we want for the movie system + //fRLDUTSBAYXWEg + //we don't really need nds.pad anymore, but removing it would be a pain + + nds.pad = + ((input.buttons.R ? 1 : 0) << 12)| + ((input.buttons.L ? 1 : 0) << 11)| + ((input.buttons.D ? 1 : 0) << 10)| + ((input.buttons.U ? 1 : 0) << 9)| + ((input.buttons.T ? 1 : 0) << 8)| + ((input.buttons.S ? 1 : 0) << 7)| + ((input.buttons.B ? 1 : 0) << 6)| + ((input.buttons.A ? 1 : 0) << 5)| + ((input.buttons.Y ? 1 : 0) << 4)| + ((input.buttons.X ? 1 : 0) << 3)| + ((input.buttons.W ? 1 : 0) << 2)| + ((input.buttons.E ? 1 : 0) << 1); + + //these values are arbitrarily chosen to make arkanoid paddle control act similarly to its dpad controls + if(input.buttons.R) + nds.paddle += 5; + else if(input.buttons.L) + nds.paddle -= 5; + + // TODO: low power IRQ +} + + +void NDS_suspendProcessingInput(bool suspend) +{ + static int suspendCount = 0; + if(suspend) + { + // enter non-processing block + assert(validToProcessInput); + validToProcessInput = false; + suspendCount++; + } + else if(suspendCount) + { + // exit non-processing block + validToProcessInput = true; + suspendCount--; + } + else + { + // unwound past first time -> not processing + validToProcessInput = false; + } +} + + +void emu_halt() { + //printf("halting emu: ARM9 PC=%08X/%08X, ARM7 PC=%08X/%08X\n", NDS_ARM9.R[15], NDS_ARM9.instruct_adr, NDS_ARM7.R[15], NDS_ARM7.instruct_adr); + execute = false; +#ifdef LOG_ARM9 + if (fp_dis9) + { + char buf[256] = { 0 }; + sprintf(buf, "halting emu: ARM9 PC=%08X/%08X\n", NDS_ARM9.R[15], NDS_ARM9.instruct_adr); + fwrite(buf, 1, strlen(buf), fp_dis9); + INFO("ARM9 halted\n"); + } +#endif + +#ifdef LOG_ARM7 + if (fp_dis7) + { + char buf[256] = { 0 }; + sprintf(buf, "halting emu: ARM7 PC=%08X/%08X\n", NDS_ARM7.R[15], NDS_ARM7.instruct_adr); + fwrite(buf, 1, strlen(buf), fp_dis7); + INFO("ARM7 halted\n"); + } +#endif +} + +//returns true if exmemcnt specifies satisfactory parameters for the device, which calls this function +bool ValidateSlot2Access(u32 procnum, u32 demandSRAMSpeed, u32 demand1stROMSpeed, u32 demand2ndROMSpeed, int clockbits) +{ + static const u32 _sramSpeeds[] = {10,8,6,18}; + static const u32 _rom1Speeds[] = {10,8,6,18}; + static const u32 _rom2Speeds[] = {6,4}; + u16 exmemcnt = T1ReadWord(MMU.MMU_MEM[procnum][0x40], 0x204); + u16 exmemcnt9 = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x204); + u32 arm7access = (exmemcnt9 & EXMEMCNT_MASK_SLOT2_ARM7); + u32 sramSpeed = _sramSpeeds[(exmemcnt & EXMEMCNT_MASK_SLOT2_SRAM_TIME)]; + u32 romSpeed1 = _rom1Speeds[(exmemcnt & EXMEMCNT_MASK_SLOT2_ROM_1ST_TIME)>>2]; + u32 romSpeed2 = _rom2Speeds[(exmemcnt & EXMEMCNT_MASK_SLOT2_ROM_2ND_TIME)>>4]; + u32 curclockbits = (exmemcnt & EXMEMCNT_MASK_SLOT2_CLOCKRATE)>>5; + + if(procnum==ARMCPU_ARM9 && arm7access) return false; + if(procnum==ARMCPU_ARM7 && !arm7access) return false; + + //what we're interested in here is whether the rom/ram are too low -> too fast. then accesses won't have enough time to work. + //i'm not sure if this gives us enough flexibility, but it is good enough for now. + //should make the arguments to this function bitmasks later if we need better. + if(sramSpeed < demandSRAMSpeed) return false; + if(romSpeed1 < demand1stROMSpeed) return false; + if(romSpeed2 < demand2ndROMSpeed) return false; + + if(clockbits != -1 && clockbits != (int)curclockbits) return false; + + return true; +} + +//these templates needed to be instantiated manually +template void NDS_exec(s32 nb); +template void NDS_exec(s32 nb); diff --git a/jni/desmume/src/NDSSystem.h b/jni/desmume/src/NDSSystem.h new file mode 100755 index 0000000..9e1132e --- /dev/null +++ b/jni/desmume/src/NDSSystem.h @@ -0,0 +1,625 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2008-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ + +#ifndef NDSSYSTEM_H +#define NDSSYSTEM_H + +#include +#include "armcpu.h" +#include "MMU.h" +#include "driver.h" +#include "GPU.h" +#include "SPU.h" +#include "mem.h" +#include "wifi.h" +#include "emufile.h" +#include "firmware.h" +#include "types.h" + +#include + +#if defined(_WINDOWS) && !defined(WXPORT) +#include "pathsettings.h" +#endif + +template +struct buttonstruct { + union { + struct { + // changing the order of these fields would break stuff + //fRLDUTSBAYXWEg + Type G; // debug + Type E; // right shoulder + Type W; // left shoulder + Type X; + Type Y; + Type A; + Type B; + Type S; // start + Type T; // select + Type U; // up + Type D; // down + Type L; // left + Type R; // right + Type F; // lid + }; + Type array[14]; + }; +}; + +extern buttonstruct Turbo; +extern buttonstruct TurboTime; +extern buttonstruct AutoHold; + +int NDS_WritePNG(const char *fname); + +extern volatile bool execute; +extern BOOL click; + +/* + * The firmware language values + */ +#define NDS_FW_LANG_JAP 0 +#define NDS_FW_LANG_ENG 1 +#define NDS_FW_LANG_FRE 2 +#define NDS_FW_LANG_GER 3 +#define NDS_FW_LANG_ITA 4 +#define NDS_FW_LANG_SPA 5 +#define NDS_FW_LANG_CHI 6 +#define NDS_FW_LANG_RES 7 + + +//#define LOG_ARM9 +//#define LOG_ARM7 + +struct NDS_header +{ + char gameTile[12]; + char gameCode[4]; + u16 makerCode; + u8 unitCode; + u8 deviceCode; + u8 cardSize; + u8 cardInfo[8]; + u8 flags; + u8 romversion; + + u32 ARM9src; + u32 ARM9exe; + u32 ARM9cpy; + u32 ARM9binSize; + + u32 ARM7src; + u32 ARM7exe; + u32 ARM7cpy; + u32 ARM7binSize; + + u32 FNameTblOff; + u32 FNameTblSize; + + u32 FATOff; + u32 FATSize; + + u32 ARM9OverlayOff; + u32 ARM9OverlaySize; + u32 ARM7OverlayOff; + u32 ARM7OverlaySize; + + u32 unknown2a; + u32 unknown2b; + + u32 IconOff; + u16 CRC16; + u16 ROMtimeout; + u32 ARM9unk; + u32 ARM7unk; + + u8 unknown3c[8]; + u32 ROMSize; + u32 HeaderSize; + u8 unknown5[56]; + u8 logo[156]; + u16 logoCRC16; + u16 headerCRC16; + u8 reserved[160]; +}; + +extern void debug(); +void emu_halt(); + +extern u64 nds_timer; +void NDS_Reschedule(); +void NDS_RescheduleGXFIFO(u32 cost); +void NDS_RescheduleDMA(); +void NDS_RescheduleTimers(); + +enum ENSATA_HANDSHAKE +{ + ENSATA_HANDSHAKE_none = 0, + ENSATA_HANDSHAKE_query = 1, + ENSATA_HANDSHAKE_ack = 2, + ENSATA_HANDSHAKE_confirm = 3, + ENSATA_HANDSHAKE_complete = 4, +}; + +enum NDS_CONSOLE_TYPE +{ + NDS_CONSOLE_TYPE_FAT, + NDS_CONSOLE_TYPE_LITE, + NDS_CONSOLE_TYPE_IQUE, + NDS_CONSOLE_TYPE_DSI +}; + +struct NDSSystem +{ + s32 wifiCycle; + s32 cycles; + u64 timerCycle[2][4]; + u32 VCount; + u32 old; + + //raw adc touch coords for old NDS + u16 adc_touchX; + u16 adc_touchY; + s32 adc_jitterctr; + + //the DSI returns calibrated touch coords from its TSC (?), so we need to save these separately + u16 scr_touchX; + u16 scr_touchY; + + BOOL isTouch; + u16 pad; + + u16 paddle; + + u8 *FW_ARM9BootCode; + u8 *FW_ARM7BootCode; + u32 FW_ARM9BootCodeAddr; + u32 FW_ARM7BootCodeAddr; + u32 FW_ARM9BootCodeSize; + u32 FW_ARM7BootCodeSize; + + BOOL sleeping; + BOOL cardEjected; + u32 freezeBus; + + //this is not essential NDS runtime state. + //it was perhaps a mistake to put it here. + //it is far less important than the above. + //maybe I should move it. + s32 idleCycles[2]; + s32 runCycleCollector[2][16]; + s32 idleFrameCounter; + s32 cpuloopIterationCount; //counts the number of times during a frame that a reschedule happened + + //console type must be copied in when the system boots. it can't be changed on the fly. + int ConsoleType; + bool Is_DSI() { return ConsoleType == NDS_CONSOLE_TYPE_DSI; } + bool Is_DebugConsole() { return _DebugConsole!=0; } + BOOL _DebugConsole; + + //set if the user requests ensata emulation + BOOL ensataEmulation; + + //there is a hack in the ipc sync for ensata. this tracks its state + u32 ensataIpcSyncCounter; + + //maintains the state of the ensata handshaking protocol + u32 ensataHandshake; + + struct { + u8 lcd, gpuMain, gfx3d_render, gfx3d_geometry, gpuSub, dispswap; + } power1; //POWCNT1 + + struct { + u8 speakers, wifi /*(initial value=0)*/; + } power2; //POWCNT2 + + bool isInVblank() const { return VCount >= 192; } + bool isIn3dVblank() const { return VCount >= 192 && VCount<215; } +}; + +/** /brief A touchscreen calibration point. + */ +struct NDS_fw_touchscreen_cal { + u16 adc_x; + u16 adc_y; + + u8 screen_x; + u8 screen_y; +}; + +#define MAX_FW_NICKNAME_LENGTH 10 +#define MAX_FW_MESSAGE_LENGTH 26 + +struct NDS_fw_config_data +{ + NDS_CONSOLE_TYPE ds_type; + + u8 fav_colour; + u8 birth_month; + u8 birth_day; + + u16 nickname[MAX_FW_NICKNAME_LENGTH]; + u8 nickname_len; + + u16 message[MAX_FW_MESSAGE_LENGTH]; + u8 message_len; + + u8 language; + + //touchscreen calibration + NDS_fw_touchscreen_cal touch_cal[2]; +}; + +extern NDSSystem nds; + +#ifdef GDB_STUB +int NDS_Init( struct armcpu_memory_iface *arm9_mem_if, + struct armcpu_ctrl_iface **arm9_ctrl_iface, + struct armcpu_memory_iface *arm7_mem_if, + struct armcpu_ctrl_iface **arm7_ctrl_iface); +#else +int NDS_Init ( void); +#endif + +void Desmume_InitOnce(); + +void NDS_DeInit(void); + +BOOL NDS_SetROM(u8 * rom, u32 mask); +NDS_header * NDS_getROMHeader(void); + +struct RomBanner +{ + RomBanner(bool defaultInit); + u16 version; //Version (0001h) + u16 crc16; //CRC16 across entries 020h..83Fh + u8 reserved[0x1C]; //Reserved (zero-filled) + u8 bitmap[0x200]; //Icon Bitmap (32x32 pix) (4x4 tiles, each 4x8 bytes, 4bit depth) + u16 palette[0x10]; //Icon Palette (16 colors, 16bit, range 0000h-7FFFh) (Color 0 is transparent, so the 1st palette entry is ignored) + enum { NUM_TITLES = 6 }; + union { + struct { + u16 title_jp[0x80]; //Title 0 Japanese (128 characters, 16bit Unicode) + u16 title_en[0x80]; //Title 1 English ("") + u16 title_fr[0x80]; //Title 2 French ("") + u16 title_de[0x80]; //Title 3 German ("") + u16 title_it[0x80]; //Title 4 Italian ("") + u16 title_es[0x80]; //Title 5 Spanish ("") + }; + u16 titles[NUM_TITLES][0x80]; + }; + u8 end0xFF[0x1C0]; + //840h ? (Maybe newer/chinese firmware do also support chinese title?) + //840h - End of Icon/Title structure (next 1C0h bytes usually FFh-filled) +}; + +struct GameInfo +{ + GameInfo() + : romdata(NULL) + {} + + void loadData(char* buf, int size) + { + resize(size); + memcpy(romdata,buf,size); + romsize = (u32)size; + fillGap(); + } + + void fillGap() + { + memset(romdata+romsize,0xFF,allocatedSize-romsize); + } + + void resize(int size) { + if(romdata != NULL) delete[] romdata; + + //calculate the necessary mask for the requested size + mask = size-1; + mask |= (mask >>1); + mask |= (mask >>2); + mask |= (mask >>4); + mask |= (mask >>8); + mask |= (mask >>16); + + //now, we actually need to over-allocate, because bytes from anywhere protected by that mask + //could be read from the rom + allocatedSize = mask+4; + + romdata = new char[allocatedSize]; + romsize = size; + } + u32 crc; + NDS_header header; + char ROMserial[20]; + char ROMname[20]; + //char ROMfullName[7][0x100]; + void populate(); + char* romdata; + u32 romsize; + u32 allocatedSize; + u32 mask; + const RomBanner& getRomBanner(); + bool hasRomBanner(); + bool isHomebrew; +}; + +typedef struct TSCalInfo +{ + struct + { + u16 x1, x2; + u16 y1, y2; + u16 width; + u16 height; + } adc; + + struct + { + u8 x1, x2; + u8 y1, y2; + u16 width; + u16 height; + } scr; + +} TSCalInfo; + +extern GameInfo gameInfo; + + +struct UserButtons : buttonstruct +{ +}; +struct UserTouch +{ + u16 touchX; + u16 touchY; + bool isTouch; +}; +struct UserMicrophone +{ + u32 micButtonPressed; +}; +struct UserInput +{ + UserButtons buttons; + UserTouch touch; + UserMicrophone mic; +}; + +// set physical user input +// these functions merely request the input to be changed. +// the actual change happens later at a specific time during the frame. +// this is to minimize the risk of desyncs. +void NDS_setTouchPos(u16 x, u16 y); +void NDS_releaseTouch(void); +void NDS_setPad(bool right,bool left,bool down,bool up,bool select,bool start,bool B,bool A,bool Y,bool X,bool leftShoulder,bool rightShoulder,bool debug, bool lid); +void NDS_setMic(bool pressed); + +// get physical user input +// not including the results of autofire/etc. +// the effects of calls to "set physical user input" functions will be immediately reflected here though. +const UserInput& NDS_getRawUserInput(); +const UserInput& NDS_getPrevRawUserInput(); + +// get final (fully processed) user input +// this should match whatever was or would be sent to the game +const UserInput& NDS_getFinalUserInput(); + +// set/get to-be-processed or in-the-middle-of-being-processed user input +// to process input, simply call this function and edit the return value. +// (applying autofire is one example of processing the input.) +// (movie playback is another example.) +// this must be done after the raw user input is set +// and before that input is sent to the game's memory. +UserInput& NDS_getProcessingUserInput(); +bool NDS_isProcessingUserInput(); +// call once per frame to prepare input for processing +void NDS_beginProcessingInput(); +// call once per frame to copy the processed input to the final input +void NDS_endProcessingInput(); + +// this is in case something needs reentrancy while processing input +void NDS_suspendProcessingInput(bool suspend); + + + +int NDS_LoadROM(const char *filename, const char* logicalFilename=0); +void NDS_FreeROM(void); +void NDS_Reset(); +int NDS_ImportSave(const char *filename, u32 force_size = 0); +u32 NDS_ImportSaveSize(const char *filename); +bool NDS_ExportSave(const char *filename); + +void nds_savestate(EMUFILE* os); +bool nds_loadstate(EMUFILE* is, int size); + +int NDS_WriteBMP(const char *filename); + +void NDS_Sleep(); +void NDS_ToggleCardEject(); + +void NDS_SkipNextFrame(); +#define NDS_SkipFrame(s) if(s) NDS_SkipNext2DFrame(); +void NDS_OmitFrameSkip(int force=0); + +void NDS_debug_break(); +void NDS_debug_continue(); +void NDS_debug_step(); + +void execHardware_doAllDma(EDMAMode modeNum); + +template void NDS_exec(s32 nb = 560190<<1); + +extern int lagframecounter; + +static INLINE void NDS_swapScreen(void) +{ + u16 tmp = MainScreen.offset; + MainScreen.offset = SubScreen.offset; + SubScreen.offset = tmp; +} + +int NDS_WriteBMP_32bppBuffer(int width, int height, const void* buf, const char *filename); + +extern struct TCommonSettings { + TCommonSettings() + : GFX3D_HighResolutionInterpolateColor(true) + , GFX3D_EdgeMark(true) + , GFX3D_Fog(true) + , GFX3D_Texture(true) + , GFX3D_LineHack(true) + , GFX3D_Zelda_Shadow_Depth_Hack(0) + , UseExtBIOS(false) + , SWIFromBIOS(false) + , PatchSWI3(false) + , UseExtFirmware(false) + , BootFromFirmware(false) + , DebugConsole(false) + , EnsataEmulation(false) + , cheatsDisable(false) + , num_cores(1) + , rigorous_timing(false) + , advanced_timing(true) + , micMode(InternalNoise) + , spuInterpolationMode(SPUInterpolation_Linear) + , manualBackupType(0) + , autodetectBackupMethod(0) + , spu_captureMuted(false) + , spu_advanced(false) + , StylusPressure(50) + , ConsoleType(NDS_CONSOLE_TYPE_FAT) + { + strcpy(ARM9BIOS, "biosnds9.bin"); + strcpy(ARM7BIOS, "biosnds7.bin"); + strcpy(Firmware, "firmware.bin"); + NDS_FillDefaultFirmwareConfigData(&InternalFirmConf); + + /* WIFI mode: adhoc = 0, infrastructure = 1 */ + wifi.mode = 1; + wifi.infraBridgeAdapter = 0; + + for(int i=0;i<16;i++) + spu_muteChannels[i] = false; + + for(int g=0;g<2;g++) + for(int x=0;x<5;x++) + dispLayers[g][x]=true; + } + bool GFX3D_HighResolutionInterpolateColor; + bool GFX3D_EdgeMark; + bool GFX3D_Fog; + bool GFX3D_Texture; + bool GFX3D_LineHack; + int GFX3D_Zelda_Shadow_Depth_Hack; + + bool UseExtBIOS; + char ARM9BIOS[256]; + char ARM7BIOS[256]; + bool SWIFromBIOS; + bool PatchSWI3; + + bool UseExtFirmware; + char Firmware[256]; + bool BootFromFirmware; + struct NDS_fw_config_data InternalFirmConf; + + NDS_CONSOLE_TYPE ConsoleType; + bool DebugConsole; + bool EnsataEmulation; + + bool cheatsDisable; + + int num_cores; + bool single_core() { return num_cores==1; } + bool rigorous_timing; + + int StylusPressure; + + bool dispLayers[2][5]; + + FAST_ALIGN bool advanced_timing; + + struct _Wifi { + int mode; + int infraBridgeAdapter; + } wifi; + + enum MicMode + { + InternalNoise = 0, + Sample = 1, + Random = 2, + Physical = 3, + } micMode; + + + SPUInterpolationMode spuInterpolationMode; + + //this is a temporary hack until we straighten out the flushing logic and/or gxfifo + //int gfx3d_flushMode; + + int autodetectBackupMethod; + //this is the user's choice of manual backup type, for cases when the autodetection can't be trusted + int manualBackupType; + + bool spu_muteChannels[16]; + bool spu_captureMuted; + bool spu_advanced; + + struct _ShowGpu { + _ShowGpu() : main(true), sub(true) {} + union { + struct { bool main,sub; }; + bool screens[2]; + }; + } showGpu; + + struct _Hud { + _Hud() + : ShowInputDisplay(false) + , ShowGraphicalInputDisplay(false) + , FpsDisplay(false) + , FrameCounterDisplay(false) + , ShowLagFrameCounter(false) + , ShowMicrophone(false) + , ShowRTC(false) + {} + bool ShowInputDisplay, ShowGraphicalInputDisplay, FpsDisplay, FrameCounterDisplay, ShowLagFrameCounter, ShowMicrophone, ShowRTC; + } hud; + +} CommonSettings; + + +extern std::string InputDisplayString; +extern int LagFrameFlag; +extern int lastLag, TotalLagFrames; + +void MovieSRAM(); + +void ClearAutoHold(void); + +bool ValidateSlot2Access(u32 procnum, u32 demandSRAMSpeed, u32 demand1stROMSpeed, u32 demand2ndROMSpeed, int clockbits); + +extern ADVANsCEne advsc; + +#endif + diff --git a/jni/desmume/src/OGLRender.cpp b/jni/desmume/src/OGLRender.cpp new file mode 100755 index 0000000..39a9167 --- /dev/null +++ b/jni/desmume/src/OGLRender.cpp @@ -0,0 +1,1211 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2006-2007 shash + Copyright (C) 2008-2011 DeSmuME team + Copyright (C) 2012 Jeffrey Quesnelle + + This file 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 file 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 the this software. If not, see . +*/ + +//problem - alpha-on-alpha texture rendering might work but the dest alpha buffer isnt tracked correctly +//due to zeromus not having any idea how to set dest alpha blending in opengl. +//so, it doesnt composite to 2d correctly. +//(re: new super mario brothers renders the stormclouds at the beginning) +//!!! fixed on rev.3996 + +#include + +#include "OGLRender.h" +#include "debug.h" + +CACHE_ALIGN float material_8bit_to_float[255] = {0}; + +bool (*oglrender_init)() = 0; +bool (*oglrender_beginOpenGL)() = 0; +void (*oglrender_endOpenGL)() = 0; + +static bool BEGINGL() { + if(oglrender_beginOpenGL) + return oglrender_beginOpenGL(); + else return true; +} + +static void ENDGL() { + if(oglrender_endOpenGL) + oglrender_endOpenGL(); +} + +#if defined(_WIN32) && !defined(WXPORT) + #define WIN32_LEAN_AND_MEAN + #include + #include + #include +#else +#ifdef __APPLE__ + #include + #include +#elif defined(ANDROID) + #include + #include +#else + #include + #include + /* This is a workaround needed to compile against nvidia GL headers */ + #ifndef GL_ALPHA_BLEND_EQUATION_ATI + #undef GL_VERSION_1_3 + #endif +#endif +#endif + +#include "types.h" +#include "debug.h" +#include "MMU.h" +#include "bits.h" +#include "matrix.h" +#include "NDSSystem.h" +#include "OGLRender.h" +#include "gfx3d.h" + +#include "shaders.h" +#include "texcache.h" + +static DS_ALIGN(16) u8 GPU_screen3D [256*192*4]; + +static const unsigned short map3d_cull[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BACK, 0}; +static const int texEnv[4] = { GL_MODULATE, GL_DECAL, GL_MODULATE, GL_MODULATE }; +static const int depthFunc[2] = { GL_LESS, GL_EQUAL }; + +//derived values extracted from polyattr etc +static bool wireframe=false, alpha31=false; +static unsigned int polyID=0; +static unsigned int depthFuncMode=0; +static unsigned int envMode=0; +static unsigned int lastEnvMode=0; +static unsigned int cullingMask=0; +static bool alphaDepthWrite; +static unsigned int lightMask=0; +static bool isTranslucent; + +static u32 textureFormat=0, texturePalette=0; + +// ClearImage/Rear-plane (FBO) +GLenum oglClearImageTextureID[2] = {0}; // 0 - image, 1 - depth +GLuint oglClearImageBuffers = 0; +GLuint oglClearImageRender[1] = {0}; +bool oglFBOdisabled = true; +u32 *oglClearImageColor = NULL; +float *oglClearImageDepth = NULL; +u16 *oglClearImageColorTemp = NULL; +u16 *oglClearImageDepthTemp = NULL; +u32 oglClearImageScrollOld = 0; + +//------------------------------------------------------------ + +#define OGLEXT(x,y) x y = 0; + +#ifdef _WIN32 +#define INITOGLEXT(x,y) y = (x)wglGetProcAddress(#y); +#elif !defined(__APPLE__) && !defined(ANDROID) +#include +#define INITOGLEXT(x,y) y = (x)glXGetProcAddress((const GLubyte *) #y); +#endif + +#if !defined(__APPLE__) && !defined(ANDROID) +OGLEXT(PFNGLCREATESHADERPROC,glCreateShader) +//zero: i dont understand this at all. my glext.h has the wrong thing declared here... so I have to do it myself +typedef void (APIENTRYP X_PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, const GLchar **source, GLsizei *length); +OGLEXT(X_PFNGLGETSHADERSOURCEPROC,glShaderSource) +OGLEXT(PFNGLCOMPILESHADERPROC,glCompileShader) +OGLEXT(PFNGLCREATEPROGRAMPROC,glCreateProgram) +OGLEXT(PFNGLATTACHSHADERPROC,glAttachShader) +OGLEXT(PFNGLDETACHSHADERPROC,glDetachShader) +OGLEXT(PFNGLLINKPROGRAMPROC,glLinkProgram) +OGLEXT(PFNGLUSEPROGRAMPROC,glUseProgram) +OGLEXT(PFNGLGETSHADERIVPROC,glGetShaderiv) +OGLEXT(PFNGLGETSHADERINFOLOGPROC,glGetShaderInfoLog) +OGLEXT(PFNGLDELETESHADERPROC,glDeleteShader) +OGLEXT(PFNGLDELETEPROGRAMPROC,glDeleteProgram) +OGLEXT(PFNGLGETPROGRAMIVPROC,glGetProgramiv) +OGLEXT(PFNGLGETPROGRAMINFOLOGPROC,glGetProgramInfoLog) +OGLEXT(PFNGLVALIDATEPROGRAMPROC,glValidateProgram) +OGLEXT(PFNGLBLENDFUNCSEPARATEPROC,glBlendFuncSeparate) +OGLEXT(PFNGLBLENDEQUATIONSEPARATEPROC,glBlendEquationSeparate) +OGLEXT(PFNGLGETUNIFORMLOCATIONPROC,glGetUniformLocation) +OGLEXT(PFNGLUNIFORM1IPROC,glUniform1i) +OGLEXT(PFNGLUNIFORM1IVPROC,glUniform1iv) +// FBO +OGLEXT(PFNGLGENFRAMEBUFFERSEXTPROC,glGenFramebuffersEXT); +OGLEXT(PFNGLBINDFRAMEBUFFEREXTPROC,glBindFramebufferEXT); +OGLEXT(PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC,glFramebufferRenderbufferEXT); +OGLEXT(PFNGLFRAMEBUFFERTEXTURE2DEXTPROC,glFramebufferTexture2DEXT); +OGLEXT(PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC,glCheckFramebufferStatusEXT); +OGLEXT(PFNGLDELETEFRAMEBUFFERSEXTPROC,glDeleteFramebuffersEXT); +OGLEXT(PFNGLBLITFRAMEBUFFEREXTPROC,glBlitFramebufferEXT); +#endif + +#if !defined(GL_VERSION_1_3) || defined(_MSC_VER) || defined(__INTEL_COMPILER) +#ifndef ANDROID +OGLEXT(PFNGLACTIVETEXTUREPROC,glActiveTexture) +#endif +#endif + +#ifdef ANDROID +#define GLdouble GLfloat +#define GL_CLAMP GL_CLAMP_TO_EDGE +#define glClearDepth glClearDepthf +#define glOrtho glOrthof +#define glFrustum glFrustumf +//TODO: get extensions for these +#define GL_MIRRORED_REPEAT 0x8370 +#endif + +//opengl state caching: +//This is of dubious performance assistance, but it is easy to take out so I am leaving it for now. +//every function that is xgl* can be replaced with gl* if we decide to rip this out or if anyone else +//doesnt feel like sticking with it (or if it causes trouble) + +static void xglDepthFunc(GLenum func) { + static GLenum oldfunc = -1; + if(oldfunc == func) return; + glDepthFunc(oldfunc=func); +} + +#ifndef ANDROID +static void xglPolygonMode(GLenum face,GLenum mode) { + static GLenum oldmodes[2] = {-1,-1}; + switch(face) { + case GL_FRONT: if(oldmodes[0]==mode) return; else glPolygonMode(GL_FRONT,oldmodes[0]=mode); return; + case GL_BACK: if(oldmodes[1]==mode) return; else glPolygonMode(GL_BACK,oldmodes[1]=mode); return; + case GL_FRONT_AND_BACK: if(oldmodes[0]==mode && oldmodes[1]==mode) return; else glPolygonMode(GL_FRONT_AND_BACK,oldmodes[0]=oldmodes[1]=mode); + } +} +#endif + +#if 0 +#ifdef _WIN32 +static void xglUseProgram(GLuint program) { + if(!glUseProgram) return; + static GLuint oldprogram = -1; + if(oldprogram==program) return; + glUseProgram(oldprogram=program); +} +#else +#if 0 /* not used */ +static void xglUseProgram(GLuint program) { + (void)program; + return; +} +#endif +#endif +#endif + +static void xglDepthMask (GLboolean flag) { + static GLboolean oldflag = -1; + if(oldflag==flag) return; + glDepthMask(oldflag=flag); +} + +struct GLCaps { + u8 caps[0x100]; + GLCaps() { + memset(caps,0xFF,sizeof(caps)); + } +}; +static GLCaps glcaps; + +static void _xglEnable(GLenum cap) { + cap -= 0x0B00; + if(glcaps.caps[cap] == 0xFF || glcaps.caps[cap] == 0) { + glEnable(cap+0x0B00); + glcaps.caps[cap] = 1; + } +} + +static void _xglDisable(GLenum cap) { + cap -= 0x0B00; + if(glcaps.caps[cap]) { + glDisable(cap+0x0B00); + glcaps.caps[cap] = 0; + } +} + +#define xglEnable(cap) { \ + CTASSERT((cap-0x0B00)<0x100); \ + _xglEnable(cap); } + +#define xglDisable(cap) {\ + CTASSERT((cap-0x0B00)<0x100); \ + _xglDisable(cap); } + +static std::queue freeTextureIds; + +GLenum oglToonTableTextureID; + +#define NOSHADERS(s) { hasShaders = false; INFO("Shaders aren't supported on your system, using fixed pipeline\n(%s)\n", s); return; } + +#define SHADER_COMPCHECK(s, t) { \ + GLint status = GL_TRUE; \ + glGetShaderiv(s, GL_COMPILE_STATUS, &status); \ + if(status != GL_TRUE) \ + { \ + GLint logSize; \ + GLchar *log; \ + glGetShaderiv(s, GL_INFO_LOG_LENGTH, &logSize); \ + log = new GLchar[logSize]; \ + glGetShaderInfoLog(s, logSize, &logSize, log); \ + INFO("SEVERE : FAILED TO COMPILE GL SHADER : %s\n", log); \ + delete[] log; \ + if(s)glDeleteShader(s); \ + NOSHADERS("Failed to compile the "t" shader."); \ + } \ +} + +#define PROGRAM_COMPCHECK(p, s1, s2) { \ + GLint status = GL_TRUE; \ + glGetProgramiv(p, GL_LINK_STATUS, &status); \ + if(status != GL_TRUE) \ + { \ + GLint logSize; \ + GLchar *log; \ + glGetProgramiv(p, GL_INFO_LOG_LENGTH, &logSize); \ + log = new GLchar[logSize]; \ + glGetProgramInfoLog(p, logSize, &logSize, log); \ + INFO("SEVERE : FAILED TO LINK GL SHADER PROGRAM : %s\n", log); \ + delete[] log; \ + if(s1)glDeleteShader(s1); \ + if(s2)glDeleteShader(s2); \ + NOSHADERS("Failed to link the shader program."); \ + } \ +} + +bool hasShaders = false; + +GLuint vertexShaderID; +GLuint fragmentShaderID; +GLuint shaderProgram; + +static GLint hasTexLoc; +static GLint texBlendLoc; +static GLint oglWBuffer; +static bool hasTexture = false; + +static TexCacheItem* currTexture = NULL; + +/* Shaders init */ + +static void createShaders() +{ + return; +#ifndef ANDROID + hasShaders = true; + +#ifdef HAVE_LIBOSMESA + NOSHADERS("Shaders aren't supported by OSMesa."); +#endif + + /* This check is just plain wrong. */ + /* It will always pass if you've OpenGL 2.0 or later, */ + /* even if your GFX card doesn't support shaders. */ +/* if (glCreateShader == NULL || //use ==NULL instead of !func to avoid always true warnings for some systems + glShaderSource == NULL || + glCompileShader == NULL || + glCreateProgram == NULL || + glAttachShader == NULL || + glLinkProgram == NULL || + glUseProgram == NULL || + glGetShaderInfoLog == NULL) + NOSHADERS("Shaders aren't supported by your system.");*/ + + const char *extString = (const char*)glGetString(GL_EXTENSIONS); + if ((strstr(extString, "GL_ARB_shader_objects") == NULL) || + (strstr(extString, "GL_ARB_vertex_shader") == NULL) || + (strstr(extString, "GL_ARB_fragment_shader") == NULL)) + NOSHADERS("Shaders aren't supported by your system."); + + vertexShaderID = glCreateShader(GL_VERTEX_SHADER); + if(!vertexShaderID) + NOSHADERS("Failed to create the vertex shader."); + + glShaderSource(vertexShaderID, 1, (const GLchar**)&vertexShader, NULL); + glCompileShader(vertexShaderID); + SHADER_COMPCHECK(vertexShaderID, "vertex"); + + fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); + if(!fragmentShaderID) + NOSHADERS("Failed to create the fragment shader."); + + glShaderSource(fragmentShaderID, 1, (const GLchar**)&fragmentShader, NULL); + glCompileShader(fragmentShaderID); + SHADER_COMPCHECK(fragmentShaderID, "fragment"); + + shaderProgram = glCreateProgram(); + if(!shaderProgram) + NOSHADERS("Failed to create the shader program."); + + glAttachShader(shaderProgram, vertexShaderID); + glAttachShader(shaderProgram, fragmentShaderID); + + glLinkProgram(shaderProgram); + PROGRAM_COMPCHECK(shaderProgram, vertexShaderID, fragmentShaderID); + + glValidateProgram(shaderProgram); + glUseProgram(shaderProgram); + + INFO("Successfully created OpenGL shaders.\n"); + #endif +} + +//================================================= + +static void OGLReset() +{ +#ifndef ANDROID + if(hasShaders) + { + glUniform1i(hasTexLoc, 0); + hasTexture = false; + glUniform1i(texBlendLoc, 0); + glUniform1i(oglWBuffer, 0); + } +#endif + + TexCache_Reset(); + if (currTexture) + delete currTexture; + currTexture = NULL; + +// memset(GPU_screenStencil,0,sizeof(GPU_screenStencil)); + memset(GPU_screen3D,0,sizeof(GPU_screen3D)); + + if(!oglFBOdisabled) + { + memset(oglClearImageColor, 0, 256*192*sizeof(u32)); + memset(oglClearImageDepth, 0, 256*192*sizeof(float)); + memset(oglClearImageColorTemp, 0, 256*192*sizeof(u16)); + memset(oglClearImageDepthTemp, 0, 256*192*sizeof(u16)); + oglClearImageScrollOld = 0; + } +} + +//static class OGLTexCacheUser : public ITexCacheUser +//{ +//public: +// virtual void BindTexture(u32 tx) +// { +// glBindTexture(GL_TEXTURE_2D,(GLuint)texcache[tx].id); +// glMatrixMode (GL_TEXTURE); +// glLoadIdentity (); +// glScaled (texcache[tx].invSizeX, texcache[tx].invSizeY, 1.0f); +// +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); +// +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (BIT16(texcache[tx].frm) ? (BIT18(texcache[tx].frm)?GL_MIRRORED_REPEAT:GL_REPEAT) : GL_CLAMP)); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (BIT17(texcache[tx].frm) ? (BIT19(texcache[tx].frm)?GL_MIRRORED_REPEAT:GL_REPEAT) : GL_CLAMP)); +// } +// +// virtual void BindTextureData(u32 tx, u8* data) +// { +// BindTexture(tx); +// +// #if 0 +// for (int i=0; i < texcache[tx].sizeX * texcache[tx].sizeY*4; i++) +// data[i] = 0xFF; +// #endif +// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, +// texcache[tx].sizeX, texcache[tx].sizeY, 0, +// GL_RGBA, GL_UNSIGNED_BYTE, data); +// } +//} textures; +// +//static TexCacheUnit texCacheUnit; + +static void expandFreeTextures() +{ + const int kInitTextures = 128; + GLuint oglTempTextureID[kInitTextures]; + glGenTextures(kInitTextures, &oglTempTextureID[0]); + for(int i=0;i [0,31] math + + // Restore Toon table + u32 rgbToonTable[32]; + for(int i=0;i<32;i++) + rgbToonTable[i] = RGB15TO32_NOALPHA(gfx3d.renderState.u16ToonTable[i]); + glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, &rgbToonTable[0]); + gfx3d.state.invalidateToon = false; + } + + + // ClearImage/Rear-plane + glGenTextures (2, &oglClearImageTextureID[0]); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, oglClearImageTextureID[0]); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 192, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + glBindTexture(GL_TEXTURE_2D, oglClearImageTextureID[1]); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); + glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 256, 192, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); + + + // FBO + oglFBOdisabled = false; + glGenFramebuffersEXT(1, &oglClearImageBuffers); + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oglClearImageBuffers); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, oglClearImageTextureID[0], 0); + + //glDrawBuffer(GL_NONE); + //glReadBuffer(GL_NONE); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, oglClearImageTextureID[1], 0); + + if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)==GL_FRAMEBUFFER_COMPLETE_EXT) + INFO("Successfully created OpenGL Framebuffer object (FBO)\n"); + else + { + INFO("Failed to created OpenGL Framebuffer object (FBO): ClearImage disabled\n"); + oglFBOdisabled = true; + } + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + + oglClearImageColor = new u32[256*192]; + oglClearImageColorTemp = new u16[256*192]; + oglClearImageDepth = new float[256*192]; + oglClearImageDepthTemp = new u16[256*192]; +#endif + glActiveTexture(GL_TEXTURE0); + + OGLReset(); + + ENDGL(); + + return 1; +} + +static void OGLClose() +{ + if(!BEGINGL()) + return; + +#ifndef ANDROID + if(hasShaders) + { + glUseProgram(0); + + glDetachShader(shaderProgram, vertexShaderID); + glDetachShader(shaderProgram, fragmentShaderID); + + glDeleteProgram(shaderProgram); + glDeleteShader(vertexShaderID); + glDeleteShader(fragmentShaderID); + + hasShaders = false; + } +#endif + + //kill the tex cache to free all the texture ids + TexCache_Reset(); + + while(!freeTextureIds.empty()) + { + GLuint temp = freeTextureIds.front(); + freeTextureIds.pop(); + glDeleteTextures(1,&temp); + } + //glDeleteTextures(MAX_TEXTURE, &oglTempTextureID[0]); + glDeleteTextures(1, &oglToonTableTextureID); + + // FBO +#ifndef ANDROID + glDeleteTextures(2, &oglClearImageTextureID[0]); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glDeleteFramebuffersEXT(1, &oglClearImageBuffers); + + if (oglClearImageColor) + { + delete [] oglClearImageColor; + oglClearImageColor = NULL; + } + + if (oglClearImageDepth) + { + delete [] oglClearImageDepth; + oglClearImageDepth = NULL; + } + + if (oglClearImageColorTemp) + { + delete [] oglClearImageColorTemp; + oglClearImageColorTemp = NULL; + } + + if (oglClearImageDepthTemp) + { + delete [] oglClearImageDepthTemp; + oglClearImageDepthTemp = NULL; + } +#endif + ENDGL(); +} + +static void texDeleteCallback(TexCacheItem* item) +{ + freeTextureIds.push((GLuint)item->texid); + if(currTexture == item) + currTexture = NULL; +} + +static void setTexture(unsigned int format, unsigned int texpal) +{ + textureFormat = format; + texturePalette = texpal; + + u32 textureMode = (unsigned short)((format>>26)&0x07); + +#ifndef ANDROID + if (format==0) + { + if(hasShaders && hasTexture) { glUniform1i(hasTexLoc, 0); hasTexture = false; } + return; + } + if (textureMode==0) + { + if(hasShaders && hasTexture) { glUniform1i(hasTexLoc, 0); hasTexture = false; } + return; + } + + if(hasShaders) + { + if(!hasTexture) { glUniform1i(hasTexLoc, 1); hasTexture = true; } + glActiveTexture(GL_TEXTURE0); + } +#endif + +// texCacheUnit.TexCache_SetTexture(format, texpal); + TexCacheItem* newTexture = TexCache_SetTexture(TexFormat_32bpp,format,texpal); + if(newTexture != currTexture) + { + currTexture = newTexture; + //has the ogl renderer initialized the texture? + if(!currTexture->deleteCallback) + { + currTexture->deleteCallback = texDeleteCallback; + if(freeTextureIds.empty()) expandFreeTextures(); + currTexture->texid = (u64)freeTextureIds.front(); + freeTextureIds.pop(); + + glBindTexture(GL_TEXTURE_2D,(GLuint)currTexture->texid); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (BIT16(currTexture->texformat) ? (BIT18(currTexture->texformat)?GL_MIRRORED_REPEAT:GL_REPEAT) : GL_CLAMP)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (BIT17(currTexture->texformat) ? (BIT19(currTexture->texformat)?GL_MIRRORED_REPEAT:GL_REPEAT) : GL_CLAMP)); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + currTexture->sizeX, currTexture->sizeY, 0, + GL_RGBA, GL_UNSIGNED_BYTE, currTexture->decoded); + } + else + { + //otherwise, just bind it + glBindTexture(GL_TEXTURE_2D,(GLuint)currTexture->texid); + } + + //in either case, we need to setup the tex mtx + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glScalef(currTexture->invSizeX, currTexture->invSizeY, 1.0f); + + } +} + + + +//controls states: +//glStencilFunc +//glStencilOp +//glColorMask +static u32 stencilStateSet = -1; + +static u32 polyalpha=0; + +static void BeginRenderPoly() +{ + bool enableDepthWrite = true; + + xglDepthFunc (depthFuncMode); + + // Cull face + if (cullingMask == 0x03) + { + xglDisable(GL_CULL_FACE); + } + else + { + xglEnable(GL_CULL_FACE); + glCullFace(map3d_cull[cullingMask]); + } + +#ifndef ANDROID + if (!wireframe) + { + xglPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + } + else + { + xglPolygonMode (GL_FRONT_AND_BACK, GL_LINE); + } +#endif + + setTexture(textureFormat, texturePalette); + + if(isTranslucent) + enableDepthWrite = alphaDepthWrite; + + //handle shadow polys + if(envMode == 3) + { + xglEnable(GL_STENCIL_TEST); + if(polyID == 0) { + enableDepthWrite = false; + if(stencilStateSet!=0) { + stencilStateSet = 0; + //when the polyID is zero, we are writing the shadow mask. + //set stencilbuf = 1 where the shadow volume is obstructed by geometry. + //do not write color or depth information. + glStencilFunc(GL_ALWAYS,65,255); + glStencilOp(GL_KEEP,GL_REPLACE,GL_KEEP); + glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); + } + } else { + enableDepthWrite = true; + if(stencilStateSet!=1) { + stencilStateSet = 1; + //when the polyid is nonzero, we are drawing the shadow poly. + //only draw the shadow poly where the stencilbuf==1. + //I am not sure whether to update the depth buffer here--so I chose not to. + glStencilFunc(GL_EQUAL,65,255); + glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP); + glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); + } + } + } else { + xglEnable(GL_STENCIL_TEST); + if(isTranslucent) + { + stencilStateSet = 3; + glStencilFunc(GL_NOTEQUAL,polyID,255); + glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE); + glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); + } + else + if(stencilStateSet!=2) { + stencilStateSet=2; + glStencilFunc(GL_ALWAYS,64,255); + glStencilOp(GL_REPLACE,GL_REPLACE,GL_REPLACE); + glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); + } + } + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, texEnv[envMode]); + +#ifndef ANDROID + if(hasShaders) + { + if(envMode != lastEnvMode) + { + lastEnvMode = envMode; + + int _envModes[4] = {0, 1, (2 + gfx3d.renderState.shading), 0}; + glUniform1i(texBlendLoc, _envModes[envMode]); + } + } +#endif + + xglDepthMask(enableDepthWrite?GL_TRUE:GL_FALSE); +} + +static void InstallPolygonAttrib(u32 val) +{ + // Light enable/disable + lightMask = (val&0xF); + + // texture environment + envMode = (val&0x30)>>4; + + // overwrite depth on alpha pass + alphaDepthWrite = BIT11(val)!=0; + + // depth test function + depthFuncMode = depthFunc[BIT14(val)]; + + // back face culling + cullingMask = (val >> 6) & 0x03; + + alpha31 = ((val>>16)&0x1F)==31; + + // Alpha value, actually not well handled, 0 should be wireframe + wireframe = ((val>>16)&0x1F)==0; + + polyalpha = ((val>>16)&0x1F); + + // polyID + polyID = (val>>24)&0x3F; +} + +static void Control() +{ + if(gfx3d.renderState.enableTexturing) glEnable (GL_TEXTURE_2D); + else glDisable (GL_TEXTURE_2D); + + if(gfx3d.renderState.enableAlphaTest) + // FIXME: alpha test should pass gfx3d.alphaTestRef==poly->getAlpha + glAlphaFunc (GL_GREATER, gfx3d.renderState.alphaTestRef/31.f); + else + glAlphaFunc (GL_GREATER, 0); + + if(gfx3d.renderState.enableAlphaBlending) + { + glEnable (GL_BLEND); + } + else + { + glDisable (GL_BLEND); + } +} + + +static void GL_ReadFramebuffer() +{ + if(!BEGINGL()) return; + glFinish(); +// glReadPixels(0,0,256,192,GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, GPU_screenStencil); + glReadPixels(0,0,256,192,GL_BGRA_EXT, GL_UNSIGNED_BYTE, GPU_screen3D); + ENDGL(); + + //convert the pixels to a different format which is more convenient + //is it safe to modify the screen buffer? if not, we could make a temp copy + for(int i=0,y=191;y>=0;y--) + { + u8* dst = gfx3d_convertedScreen + (y<<(8+2)); + + for(int x=0;x<256;x++,i++) + { + u32 &u32screen3D = ((u32*)GPU_screen3D)[i]; + u32screen3D>>=2; + u32screen3D &= 0x3F3F3F3F; + + const int t = i<<2; + const u8 a = GPU_screen3D[t+3] >> 1; + const u8 r = GPU_screen3D[t+2]; + const u8 g = GPU_screen3D[t+1]; + const u8 b = GPU_screen3D[t+0]; + *dst++ = r; + *dst++ = g; + *dst++ = b; + *dst++ = a; + } + } + +#if 0 + //convert the pixels to a different format which is more convenient + //is it safe to modify the screen buffer? if not, we could make a temp copy + for(int i=0,y=191;y>=0;y--) + { + u16* dst = gfx3d_convertedScreen + (y<<8); + u8* dstAlpha = gfx3d_convertedAlpha + (y<<8); + + //I dont know much about this kind of stuff, but this seems to help + //for some reason I couldnt make the intrinsics work + //u8* u8screen3D = (u8*)&((u32*)GPU_screen3D)[i]; + /*#define PREFETCH32(X,Y) __asm { prefetchnta [u8screen3D+32*0x##X##Y] } + #define PREFETCH128(X) PREFETCH32(X,0) PREFETCH32(X,1) PREFETCH32(X,2) PREFETCH32(X,3) \ + PREFETCH32(X,4) PREFETCH32(X,5) PREFETCH32(X,6) PREFETCH32(X,7) \ + PREFETCH32(X,8) PREFETCH32(X,9) PREFETCH32(X,A) PREFETCH32(X,B) \ + PREFETCH32(X,C) PREFETCH32(X,D) PREFETCH32(X,E) PREFETCH32(X,F) + PREFETCH128(0); PREFETCH128(1);*/ + + for(int x=0;x<256;x++,i++) + { + u32 &u32screen3D = ((u32*)GPU_screen3D)[i]; + u32screen3D>>=3; + u32screen3D &= 0x1F1F1F1F; + + const int t = i<<2; + const u8 a = GPU_screen3D[t+3]; + const u8 r = GPU_screen3D[t+2]; + const u8 g = GPU_screen3D[t+1]; + const u8 b = GPU_screen3D[t+0]; + dst[x] = R5G5B5TORGB15(r,g,b) | alpha_lookup[a]; + dstAlpha[x] = a; + } + } +#endif +} + +// TODO: optimize +// Tested: Sonic Chronicles Dark Brotherhood +// The Chronicles of Narnia - The Lion, The Witch and The Wardrobe +// Harry Potter and the Order of the Phoenix +static void oglClearImageFBO() +{ + //printf("enableClearImage\n"); + u16* clearImage = (u16*)MMU.texInfo.textureSlotAddr[2]; + u16* clearDepth = (u16*)MMU.texInfo.textureSlotAddr[3]; + u16 scroll = T1ReadWord(MMU.ARM9_REG,0x356); //CLRIMAGE_OFFSET + + if ((oglClearImageScrollOld != scroll)|| + (memcmp(clearImage, oglClearImageColorTemp, 256*192*2) != 0) || + (memcmp(clearDepth, oglClearImageDepthTemp, 256*192*2) != 0)) + { + oglClearImageScrollOld = scroll; + memcpy(oglClearImageColorTemp, clearImage, 256*192*2); + memcpy(oglClearImageDepthTemp, clearDepth, 256*192*2); + + u16 xscroll = scroll&0xFF; + u16 yscroll = (scroll>>8)&0xFF; + + u32 dd = 256*192-256; + for(int iy=0;iy<192;iy++) + { + int y = ((iy + yscroll)&255)<<8; + for(int ix=0;ix<256;ix++) + { + int x = (ix + xscroll)&255; + int adr = y + x; + + u16 col = clearImage[adr]; + oglClearImageColor[dd] = RGB15TO32(col,255*(col>>15)); + + u16 depth = clearDepth[adr] & 0x7FFF; + + oglClearImageDepth[dd] = (float)gfx3d_extendDepth_15_to_24(depth) / (float)0x00FFFFFF; + dd++; + } + dd-=256*2; + } + +#ifndef ANDROID + // color + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, oglClearImageTextureID[0]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 192, 0, GL_RGBA, GL_UNSIGNED_BYTE, &oglClearImageColor[0]); + + // depth + glBindTexture(GL_TEXTURE_2D, oglClearImageTextureID[1]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 256, 192, 0, GL_DEPTH_COMPONENT, GL_FLOAT, &oglClearImageDepth[0]); +#endif + + glActiveTexture(GL_TEXTURE0); + } + + + // color & depth +#ifndef ANDROID + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, oglClearImageBuffers); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); + glBlitFramebufferEXT(0,0,256,192,0,0,256,192,GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT,GL_LINEAR); + + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); +#endif + +} + +static void OGLRender() +{ + float alpha = 1.0f; + + if(!BEGINGL()) return; + + Control(); + +#ifndef ANDROID + if(hasShaders) + { + //NOTE: this toon invalidation logic is hopelessly buggy. + //it may sometimes fail. it would be better to always recreate this data. + //but, that may be slow. since the cost of uploading that texture is huge in opengl (relative to rasterizer). + //someone please study it. + //here is a suggestion: it may make sense to memcmp the toon tables and upload only when it actually changes + if (gfx3d.renderState.invalidateToon) + { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_1D, oglToonTableTextureID); + + u32 rgbToonTable[32]; + for(int i=0;i<32;i++) + rgbToonTable[i] = RGB15TO32_NOALPHA(gfx3d.renderState.u16ToonTable[i]); + glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, &rgbToonTable[0]); + gfx3d.state.invalidateToon = false; + } + + glUniform1i(oglWBuffer, gfx3d.renderState.wbuffer); + } +#endif + + xglDepthMask(GL_TRUE); + + glClearStencil((gfx3d.renderState.clearColor >> 24) & 0x3F); + u32 clearFlag = GL_STENCIL_BUFFER_BIT; + + if (!oglFBOdisabled && gfx3d.renderState.enableClearImage) + oglClearImageFBO(); + else + { + float clearColor[4] = { + ((float)(gfx3d.renderState.clearColor&0x1F))/31.0f, + ((float)((gfx3d.renderState.clearColor>>5)&0x1F))/31.0f, + ((float)((gfx3d.renderState.clearColor>>10)&0x1F))/31.0f, + ((float)((gfx3d.renderState.clearColor>>16)&0x1F))/31.0f, + }; + glClearColor(clearColor[0],clearColor[1],clearColor[2],clearColor[3]); + glClearDepth((float)gfx3d.renderState.clearDepth / (float)0x00FFFFFF); + clearFlag |= GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; + } + + glClear(clearFlag); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + + //render display list + //TODO - properly doublebuffer the display lists + { + + u32 lastTextureFormat = 0, lastTexturePalette = 0, lastPolyAttr = 0, lastViewport = 0xFFFFFFFF; + // int lastProjIndex = -1; + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + float verticies[16]; + float textureCoords[8]; + float colors[16]; + glVertexPointer(4, GL_FLOAT, 0, verticies); + glTexCoordPointer(2, GL_FLOAT, 0, textureCoords); + glColorPointer(4, GL_FLOAT, 0, colors); + for(int i=0;icount;i++) { + POLY *poly = &gfx3d.polylist->list[gfx3d.indexlist.list[i]]; + int type = poly->type; + + //a very macro-level state caching approach: + //these are the only things which control the GPU rendering state. + if(i==0 || lastTextureFormat != poly->texParam || lastTexturePalette != poly->texPalette || lastPolyAttr != poly->polyAttr) + { + isTranslucent = poly->isTranslucent(); + InstallPolygonAttrib(poly->polyAttr); + lastTextureFormat = textureFormat = poly->texParam; + lastTexturePalette = texturePalette = poly->texPalette; + lastPolyAttr = poly->polyAttr; + BeginRenderPoly(); + } + + if(lastViewport != poly->viewport) + { + VIEWPORT viewport; + viewport.decode(poly->viewport); + glViewport(viewport.x,viewport.y,viewport.width,viewport.height); + lastViewport = poly->viewport; + } + + if(wireframe || !isTranslucent) alpha = 1.0f; + else + alpha = poly->getAlpha()/31.0f; + + static const GLenum frm[] = {GL_TRIANGLES, GL_TRIANGLE_FAN, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, //TODO: GL_QUAD_STRIP + GL_LINE_LOOP, GL_LINE_LOOP, GL_LINE_STRIP, GL_LINE_STRIP}; + + //glBegin(frm[poly->vtxFormat]); + + for(int j = 0; j < type; j++) + { + VERT *vert = &gfx3d.vertlist->list[poly->vertIndexes[j]]; + + int jstart = j * 4; + memcpy(&verticies[jstart], vert->coord, sizeof(float) * 4); + memcpy(&textureCoords[j * 2], vert->texcoord, sizeof(float) * 2); + colors[jstart] = material_8bit_to_float[vert->color[0]]; + colors[jstart+1] = material_8bit_to_float[vert->color[1]]; + colors[jstart+2] = material_8bit_to_float[vert->color[2]]; + colors[jstart+3] = alpha; + } + + glDrawArrays(frm[poly->vtxFormat], 0, type); + + //glEnd(); + } + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + } + + //needs to happen before endgl because it could free some textureids for expired cache items + TexCache_EvictFrame(); + + ENDGL(); + + GL_ReadFramebuffer(); +} + +static void OGLVramReconfigureSignal() +{ + TexCache_Invalidate(); +} + +GPU3DInterface gpu3Dgl = { + "OpenGL", + OGLInit, + OGLReset, + OGLClose, + OGLRender, + OGLVramReconfigureSignal, +}; diff --git a/jni/desmume/src/OGLRender.h b/jni/desmume/src/OGLRender.h new file mode 100755 index 0000000..09e9782 --- /dev/null +++ b/jni/desmume/src/OGLRender.h @@ -0,0 +1,46 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2006-2007 shash + Copyright (C) 2008-2009 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ + +#ifndef OGLRENDER_H +#define OGLRENDER_H + +#include "common.h" +#include +#include +#include +#include +#include +#include "debug.h" +#include "render3D.h" + +extern GPU3DInterface gpu3Dgl; + +//This is called by OGLRender whenever it initializes. +//Platforms, please be sure to set this up. +//return true if you successfully init. +extern bool (*oglrender_init)(); + +//This is called by OGLRender before it uses opengl. +//return true if youre OK with using opengl +extern bool (*oglrender_beginOpenGL)(); + +//This is called by OGLRender after it is done using opengl. +extern void (*oglrender_endOpenGL)(); + +#endif diff --git a/jni/desmume/src/PACKED.h b/jni/desmume/src/PACKED.h new file mode 100755 index 0000000..dabd31c --- /dev/null +++ b/jni/desmume/src/PACKED.h @@ -0,0 +1,12 @@ +#ifndef __GNUC__ +#pragma pack(push, 1) +#pragma warning(disable : 4103) +#endif + +#ifndef __PACKED + #ifdef __GNUC__ + #define __PACKED __attribute__((__packed__)) + #else + #define __PACKED + #endif +#endif diff --git a/jni/desmume/src/PACKED_END.h b/jni/desmume/src/PACKED_END.h new file mode 100755 index 0000000..4c0798d --- /dev/null +++ b/jni/desmume/src/PACKED_END.h @@ -0,0 +1,3 @@ +#ifndef __GNUC__ +#pragma pack(pop) +#endif diff --git a/jni/desmume/src/ROMReader.cpp b/jni/desmume/src/ROMReader.cpp new file mode 100755 index 0000000..e6b8e43 --- /dev/null +++ b/jni/desmume/src/ROMReader.cpp @@ -0,0 +1,235 @@ +/* + Copyright 2007 Guillaume Duhamel + Copyright 2007-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ + +#include "ROMReader.h" + +#include +#include +#include +#ifdef HAVE_LIBZZIP +#include +#endif + +#ifdef WIN32 +#define stat(...) _stat(__VA_ARGS__) +#define S_IFMT _S_IFMT +#define S_IFREG _S_IFREG +#endif + +ROMReader_struct * ROMReaderInit(char ** filename) +{ +#ifdef HAVE_LIBZ + if(!strcasecmp(".gz", *filename + (strlen(*filename) - 3))) + { + (*filename)[strlen(*filename) - 3] = '\0'; + return &GZIPROMReader; + } +#endif +#ifdef HAVE_LIBZZIP + if (!strcasecmp(".zip", *filename + (strlen(*filename) - 4))) + { + (*filename)[strlen(*filename) - 4] = '\0'; + return &ZIPROMReader; + } +#endif + return &STDROMReader; +} + +void * STDROMReaderInit(const char * filename); +void STDROMReaderDeInit(void *); +u32 STDROMReaderSize(void *); +int STDROMReaderSeek(void *, int, int); +int STDROMReaderRead(void *, void *, u32); + +ROMReader_struct STDROMReader = +{ + ROMREADER_STD, + "Standard ROM Reader", + STDROMReaderInit, + STDROMReaderDeInit, + STDROMReaderSize, + STDROMReaderSeek, + STDROMReaderRead +}; + +void * STDROMReaderInit(const char * filename) +{ +#ifdef WIN32 + struct _stat sb; +#else + struct stat sb; +#endif + if (stat(filename, &sb) == -1) + return 0; + + if ((sb.st_mode & S_IFMT) != S_IFREG) + return 0; + + return (void *) fopen(filename, "rb"); +} + +void STDROMReaderDeInit(void * file) +{ + if (!file) return ; + fclose((FILE*)file); +} + +u32 STDROMReaderSize(void * file) +{ + u32 size; + + if (!file) return 0 ; + + fseek((FILE*)file, 0, SEEK_END); + size = ftell((FILE*)file); + fseek((FILE*)file, 0, SEEK_SET); + + return size; +} + +int STDROMReaderSeek(void * file, int offset, int whence) +{ + if (!file) return 0 ; + return fseek((FILE*)file, offset, whence); +} + +int STDROMReaderRead(void * file, void * buffer, u32 size) +{ + if (!file) return 0 ; + return fread(buffer, 1, size, (FILE*)file); +} + +#ifdef HAVE_LIBZ +void * GZIPROMReaderInit(const char * filename); +void GZIPROMReaderDeInit(void *); +u32 GZIPROMReaderSize(void *); +int GZIPROMReaderSeek(void *, int, int); +int GZIPROMReaderRead(void *, void *, u32); + +ROMReader_struct GZIPROMReader = +{ + ROMREADER_GZIP, + "Gzip ROM Reader", + GZIPROMReaderInit, + GZIPROMReaderDeInit, + GZIPROMReaderSize, + GZIPROMReaderSeek, + GZIPROMReaderRead +}; + +void * GZIPROMReaderInit(const char * filename) +{ + return (void*)gzopen(filename, "rb"); +} + +void GZIPROMReaderDeInit(void * file) +{ + gzclose((gzFile)file); +} + +u32 GZIPROMReaderSize(void * file) +{ + char useless[1024]; + u32 size = 0; + + /* FIXME this function should first save the current + * position and restore it after size calculation */ + gzrewind((gzFile)file); + while (gzeof ((gzFile)file) == 0) + size += gzread((gzFile)file, useless, 1024); + gzrewind((gzFile)file); + + return size; +} + +int GZIPROMReaderSeek(void * file, int offset, int whence) +{ + return gzseek((gzFile)file, offset, whence); +} + +int GZIPROMReaderRead(void * file, void * buffer, u32 size) +{ + return gzread((gzFile)file, buffer, size); +} +#endif + +#ifdef HAVE_LIBZZIP +void * ZIPROMReaderInit(const char * filename); +void ZIPROMReaderDeInit(void *); +u32 ZIPROMReaderSize(void *); +int ZIPROMReaderSeek(void *, int, int); +int ZIPROMReaderRead(void *, void *, u32); + +ROMReader_struct ZIPROMReader = +{ + ROMREADER_ZIP, + "Zip ROM Reader", + ZIPROMReaderInit, + ZIPROMReaderDeInit, + ZIPROMReaderSize, + ZIPROMReaderSeek, + ZIPROMReaderRead +}; + +void * ZIPROMReaderInit(const char * filename) +{ + ZZIP_DIR * dir = zzip_opendir(filename); + ZZIP_DIRENT * dirent = zzip_readdir(dir); + if (dir != NULL) + { + char tmp1[1024]; + char tmp2[1024]; + memset(tmp1,0,sizeof(tmp1)); + memset(tmp2,0,sizeof(tmp2)); + strncpy(tmp1, filename, strlen(filename) - 4); + sprintf(tmp2, "%s/%s", tmp1, dirent->d_name); + return zzip_fopen(tmp2, "rb"); + } + return NULL; +} + +void ZIPROMReaderDeInit(void * file) +{ + zzip_close((ZZIP_FILE*)file); +} + +u32 ZIPROMReaderSize(void * file) +{ + u32 size; + + zzip_seek((ZZIP_FILE*)file, 0, SEEK_END); + size = zzip_tell((ZZIP_FILE*)file); + zzip_seek((ZZIP_FILE*)file, 0, SEEK_SET); + + return size; +} + +int ZIPROMReaderSeek(void * file, int offset, int whence) +{ + return zzip_seek((ZZIP_FILE*)file, offset, whence); +} + +int ZIPROMReaderRead(void * file, void * buffer, u32 size) +{ +#ifdef ZZIP_OLD_READ + return zzip_read((ZZIP_FILE*)file, (char *) buffer, size); +#else + return zzip_read((ZZIP_FILE*)file, buffer, size); +#endif +} +#endif diff --git a/jni/desmume/src/ROMReader.h b/jni/desmume/src/ROMReader.h new file mode 100755 index 0000000..166f0a0 --- /dev/null +++ b/jni/desmume/src/ROMReader.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2007 Guillaume Duhamel + Copyright (C) 2007 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ + +#ifdef HAVE_LIBZ +#include +#endif +#include + +#include "types.h" + +#define ROMREADER_DEFAULT -1 +#define ROMREADER_STD 0 +#define ROMREADER_GZIP 1 +#define ROMREADER_ZIP 2 + +typedef struct +{ + int id; + const char * Name; + void * (*Init)(const char * filename); + void (*DeInit)(void * file); + u32 (*Size)(void * file); + int (*Seek)(void * file, int offset, int whence); + int (*Read)(void * file, void * buffer, u32 size); +} ROMReader_struct; + +extern ROMReader_struct STDROMReader; +#ifdef HAVE_LIBZ +extern ROMReader_struct GZIPROMReader; +#endif +#ifdef HAVE_LIBZZIP +extern ROMReader_struct ZIPROMReader; +#endif + +ROMReader_struct * ROMReaderInit(char ** filename); diff --git a/jni/desmume/src/SPU.cpp b/jni/desmume/src/SPU.cpp new file mode 100755 index 0000000..9a08084 --- /dev/null +++ b/jni/desmume/src/SPU.cpp @@ -0,0 +1,1779 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2006 Theo Berkau + Copyright (C) 2008-2012 DeSmuME team + + Ideas borrowed from Stephane Dallongeville's SCSP core + + This file 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 file 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 the this software. If not, see . +*/ + + +#define _USE_MATH_DEFINES +#include +#ifndef M_PI +#define M_PI 3.1415926535897932386 +#endif + +#include +#include +#include +#include + +#include "debug.h" +#include "MMU.h" +#include "SPU.h" +#include "mem.h" +#include "readwrite.h" +#include "armcpu.h" +#include "NDSSystem.h" +#include "matrix.h" + +#include "metaspu/metaspu.h" + +#define K_ADPCM_LOOPING_RECOVERY_INDEX 99999 +#define COSINE_INTERPOLATION_RESOLUTION 8192 + +//#ifdef FASTBUILD + #undef FORCEINLINE + #define FORCEINLINE +//#endif + +//static ISynchronizingAudioBuffer* synchronizer = metaspu_construct(ESynchMethod_Z); +static ISynchronizingAudioBuffer* synchronizer = metaspu_construct(ESynchMethod_N); + +SPU_struct *SPU_core = 0; +SPU_struct *SPU_user = 0; +int SPU_currentCoreNum = SNDCORE_DUMMY; +static int volume = 100; + + +static int buffersize = 0; +static ESynchMode synchmode = ESynchMode_DualSynchAsynch; +static ESynchMethod synchmethod = ESynchMethod_N; + +static int SNDCoreId=-1; +static SoundInterface_struct *SNDCore=NULL; +extern SoundInterface_struct *SNDCoreList[]; + +//const int shift = (FORMAT == 0 ? 2 : 1); +static const int format_shift[] = { 2, 1, 3, 0 }; + +static const s8 indextbl[8] = +{ + -1, -1, -1, -1, 2, 4, 6, 8 +}; + +static const u16 adpcmtbl[89] = +{ + 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x0010, + 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001C, 0x001F, 0x0022, 0x0025, + 0x0029, 0x002D, 0x0032, 0x0037, 0x003C, 0x0042, 0x0049, 0x0050, 0x0058, + 0x0061, 0x006B, 0x0076, 0x0082, 0x008F, 0x009D, 0x00AD, 0x00BE, 0x00D1, + 0x00E6, 0x00FD, 0x0117, 0x0133, 0x0151, 0x0173, 0x0198, 0x01C1, 0x01EE, + 0x0220, 0x0256, 0x0292, 0x02D4, 0x031C, 0x036C, 0x03C3, 0x0424, 0x048E, + 0x0502, 0x0583, 0x0610, 0x06AB, 0x0756, 0x0812, 0x08E0, 0x09C3, 0x0ABD, + 0x0BD0, 0x0CFF, 0x0E4C, 0x0FBA, 0x114C, 0x1307, 0x14EE, 0x1706, 0x1954, + 0x1BDC, 0x1EA5, 0x21B6, 0x2515, 0x28CA, 0x2CDF, 0x315B, 0x364B, 0x3BB9, + 0x41B2, 0x4844, 0x4F7E, 0x5771, 0x602F, 0x69CE, 0x7462, 0x7FFF +}; + +static const s16 wavedutytbl[8][8] = { + { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF }, + { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF }, + { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF }, + { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF }, + { -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF }, + { -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF }, + { -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF }, + { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF } +}; + +static s32 precalcdifftbl[89][16]; +static u8 precalcindextbl[89][8]; +static double cos_lut[COSINE_INTERPOLATION_RESOLUTION]; + +static const double ARM7_CLOCK = 33513982; + +static const double samples_per_hline = (DESMUME_SAMPLE_RATE / 59.8261f) / 263.0f; + +static double samples = 0; + +template +static FORCEINLINE T MinMax(T val, T min, T max) +{ + if (val < min) + return min; + else if (val > max) + return max; + + return val; +} + +//--------------external spu interface--------------- + +int SPU_ChangeSoundCore(int coreid, int buffersize) +{ + int i; + + ::buffersize = buffersize; + + delete SPU_user; SPU_user = NULL; + + // Make sure the old core is freed + if (SNDCore) + SNDCore->DeInit(); + + // So which core do we want? + if (coreid == SNDCORE_DEFAULT) + coreid = 0; // Assume we want the first one + + SPU_currentCoreNum = coreid; + + // Go through core list and find the id + for (i = 0; SNDCoreList[i] != NULL; i++) + { + if (SNDCoreList[i]->id == coreid) + { + // Set to current core + SNDCore = SNDCoreList[i]; + break; + } + } + + SNDCoreId = coreid; + + //If the user picked the dummy core, disable the user spu + if(SNDCore == &SNDDummy) + return 0; + + //If the core wasnt found in the list for some reason, disable the user spu + if (SNDCore == NULL) + return -1; + + // Since it failed, instead of it being fatal, disable the user spu + if (SNDCore->Init(buffersize * 2) == -1) + { + SNDCore = 0; + return -1; + } + + SNDCore->SetVolume(volume); + + SPU_SetSynchMode(synchmode,synchmethod); + + return 0; +} + +SoundInterface_struct *SPU_SoundCore() +{ + return SNDCore; +} + +void SPU_ReInit() +{ + SPU_Init(SNDCoreId, buffersize); +} + +int SPU_Init(int coreid, int buffersize) +{ + int i, j; + + // Build the cosine interpolation LUT + for(unsigned int i = 0; i < COSINE_INTERPOLATION_RESOLUTION; i++) + cos_lut[i] = (1.0 - cos(((double)i/(double)COSINE_INTERPOLATION_RESOLUTION) * M_PI)) * 0.5; + + SPU_core = new SPU_struct((int)ceil(samples_per_hline)); + SPU_Reset(); + + //create adpcm decode accelerator lookups + for(i = 0; i < 16; i++) + { + for(j = 0; j < 89; j++) + { + precalcdifftbl[j][i] = (((i & 0x7) * 2 + 1) * adpcmtbl[j] / 8); + if(i & 0x8) precalcdifftbl[j][i] = -precalcdifftbl[j][i]; + } + } + for(i = 0; i < 8; i++) + { + for(j = 0; j < 89; j++) + { + precalcindextbl[j][i] = MinMax((j + indextbl[i]), 0, 88); + } + } + + return SPU_ChangeSoundCore(coreid, buffersize); +} + +void SPU_Pause(int pause) +{ + if (SNDCore == NULL) return; + + if(pause) + SNDCore->MuteAudio(); + else + SNDCore->UnMuteAudio(); +} + +void SPU_CloneUser() +{ + if(SPU_user) { + memcpy(SPU_user->channels,SPU_core->channels,sizeof(SPU_core->channels)); + SPU_user->regs = SPU_core->regs; + } +} + + +void SPU_SetSynchMode(int mode, int method) +{ + synchmode = (ESynchMode)mode; + if(synchmethod != (ESynchMethod)method) + { + synchmethod = (ESynchMethod)method; + delete synchronizer; + //grr does this need to be locked? spu might need a lock method + // or maybe not, maybe the platform-specific code that calls this function can deal with it. + synchronizer = metaspu_construct(synchmethod); + } + + delete SPU_user; + SPU_user = NULL; + + if(synchmode == ESynchMode_DualSynchAsynch) + { + SPU_user = new SPU_struct(buffersize); + SPU_CloneUser(); + } +} + +void SPU_ClearOutputBuffer() +{ + if(SNDCore && SNDCore->ClearBuffer) + SNDCore->ClearBuffer(); +} + +void SPU_SetVolume(int volume) +{ + ::volume = volume; + if (SNDCore) + SNDCore->SetVolume(volume); +} + + +void SPU_Reset(void) +{ + int i; + + SPU_core->reset(); + + if(SPU_user) { + if(SNDCore) + { + SNDCore->DeInit(); + SNDCore->Init(SPU_user->bufsize*2); + SNDCore->SetVolume(volume); + } + SPU_user->reset(); + } + + //zero - 09-apr-2010: this concerns me, regarding savestate synch. + //After 0.9.6, lets experiment with removing it and just properly zapping the spu instead + // Reset Registers + for (i = 0x400; i < 0x51D; i++) + T1WriteByte(MMU.ARM7_REG, i, 0); + + samples = 0; +} + +//------------------------------------------ + +void SPU_struct::reset() +{ + memset(sndbuf,0,bufsize*2*4); + memset(outbuf,0,bufsize*2*2); + + memset((void *)channels, 0, sizeof(channel_struct) * 16); + + reconstruct(®s); + + for(int i = 0; i < 16; i++) + { + channels[i].num = i; + } +} + +SPU_struct::SPU_struct(int buffersize) + : bufpos(0) + , buflength(0) + , sndbuf(0) + , outbuf(0) + , bufsize(buffersize) +{ + sndbuf = new s32[buffersize*2]; + outbuf = new s16[buffersize*2]; + reset(); +} + +SPU_struct::~SPU_struct() +{ + if(sndbuf) delete[] sndbuf; + if(outbuf) delete[] outbuf; +} + +void SPU_DeInit(void) +{ + if(SNDCore) + SNDCore->DeInit(); + SNDCore = 0; + + delete SPU_core; SPU_core=0; + delete SPU_user; SPU_user=0; +} + +////////////////////////////////////////////////////////////////////////////// + +void SPU_struct::ShutUp() +{ + for(int i=0;i<16;i++) + channels[i].status = CHANSTAT_STOPPED; +} + +static FORCEINLINE void adjust_channel_timer(channel_struct *chan) +{ + chan->sampinc = (((double)ARM7_CLOCK) / (DESMUME_SAMPLE_RATE * 2)) / (double)(0x10000 - chan->timer); +} + +void SPU_struct::KeyProbe(int chan_num) +{ + channel_struct &thischan = channels[chan_num]; + if(thischan.status == CHANSTAT_STOPPED) + { + if(thischan.keyon && regs.masteren) + KeyOn(chan_num); + } + else if(thischan.status == CHANSTAT_PLAY) + { + if(!thischan.keyon || !regs.masteren) + KeyOff(chan_num); + } +} + +void SPU_struct::KeyOff(int channel) +{ + //printf("keyoff%d\n",channel); + channel_struct &thischan = channels[channel]; + thischan.status = CHANSTAT_STOPPED; +} + +void SPU_struct::KeyOn(int channel) +{ + channel_struct &thischan = channels[channel]; + thischan.status = CHANSTAT_PLAY; + + thischan.totlength = thischan.length + thischan.loopstart; + adjust_channel_timer(&thischan); + + //printf("keyon %d totlength:%d\n",channel,thischan.totlength); + + + //LOG("Channel %d key on: vol = %d, datashift = %d, hold = %d, pan = %d, waveduty = %d, repeat = %d, format = %d, source address = %07X," + // "timer = %04X, loop start = %04X, length = %06X, MMU.ARM7_REG[0x501] = %02X\n", channel, chan->vol, chan->datashift, chan->hold, + // chan->pan, chan->waveduty, chan->repeat, chan->format, chan->addr, chan->timer, chan->loopstart, chan->length, T1ReadByte(MMU.ARM7_REG, 0x501)); + + switch(thischan.format) + { + case 0: // 8-bit + thischan.buf8 = (s8*)&MMU.MMU_MEM[1][(thischan.addr>>20)&0xFF][(thischan.addr & MMU.MMU_MASK[1][(thischan.addr >> 20) & 0xFF])]; + // thischan.loopstart = thischan.loopstart << 2; + // thischan.length = (thischan.length << 2) + thischan.loopstart; + thischan.sampcnt = -3; + break; + case 1: // 16-bit + thischan.buf16 = (s16 *)&MMU.MMU_MEM[1][(thischan.addr>>20)&0xFF][(thischan.addr & MMU.MMU_MASK[1][(thischan.addr >> 20) & 0xFF])]; + // thischan.loopstart = thischan.loopstart << 1; + // thischan.length = (thischan.length << 1) + thischan.loopstart; + thischan.sampcnt = -3; + break; + case 2: // ADPCM + { + thischan.buf8 = (s8*)&MMU.MMU_MEM[1][(thischan.addr>>20)&0xFF][(thischan.addr & MMU.MMU_MASK[1][(thischan.addr >> 20) & 0xFF])]; + thischan.pcm16b = (s16)((thischan.buf8[1] << 8) | thischan.buf8[0]); + thischan.pcm16b_last = thischan.pcm16b; + thischan.index = thischan.buf8[2] & 0x7F; + thischan.lastsampcnt = 7; + thischan.sampcnt = -3; + thischan.loop_index = K_ADPCM_LOOPING_RECOVERY_INDEX; + // thischan.loopstart = thischan.loopstart << 3; + // thischan.length = (thischan.length << 3) + thischan.loopstart; + break; + } + case 3: // PSG + { + thischan.sampcnt = -1; + thischan.x = 0x7FFF; + break; + } + default: break; + } + + thischan.double_totlength_shifted = (double)(thischan.totlength << format_shift[thischan.format]); + + if(thischan.format != 3) + { + if(thischan.double_totlength_shifted == 0) + { + printf("INFO: Stopping channel %d due to zero length\n",channel); + thischan.status = CHANSTAT_STOPPED; + } + } +} + +////////////////////////////////////////////////////////////////////////////// + +#define SETBYTE(which,oldval,newval) oldval = (oldval & (~(0xFF<<(which*8)))) | ((newval)<<(which*8)) +#define GETBYTE(which,val) ((val>>(which*8))&0xFF) + + +u8 SPU_ReadByte(u32 addr) { + addr &= 0xFFF; + return SPU_core->ReadByte(addr); +} +u16 SPU_ReadWord(u32 addr) { + addr &= 0xFFF; + return SPU_core->ReadWord(addr); +} +u32 SPU_ReadLong(u32 addr) { + addr &= 0xFFF; + return SPU_core->ReadLong(addr); +} + +u16 SPU_struct::ReadWord(u32 addr) +{ + return ReadByte(addr)|(ReadByte(addr+1)<<8); +} + +u32 SPU_struct::ReadLong(u32 addr) +{ + return ReadByte(addr)|(ReadByte(addr+1)<<8)|(ReadByte(addr+2)<<16)|(ReadByte(addr+3)<<24); +} + +u8 SPU_struct::ReadByte(u32 addr) +{ + switch(addr) + { + //SOUNDCNT + case 0x500: return regs.mastervol; + case 0x501: + return (regs.ctl_left)|(regs.ctl_right<<2)|(regs.ctl_ch1bypass<<4)|(regs.ctl_ch3bypass<<5)|(regs.masteren<<7); + case 0x502: return 0; + case 0x503: return 0; + + //SOUNDBIAS + case 0x504: return regs.soundbias&0xFF; + case 0x505: return (regs.soundbias>>8)&0xFF; + case 0x506: return 0; + case 0x507: return 0; + + //SNDCAP0CNT/SNDCAP1CNT + case 0x508: + case 0x509: { + u32 which = addr-0x508; + return regs.cap[which].add + | (regs.cap[which].source<<1) + | (regs.cap[which].oneshot<<2) + | (regs.cap[which].bits8<<3) + //| (regs.cap[which].active<<7); //? which is right? need test + | (regs.cap[which].runtime.running<<7); + } + + //SNDCAP0DAD + case 0x510: return GETBYTE(0,regs.cap[0].dad); + case 0x511: return GETBYTE(1,regs.cap[0].dad); + case 0x512: return GETBYTE(2,regs.cap[0].dad); + case 0x513: return GETBYTE(3,regs.cap[0].dad); + + //SNDCAP0LEN + case 0x514: return GETBYTE(0,regs.cap[0].len); + case 0x515: return GETBYTE(1,regs.cap[0].len); + case 0x516: return 0; //not used + case 0x517: return 0; //not used + + //SNDCAP1DAD + case 0x518: return GETBYTE(0,regs.cap[1].dad); + case 0x519: return GETBYTE(1,regs.cap[1].dad); + case 0x51A: return GETBYTE(2,regs.cap[1].dad); + case 0x51B: return GETBYTE(3,regs.cap[1].dad); + + //SNDCAP1LEN + case 0x51C: return GETBYTE(0,regs.cap[1].len); + case 0x51D: return GETBYTE(1,regs.cap[1].len); + case 0x51E: return 0; //not used + case 0x51F: return 0; //not used + + default: { + //individual channel regs + + u32 chan_num = (addr >> 4) & 0xF; + if(chan_num>0xF) return 0; + channel_struct &thischan=channels[chan_num]; + + switch(addr & 0xF) { + case 0x0: return thischan.vol; + case 0x1: { + u8 ret = thischan.datashift; + if(ret==4) ret=3; + ret |= thischan.hold<<7; + return ret; + } + case 0x2: return thischan.pan; + case 0x3: return thischan.waveduty|(thischan.repeat<<3)|(thischan.format<<5)|((thischan.status == CHANSTAT_PLAY)?0x80:0); + case 0x4: return 0; //return GETBYTE(0,thischan.addr); //not readable + case 0x5: return 0; //return GETBYTE(1,thischan.addr); //not readable + case 0x6: return 0; //return GETBYTE(2,thischan.addr); //not readable + case 0x7: return 0; //return GETBYTE(3,thischan.addr); //not readable + case 0x8: return GETBYTE(0,thischan.timer); + case 0x9: return GETBYTE(1,thischan.timer); + case 0xA: return GETBYTE(0,thischan.loopstart); + case 0xB: return GETBYTE(1,thischan.loopstart); + case 0xC: return 0; //return GETBYTE(0,thischan.length); //not readable + case 0xD: return 0; //return GETBYTE(1,thischan.length); //not readable + case 0xE: return 0; //return GETBYTE(2,thischan.length); //not readable + case 0xF: return 0; //return GETBYTE(3,thischan.length); //not readable + default: return 0; //impossible + } //switch on individual channel regs + } //default case + } //switch on address +} + +SPUFifo::SPUFifo() +{ + reset(); +} + +void SPUFifo::reset() +{ + head = tail = size = 0; +} + +void SPUFifo::enqueue(s16 val) +{ + if(size==16) return; + buffer[tail] = val; + tail++; + tail &= 15; + size++; +} + +s16 SPUFifo::dequeue() +{ + if(size==0) return 0; + head++; + head &= 15; + s16 ret = buffer[head]; + size--; + return ret; +} + +void SPUFifo::save(EMUFILE* fp) +{ + u32 version = 1; + write32le(version,fp); + write32le(head,fp); + write32le(tail,fp); + write32le(size,fp); + for(int i=0;i<16;i++) + write16le(buffer[i],fp); +} + +bool SPUFifo::load(EMUFILE* fp) +{ + u32 version; + if(read32le(&version,fp) != 1) return false; + read32le(&head,fp); + read32le(&tail,fp); + read32le(&size,fp); + for(int i=0;i<16;i++) + read16le(&buffer[i],fp); + return true; +} + +void SPU_struct::ProbeCapture(int which) +{ + //VERY UNTESTED -- HOW MUCH OF THIS RESETS, AND WHEN? + + if(!regs.cap[which].active) + { + regs.cap[which].runtime.running = 0; + return; + } + + REGS::CAP &cap = regs.cap[which]; + cap.runtime.running = 1; + cap.runtime.curdad = cap.dad; + u32 len = cap.len; + if(len==0) len=1; + cap.runtime.maxdad = cap.dad + len*4; + cap.runtime.sampcnt = 0; + cap.runtime.fifo.reset(); +} + +void SPU_struct::WriteByte(u32 addr, u8 val) +{ + switch(addr) + { + //SOUNDCNT + case 0x500: + regs.mastervol = val&0x7F; + break; + case 0x501: + regs.ctl_left = (val>>0)&3; + regs.ctl_right = (val>>2)&3; + regs.ctl_ch1bypass = (val>>4)&1; + regs.ctl_ch3bypass = (val>>5)&1; + regs.masteren = (val>>7)&1; + for(int i=0;i<16;i++) + KeyProbe(i); + break; + case 0x502: break; //not used + case 0x503: break; //not used + + //SOUNDBIAS + case 0x504: SETBYTE(0,regs.soundbias, val); break; + case 0x505: SETBYTE(1,regs.soundbias, val&3); break; + case 0x506: break; //these dont answer anyway + case 0x507: break; //these dont answer anyway + + //SNDCAP0CNT/SNDCAP1CNT + case 0x508: + case 0x509: { + u32 which = addr-0x508; + regs.cap[which].add = BIT0(val); + regs.cap[which].source = BIT1(val); + regs.cap[which].oneshot = BIT2(val); + regs.cap[which].bits8 = BIT3(val); + regs.cap[which].active = BIT7(val); + ProbeCapture(which); + break; + } + + //SNDCAP0DAD + case 0x510: SETBYTE(0,regs.cap[0].dad,val); break; + case 0x511: SETBYTE(1,regs.cap[0].dad,val); break; + case 0x512: SETBYTE(2,regs.cap[0].dad,val); break; + case 0x513: SETBYTE(3,regs.cap[0].dad,val&7); break; + + //SNDCAP0LEN + case 0x514: SETBYTE(0,regs.cap[0].len,val); break; + case 0x515: SETBYTE(1,regs.cap[0].len,val); break; + case 0x516: break; //not used + case 0x517: break; //not used + + //SNDCAP1DAD + case 0x518: SETBYTE(0,regs.cap[1].dad,val); break; + case 0x519: SETBYTE(1,regs.cap[1].dad,val); break; + case 0x51A: SETBYTE(2,regs.cap[1].dad,val); break; + case 0x51B: SETBYTE(3,regs.cap[1].dad,val&7); break; + + //SNDCAP1LEN + case 0x51C: SETBYTE(0,regs.cap[1].len,val); break; + case 0x51D: SETBYTE(1,regs.cap[1].len,val); break; + case 0x51E: break; //not used + case 0x51F: break; //not used + + + + default: { + //individual channel regs + + u32 chan_num = (addr >> 4) & 0xF; + if(chan_num>0xF) break; + channel_struct &thischan=channels[chan_num]; + + switch(addr & 0xF) { + case 0x0: + thischan.vol = val & 0x7F; + break; + case 0x1: + thischan.datashift = val & 0x3; + if (thischan.datashift == 3) + thischan.datashift = 4; + thischan.hold = (val >> 7) & 0x1; + break; + case 0x2: + thischan.pan = val & 0x7F; + break; + case 0x3: + thischan.waveduty = val & 0x7; + thischan.repeat = (val >> 3) & 0x3; + thischan.format = (val >> 5) & 0x3; + thischan.keyon = BIT7(val); + KeyProbe(chan_num); + break; + case 0x4: SETBYTE(0,thischan.addr,val); break; + case 0x5: SETBYTE(1,thischan.addr,val); break; + case 0x6: SETBYTE(2,thischan.addr,val); break; + case 0x7: SETBYTE(3,thischan.addr,val&0x7); break; //only 27 bits of this register are used + case 0x8: + SETBYTE(0,thischan.timer,val); + adjust_channel_timer(&thischan); + break; + case 0x9: + SETBYTE(1,thischan.timer,val); + adjust_channel_timer(&thischan); + break; + case 0xA: SETBYTE(0,thischan.loopstart,val); break; + case 0xB: SETBYTE(1,thischan.loopstart,val); break; + case 0xC: SETBYTE(0,thischan.length,val); break; + case 0xD: SETBYTE(1,thischan.length,val); break; + case 0xE: SETBYTE(2,thischan.length,val & 0x3F); break; //only 22 bits of this register are used + case 0xF: SETBYTE(3,thischan.length,0); break; + } //switch on individual channel regs + } //default case + } //switch on address +} + +void SPU_WriteByte(u32 addr, u8 val) +{ + //printf("%08X: chan:%02X reg:%02X val:%02X\n",addr,(addr>>4)&0xF,addr&0xF,val); + addr &= 0xFFF; + + SPU_core->WriteByte(addr,val); + if(SPU_user) SPU_user->WriteByte(addr,val); +} + +////////////////////////////////////////////////////////////////////////////// + +void SPU_struct::WriteWord(u32 addr, u16 val) +{ + WriteByte(addr,val&0xFF); + WriteByte(addr+1,(val>>8)&0xFF); +} + +void SPU_WriteWord(u32 addr, u16 val) +{ + //printf("%08X: chan:%02X reg:%02X val:%04X\n",addr,(addr>>4)&0xF,addr&0xF,val); + addr &= 0xFFF; + + SPU_core->WriteWord(addr,val); + if(SPU_user) SPU_user->WriteWord(addr,val); +} + +////////////////////////////////////////////////////////////////////////////// + +void SPU_struct::WriteLong(u32 addr, u32 val) +{ + WriteByte(addr,val&0xFF); + WriteByte(addr+1,(val>>8)&0xFF); + WriteByte(addr+2,(val>>16)&0xFF); + WriteByte(addr+3,(val>>24)&0xFF); +} + +void SPU_WriteLong(u32 addr, u32 val) +{ + //printf("%08X: chan:%02X reg:%02X val:%08X\n",addr,(addr>>4)&0xF,addr&0xF,val); + addr &= 0xFFF; + + SPU_core->WriteLong(addr,val); + if(SPU_user) + SPU_user->WriteLong(addr,val); +} + +////////////////////////////////////////////////////////////////////////////// + +template static FORCEINLINE s32 Interpolate(s32 a, s32 b, double ratio) +{ + double sampleA = (double)a; + double sampleB = (double)b; + ratio = ratio - sputrunc(ratio); + + switch (INTERPOLATE_MODE) + { + case SPUInterpolation_Cosine: + // Cosine Interpolation Formula: + // ratio2 = (1 - cos(ratio * M_PI)) / 2 + // sampleI = sampleA * (1 - ratio2) + sampleB * ratio2 + return s32floor((cos_lut[(unsigned int)(ratio * (double)COSINE_INTERPOLATION_RESOLUTION)] * (sampleB - sampleA)) + sampleA); + break; + + case SPUInterpolation_Linear: + // Linear Interpolation Formula: + // sampleI = sampleA * (1 - ratio) + sampleB * ratio + return s32floor((ratio * (sampleB - sampleA)) + sampleA); + break; + + default: + break; + } + + return a; +} + +////////////////////////////////////////////////////////////////////////////// + +template static FORCEINLINE void Fetch8BitData(channel_struct *chan, s32 *data) +{ + if (chan->sampcnt < 0) + { + *data = 0; + return; + } + + u32 loc = sputrunc(chan->sampcnt); + if(INTERPOLATE_MODE != SPUInterpolation_None) + { + s32 a = (s32)(chan->buf8[loc] << 8); + if(loc < (chan->totlength << 2) - 1) { + s32 b = (s32)(chan->buf8[loc + 1] << 8); + a = Interpolate(a, b, chan->sampcnt); + } + *data = a; + } + else + *data = (s32)chan->buf8[loc] << 8; +} + +template static FORCEINLINE void Fetch16BitData(const channel_struct * const chan, s32 *data) +{ + if (chan->sampcnt < 0) + { + *data = 0; + return; + } + + if(INTERPOLATE_MODE != SPUInterpolation_None) + { + u32 loc = sputrunc(chan->sampcnt); + s32 a = (s32)chan->buf16[loc], b; + if(loc < (chan->totlength << 1) - 1) + { + b = (s32)chan->buf16[loc + 1]; + a = Interpolate(a, b, chan->sampcnt); + } + *data = a; + } + else + *data = (s32)chan->buf16[sputrunc(chan->sampcnt)]; +} + +template static FORCEINLINE void FetchADPCMData(channel_struct * const chan, s32 * const data) +{ + if (chan->sampcnt < 8) + { + *data = 0; + return; + } + + // No sense decoding, just return the last sample + if (chan->lastsampcnt != sputrunc(chan->sampcnt)){ + + const u32 endExclusive = sputrunc(chan->sampcnt+1); + for (u32 i = chan->lastsampcnt+1; i < endExclusive; i++) + { + const u32 shift = (i&1)<<2; + const u32 data4bit = (((u32)chan->buf8[i >> 1]) >> shift); + + const s32 diff = precalcdifftbl[chan->index][data4bit & 0xF]; + chan->index = precalcindextbl[chan->index][data4bit & 0x7]; + + chan->pcm16b_last = chan->pcm16b; + chan->pcm16b = MinMax(chan->pcm16b+diff, -0x8000, 0x7FFF); + + if(i == (chan->loopstart<<3)) { + if(chan->loop_index != K_ADPCM_LOOPING_RECOVERY_INDEX) printf("over-snagging\n"); + chan->loop_pcm16b = chan->pcm16b; + chan->loop_index = chan->index; + } + } + + chan->lastsampcnt = sputrunc(chan->sampcnt); + } + + if(INTERPOLATE_MODE != SPUInterpolation_None) + *data = Interpolate((s32)chan->pcm16b_last,(s32)chan->pcm16b,chan->sampcnt); + else + *data = (s32)chan->pcm16b; +} + +static FORCEINLINE void FetchPSGData(channel_struct *chan, s32 *data) +{ + if (chan->sampcnt < 0) + { + *data = 0; + return; + } + + if(chan->num < 8) + { + *data = 0; + } + else if(chan->num < 14) + { + *data = (s32)wavedutytbl[chan->waveduty][(sputrunc(chan->sampcnt)) & 0x7]; + } + else + { + if(chan->lastsampcnt == sputrunc(chan->sampcnt)) + { + *data = (s32)chan->psgnoise_last; + return; + } + + u32 max = sputrunc(chan->sampcnt); + for(u32 i = chan->lastsampcnt; i < max; i++) + { + if(chan->x & 0x1) + { + chan->x = (chan->x >> 1) ^ 0x6000; + chan->psgnoise_last = -0x7FFF; + } + else + { + chan->x >>= 1; + chan->psgnoise_last = 0x7FFF; + } + } + + chan->lastsampcnt = sputrunc(chan->sampcnt); + + *data = (s32)chan->psgnoise_last; + } +} + +////////////////////////////////////////////////////////////////////////////// + +static FORCEINLINE void MixL(SPU_struct* SPU, channel_struct *chan, s32 data) +{ + data = spumuldiv7(data, chan->vol) >> chan->datashift; + SPU->sndbuf[SPU->bufpos<<1] += data; +} + +static FORCEINLINE void MixR(SPU_struct* SPU, channel_struct *chan, s32 data) +{ + data = spumuldiv7(data, chan->vol) >> chan->datashift; + SPU->sndbuf[(SPU->bufpos<<1)+1] += data; +} + +static FORCEINLINE void MixLR(SPU_struct* SPU, channel_struct *chan, s32 data) +{ + data = spumuldiv7(data, chan->vol) >> chan->datashift; + SPU->sndbuf[SPU->bufpos<<1] += spumuldiv7(data, 127 - chan->pan); + SPU->sndbuf[(SPU->bufpos<<1)+1] += spumuldiv7(data, chan->pan); +} + +////////////////////////////////////////////////////////////////////////////// + +template static FORCEINLINE void TestForLoop(SPU_struct *SPU, channel_struct *chan) +{ + const int shift = (FORMAT == 0 ? 2 : 1); + + chan->sampcnt += chan->sampinc; + + if (chan->sampcnt > chan->double_totlength_shifted) + { + // Do we loop? Or are we done? + if (chan->repeat == 1) + { + while (chan->sampcnt > chan->double_totlength_shifted) + chan->sampcnt -= chan->double_totlength_shifted - (double)(chan->loopstart << shift); + //chan->sampcnt = (double)(chan->loopstart << shift); + } + else + { + SPU->KeyOff(chan->num); + SPU->bufpos = SPU->buflength; + } + } +} + +static FORCEINLINE void TestForLoop2(SPU_struct *SPU, channel_struct *chan) +{ + chan->sampcnt += chan->sampinc; + + if (chan->sampcnt > chan->double_totlength_shifted) + { + // Do we loop? Or are we done? + if (chan->repeat == 1) + { + while (chan->sampcnt > chan->double_totlength_shifted) + chan->sampcnt -= chan->double_totlength_shifted - (double)(chan->loopstart << 3); + + if(chan->loop_index == K_ADPCM_LOOPING_RECOVERY_INDEX) + { + chan->pcm16b = (s16)((chan->buf8[1] << 8) | chan->buf8[0]); + chan->index = chan->buf8[2] & 0x7F; + chan->lastsampcnt = 7; + } + else + { + chan->pcm16b = chan->loop_pcm16b; + chan->index = chan->loop_index; + chan->lastsampcnt = (chan->loopstart << 3); + } + } + else + { + chan->status = CHANSTAT_STOPPED; + SPU->KeyOff(chan->num); + SPU->bufpos = SPU->buflength; + } + } +} + +template FORCEINLINE static void SPU_Mix(SPU_struct* SPU, channel_struct *chan, s32 data) +{ + switch(CHANNELS) + { + case 0: MixL(SPU, chan, data); break; + case 1: MixLR(SPU, chan, data); break; + case 2: MixR(SPU, chan, data); break; + } + SPU->lastdata = data; +} + +//WORK +template + FORCEINLINE static void ____SPU_ChanUpdate(SPU_struct* const SPU, channel_struct* const chan) +{ + for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) + { + if(CHANNELS != -1) + { + s32 data; + switch(FORMAT) + { + case 0: Fetch8BitData(chan, &data); break; + case 1: Fetch16BitData(chan, &data); break; + case 2: FetchADPCMData(chan, &data); break; + case 3: FetchPSGData(chan, &data); break; + } + SPU_Mix(SPU, chan, data); + } + + switch(FORMAT) { + case 0: case 1: TestForLoop(SPU, chan); break; + case 2: TestForLoop2(SPU, chan); break; + case 3: chan->sampcnt += chan->sampinc; break; + } + } +} + +template + FORCEINLINE static void ___SPU_ChanUpdate(const bool actuallyMix, SPU_struct* const SPU, channel_struct* const chan) +{ + if(!actuallyMix) + ____SPU_ChanUpdate(SPU,chan); + else if (chan->pan == 0) + ____SPU_ChanUpdate(SPU,chan); + else if (chan->pan == 127) + ____SPU_ChanUpdate(SPU,chan); + else + ____SPU_ChanUpdate(SPU,chan); +} + +template + FORCEINLINE static void __SPU_ChanUpdate(const bool actuallyMix, SPU_struct* const SPU, channel_struct* const chan) +{ + switch(chan->format) + { + case 0: ___SPU_ChanUpdate<0,INTERPOLATE_MODE>(actuallyMix, SPU, chan); break; + case 1: ___SPU_ChanUpdate<1,INTERPOLATE_MODE>(actuallyMix, SPU, chan); break; + case 2: ___SPU_ChanUpdate<2,INTERPOLATE_MODE>(actuallyMix, SPU, chan); break; + case 3: ___SPU_ChanUpdate<3,INTERPOLATE_MODE>(actuallyMix, SPU, chan); break; + default: assert(false); + } +} + +FORCEINLINE static void _SPU_ChanUpdate(const bool actuallyMix, SPU_struct* const SPU, channel_struct* const chan) +{ + switch(CommonSettings.spuInterpolationMode) + { + case SPUInterpolation_None: __SPU_ChanUpdate(actuallyMix, SPU, chan); break; + case SPUInterpolation_Linear: __SPU_ChanUpdate(actuallyMix, SPU, chan); break; + case SPUInterpolation_Cosine: __SPU_ChanUpdate(actuallyMix, SPU, chan); break; + default: assert(false); + } +} + +//ENTERNEW +static void SPU_MixAudio_Advanced(bool actuallyMix, SPU_struct *SPU, int length) +{ + //the advanced spu function correctly handles all sound control mixing options, as well as capture + //this code is not entirely optimal, as it relies on sort of manhandling the core mixing functions + //in order to get the results it needs. + + //THIS IS MAX HACKS!!!! + //AND NEEDS TO BE REWRITTEN ALONG WITH THE DEEPEST PARTS OF THE SPU + //ONCE WE KNOW THAT IT WORKS + + //BIAS gets ignored since our spu is still not bit perfect, + //and it doesnt matter for purposes of capture + + //-----------DEBUG CODE + bool skipcap = false; + //----------------- + + s32 samp0[2]; + + //believe it or not, we are going to do this one sample at a time. + //like i said, it is slower. + for(int samp=0;sampsndbuf[0] = 0; + SPU->sndbuf[1] = 0; + SPU->buflength = 1; + + s32 capmix[2] = {0,0}; + s32 mix[2] = {0,0}; + s32 chanout[16]; + s32 submix[32]; + + //generate each channel, and helpfully mix it at the same time + for(int i=0;i<16;i++) + { + channel_struct *chan = &SPU->channels[i]; + + if (chan->status == CHANSTAT_PLAY) + { + SPU->bufpos = 0; + + bool bypass = false; + if(i==1 && SPU->regs.ctl_ch1bypass) bypass=true; + if(i==3 && SPU->regs.ctl_ch3bypass) bypass=true; + + + //output to mixer unless we are bypassed. + //dont output to mixer if the user muted us + bool outputToMix = true; + if(CommonSettings.spu_muteChannels[i]) outputToMix = false; + if(bypass) outputToMix = false; + bool outputToCap = outputToMix; + if(CommonSettings.spu_captureMuted && !bypass) outputToCap = true; + + //channels 1 and 3 should probably always generate their audio + //internally at least, just in case they get used by the spu output + bool domix = outputToCap || outputToMix || i==1 || i==3; + + //clear the output buffer since this is where _SPU_ChanUpdate wants to accumulate things + SPU->sndbuf[0] = SPU->sndbuf[1] = 0; + + //get channel's next output sample. + _SPU_ChanUpdate(domix, SPU, chan); + chanout[i] = SPU->lastdata >> chan->datashift; + + //save the panned results + submix[i*2] = SPU->sndbuf[0]; + submix[i*2+1] = SPU->sndbuf[1]; + + //send sample to our capture mix + if(outputToCap) + { + capmix[0] += submix[i*2]; + capmix[1] += submix[i*2+1]; + } + + //send sample to our main mixer + if(outputToMix) + { + mix[0] += submix[i*2]; + mix[1] += submix[i*2+1]; + } + } + else + { + chanout[i] = 0; + submix[i*2] = 0; + submix[i*2+1] = 0; + } + } //foreach channel + + s32 mixout[2] = {mix[0],mix[1]}; + s32 capmixout[2] = {capmix[0],capmix[1]}; + s32 sndout[2]; + s32 capout[2]; + + //create SPU output + switch(SPU->regs.ctl_left) + { + case SPU_struct::REGS::LOM_LEFT_MIXER: sndout[0] = mixout[0]; break; + case SPU_struct::REGS::LOM_CH1: sndout[0] = submix[1*2+0]; break; + case SPU_struct::REGS::LOM_CH3: sndout[0] = submix[3*2+0]; break; + case SPU_struct::REGS::LOM_CH1_PLUS_CH3: sndout[0] = submix[1*2+0] + submix[3*2+0]; break; + } + switch(SPU->regs.ctl_right) + { + case SPU_struct::REGS::ROM_RIGHT_MIXER: sndout[1] = mixout[1]; break; + case SPU_struct::REGS::ROM_CH1: sndout[1] = submix[1*2+1]; break; + case SPU_struct::REGS::ROM_CH3: sndout[1] = submix[3*2+1]; break; + case SPU_struct::REGS::ROM_CH1_PLUS_CH3: sndout[1] = submix[1*2+1] + submix[3*2+1]; break; + } + + + //generate capture output ("capture bugs" from gbatek are not emulated) + if(SPU->regs.cap[0].source==0) + capout[0] = capmixout[0]; //cap0 = L-mix + else if(SPU->regs.cap[0].add) + capout[0] = chanout[0] + chanout[1]; //cap0 = ch0+ch1 + else capout[0] = chanout[0]; //cap0 = ch0 + + if(SPU->regs.cap[1].source==0) + capout[1] = capmixout[1]; //cap1 = R-mix + else if(SPU->regs.cap[1].add) + capout[1] = chanout[2] + chanout[3]; //cap1 = ch2+ch3 + else capout[1] = chanout[2]; //cap1 = ch2 + + capout[0] = MinMax(capout[0],-0x8000,0x7FFF); + capout[1] = MinMax(capout[1],-0x8000,0x7FFF); + + //write the output sample where it is supposed to go + if(samp==0) + { + samp0[0] = sndout[0]; + samp0[1] = sndout[1]; + } + else + { + SPU->sndbuf[samp*2+0] = sndout[0]; + SPU->sndbuf[samp*2+1] = sndout[1]; + } + + for(int capchan=0;capchan<2;capchan++) + { + if(SPU->regs.cap[capchan].runtime.running) + { + SPU_struct::REGS::CAP& cap = SPU->regs.cap[capchan]; + u32 last = sputrunc(cap.runtime.sampcnt); + cap.runtime.sampcnt += SPU->channels[1+2*capchan].sampinc; + u32 curr = sputrunc(cap.runtime.sampcnt); + for(u32 j=last;j>8; + if(skipcap) _MMU_write08<1,MMU_AT_DMA>(cap.runtime.curdad,0); + else _MMU_write08<1,MMU_AT_DMA>(cap.runtime.curdad,sample8); + cap.runtime.curdad++; + multiplier = 4; + } + else + { + s16 sample16 = sample; + if(skipcap) _MMU_write16<1,MMU_AT_DMA>(cap.runtime.curdad,0); + else _MMU_write16<1,MMU_AT_DMA>(cap.runtime.curdad,sample16); + cap.runtime.curdad+=2; + multiplier = 2; + } + + if(cap.runtime.curdad>=cap.runtime.maxdad) { + cap.runtime.curdad = cap.dad; + cap.runtime.sampcnt -= cap.len*multiplier; + } + } //sampinc loop + } //if capchan running + } //capchan loop + } //main sample loop + + SPU->sndbuf[0] = samp0[0]; + SPU->sndbuf[1] = samp0[1]; +} + +//ENTER +static void SPU_MixAudio(bool actuallyMix, SPU_struct *SPU, int length) +{ + if(actuallyMix) + { + memset(SPU->sndbuf, 0, length*4*2); + memset(SPU->outbuf, 0, length*2*2); + } + + //we used to use master enable here, and do nothing if audio is disabled. + //now, master enable is emulated better.. + //but for a speed optimization we will still do it + if(!SPU->regs.masteren) return; + + bool advanced = CommonSettings.spu_advanced ; + + //branch here so that slow computers don't have to take the advanced (slower) codepath. + //it remainds to be seen exactly how much slower it is + //if it isnt much slower then we should refactor everything to be simpler, once it is working + if(advanced && SPU == SPU_core) + { + SPU_MixAudio_Advanced(actuallyMix, SPU, length); + } + else + { + //non-advanced mode + for(int i=0;i<16;i++) + { + channel_struct *chan = &SPU->channels[i]; + + if (chan->status != CHANSTAT_PLAY) + continue; + + SPU->bufpos = 0; + SPU->buflength = length; + + // Mix audio + _SPU_ChanUpdate(!CommonSettings.spu_muteChannels[i] && actuallyMix, SPU, chan); + } + } + + //we used to bail out if speakers were disabled. + //this is technically wrong. sound may still be captured, or something. + //in all likelihood, any game doing this probably master disabled the SPU also + //so, optimization of this case is probably not necessary. + //later, we'll just silence the output + bool speakers = T1ReadWord(MMU.ARM7_REG, 0x304) & 0x01; + + u8 vol = SPU->regs.mastervol; + + // convert from 32-bit->16-bit + if(actuallyMix && speakers) + for (int i = 0; i < length*2; i++) + { + // Apply Master Volume + SPU->sndbuf[i] = spumuldiv7(SPU->sndbuf[i], vol); + s16 outsample = MinMax(SPU->sndbuf[i],-0x8000,0x7FFF); + SPU->outbuf[i] = outsample; + } + + +} + +////////////////////////////////////////////////////////////////////////////// + + +//emulates one hline of the cpu core. +//this will produce a variable number of samples, calculated to keep a 44100hz output +//in sync with the emulator framerate +int spu_core_samples = 0; +void SPU_Emulate_core() +{ +#ifdef ANDROID + return; //for now, disable all sound +#endif + samples += samples_per_hline; + spu_core_samples = (int)(samples); + samples -= spu_core_samples; + + bool synchronize = (synchmode == ESynchMode_Synchronous); + bool mix = driver->AVI_IsRecording() || driver->WAV_IsRecording() || synchronize; + + SPU_MixAudio(mix,SPU_core,spu_core_samples); + if(synchronize && SPU_currentCoreNum != SNDCORE_DUMMY) + synchronizer->enqueue_samples(SPU_core->outbuf, spu_core_samples); +} + +void SPU_Emulate_user(bool mix) +{ +#ifdef ANDROID + return; //for now, disable all sound +#endif + u32 audiosize; + + // Check to see how much free space there is + // If there is some, fill up the buffer + if(!SNDCore) return; + audiosize = SNDCore->GetAudioSpace(); + + if (audiosize > 0) + { + //printf("mix %i samples\n", audiosize); + if (audiosize > buffersize) + audiosize = buffersize; + + s16* outbuf; + int samplesOutput; + if(synchmode == ESynchMode_Synchronous) + { + static std::vector tempbuf; + if(tempbuf.size() < audiosize*2) tempbuf.resize(audiosize*2); + outbuf = &tempbuf[0]; + samplesOutput = synchronizer->output_samples(outbuf, audiosize); + } + else if(SPU_user != NULL) + { + outbuf = SPU_user->outbuf; + samplesOutput = (SPU_MixAudio(mix,SPU_user,audiosize), audiosize); + } + else return; + + SNDCore->UpdateAudio(outbuf, samplesOutput); + WAV_WavSoundUpdate(outbuf, samplesOutput, WAVMODE_USER); + } +} + +////////////////////////////////////////////////////////////////////////////// +// Dummy Sound Interface +////////////////////////////////////////////////////////////////////////////// + +int SNDDummyInit(int buffersize); +void SNDDummyDeInit(); +void SNDDummyUpdateAudio(s16 *buffer, u32 num_samples); +u32 SNDDummyGetAudioSpace(); +void SNDDummyMuteAudio(); +void SNDDummyUnMuteAudio(); +void SNDDummySetVolume(int volume); + +SoundInterface_struct SNDDummy = { + SNDCORE_DUMMY, + "Dummy Sound Interface", + SNDDummyInit, + SNDDummyDeInit, + SNDDummyUpdateAudio, + SNDDummyGetAudioSpace, + SNDDummyMuteAudio, + SNDDummyUnMuteAudio, + SNDDummySetVolume +}; + +int SNDDummyInit(int buffersize) { return 0; } +void SNDDummyDeInit() {} +void SNDDummyUpdateAudio(s16 *buffer, u32 num_samples) { } +u32 SNDDummyGetAudioSpace() { return DESMUME_SAMPLE_RATE/60 + 5; } +void SNDDummyMuteAudio() {} +void SNDDummyUnMuteAudio() {} +void SNDDummySetVolume(int volume) {} + +//---------wav writer------------ + +typedef struct { + char id[4]; + u32 size; +} chunk_struct; + +typedef struct { + chunk_struct riff; + char rifftype[4]; +} waveheader_struct; + +typedef struct { + chunk_struct chunk; + u16 compress; + u16 numchan; + u32 rate; + u32 bytespersec; + u16 blockalign; + u16 bitspersample; +} fmt_struct; + +WavWriter::WavWriter() +: spufp(NULL) +{ +} +bool WavWriter::open(const std::string & fname) +{ + waveheader_struct waveheader; + fmt_struct fmt; + chunk_struct data; + size_t elems_written = 0; + + if ((spufp = fopen(fname.c_str(), "wb")) == NULL) + return false; + + // Do wave header + memcpy(waveheader.riff.id, "RIFF", 4); + waveheader.riff.size = 0; // we'll fix this after the file is closed + memcpy(waveheader.rifftype, "WAVE", 4); + elems_written += fwrite((void *)&waveheader, 1, sizeof(waveheader_struct), spufp); + + // fmt chunk + memcpy(fmt.chunk.id, "fmt ", 4); + fmt.chunk.size = 16; // we'll fix this at the end + fmt.compress = 1; // PCM + fmt.numchan = 2; // Stereo + fmt.rate = DESMUME_SAMPLE_RATE; + fmt.bitspersample = 16; + fmt.blockalign = fmt.bitspersample / 8 * fmt.numchan; + fmt.bytespersec = fmt.rate * fmt.blockalign; + elems_written += fwrite((void *)&fmt, 1, sizeof(fmt_struct), spufp); + + // data chunk + memcpy(data.id, "data", 4); + data.size = 0; // we'll fix this at the end + elems_written += fwrite((void *)&data, 1, sizeof(chunk_struct), spufp); + + return true; +} + +void WavWriter::close() +{ + if(!spufp) return; + size_t elems_written = 0; + long length = ftell(spufp); + + // Let's fix the riff chunk size and the data chunk size + fseek(spufp, sizeof(waveheader_struct)-0x8, SEEK_SET); + length -= 0x8; + elems_written += fwrite((void *)&length, 1, 4, spufp); + + fseek(spufp, sizeof(waveheader_struct)+sizeof(fmt_struct)+0x4, SEEK_SET); + length -= sizeof(waveheader_struct)+sizeof(fmt_struct); + elems_written += fwrite((void *)&length, 1, 4, spufp); + fclose(spufp); + spufp = NULL; +} + +void WavWriter::update(void* soundData, int numSamples) +{ + if(!spufp) return; + //TODO - big endian for the s16 samples?? + size_t elems_written = fwrite(soundData, numSamples*2, 2, spufp); +} + +bool WavWriter::isRecording() const +{ + return spufp != NULL; +} + + +static WavWriter wavWriter; + +void WAV_End() +{ + wavWriter.close(); +} + +bool WAV_Begin(const char* fname, WAVMode mode) +{ + WAV_End(); + + if(!wavWriter.open(fname)) + return false; + + if(mode == WAVMODE_ANY) + mode = WAVMODE_CORE; + wavWriter.mode = mode; + + driver->USR_InfoMessage("WAV recording started."); + + return true; +} + +bool WAV_IsRecording(WAVMode mode) +{ + if(wavWriter.mode == mode || mode == WAVMODE_ANY) + return wavWriter.isRecording(); + return false; +} + +void WAV_WavSoundUpdate(void* soundData, int numSamples, WAVMode mode) +{ + if(wavWriter.mode == mode || mode == WAVMODE_ANY) + wavWriter.update(soundData, numSamples); +} + + + +////////////////////////////////////////////////////////////////////////////// + +void spu_savestate(EMUFILE* os) +{ + //version + write32le(6,os); + + SPU_struct *spu = SPU_core; + + for(int j=0;j<16;j++) { + channel_struct &chan = spu->channels[j]; + write32le(chan.num,os); + write8le(chan.vol,os); + write8le(chan.datashift,os); + write8le(chan.hold,os); + write8le(chan.pan,os); + write8le(chan.waveduty,os); + write8le(chan.repeat,os); + write8le(chan.format,os); + write8le(chan.status,os); + write32le(chan.addr,os); + write16le(chan.timer,os); + write16le(chan.loopstart,os); + write32le(chan.length,os); + write64le(double_to_u64(chan.sampcnt),os); + write64le(double_to_u64(chan.sampinc),os); + write32le(chan.lastsampcnt,os); + write16le(chan.pcm16b,os); + write16le(chan.pcm16b_last,os); + write32le(chan.index,os); + write16le(chan.x,os); + write16le(chan.psgnoise_last,os); + write8le(chan.keyon,os); + } + + write64le(double_to_u64(samples),os); + + write8le(spu->regs.mastervol,os); + write8le(spu->regs.ctl_left,os); + write8le(spu->regs.ctl_right,os); + write8le(spu->regs.ctl_ch1bypass,os); + write8le(spu->regs.ctl_ch3bypass,os); + write8le(spu->regs.masteren,os); + write16le(spu->regs.soundbias,os); + + for(int i=0;i<2;i++) + { + write8le(spu->regs.cap[i].add,os); + write8le(spu->regs.cap[i].source,os); + write8le(spu->regs.cap[i].oneshot,os); + write8le(spu->regs.cap[i].bits8,os); + write8le(spu->regs.cap[i].active,os); + write32le(spu->regs.cap[i].dad,os); + write16le(spu->regs.cap[i].len,os); + write8le(spu->regs.cap[i].runtime.running,os); + write32le(spu->regs.cap[i].runtime.curdad,os); + write32le(spu->regs.cap[i].runtime.maxdad,os); + write_double_le(spu->regs.cap[i].runtime.sampcnt,os); + } + + for(int i=0;i<2;i++) + spu->regs.cap[i].runtime.fifo.save(os); +} + +bool spu_loadstate(EMUFILE* is, int size) +{ + u64 temp64; + + //read version + u32 version; + if(read32le(&version,is) != 1) return false; + + SPU_struct *spu = SPU_core; + reconstruct(&SPU_core->regs); + + for(int j=0;j<16;j++) { + channel_struct &chan = spu->channels[j]; + read32le(&chan.num,is); + read8le(&chan.vol,is); + read8le(&chan.datashift,is); + read8le(&chan.hold,is); + read8le(&chan.pan,is); + read8le(&chan.waveduty,is); + read8le(&chan.repeat,is); + read8le(&chan.format,is); + read8le(&chan.status,is); + read32le(&chan.addr,is); + read16le(&chan.timer,is); + read16le(&chan.loopstart,is); + read32le(&chan.length,is); + chan.totlength = chan.length + chan.loopstart; + chan.double_totlength_shifted = (double)(chan.totlength << format_shift[chan.format]); + //printf("%f\n",chan.double_totlength_shifted); + if(version >= 2) + { + read64le(&temp64,is); chan.sampcnt = u64_to_double(temp64); + read64le(&temp64,is); chan.sampinc = u64_to_double(temp64); + } + else + { + read32le((u32*)&chan.sampcnt,is); + read32le((u32*)&chan.sampinc,is); + } + read32le(&chan.lastsampcnt,is); + read16le(&chan.pcm16b,is); + read16le(&chan.pcm16b_last,is); + read32le(&chan.index,is); + read16le(&chan.x,is); + read16le(&chan.psgnoise_last,is); + + if(version>=4) + read8le(&chan.keyon,is); + + //hopefully trigger a recovery of the adpcm looping system + chan.loop_index = K_ADPCM_LOOPING_RECOVERY_INDEX; + + //fixup the pointers which we had are supposed to keep cached + chan.buf8 = (s8*)&MMU.MMU_MEM[1][(chan.addr>>20)&0xFF][(chan.addr & MMU.MMU_MASK[1][(chan.addr >> 20) & 0xFF])]; + chan.buf16 = (s16*)chan.buf8; + } + + if(version>=2) { + read64le(&temp64,is); samples = u64_to_double(temp64); + } + + if(version>=4) + { + read8le(&spu->regs.mastervol,is); + read8le(&spu->regs.ctl_left,is); + read8le(&spu->regs.ctl_right,is); + read8le(&spu->regs.ctl_ch1bypass,is); + read8le(&spu->regs.ctl_ch3bypass,is); + read8le(&spu->regs.masteren,is); + read16le(&spu->regs.soundbias,is); + } + + if(version>=5) + { + for(int i=0;i<2;i++) + { + read8le(&spu->regs.cap[i].add,is); + read8le(&spu->regs.cap[i].source,is); + read8le(&spu->regs.cap[i].oneshot,is); + read8le(&spu->regs.cap[i].bits8,is); + read8le(&spu->regs.cap[i].active,is); + read32le(&spu->regs.cap[i].dad,is); + read16le(&spu->regs.cap[i].len,is); + read8le(&spu->regs.cap[i].runtime.running,is); + read32le(&spu->regs.cap[i].runtime.curdad,is); + read32le(&spu->regs.cap[i].runtime.maxdad,is); + read_double_le(&spu->regs.cap[i].runtime.sampcnt,is); + } + } + + if(version>=6) + for(int i=0;i<2;i++) spu->regs.cap[i].runtime.fifo.load(is); + else + for(int i=0;i<2;i++) spu->regs.cap[i].runtime.fifo.reset(); + + //older versions didnt store a mastervol; + //we must reload this or else games will start silent + if(version<4) + { + spu->regs.mastervol = T1ReadByte(MMU.ARM7_REG, 0x500) & 0x7F; + spu->regs.masteren = BIT15(T1ReadWord(MMU.ARM7_REG, 0x500)); + } + + //copy the core spu (the more accurate) to the user spu + SPU_CloneUser(); + + return true; +} diff --git a/jni/desmume/src/SPU.h b/jni/desmume/src/SPU.h new file mode 100755 index 0000000..9ea6de9 --- /dev/null +++ b/jni/desmume/src/SPU.h @@ -0,0 +1,252 @@ +/* + Copyright 2006 Theo Berkau + Copyright (C) 2006-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ + +#ifndef SPU_H +#define SPU_H + +#include +#include +#include +#include "types.h" +#include "matrix.h" +#include "emufile.h" + + +#define SNDCORE_DEFAULT -1 +#define SNDCORE_DUMMY 0 + +#define CHANSTAT_STOPPED 0 +#define CHANSTAT_PLAY 1 + +//who made these static? theyre used in multiple places. +FORCEINLINE u32 sputrunc(float f) { return u32floor(f); } +FORCEINLINE u32 sputrunc(double d) { return u32floor(d); } +FORCEINLINE s32 spumuldiv7(s32 val, u8 multiplier) { + assert(multiplier <= 127); + return (multiplier == 127) ? val : ((val * multiplier) >> 7); +} + +enum SPUInterpolationMode +{ + SPUInterpolation_None = 0, + SPUInterpolation_Linear = 1, + SPUInterpolation_Cosine = 2 +}; + +struct SoundInterface_struct +{ + int id; + const char *Name; + int (*Init)(int buffersize); + void (*DeInit)(); + void (*UpdateAudio)(s16 *buffer, u32 num_samples); + u32 (*GetAudioSpace)(); + void (*MuteAudio)(); + void (*UnMuteAudio)(); + void (*SetVolume)(int volume); + void (*ClearBuffer)(); +}; + +extern SoundInterface_struct SNDDummy; +extern SoundInterface_struct SNDFile; +extern int SPU_currentCoreNum; + +struct channel_struct +{ + channel_struct() + {} + u32 num; + u8 vol; + u8 datashift; + u8 hold; + u8 pan; + u8 waveduty; + u8 repeat; + u8 format; + u8 keyon; + u8 status; + u32 addr; + u16 timer; + u16 loopstart; + u32 length; + u32 totlength; + double double_totlength_shifted; + union { + s8 *buf8; + s16 *buf16; + }; + double sampcnt; + double sampinc; + // ADPCM specific + u32 lastsampcnt; + s16 pcm16b, pcm16b_last; + s16 loop_pcm16b; + int index; + int loop_index; + u16 x; + s16 psgnoise_last; +}; + +class SPUFifo +{ +public: + SPUFifo(); + void enqueue(s16 val); + s16 dequeue(); + s16 buffer[16]; + s32 head,tail,size; + void save(EMUFILE* fp); + bool load(EMUFILE* fp); + void reset(); +}; + +class SPU_struct +{ +public: + SPU_struct(int buffersize); + u32 bufpos; + u32 buflength; + s32 *sndbuf; + s32 lastdata; //the last sample that a channel generated + s16 *outbuf; + u32 bufsize; + channel_struct channels[16]; + + //registers + struct REGS { + REGS() + : mastervol(0) + , ctl_left(0) + , ctl_right(0) + , ctl_ch1bypass(0) + , ctl_ch3bypass(0) + , masteren(0) + , soundbias(0) + {} + + u8 mastervol; + u8 ctl_left, ctl_right; + u8 ctl_ch1bypass, ctl_ch3bypass; + u8 masteren; + u16 soundbias; + + enum LeftOutputMode + { + LOM_LEFT_MIXER=0, LOM_CH1=1, LOM_CH3=2, LOM_CH1_PLUS_CH3=3 + }; + + enum RightOutputMode + { + ROM_RIGHT_MIXER=0, ROM_CH1=1, ROM_CH3=2, ROM_CH1_PLUS_CH3=3 + }; + + struct CAP { + CAP() + : add(0), source(0), oneshot(0), bits8(0), active(0), dad(0), len(0) + {} + u8 add, source, oneshot, bits8, active; + u32 dad; + u16 len; + struct Runtime { + Runtime() + : running(0), curdad(0), maxdad(0) + {} + u8 running; + u32 curdad; + u32 maxdad; + double sampcnt; + SPUFifo fifo; + } runtime; + } cap[2]; + } regs; + + void reset(); + ~SPU_struct(); + void KeyOff(int channel); + void KeyOn(int channel); + void KeyProbe(int channel); + void ProbeCapture(int which); + void WriteByte(u32 addr, u8 val); + u8 ReadByte(u32 addr); + u16 ReadWord(u32 addr); + u32 ReadLong(u32 addr); + void WriteWord(u32 addr, u16 val); + void WriteLong(u32 addr, u32 val); + + //kills all channels but leaves SPU otherwise running normally + void ShutUp(); +}; + +int SPU_ChangeSoundCore(int coreid, int buffersize); +SoundInterface_struct *SPU_SoundCore(); + +void SPU_ReInit(); +int SPU_Init(int coreid, int buffersize); +void SPU_Pause(int pause); +void SPU_SetVolume(int volume); +void SPU_SetSynchMode(int mode, int method); +void SPU_ClearOutputBuffer(void); +void SPU_Reset(void); +void SPU_DeInit(void); +void SPU_KeyOn(int channel); +void SPU_WriteByte(u32 addr, u8 val); +void SPU_WriteWord(u32 addr, u16 val); +void SPU_WriteLong(u32 addr, u32 val); +u8 SPU_ReadByte(u32 addr); +u16 SPU_ReadWord(u32 addr); +u32 SPU_ReadLong(u32 addr); +void SPU_Emulate_core(void); +void SPU_Emulate_user(bool mix = true); + +extern SPU_struct *SPU_core, *SPU_user; +extern int spu_core_samples; + +void spu_savestate(EMUFILE* os); +bool spu_loadstate(EMUFILE* is, int size); + +enum WAVMode +{ + WAVMODE_ANY = -1, + WAVMODE_CORE = 0, + WAVMODE_USER = 1 +}; + +class WavWriter +{ +public: + WavWriter(); + bool open(const std::string & fname); + void close(); + void update(void* soundData, int numSamples); + bool isRecording() const; + WAVMode mode; +private: + FILE *spufp; +}; + +void WAV_End(); +bool WAV_Begin(const char* fname, WAVMode mode=WAVMODE_CORE); +bool WAV_IsRecording(WAVMode mode=WAVMODE_ANY); +void WAV_WavSoundUpdate(void* soundData, int numSamples, WAVMode mode=WAVMODE_CORE); + +// we should make this configurable eventually +// but at least defining it somewhere is probably a step in the right direction +#define DESMUME_SAMPLE_RATE 44100 +//#define DESMUME_SAMPLE_RATE 48000 + +#endif diff --git a/jni/desmume/src/addons.cpp b/jni/desmume/src/addons.cpp new file mode 100755 index 0000000..1af85e8 --- /dev/null +++ b/jni/desmume/src/addons.cpp @@ -0,0 +1,76 @@ +/* + Copyright (C) 2009-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ +#include "addons.h" +#include + +//this is the currently-configured cflash mode +ADDON_CFLASH_MODE CFlash_Mode; + +//this is the currently-configured path (directory or filename) for cflash. +//it should be viewed as a parameter for the above. +std::string CFlash_Path; + +char GBAgameName[MAX_PATH]; + +extern ADDONINTERFACE addonNone; +extern ADDONINTERFACE addonCFlash; +extern ADDONINTERFACE addonRumblePak; +extern ADDONINTERFACE addonGBAgame; +extern ADDONINTERFACE addonGuitarGrip; +extern ADDONINTERFACE addonExpMemory; +extern ADDONINTERFACE addonPiano; +extern ADDONINTERFACE addonPaddle; +//extern ADDONINTERFACE addonExternalMic; + +ADDONINTERFACE addonList[NDS_ADDON_COUNT] = { + addonNone, + addonCFlash, + addonRumblePak, + addonGBAgame, + addonGuitarGrip, + addonExpMemory, + addonPiano, + addonPaddle +}; + +ADDONINTERFACE addon = addonCFlash; // default none pak +NDS_ADDON_TYPE addon_type = NDS_ADDON_CFLASH; + +BOOL addonsInit() +{ + return addon.init(); +} + +void addonsClose() +{ + addon.close(); +} + +void addonsReset() +{ + addon.reset(); +} + +BOOL addonsChangePak(NDS_ADDON_TYPE type) +{ + if (type > NDS_ADDON_COUNT) return FALSE; + addon.close(); + addon = addonList[type]; + addon_type = type; + printf("Slot 2: %s\n", addon.name); + return addon.init(); +} diff --git a/jni/desmume/src/addons.h b/jni/desmume/src/addons.h new file mode 100755 index 0000000..65e935f --- /dev/null +++ b/jni/desmume/src/addons.h @@ -0,0 +1,94 @@ +/* + Copyright (C) 2009-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ + +#ifndef __ADDONS_H__ +#define __ADDONS_H__ + +#include "common.h" +#include "types.h" +#include "debug.h" + +struct ADDONINTERFACE +{ + // The name of the plugin, this name will appear in the plugins list + const char * name; + + //called once when the plugin starts up + BOOL (*init)(void); + + //called when the emulator resets + void (*reset)(void); + + //called when the plugin shuts down + void (*close)(void); + + //called when the user configurating plugin + void (*config)(void); + + //called when the emulator write to addon + void (*write08)(u32 procnum, u32 adr, u8 val); + void (*write16)(u32 procnum, u32 adr, u16 val); + void (*write32)(u32 procnum, u32 adr, u32 val); + + //called when the emulator read from addon + u8 (*read08)(u32 procnum, u32 adr); + u16 (*read16)(u32 procnum, u32 adr); + u32 (*read32)(u32 procnum, u32 adr); + + //called when the user get info about addon pak (description) + void (*info)(char *info); +}; + +enum NDS_ADDON_TYPE +{ + NDS_ADDON_NONE, + NDS_ADDON_CFLASH, // compact flash + NDS_ADDON_RUMBLEPAK, // rumble pack + NDS_ADDON_GBAGAME, // gba game in slot + NDS_ADDON_GUITARGRIP, // Guitar Grip + NDS_ADDON_EXPMEMORY, // Memory Expansion + NDS_ADDON_PIANO, // Piano + NDS_ADDON_PADDLE, + //NDS_ADDON_EXTERNALMIC, + NDS_ADDON_COUNT // use for counter addons - MUST TO BE LAST!!! +}; + +enum ADDON_CFLASH_MODE +{ + ADDON_CFLASH_MODE_Path, ADDON_CFLASH_MODE_File, ADDON_CFLASH_MODE_RomPath +}; + +extern ADDON_CFLASH_MODE CFlash_Mode; +extern std::string CFlash_Path; +inline bool CFlash_IsUsingPath() { return CFlash_Mode==ADDON_CFLASH_MODE_Path || CFlash_Mode==ADDON_CFLASH_MODE_RomPath; } + +extern ADDONINTERFACE addon; // current pak +extern ADDONINTERFACE addonList[NDS_ADDON_COUNT]; // lists pointer on paks +extern NDS_ADDON_TYPE addon_type; // current type pak + +extern char GBAgameName[MAX_PATH]; // file name for GBA game (rom) +extern void (*FeedbackON)(BOOL enable); // feedback on/off + +extern BOOL addonsInit(); // Init addons +extern void addonsClose(); // Shutdown addons +extern void addonsReset(); // Reset addon +extern BOOL addonsChangePak(NDS_ADDON_TYPE type); // change current adddon + +extern void guitarGrip_setKey(bool green, bool red, bool yellow, bool blue); // Guitar grip keys +extern void piano_setKey(bool c, bool cs, bool d, bool ds, bool e, bool f, bool fs, bool g, bool gs, bool a, bool as, bool b, bool hic); //piano keys + +#endif //__ADDONS_H__ diff --git a/jni/desmume/src/addons/slot1_none.cpp b/jni/desmume/src/addons/slot1_none.cpp new file mode 100755 index 0000000..f0c0ce5 --- /dev/null +++ b/jni/desmume/src/addons/slot1_none.cpp @@ -0,0 +1,62 @@ +/* Copyright (C) 2010-2011 DeSmuME team + + This file is part of DeSmuME + + DeSmuME 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. + + DeSmuME 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 DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../slot1.h" + +static void slot1_info(char *info) { strcpy(info, "Slot1 no-card emulation (card ejected!)"); } +static void slot1_config(void) {} + +static BOOL slot1_init() { return (TRUE); } + +static void slot1_reset() {} + +static void slot1_close() {} + + +static void slot1_write08(u8 PROCNUM, u32 adr, u8 val) {} +static void slot1_write16(u8 PROCNUM, u32 adr, u16 val) {} +static void slot1_write32(u8 PROCNUM, u32 adr, u32 val) {} + +static u8 slot1_read08(u8 PROCNUM, u32 adr) +{ + return 0xFF; +} +static u16 slot1_read16(u8 PROCNUM, u32 adr) +{ + return 0xFFFF; +} +static u32 slot1_read32(u8 PROCNUM, u32 adr) +{ + return 0xFFFFFFFF; +} + + +SLOT1INTERFACE slot1None = { + "None", + slot1_init, + slot1_reset, + slot1_close, + slot1_config, + slot1_write08, + slot1_write16, + slot1_write32, + slot1_read08, + slot1_read16, + slot1_read32, + slot1_info}; diff --git a/jni/desmume/src/addons/slot1_r4.cpp b/jni/desmume/src/addons/slot1_r4.cpp new file mode 100755 index 0000000..31285f0 --- /dev/null +++ b/jni/desmume/src/addons/slot1_r4.cpp @@ -0,0 +1,237 @@ +/* Copyright (C) 2010-2011 DeSmuME team + + This file is part of DeSmuME + + DeSmuME 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. + + DeSmuME 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 DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +#include "../slot1.h" +#include "../registers.h" +#include "../MMU.h" +#include "../NDSSystem.h" +#include "../emufile.h" + +static EMUFILE *img = NULL; +static u32 write_count = 0; +static u32 write_enabled = 0; +static void init_r4_flash() +{ + srand(time(NULL)); + + if (!img) + img = slot1GetFatImage(); + + if(!img) + { + INFO("slot1 fat not successfully mounted\n"); + } +} + +static void info(char *info) { strcpy(info, "Slot1 R4 Emulation"); } +static void config(void) {} + +static BOOL init() +{ + init_r4_flash(); + return TRUE; +} + +static void reset() { + init_r4_flash(); +} + +static void close() { + img = NULL; +} + + +static void write08(u8 PROCNUM, u32 adr, u8 val) {} +static void write16(u8 PROCNUM, u32 adr, u16 val) {} + +static void write32_GCROMCTRL(u32 val) +{ + nds_dscard& card = MMU.dscard[0]; + + switch(card.command[0]) + { + case 0xB0: + break; + case 0xB9: + case 0xBA: + card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4]; + img->fseek(card.address,SEEK_SET); + break; + case 0xBB: + write_enabled = 1; + write_count = 0x80; + case 0xBC: + card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4]; + img->fseek(card.address,SEEK_SET); + break; + } +} + +static void write32_GCDATAIN(u32 val) +{ + nds_dscard& card = MMU.dscard[0]; + //bool log=false; + + memcpy(&card.command[0], &MMU.MMU_MEM[0][0x40][0x1A8], 8); + + //last_write_count = write_count; + if(card.command[4]) + { + // transfer is done + T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4,val & 0x7F7FFFFF); + + // if needed, throw irq for the end of transfer + if(MMU.AUX_SPI_CNT & 0x4000) + NDS_makeIrq(ARMCPU_ARM9, IRQ_BIT_GC_TRANSFER_COMPLETE); + + return; + } + + switch(card.command[0]) + { + case 0xBB: + { + if(write_count && write_enabled) + { + img->fwrite(&val, 4); + img->fflush(); + write_count--; + } + break; + } + default: + break; + } + + if(write_count==0) + { + write_enabled = 0; + + // transfer is done + T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4,val & 0x7F7FFFFF); + + // if needed, throw irq for the end of transfer + if(MMU.AUX_SPI_CNT & 0x4000) + NDS_makeIrq(ARMCPU_ARM9, IRQ_BIT_GC_TRANSFER_COMPLETE); + } + + /*if(log) + { + INFO("WRITE CARD command: %02X%02X%02X%02X%02X%02X%02X%02X\t", + card.command[0], card.command[1], card.command[2], card.command[3], + card.command[4], card.command[5], card.command[6], card.command[7]); + INFO("FROM: %08X\t", NDS_ARM9.instruct_adr); + INFO("VAL: %08X\n", val); + }*/ +} + +static void write32(u8 PROCNUM, u32 adr, u32 val) +{ + switch(adr) + { + case REG_GCROMCTRL: + write32_GCROMCTRL(val); + break; + case REG_GCDATAIN: + write32_GCDATAIN(val); + break; + } +} + +static u8 read08(u8 PROCNUM, u32 adr) +{ + return 0xFF; +} +static u16 read16(u8 PROCNUM, u32 adr) +{ + return 0xFFFF; +} + + +static u32 read32_GCDATAIN() +{ + nds_dscard& card = MMU.dscard[0]; + + u32 val; + + switch(card.command[0]) + { + //Get ROM chip ID + case 0x90: + case 0xB8: + val = 0xFC2; + break; + + case 0xB0: + val = 0x1F4; + break; + case 0xB9: + val = (rand() % 100) ? 0x1F4 : 0; + break; + case 0xBB: + case 0xBC: + val = 0; + break; + case 0xBA: + //INFO("Read from sd at sector %08X at adr %08X ",card.address/512,ftell(img)); + img->fread(&val, 4); + //INFO("val %08X\n",val); + break; + + default: + val = 0; + } + + /*INFO("READ CARD command: %02X%02X%02X%02X% 02X%02X%02X%02X RET: %08X ", + card.command[0], card.command[1], card.command[2], card.command[3], + card.command[4], card.command[5], card.command[6], card.command[7], + val); + INFO("FROM: %08X LR: %08X\n", NDS_ARM9.instruct_adr, NDS_ARM9.R[14]);*/ + + + return val; +} //read32_GCDATAIN + + +static u32 read32(u8 PROCNUM, u32 adr) +{ + switch(adr) + { + case REG_GCDATAIN: + return read32_GCDATAIN(); + default: + return 0; + } +} + +SLOT1INTERFACE slot1R4 = { + "R4", + init, + reset, + close, + config, + write08, + write16, + write32, + read08, + read16, + read32, + info}; diff --git a/jni/desmume/src/addons/slot1_retail.cpp b/jni/desmume/src/addons/slot1_retail.cpp new file mode 100755 index 0000000..8fb6cea --- /dev/null +++ b/jni/desmume/src/addons/slot1_retail.cpp @@ -0,0 +1,285 @@ +/* Copyright (C) 2010-2011 DeSmuME team + + This file is part of DeSmuME + + DeSmuME 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. + + DeSmuME 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 DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../slot1.h" +#include "../registers.h" +#include "../MMU.h" +#include "../NDSSystem.h" + +static void info(char *info) { strcpy(info, "Slot1 Retail card emulation"); } +static void config(void) {} + +static BOOL init() { return (TRUE); } + +static void reset() {} + +static void close() {} + + +static void write08(u8 PROCNUM, u32 adr, u8 val) {} +static void write16(u8 PROCNUM, u32 adr, u16 val) {} + +static void write32_GCROMCTRL(u8 PROCNUM, u32 val) +{ + nds_dscard& card = MMU.dscard[PROCNUM]; + + switch(card.command[0]) + { + case 0x00: //Data read + case 0xB7: + card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4]; + card.transfer_count = 0x80; + break; + + case 0xB8: // Chip ID + card.address = 0; + card.transfer_count = 1; + break; + + default: + card.address = 0; + card.transfer_count = 0; + break; + } +} + +static void write32(u8 PROCNUM, u32 adr, u32 val) +{ + switch(adr) + { + case REG_GCROMCTRL: + write32_GCROMCTRL(PROCNUM, val); + break; + } +} + +static u8 read08(u8 PROCNUM, u32 adr) +{ + return 0xFF; +} +static u16 read16(u8 PROCNUM, u32 adr) +{ + return 0xFFFF; +} + +static u32 read32_GCDATAIN(u8 PROCNUM) +{ + nds_dscard& card = MMU.dscard[PROCNUM]; + + switch(card.command[0]) + { + //Get ROM chip ID + case 0x90: + case 0xB8: + { + // Note: the BIOS stores the chip ID in main memory + // Most games continuously compare the chip ID with + // the value in memory, probably to know if the card + // was removed. + // As DeSmuME boots directly from the game, the chip + // ID in main mem is zero and this value needs to be + // zero too. + + //staff of kings verifies this (it also uses the arm7 IRQ 20) + if(nds.cardEjected) //TODO - handle this with ejected card slot1 device (and verify using this case) + return 0xFFFFFFFF; + else return 0; + } + break; + + + // Data read + case 0x00: + case 0xB7: + { + //it seems that etrian odyssey 3 doesnt work unless we mask this to cart size. + //but, a thought: does the internal rom address counter register wrap around? we may be making a mistake by keeping the extra precision + //but there is no test case yet + u32 address = card.address & (gameInfo.mask); + + // Make sure any reads below 0x8000 redirect to 0x8000+(adr&0x1FF) as on real cart + if((card.command[0] == 0xB7) && (address < 0x8000)) + { + //TODO - refactor this to include the PROCNUM, for debugging purposes if nothing else + //(can refactor gbaslot also) + + //INFO("Read below 0x8000 (0x%04X) from: ARM%s %08X\n", + // card.address, (PROCNUM ? "7":"9"), (PROCNUM ? NDS_ARM7:NDS_ARM9).instruct_adr); + + address = (0x8000 + (address&0x1FF)); + } + + //as a sanity measure for funny-sized roms (homebrew and perhaps truncated retail roms) + //we need to protect ourselves by returning 0xFF for things still out of range + if(address >= gameInfo.romsize) + { + DEBUG_Notify.ReadBeyondEndOfCart(address,gameInfo.romsize); + return 0xFFFFFFFF; + } + + return T1ReadLong(MMU.CART_ROM, address); + } + break; + default: + return 0; + } //switch(card.command[0]) +} //read32_GCDATAIN + +static u32 read32(u8 PROCNUM, u32 adr) +{ + switch(adr) + { + case REG_GCDATAIN: + return read32_GCDATAIN(PROCNUM); + default: + return 0; + } +} + + +SLOT1INTERFACE slot1Retail = { + "Retail", + init, + reset, + close, + config, + write08, + write16, + write32, + read08, + read16, + read32, + info +}; + + + + // ///writetoGCControl: + //// --- Ninja SD commands ------------------------------------- + + // // NJSD init/reset + // case 0x20: + // { + // card.address = 0; + // card.transfer_count = 0; + // } + // break; + + // // NJSD_sendCLK() + // case 0xE0: + // { + // card.address = 0; + // card.transfer_count = 0; + // NDS_makeInt(PROCNUM, 20); + // } + // break; + + // // NJSD_sendCMDN() / NJSD_sendCMDR() + // case 0xF0: + // case 0xF1: + // switch (card.command[2]) + // { + // // GO_IDLE_STATE + // case 0x40: + // card.address = 0; + // card.transfer_count = 0; + // NDS_makeInt(PROCNUM, 20); + // break; + + // case 0x42: // ALL_SEND_CID + // case 0x43: // SEND_RELATIVE_ADDR + // case 0x47: // SELECT_CARD + // case 0x49: // SEND_CSD + // case 0x4D: + // case 0x77: // APP_CMD + // case 0x69: // SD_APP_OP_COND + // card.address = 0; + // card.transfer_count = 6; + // NDS_makeInt(PROCNUM, 20); + // break; + + // // SET_BLOCKLEN + // case 0x50: + // card.address = 0; + // card.transfer_count = 6; + // card.blocklen = card.command[6] | (card.command[5] << 8) | (card.command[4] << 16) | (card.command[3] << 24); + // NDS_makeInt(PROCNUM, 20); + // break; + + // // READ_SINGLE_BLOCK + // case 0x51: + // card.address = card.command[6] | (card.command[5] << 8) | (card.command[4] << 16) | (card.command[3] << 24); + // card.transfer_count = (card.blocklen + 3) >> 2; + // NDS_makeInt(PROCNUM, 20); + // break; + // } + // break; + + // // --- Ninja SD commands end --------------------------------- + + + + // //GCDATAIN: + // // --- Ninja SD commands ------------------------------------- + + // // NJSD_sendCMDN() / NJSD_sendCMDR() + // case 0xF0: + // case 0xF1: + // switch (card.command[2]) + // { + // // ALL_SEND_CID + // case 0x42: + // if (card.transfer_count == 2) val = 0x44534A4E; + // else val = 0x00000000; + + // // SEND_RELATIVE_ADDR + // case 0x43: + // case 0x47: + // case 0x49: + // case 0x50: + // val = 0x00000000; + // break; + + // case 0x4D: + // if (card.transfer_count == 2) val = 0x09000000; + // else val = 0x00000000; + // break; + + // // APP_CMD + // case 0x77: + // if (card.transfer_count == 2) val = 0x00000037; + // else val = 0x00000000; + // break; + + // // SD_APP_OP_COND + // case 0x69: + // if (card.transfer_count == 2) val = 0x00008000; + // else val = 0x00000000; + // break; + + // // READ_SINGLE_BLOCK + // case 0x51: + // val = 0x00000000; + // break; + // } + // break; + + // // --- Ninja SD commands end --------------------------------- + + diff --git a/jni/desmume/src/addons/slot1_retail_nand.cpp b/jni/desmume/src/addons/slot1_retail_nand.cpp new file mode 100755 index 0000000..ee6df7a --- /dev/null +++ b/jni/desmume/src/addons/slot1_retail_nand.cpp @@ -0,0 +1,202 @@ +/* Copyright (C) 2011 DeSmuME team + + This file is part of DeSmuME + + DeSmuME 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. + + DeSmuME 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 DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../slot1.h" +#include "../registers.h" +#include "../MMU.h" +#include "../NDSSystem.h" + +static void info(char *info) { strcpy(info, "Slot1 Retail NAND card emulation"); } +static void config(void) {} + +static BOOL init() { return (TRUE); } + +static void reset() {} + +static void close() {} + + +static void write08(u8 PROCNUM, u32 adr, u8 val) {} +static void write16(u8 PROCNUM, u32 adr, u16 val) {} + +static void write32_GCROMCTRL(u8 PROCNUM, u32 val) +{ + nds_dscard& card = MMU.dscard[PROCNUM]; + + switch(card.command[0]) + { + case 0x00: //Data read + case 0xB7: + card.address = (card.command[1] << 24) | (card.command[2] << 16) | (card.command[3] << 8) | card.command[4]; + card.transfer_count = 0x80; + break; + + case 0xB8: // Chip ID + card.address = 0; + card.transfer_count = 1; + break; + + // Nand Init + case 0x94: + card.address = 0; + card.transfer_count = 0x80; + break; + + // Nand Error? + case 0xD6: + card.address = 0; + card.transfer_count = 1; + break; + + // Nand Write? ---- PROGRAM for INTERNAL DATA MOVE/RANDOM DATA INPUT + //case 0x8B: + case 0x85: + card.address = 0; + card.transfer_count = 0x80; + break; + + default: + card.address = 0; + card.transfer_count = 0; + break; + } +} + +static void write32(u8 PROCNUM, u32 adr, u32 val) +{ + switch(adr) + { + case REG_GCROMCTRL: + write32_GCROMCTRL(PROCNUM, val); + break; + } +} + +static u8 read08(u8 PROCNUM, u32 adr) +{ + return 0xFF; +} +static u16 read16(u8 PROCNUM, u32 adr) +{ + return 0xFFFF; +} + +static u32 read32_GCDATAIN(u8 PROCNUM) +{ + nds_dscard& card = MMU.dscard[PROCNUM]; + + switch(card.command[0]) + { + //Get ROM chip ID + case 0x90: + case 0xB8: + { + // Note: the BIOS stores the chip ID in main memory + // Most games continuously compare the chip ID with + // the value in memory, probably to know if the card + // was removed. + // As DeSmuME boots directly from the game, the chip + // ID in main mem is zero and this value needs to be + // zero too. + + //staff of kings verifies this (it also uses the arm7 IRQ 20) + if(nds.cardEjected) //TODO - handle this with ejected card slot1 device (and verify using this case) + return 0xFFFFFFFF; + else return 0; + } + break; + + + // Data read + case 0x00: + case 0xB7: + { + // Make sure any reads below 0x8000 redirect to 0x8000+(adr&0x1FF) as on real cart + if((card.command[0] == 0xB7) && (card.address < 0x8000)) + { + //TODO - refactor this to include the PROCNUM, for debugging purposes if nothing else + //(can refactor gbaslot also) + + //INFO("Read below 0x8000 (0x%04X) from: ARM%s %08X\n", + // card.address, (PROCNUM ? "7":"9"), (PROCNUM ? NDS_ARM7:NDS_ARM9).instruct_adr); + + card.address = (0x8000 + (card.address&0x1FF)); + } + + //it seems that etrian odyssey 3 doesnt work unless we mask this to cart size. + //but, a thought: does the internal rom address counter register wrap around? we may be making a mistake by keeping the extra precision + //but there is no test case yet + u32 address = card.address & (gameInfo.mask); + + //as a sanity measure for funny-sized roms (homebrew and perhaps truncated retail roms) + //we need to protect ourselves by returning 0xFF for things still out of range + if(address >= gameInfo.romsize) + { + DEBUG_Notify.ReadBeyondEndOfCart(address,gameInfo.romsize); + return 0xFFFFFFFF; + } + + return T1ReadLong(MMU.CART_ROM, address); + } + break; + + // Nand Init? + case 0x94: + return 0; //Unsure what to return here so return 0 for now + + // Nand Status? + case 0xD6: + //0x80 == busy + // Made in Ore/WariWare D.I.Y. need set value to 0x80 + return 0x80; //0x20 == ready + + default: + return 0; + } //switch(card.command[0]) +} //read32_GCDATAIN + +static u32 read32(u8 PROCNUM, u32 adr) +{ + switch(adr) + { + case REG_GCDATAIN: + return read32_GCDATAIN(PROCNUM); + default: + return 0; + } +} + + +SLOT1INTERFACE slot1Retail_NAND = { + "Retail with NAND Flash", + init, + reset, + close, + config, + write08, + write16, + write32, + read08, + read16, + read32, + info +}; + + + diff --git a/jni/desmume/src/addons/slot2_expMemory.cpp b/jni/desmume/src/addons/slot2_expMemory.cpp new file mode 100755 index 0000000..ff22393 --- /dev/null +++ b/jni/desmume/src/addons/slot2_expMemory.cpp @@ -0,0 +1,156 @@ +/* Copyright (C) 2009-2010 DeSmuME team + + This file is part of DeSmuME + + DeSmuME 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. + + DeSmuME 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 DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../addons.h" +#include "../mem.h" +#include +#include "../MMU.h" + +u8 *expMemory = NULL; +u32 expMemSize = 8 * 1024 * 1024; // 8Mb + +#if 0 +#define EXPINFO(...) INFO(__VA_ARGS__) +#else +#define EXPINFO(...) +#endif + +static BOOL ExpMemory_init(void) { return (TRUE); } +static void ExpMemory_reset(void) +{ + if (expMemory) + { + delete [] expMemory; + expMemory = NULL; + } + expMemory = new u8 [expMemSize]; + memset(expMemory, 0xFF, expMemSize); +} +static void ExpMemory_close(void) +{ + if (expMemory) + { + delete [] expMemory; + expMemory = NULL; + } +} +static void ExpMemory_config(void) {} +static void ExpMemory_write08(u32 procnum, u32 adr, u8 val) +{ + if (adr >= 0x09000000) + { + u32 offs = (adr - 0x09000000); + if (offs >= expMemSize) return; + T1WriteByte(expMemory, offs, val); + } + EXPINFO("ExpMemory: write 08 at 0x%08X = 0x%02X\n", adr, val); +} +static void ExpMemory_write16(u32 procnum, u32 adr, u16 val) +{ + if (adr >= 0x09000000) + { + u32 offs = (adr - 0x09000000); + if (offs >= expMemSize) return; + T1WriteWord(expMemory, offs, val); + } + EXPINFO("ExpMemory: write 16 at 0x%08X = 0x%04X\n", adr, val); +} +static void ExpMemory_write32(u32 procnum, u32 adr, u32 val) +{ + + if (adr >= 0x09000000) + { + u32 offs = (adr - 0x09000000); + if (offs >= expMemSize) return; + T1WriteLong(expMemory, offs, val); + } + EXPINFO("ExpMemory: write 32 at 0x%08X = 0x%08X\n", adr, val); +} + +static u8 header_0x00B0[] = +{ 0xFF, 0xFF, 0x96, 0x00, //this 0x96 is strange. it can't be read from the pak when it boots, it must appear later + 0x00, 0x24, 0x24, 0x24, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x7F +}; + +static u8 ExpMemory_read08(u32 procnum, u32 adr) +{ + EXPINFO("ExpMemory: read 08 at 0x%08X\n", adr); + + if(adr>=0x080000B0 && adr<0x080000C0) + return T1ReadByte(header_0x00B0,adr-0x080000B0); + + if (adr >= 0x09000000) + { + u32 offs = (adr - 0x09000000); + if (offs >= expMemSize) return (0xFF); + return T1ReadByte(expMemory, offs); + } + + return 0xFF; +} +static u16 ExpMemory_read16(u32 procnum, u32 adr) +{ + if(adr>=0x080000B0 && adr<0x080000C0) + return T1ReadWord(header_0x00B0,adr-0x080000B0); + + if (adr == 0x0801FFFC) return 0x7FFF; + if (adr == 0x08240002) return 0; //this can't be 0xFFFF. dunno why, we just guessed 0 + + if (adr >= 0x09000000) + { + u32 offs = (adr - 0x09000000); + if (offs >= expMemSize) return (0xFFFF); + return T1ReadWord(expMemory, offs); + } + + EXPINFO("ExpMemory: read 16 at 0x%08X\n", adr); + return 0xFFFF; +} +static u32 ExpMemory_read32(u32 procnum, u32 adr) +{ + if(adr>=0x080000B0 && adr<0x080000C0) + return T1ReadLong(header_0x00B0,adr-0x080000B0); + + if (adr >= 0x09000000) + { + u32 offs = (adr - 0x09000000); + if (offs >= expMemSize) return 0xFFFFFFFF; + return T1ReadLong(expMemory, offs); + } + + EXPINFO("ExpMemory: read 32 at 0x%08X\n", adr); + return 0xFFFFFFFF; +} +static void ExpMemory_info(char *info) { strcpy(info, "Memory Expansion Pak"); } + +ADDONINTERFACE addonExpMemory = { + "Memory Expansion Pak", + ExpMemory_init, + ExpMemory_reset, + ExpMemory_close, + ExpMemory_config, + ExpMemory_write08, + ExpMemory_write16, + ExpMemory_write32, + ExpMemory_read08, + ExpMemory_read16, + ExpMemory_read32, + ExpMemory_info}; diff --git a/jni/desmume/src/addons/slot2_gbagame.cpp b/jni/desmume/src/addons/slot2_gbagame.cpp new file mode 100755 index 0000000..bcc3451 --- /dev/null +++ b/jni/desmume/src/addons/slot2_gbagame.cpp @@ -0,0 +1,473 @@ +/* Copyright (C) 2009 CrazyMax + Copyright (C) 2009 DeSmuME team + + This file is part of DeSmuME + + DeSmuME 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. + + DeSmuME 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 DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../addons.h" +#include "../mem.h" +#include +#include "../MMU.h" +#include "../path.h" + +//SRAM is going to be stored just above the rom. +//that is convenient for us, since it mirrors the nds memory map +#define GBA_ROMSIZE (32 * 1024 * 1024) + 1 +#define GBA_SAVESIZE (512 * 1024) + 1 + +static u8 *GBArom = NULL; +static u8 *saveData = NULL; +static u8 saveType = 0xFF; + +//================================================================================== Flash GBA +typedef struct +{ + u8 state; + u8 cmd; + u32 size; + u8 idDevice; + u8 idManufacturer; + u8 bank; +} FLASH_GBA; + +FLASH_GBA gbaFlash = {0}; + +static void gbaWriteFlash(u32 adr, u8 val) +{ + switch (gbaFlash.state) + { + case 0: + if (adr == 0x0A005555) + { + if (val == 0xF0) + { + //INFO("GBAgame: Flash: reset\n"); + gbaFlash.state = 0; + gbaFlash.cmd = 0; + return; + } + if (val == 0xAA) + { + gbaFlash.state = 1; + return; + } + } + + if (adr == 0x0A000000) + { + if (gbaFlash.cmd == 0xB0) + { + gbaFlash.bank = val; + gbaFlash.cmd = 0; + //INFO("GBAgame: Flash: change bank %i\n", val); + return; + } + } + break; + case 1: + if ( (adr == 0x0A002AAA) && (val == 0x55) ) + { + gbaFlash.state = 2; + return; + } + gbaFlash.state = 0; + break; + case 2: + if (adr == 0x0A005555) + { + //INFO("GBAgame: Flash: send command flash 0x%02X\n", val); + switch (val) + { + case 0x80: // Erase + gbaFlash.state = 0x80; + break; + + case 0x90: // Chip Identification + gbaFlash.state = 0x90; + break; + + case 0xA0: // Write + gbaFlash.state = 0; + break; + + default: + gbaFlash.state = 0; + break; + } + gbaFlash.cmd = val; + return; + } + gbaFlash.state = 0; + break; + + // erase + case 0x80: + if ( (adr == 0x0A005555) && (val == 0xAA) ) + { + gbaFlash.state = 0x81; + return; + } + gbaFlash.state = 0; + break; + + case 0x81: + if ( (adr == 0x0A002AAA) && (val == 0x55) ) + { + gbaFlash.state = 0x82; + return; + } + gbaFlash.state = 0; + break; + + case 0x82: + if (val == 0x30) + { + u32 ofs = (adr & 0x0000F000); + //INFO("GBAgame: Flash: erase from 0x%08X to 0x%08X\n", ofs + 0x0A000000, ofs + 0x0A001000); + for (u32 i = ofs; i < (ofs + 0x1000); i++) + saveData[i] = 0xFF; + } + gbaFlash.state = 0; + gbaFlash.cmd = 0; + return; + + // Chip Identification + case 0x90: + if ( (adr == 0x0A005555) && (val == 0xAA) ) + { + gbaFlash.state = 0x91; + return; + } + gbaFlash.state = 0; + break; + + case 0x91: + if ( (adr == 0x0A002AAA) && (val == 0x55) ) + { + gbaFlash.state = 0x92; + return; + } + gbaFlash.state = 0; + break; + + case 0x92: + gbaFlash.state = 0; + gbaFlash.cmd = 0; + return; + } + + if (gbaFlash.cmd == 0xA0) // write + { + saveData[(adr & 0x1FFFF)+(0x10000*gbaFlash.bank)] = val; + gbaFlash.state = 0; + gbaFlash.cmd = 0; + return; + } + INFO("GBAgame: Flash: write unknown atn 0x%08X = 0x%02X\n", adr, val); +} + +static u8 gbaReadFlash(u32 adr) +{ + if (gbaFlash.cmd == 0) + { + //INFO("GBAgame: flash read at 0x%08X = 0x%02X\n", adr, saveData[(adr & 0x1FFFF)+(0x10000*gbaFlash.bank)]); + return saveData[(adr & 0x1FFFF)+(0x10000*gbaFlash.bank)]; + } + + //INFO("GBAgame: flash read at 0x%08X\n", adr); + + switch (gbaFlash.cmd) + { + case 0x90: // Chip Identification + if (adr == 0x0A000000) return gbaFlash.idManufacturer; + if (adr == 0x0A000001) return gbaFlash.idDevice; + break; + + case 0xF0: // + //INFO("GBAgame: Flash: reset2\n"); + gbaFlash.state = 0; + gbaFlash.cmd = 0; + break; + + case 0xB0: // Bank switching + break; + + default: + INFO("GBAgame: Flash: read - unknown command at 0x%08X = 0x%02X\n", adr, gbaFlash.cmd); + break; + } + + return 0xFF; +} +//================================================================================== + +static u8 getSaveTypeGBA(const u8 *data, const u32 size) +{ + u8 *dat = (u8 *)data; + + for (u32 i = 0; i < size; i++) + { + u32 tmp = T1ReadLong(dat, 0); + + if (tmp == 0x52504545) + { + if(memcmp(dat, "EEPROM_", 7) == 0) + { + return 1; + } + } + + if (tmp == 0x4D415253) + { + if(memcmp(dat, "SRAM_", 5) == 0) + { + return 2; + } + } + + if (tmp == 0x53414C46) + { + if(memcmp(dat, "FLASH1M_", 8) == 0) + { + return 3; + } + } + + if (tmp == 0x52494953) + { + if(memcmp(dat, "SIIRTC_V", 8) == 0) + { + return 4; + } + } + + if(memcmp(dat, "FLASH", 5) == 0) + { + return 5; + } + dat++; + } + + return 0xFF; // NONE +} + +static BOOL GBAgame_init(void) +{ + return (TRUE); +} + +static void GBAgame_reset(void) +{ + memset(&gbaFlash, 0, sizeof(gbaFlash)); + + if (GBArom) + { + delete [] GBArom; + GBArom = NULL; + } + GBArom = new u8 [GBA_ROMSIZE]; + memset(GBArom, 0xFF, GBA_ROMSIZE); + + if (saveData) + { + delete [] saveData; + saveData = NULL; + } + saveData = new u8 [GBA_SAVESIZE]; + memset(saveData, 0xFF, GBA_SAVESIZE); + + if (!strlen(GBAgameName)) return; + FILE *fgame = 0; + + //perk: if the gbagame name is "self" this is a special indicator that we should mount the main rom that we're running as the gba game + if(!strcasecmp(GBAgameName,"self")) + { + strcpy(GBAgameName,path.path.c_str()); + } + + fgame = fopen(GBAgameName,"rb"); + if (!fgame) return; + fseek(fgame, 0, SEEK_END); + u32 size = ftell(fgame); + rewind(fgame); + + if (!fread(GBArom, 1, size, fgame)) + { + fclose(fgame); + return; + } + fclose(fgame); + + saveType = getSaveTypeGBA(GBArom, size); + INFO("Loaded \"%s\" in GBA slot (save type %i)\n", GBAgameName, saveType); + + //try loading the sram + char * dot = strrchr(GBAgameName,'.'); + if(!dot) return; + std::string sram_fname = GBAgameName; + sram_fname.resize(dot-GBAgameName); + sram_fname += ".sav"; + fgame = fopen(sram_fname.c_str(),"rb"); + if(!fgame) return; + + fseek(fgame, 0, SEEK_END); + size = ftell(fgame); + rewind(fgame); + + if (!fread(saveData, 1, size, fgame)) + { + fclose(fgame); + return; + } + fclose(fgame); + + gbaFlash.size = size; + if (gbaFlash.size <= (64 * 1024)) + { + gbaFlash.idDevice = 0x1B; + gbaFlash.idManufacturer = 0x32; + } + else + { + gbaFlash.idDevice = 0x09; + gbaFlash.idManufacturer = 0xC2; + } + + INFO("Loaded save \"%s\" in GBA slot\n", sram_fname.c_str()); +} + +static void GBAgame_close(void) +{ + if (GBArom) + { + delete [] GBArom; + GBArom = NULL; + } + + if (saveData) + { + delete [] saveData; + saveData = NULL; + } +} + +static void GBAgame_config(void) {} + +static void GBAgame_write08(u32 procnum, u32 adr, u8 val) +{ + //INFO("GBAgame: write08 at 0x%08X val=0x%02X\n", adr, val); + if ( (adr >= 0x0A000000) && (adr < 0x0A010000) ) + { + switch (saveType) + { + case 3: // Flash + case 5: + gbaWriteFlash(adr, val); + break; + + default: + break; + } + //return (u8)T1ReadByte(saveData, (adr - 0x0A000000)); + } +} +static void GBAgame_write16(u32 procnum, u32 adr, u16 val) +{ + //INFO("GBAgame: write16 at 0x%08X val=0x%04X\n", adr, val); +} + +static void GBAgame_write32(u32 procnum, u32 adr, u32 val) +{ + //INFO("GBAgame: write32 at 0x%08X val=0x%08X\n", adr, val); +} + +static u8 GBAgame_read08(u32 procnum, u32 adr) +{ + //INFO("GBAgame: read08 at 0x%08X value 0x%02X\n", adr, (u8)T1ReadByte(GBArom, (adr - 0x08000000))); + + if (adr < 0x0A000000) + return (u8)T1ReadByte(GBArom, (adr - 0x08000000)); + + if (adr < 0x0A010000) + { + switch (saveType) + { + case 3: // Flash + case 5: + return gbaReadFlash(adr); + + default: + break; + } + + //INFO("Read08 at 0x%08X val=0x%08X\n", adr, (u8)T1ReadByte(GBArom, (adr - 0x08000000)) ); + return (u8)T1ReadByte(saveData, (adr - 0x0A000000)); + } + + //INFO("Read08 at 0x%08X val=0x%08X\n", adr, (u8)T1ReadByte(GBArom, (adr - 0x08000000)) ); + + return 0xFF; +} + +static u16 GBAgame_read16(u32 procnum, u32 adr) +{ + //INFO("GBAgame: read16 at 0x%08X value 0x%04X\n", adr, (u16)T1ReadWord(GBArom, (adr - 0x08000000))); + + if (adr < 0x0A000000) + return (u16)T1ReadWord(GBArom, (adr - 0x08000000)); + + if (adr < 0x0A010000) + { + //INFO("GBAgame: flash read16 at 0x%08X\n", adr); + return (u16)T1ReadWord(saveData, (adr - 0x0A000000)); + } + return 0xFFFF; +} + +static u32 GBAgame_read32(u32 procnum, u32 adr) +{ + //INFO("GBAgame: read32 at 0x%08X value 0x%08X\n", adr, (u32)T1ReadLong(GBArom, (adr - 0x08000000))); + + if (adr < 0x0A000000) + return (u32)T1ReadLong(GBArom, (adr - 0x08000000)); + + if (adr < 0x0A010000) + { + //INFO("GBAgame: flash read32 at 0x%08X\n", adr); + return (u32)T1ReadLong(saveData, (adr - 0x0A000000)); + } + return 0xFFFFFFFF; +} + +static void GBAgame_info(char *info) +{ + strcpy(info, "GBA game in slot"); +} + +ADDONINTERFACE addonGBAgame = { + "GBA game", + GBAgame_init, + GBAgame_reset, + GBAgame_close, + GBAgame_config, + GBAgame_write08, + GBAgame_write16, + GBAgame_write32, + GBAgame_read08, + GBAgame_read16, + GBAgame_read32, + GBAgame_info}; diff --git a/jni/desmume/src/addons/slot2_guitarGrip.cpp b/jni/desmume/src/addons/slot2_guitarGrip.cpp new file mode 100755 index 0000000..8c94cb2 --- /dev/null +++ b/jni/desmume/src/addons/slot2_guitarGrip.cpp @@ -0,0 +1,72 @@ +/* Copyright (C) 2009-2010 DeSmuME team + + This file is part of DeSmuME + + DeSmuME 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. + + DeSmuME 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 DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../addons.h" +#include + +static u8 guitarKeyStatus = 0; + +static BOOL guitarGrip_init(void) { return (TRUE); } +static void guitarGrip_reset(void) +{ + //INFO("GuitarGrip: Reset\n"); + guitarKeyStatus = 0; +} +static void guitarGrip_close(void) {} +static void guitarGrip_config(void) {} +static void guitarGrip_write08(u32 procnum, u32 adr, u8 val) {} +static void guitarGrip_write16(u32 procnum, u32 adr, u16 val) {} +static void guitarGrip_write32(u32 procnum, u32 adr, u32 val) {} +static u8 guitarGrip_read08(u32 procnum, u32 adr) +{ + //INFO("GuitarGrip: read 08 at 0x%08X\n", adr); + if (adr == 0x0A000000) return (~guitarKeyStatus); + else if(adr&1) return 0xF9; + else return 0xFF; +} +static u16 guitarGrip_read16(u32 procnum, u32 adr) +{ + //INFO("GuitarGrip: read 16 at 0x%08X\n", adr); + return 0xF9FF; +} +static u32 guitarGrip_read32(u32 procnum, u32 adr) +{ + //INFO("GuitarGrip: read 32 at 0x%08X\n", adr); + return (0xF9FFF9FF); +} +static void guitarGrip_info(char *info) { strcpy(info, "Guitar Grip for Guitar Hero games"); } + +void guitarGrip_setKey(bool green, bool red, bool yellow, bool blue) +{ + guitarKeyStatus = 0 | (green << 6) | (red << 5) | (yellow << 4) | (blue << 3); +} + +ADDONINTERFACE addonGuitarGrip = { + "Guitar Grip", + guitarGrip_init, + guitarGrip_reset, + guitarGrip_close, + guitarGrip_config, + guitarGrip_write08, + guitarGrip_write16, + guitarGrip_write32, + guitarGrip_read08, + guitarGrip_read16, + guitarGrip_read32, + guitarGrip_info}; diff --git a/jni/desmume/src/addons/slot2_mpcf.cpp b/jni/desmume/src/addons/slot2_mpcf.cpp new file mode 100755 index 0000000..217d826 --- /dev/null +++ b/jni/desmume/src/addons/slot2_mpcf.cpp @@ -0,0 +1,338 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2006 Mic + Copyright (C) 2009-2011 DeSmuME team + + This file is part of DeSmuME + + DeSmuME 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. + + DeSmuME 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 DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../addons.h" +#include +#include +#include "debug.h" +#include +#include +#include + +#include "types.h" +#include "../utils/vfat.h" +#include "../path.h" + +#include "MMU.h" +#include "NDSSystem.h" + +// Set up addresses for GBAMP +#define CF_REG_DATA 0x9000000 +#define CF_REG_ERR 0x9020000 +#define CF_REG_SEC 0x9040000 +#define CF_REG_LBA1 0x9060000 +#define CF_REG_LBA2 0x9080000 +#define CF_REG_LBA3 0x90A0000 +#define CF_REG_LBA4 0x90C0000 +#define CF_REG_CMD 0x90E0000 +#define CF_REG_STS 0x98C0000 + +// CF Card commands +#define CF_CMD_LBA 0xE0 +#define CF_CMD_READ 0x20 +#define CF_CMD_WRITE 0x30 + +static u16 cf_reg_sts, + cf_reg_lba1, + cf_reg_lba2, + cf_reg_lba3, + cf_reg_lba4, + cf_reg_cmd; +static off_t currLBA; + +static const int lfnPos[13] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; + +static u32 fileStartLBA,fileEndLBA; +static std::string sFlashPath; +static BOOL cflashDeviceEnabled = FALSE; + +static EMUFILE* file = NULL; + +// =========================== +BOOL inited; + +enum EListCallbackArg { + EListCallbackArg_Item, EListCallbackArg_Pop +}; + +static BOOL cflash_init() +{ + if (inited) return FALSE; + BOOL init_good = FALSE; + + CFLASHLOG("CFlash_Mode: %d\n",CFlash_Mode); + + if (CFlash_Mode == ADDON_CFLASH_MODE_RomPath) + { + sFlashPath = path.RomDirectory; + INFO("Using CFlash directory of rom: %s\n", sFlashPath.c_str()); + } + else if(CFlash_Mode == ADDON_CFLASH_MODE_Path) + { + sFlashPath = CFlash_Path; + INFO("Using CFlash directory: %s\n", sFlashPath.c_str()); + } + + if(CFlash_IsUsingPath()) + { + cflashDeviceEnabled = FALSE; + currLBA = 0; + + fileStartLBA = fileEndLBA = 0xFFFFFFFF; + VFAT vfat; + bool ret = vfat.build(sFlashPath.c_str(),16); //allocate 16MB extra for writing. this is probably enough for anyone, but maybe it should be configurable. + //we could always suggest to users to add a big file to their directory to overwrite (that would cause the image to get padded) + + if(!ret) + { + CFLASHLOG("FAILED cflash_build_fat\n"); + return FALSE; + } + + file = vfat.detach(); + + cf_reg_sts = 0x58; // READY + + cflashDeviceEnabled = TRUE; + init_good = TRUE; + } + else + { + sFlashPath = CFlash_Path; + INFO("Using CFlash disk image file %s\n", sFlashPath.c_str()); + file = new EMUFILE_FILE(sFlashPath.c_str(),"rb+"); + if(file->fail()) + { + INFO("Failed to open file %s\n", sFlashPath.c_str()); + delete file; + file = NULL; + } + } + + // READY + cf_reg_sts = 0x58; + + currLBA = 0; + cf_reg_lba1 = cf_reg_lba2 = + cf_reg_lba3 = cf_reg_lba4 = 0; + + inited = TRUE; + return init_good; +} + +static unsigned int cflash_read(unsigned int address) +{ + unsigned int ret_value = 0; + size_t elems_read = 0; + + switch (address) + { + case CF_REG_STS: + ret_value = cf_reg_sts; + break; + + case CF_REG_DATA: + if (cf_reg_cmd == CF_CMD_READ) + { + if(file) + { + u8 data[2]; + file->fseek(currLBA, SEEK_SET); + elems_read += file->fread(data,2); + ret_value = data[1] << 8 | data[0]; + } + currLBA += 2; + } + break; + + case CF_REG_CMD: + break; + + case CF_REG_LBA1: + ret_value = cf_reg_lba1; + break; + } + + return ret_value; +} + +static void cflash_write(unsigned int address,unsigned int data) +{ + static u8 sector_data[512]; + static u32 sector_write_index = 0; + + switch (address) + { + case CF_REG_STS: + cf_reg_sts = data&0xFFFF; + break; + + case CF_REG_DATA: + if (cf_reg_cmd == CF_CMD_WRITE) + { + { + sector_data[sector_write_index] = (data >> 0) & 0xff; + sector_data[sector_write_index + 1] = (data >> 8) & 0xff; + + sector_write_index += 2; + + if (sector_write_index == 512) + { + CFLASHLOG( "Write sector to %ld\n", currLBA); + size_t written = 0; + + if(file) + if(currLBA + 512 < file->size()) + { + file->fseek(currLBA,SEEK_SET); + + while(written < 512) + { + size_t todo = 512-written; + file->fwrite(§or_data[written], todo); + size_t cur_write = todo; + written += cur_write; + if ( cur_write == (size_t)-1) break; + } + } + + CFLASHLOG("Wrote %u bytes\n", written); + + currLBA += 512; + sector_write_index = 0; + } + } + } + break; + + case CF_REG_CMD: + cf_reg_cmd = data&0xFF; + cf_reg_sts = 0x58; // READY + break; + + case CF_REG_LBA1: + cf_reg_lba1 = data&0xFF; + currLBA = (currLBA&0xFFFFFF00)| cf_reg_lba1; + break; + + case CF_REG_LBA2: + cf_reg_lba2 = data&0xFF; + currLBA = (currLBA&0xFFFF00FF)|(cf_reg_lba2<<8); + break; + + case CF_REG_LBA3: + cf_reg_lba3 = data&0xFF; + currLBA = (currLBA&0xFF00FFFF)|(cf_reg_lba3<<16); + break; + + case CF_REG_LBA4: + cf_reg_lba4 = data&0xFF; + + if ((cf_reg_lba4 & 0xf0) == CF_CMD_LBA) + { + currLBA = (currLBA&0x00FFFFFF)|((cf_reg_lba4&0x0F)<<24); + currLBA *= 512; + sector_write_index = 0; + } + break; + } +} + +static void cflash_close( void) +{ + if (!inited) return; + if(file) delete file; + cflashDeviceEnabled = FALSE; + file = NULL; + inited = FALSE; +} + +static BOOL init(void) +{ + return TRUE; +} + +static void reset(void) +{ + cflash_close(); + cflash_init(); +} + +static void close(void) +{ + cflash_close(); +} + +static void config(void) +{ +} + +static void write08(u32 procnum, u32 adr, u8 val) +{ + cflash_write(adr, val); +} + +static void write16(u32 procnum, u32 adr, u16 val) +{ + cflash_write(adr, val); +} + +static void write32(u32 procnum, u32 adr, u32 val) +{ + cflash_write(adr, val); +} + +static u8 read08(u32 procnum, u32 adr) +{ + return (cflash_read(adr)); +} + +static u16 read16(u32 procnum, u32 adr) +{ + return (cflash_read(adr)); +} + +static u32 read32(u32 procnum, u32 adr) +{ + return (cflash_read(adr)); +} + +static void info(char *info) +{ + strcpy(info, "MPCF Flash Card Device"); +} + +ADDONINTERFACE addonCFlash = { + "MPCF Flash Card Device", + init, + reset, + close, + config, + write08, + write16, + write32, + read08, + read16, + read32, + info}; + +#undef CFLASHDEBUG diff --git a/jni/desmume/src/addons/slot2_none.cpp b/jni/desmume/src/addons/slot2_none.cpp new file mode 100755 index 0000000..60acb41 --- /dev/null +++ b/jni/desmume/src/addons/slot2_none.cpp @@ -0,0 +1,48 @@ +/* Copyright (C) 2009 CrazyMax + Copyright (C) 2009 DeSmuME team + + This file is part of DeSmuME + + DeSmuME 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. + + DeSmuME 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 DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../addons.h" +#include + +static BOOL None_init(void) { return (TRUE); } +static void None_reset(void) {} +static void None_close(void) {} +static void None_config(void) {} +static void None_write08(u32 procnum, u32 adr, u8 val) {} +static void None_write16(u32 procnum, u32 adr, u16 val) {} +static void None_write32(u32 procnum, u32 adr, u32 val) {} +static u8 None_read08(u32 procnum, u32 adr){ return (0xFF); } +static u16 None_read16(u32 procnum, u32 adr){ return (0xFFFF); } +static u32 None_read32(u32 procnum, u32 adr){ return (0xFFFFFFFF); } +static void None_info(char *info) { strcpy(info, "Nothing in GBA slot"); } + +ADDONINTERFACE addonNone = { + "NONE", + None_init, + None_reset, + None_close, + None_config, + None_write08, + None_write16, + None_write32, + None_read08, + None_read16, + None_read32, + None_info}; diff --git a/jni/desmume/src/addons/slot2_paddle.cpp b/jni/desmume/src/addons/slot2_paddle.cpp new file mode 100755 index 0000000..c5a19d9 --- /dev/null +++ b/jni/desmume/src/addons/slot2_paddle.cpp @@ -0,0 +1,144 @@ +/* Copyright (C) 2011 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ + +/* +this device seems to have a 12bit value (like 20.12 fixed point.. get it?) located at 0x0A000000 +clockwise = right = increases. +it returns the correct little endian bytes through byte reads. +through halfword reads, it returns the LSB twice +through full word reads, it returns the LSB four times. +after that everything is 0x00. +if the slot2 timings are wrong, then this device will return glitchy or 0xFF output. +so this emulation code will attempt to validate that. +arkanoid was setting REG_EXMEMCNT = 0x082F + +the rom returns 0xEFFF for all addresses and should be used to detect this device + +writing any byte to SRAM or writing any halfword/word to rom results in a reset or some kind of recalibrate +the resulting value may be 0x000,0x001, or 0xFFF. seems mostly random, though once it is reset, resetting again won't change it. +you must wait until the paddle has been moved. + +conclusion: +The emulation in all the handling of erroneous cases is not perfect, and some other users of the paddle (do any other games use it?) +maybe legally configure the paddle differently, which could be rejected here; in which case this code will need finetuning +*/ + +#include "../addons.h" +#include +#include "NDSSystem.h" + +static BOOL init(void) { return (TRUE); } +static void reset(void) +{ +} + +static void calibrate() +{ + nds.paddle = 0; +} + +static void close(void) {} +static void config(void) {} +static void write08(u32 procnum, u32 adr, u8 val) +{ + if(adr<0x0A000000) return; + calibrate(); +} +static void write16(u32 procnum, u32 adr, u16 val) +{ + if(adr<0x0A000000) { calibrate(); return; } +} +static void write32(u32 procnum, u32 adr, u32 val) +{ + if(adr<0x0A000000) { calibrate(); return; } +} +extern int currFrameCounter; + +static bool Validate(u32 procnum, bool rom) { + if(rom) + return ValidateSlot2Access(procnum,0,0,0,-1); + else + return ValidateSlot2Access(procnum,18,0,0,1); +} +static u8 read08(u32 procnum, u32 adr) +{ + //printf("paddle: read 08 at 0x%08X\n", adr); + if(!Validate(procnum,adr<0x0A000000)) + return 0xFF; + + if(adr<0x0A000000) + { + if(adr&1) return 0xFF; + else return 0xEF; + } + + if(adr==0x0A000000) + { + return nds.paddle&0xFF; + } + if(adr==0x0A000001) + { + return (nds.paddle>>8)&0x0F; + } + return 0x00; +} +static u16 read16(u32 procnum, u32 adr) +{ + //printf("paddle : read 16 at 0x%08X\n", adr); + if(!Validate(procnum,adr<0x0A000000)) + return 0xFFFF; + + if(adr<0x0A000000) + return 0xEFFF; + if(adr==0x0A000000) + { + u8 val = nds.paddle&0xFF; + return val|(val<<8); + } + + return 0x0000; +} +static u32 read32(u32 procnum, u32 adr) +{ + //printf("paddle: read 32 at 0x%08X\n", adr); + if(!Validate(procnum,adr<0x0A000000)) + return 0xFFFFFFFF; + + if(adr<0x0A000000) + return 0xEFFFEFFF; + if(adr==0x0A000000) + { + u8 val = nds.paddle&0xFF; + return val|(val<<8)|(val<<16)|(val<<24); + } + + return 0x00000000; +} +static void info(char *info) { strcpy(info, "Paddle"); } + +ADDONINTERFACE addonPaddle = { + "Paddle", + init, + reset, + close, + config, + write08, + write16, + write32, + read08, + read16, + read32, + info}; diff --git a/jni/desmume/src/addons/slot2_piano.cpp b/jni/desmume/src/addons/slot2_piano.cpp new file mode 100755 index 0000000..97ea793 --- /dev/null +++ b/jni/desmume/src/addons/slot2_piano.cpp @@ -0,0 +1,144 @@ +/* Copyright (C) 2010-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see . +*/ + +#include "../addons.h" +#include + +static u16 pianoKeyStatus = 0; + +static BOOL piano_init(void) { return (TRUE); } +static void piano_reset(void) +{ + //INFO("piano: Reset\n"); + pianoKeyStatus = 0; +} + +static void piano_close(void) {} +static void piano_config(void) {} +static void piano_write08(u32 procnum, u32 adr, u8 val) +{ + //INFO("piano: write 08 at 0x%08X = %02X\n", adr, val); +} +static void piano_write16(u32 procnum, u32 adr, u16 val) +{ + //INFO("piano: write 16 at 0x%08X = %04X\n", adr, val); +} +static void piano_write32(u32 procnum, u32 adr, u32 val) +{ + //INFO("piano: write 32 at 0x%08X = %08X\n", adr, val); +} +extern int currFrameCounter; +static u8 piano_read08(u32 procnum, u32 adr) +{ + //printf("piano: read 08 at 0x%08X\n", adr); + + //the actual keyboard output + + //byte:bit + //0x09FFFFFE:0 = C + //0x09FFFFFE:1 = C# + //0x09FFFFFE:2 = D + //0x09FFFFFE:3 = D# + //0x09FFFFFE:4 = E + //0x09FFFFFE:5 = F + //0x09FFFFFE:6 = F# + //0x09FFFFFE:7 = G + //0x09FFFFFF:0 = G# + //0x09FFFFFF:1 = A + //0x09FFFFFF:2 = A# + //0x09FFFFFF:3 = ? + //0x09FFFFFF:4 = ? + //0x09FFFFFF:5 = B + //0x09FFFFFF:6 = hiC + //0x09FFFFFF:7 = ? + + //deassert bit if key is pressed + + //LOG("PIANO: %04X\n",pianoKeyStatus); + + if(adr == 0x09FFFFFE) return (~(pianoKeyStatus&0xFF)); + if(adr == 0x09FFFFFF) return (~((pianoKeyStatus>>8)&0xFF))&~(0x18); + + if(adr&1) return 0xE7; + else return 0xFF; +} +static u16 piano_read16(u32 procnum, u32 adr) +{ + //printf("piano: read 16 at 0x%08X\n", adr); + if(adr != 0x09FFFFFE) + return 0xE7FF; + u16 ret = piano_read08(procnum,0x09FFFFFE)|(piano_read08(procnum,0x09FFFFFF)<<8); + //return ( (PIANO_PAK & 0x1800 ) == 0 ); + return ret; +} +static u32 piano_read32(u32 procnum, u32 adr) +{ + //printf("piano: read 32 at 0x%08X\n", adr); + return 0xE7FFE7FF; +} +static void piano_info(char *info) { strcpy(info, "Piano for EasyPiano"); } + +void piano_setKey(bool c, bool cs, bool d, bool ds, bool e, bool f, bool fs, bool g, bool gs, bool a, bool as, bool b, bool hic) +{ + //0x09FFFFFE:0 = C + //0x09FFFFFE:1 = C# + //0x09FFFFFE:2 = D + //0x09FFFFFE:3 = D# + //0x09FFFFFE:4 = E + //0x09FFFFFE:5 = F + //0x09FFFFFE:6 = F# + //0x09FFFFFE:7 = G + //0x09FFFFFE:0 = G# + //0x09FFFFFE:1 = A + //0x09FFFFFF:2 = A# + //0x09FFFFFF:3 = ? + //0x09FFFFFF:4 = ? + //0x09FFFFFF:5 = B + //0x09FFFFFF:6 = hiC + //0x09FFFFFF:7 = ? + +#define BIT(N,v) ((v)?(1<<(N)):0) + pianoKeyStatus = + BIT(0,c) | + BIT(1,cs) | + BIT(2,d) | + BIT(3,ds) | + BIT(4,e) | + BIT(5,f) | + BIT(6,fs) | + BIT(7,g) | + BIT(8,gs) | + BIT(9,a) | + BIT(10,as) | + BIT(13,b) | + BIT(14,hic) + ; + pianoKeyStatus = pianoKeyStatus; +} + +ADDONINTERFACE addonPiano = { + "Piano", + piano_init, + piano_reset, + piano_close, + piano_config, + piano_write08, + piano_write16, + piano_write32, + piano_read08, + piano_read16, + piano_read32, + piano_info}; diff --git a/jni/desmume/src/addons/slot2_rumblepak.cpp b/jni/desmume/src/addons/slot2_rumblepak.cpp new file mode 100755 index 0000000..9e340e8 --- /dev/null +++ b/jni/desmume/src/addons/slot2_rumblepak.cpp @@ -0,0 +1,98 @@ +/* Copyright (C) 2009-2010 DeSmuME team + + This file is part of DeSmuME + + DeSmuME 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. + + DeSmuME 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 DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../addons.h" +#include "../mem.h" +#include "../MMU.h" +#include + +u16 old_val_rumble = 0; + +void (*FeedbackON)(BOOL enable) = NULL; + +static BOOL RumblePak_init(void) { return (TRUE); } + +static void RumblePak_reset(void) +{ + old_val_rumble = 0; + if (!FeedbackON) return; + FeedbackON(false); +} + +static void RumblePak_close(void) {} + +static void RumblePak_config(void) {} + +static void RumblePak_write08(u32 procnum, u32 adr, u8 val) +{ +} + +static void RumblePak_write16(u32 procnum, u32 adr, u16 val) +{ + if (!FeedbackON) return; + + if (old_val_rumble == val) return; + + old_val_rumble = val; + // CrazyMax 17/01/2009 + // i don't know how send to feedback (PC) impulse with small latency. + if (adr == 0x08000000) + FeedbackON(val); + if (adr == 0x08001000) + FeedbackON(val); +} + +static void RumblePak_write32(u32 procnum, u32 adr, u32 val) +{ +} + +static u8 RumblePak_read08(u32 procnum, u32 adr) +{ + if(adr&1) return 0xFF; + else return 0xFD; +} + +static u16 RumblePak_read16(u32 procnum, u32 adr) +{ + return 0xFFFD; +} + +static u32 RumblePak_read32(u32 procnum, u32 adr) +{ + return 0xFFFDFFFD; +} + +static void RumblePak_info(char *info) +{ + strcpy(info, "NDS Rumble Pak (need joystick with Feedback)"); +} + +ADDONINTERFACE addonRumblePak = { + "Rumble Pak", + RumblePak_init, + RumblePak_reset, + RumblePak_close, + RumblePak_config, + RumblePak_write08, + RumblePak_write16, + RumblePak_write32, + RumblePak_read08, + RumblePak_read16, + RumblePak_read32, + RumblePak_info}; diff --git a/jni/desmume/src/agg2d.h b/jni/desmume/src/agg2d.h new file mode 100755 index 0000000..20b3997 --- /dev/null +++ b/jni/desmume/src/agg2d.h @@ -0,0 +1,932 @@ +//---------------------------------------------------------------------------- +// Agg2D - Version 1.0 +// Based on Anti-Grain Geometry +// Copyright (C) 2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// +// 25 Jan 2007 - Ported to AGG 2.4 Jerry Evans (jerry@novadsp.com) +// 11 Jul 2009 - significant refactors for introduction to desmume +// +//---------------------------------------------------------------------------- + +#ifndef AGG2D_INCLUDED +#define AGG2D_INCLUDED + +//we're not using vector fonts right now. +//#define AGG2D_USE_VECTORFONTS + +#ifdef AGG2D_USE_VECTORFONTS +#if defined(UNDER_CE) || not defined(WIN32) +#define AGG2D_USE_FREETYPE +#endif +#endif + +#ifdef _MSC_VER +#pragma warning(disable: 4786) +#endif + +// JME +#include "agg_basics.h" +#include "agg_math_stroke.h" +#include "agg_trans_affine.h" +#include "agg_trans_viewport.h" +#include "agg_path_storage.h" +#include "agg_conv_stroke.h" +#include "agg_conv_transform.h" +#include "agg_conv_curve.h" +#include "agg_rendering_buffer.h" +#include "agg_renderer_base.h" +#include "agg_renderer_scanline.h" +#include "agg_span_gradient.h" +#include "agg_span_image_filter_rgba.h" + +//+ JME +#include "agg_span_allocator.h" +#include "agg_span_converter.h" +#include "agg_span_interpolator_linear.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_gamma_functions.h" +#include "agg_scanline_u.h" +#include "agg_bezier_arc.h" +#include "agg_rounded_rect.h" +#include "agg_font_cache_manager.h" + +#include "agg_glyph_raster_bin.h" +#include "agg_renderer_raster_text.h" +#include "agg_embedded_raster_fonts.h" + + +#include + +#ifdef AGG2D_USE_VECTORFONTS +#ifdef AGG2D_USE_FREETYPE +#ifndef WIN32 +#include "agg_font_freetype.h" +#else +#include "../font_freetype/agg_font_freetype.h" +#endif +#else +#include "../font_win32_tt/agg_font_win32_tt.h" +#endif +#endif + +#include "agg_pixfmt_rgba.h" +//+ JME +#include "agg_image_accessors.h" + +#define AGG2D_TEMPLATE template +#define AGG2D_TEMPLATE_WITH_IMAGE template +#define AGG2D_TEMPLATE_ARG +#define AGG2D_IMAGE_TEMPLATE template +#define AGG2D_IMAGE_TEMPLATE_ARG +#define TIMAGE Agg2DBase :: Image AGG2D_IMAGE_TEMPLATE_ARG + + +template +class PixFormatSetDeclaration +{ +public: + typedef Main PixFormat; + typedef Pre PixFormatPre; + typedef SG SpanGenerator; +}; + +class Agg2DBase +{ +public: + // JME + //typedef agg::rect Rect; + typedef agg::rect_i Rect; + typedef agg::rect_d RectD; + typedef agg::trans_affine Affine; + + enum LineJoin + { + JOIN_MITER = agg::miter_join, + JOIN_ROUND = agg::round_join, + JOIN_BEVEL = agg::bevel_join + }; + + enum LineCap + { + CAP_BUTT = agg::butt_cap, + CAP_SQUARE = agg::square_cap, + CAP_ROUND = agg::round_cap + }; + + enum TextAlignment + { + AlignLeft, + AlignRight, + AlignCenter, + AlignBaseline, + AlignTop = AlignRight, + AlignBottom = AlignLeft + }; + + + enum DrawPathFlag + { + FillOnly, + StrokeOnly, + FillAndStroke, + FillWithLineColor + }; + + enum ViewportOption + { + Anisotropic, + XMinYMin, + XMidYMin, + XMaxYMin, + XMinYMid, + XMidYMid, + XMaxYMid, + XMinYMax, + XMidYMax, + XMaxYMax + }; + + enum WindowFitLogic + { + WindowFitLogic_meet, + WindowFitLogic_slice + }; + + struct Transformations + { + double affineMatrix[6]; + }; + + AGG2D_IMAGE_TEMPLATE struct Image + { + agg::rendering_buffer renBuf; + + Image(const agg::rendering_buffer& srcBuf) + : renBuf(srcBuf) + {} + Image(unsigned char* buf, unsigned width, unsigned height, int stride) : + renBuf(buf, width, height, stride) {} + void attach(unsigned char* buf, unsigned width, unsigned height, int stride) + { + renBuf.attach(buf, width, height, stride); + } + int width() const { return renBuf.width(); } + int height() const { return renBuf.height(); } + + AGG2D_TEMPLATE void premultiply() + { + typename PixFormatSet::PixFormat pixf(renBuf); + pixf.premultiply(); + } + + AGG2D_TEMPLATE void demultiply() + { + typename PixFormatSet::PixFormat pixf(renBuf); + pixf.demultiply(); + } + + }; + + enum ImageFilter + { + NoFilter, + Bilinear, + Hanning, + Hermite, + Quadric, + Bicubic, + Catrom, + Spline16, + Spline36, + Blackman144 + }; + + enum ImageResample + { + NoResample, + ResampleAlways, + ResampleOnZoomOut + }; + + enum FontCacheType + { + RasterFontCache, + VectorFontCache + }; + + enum BlendMode + { + BlendAlpha = agg::end_of_comp_op_e, + BlendClear = agg::comp_op_clear, + BlendSrc = agg::comp_op_src, + BlendDst = agg::comp_op_dst, + BlendSrcOver = agg::comp_op_src_over, + BlendDstOver = agg::comp_op_dst_over, + BlendSrcIn = agg::comp_op_src_in, + BlendDstIn = agg::comp_op_dst_in, + BlendSrcOut = agg::comp_op_src_out, + BlendDstOut = agg::comp_op_dst_out, + BlendSrcAtop = agg::comp_op_src_atop, + BlendDstAtop = agg::comp_op_dst_atop, + BlendXor = agg::comp_op_xor, + BlendAdd = agg::comp_op_plus, + BlendSub = agg::comp_op_minus, + BlendMultiply = agg::comp_op_multiply, + BlendScreen = agg::comp_op_screen, + BlendOverlay = agg::comp_op_overlay, + BlendDarken = agg::comp_op_darken, + BlendLighten = agg::comp_op_lighten, + BlendColorDodge = agg::comp_op_color_dodge, + BlendColorBurn = agg::comp_op_color_burn, + BlendHardLight = agg::comp_op_hard_light, + BlendSoftLight = agg::comp_op_soft_light, + BlendDifference = agg::comp_op_difference, + BlendExclusion = agg::comp_op_exclusion, + BlendContrast = agg::comp_op_contrast + }; + + enum Direction + { + CW, CCW + }; + +}; + +template class Agg2DRenderer; + +template class Agg2D : public Agg2DBase +{ +public: + typedef typename PixFormatSet::PixFormat PixFormat; + typedef Image MyImage; + typedef agg::order_bgra ComponentOrder; // Platform dependent! + + typedef agg::rgba8 ColorType; + typedef agg::blender_rgba Blender; + typedef agg::comp_op_adaptor_rgba BlenderComp; + typedef agg::blender_rgba_pre BlenderPre; + typedef agg::comp_op_adaptor_rgba_pre BlenderCompPre; + + // JME + //typedef agg::pixel_formats_rgba PixFormat; + //typedef agg::pixfmt_bgra32 PixFormat; + // JME + //typedef agg::pixfmt_custom_blend_rgba PixFormatComp; + typedef agg::pixfmt_custom_blend_rgba PixFormatComp; + // JME + //typedef agg::pixel_formats_rgba PixFormatPre; + typedef typename PixFormatSet::PixFormatPre PixFormatPre; + // JME + //typedef agg::pixfmt_custom_blend_rgba PixFormatCompPre; + typedef agg::pixfmt_custom_blend_rgba PixFormatCompPre; + + typedef agg::renderer_base RendererBase; + typedef agg::renderer_base RendererBaseComp; + typedef agg::renderer_base RendererBasePre; + typedef agg::renderer_base RendererBaseCompPre; + + typedef agg::renderer_scanline_aa_solid RendererSolid; + typedef agg::renderer_scanline_aa_solid RendererSolidComp; + + typedef agg::span_allocator SpanAllocator; + typedef agg::pod_auto_array GradientArray; + + typedef agg::span_gradient, agg::gradient_x, GradientArray> LinearGradientSpan; + typedef agg::span_gradient, agg::gradient_circle, GradientArray> RadialGradientSpan; + +#ifdef AGG2D_USE_VECTORFONTS +#ifdef AGG2D_USE_FREETYPE + typedef agg::font_engine_freetype_int32 FontEngine; +#else + typedef agg::font_engine_win32_tt_int32 FontEngine; +#endif + + typedef agg::font_cache_manager FontCacheManager; + typedef FontCacheManager::gray8_adaptor_type FontRasterizer; + typedef FontCacheManager::gray8_scanline_type FontScanline; +#endif + + typedef agg::conv_curve ConvCurve; + typedef agg::conv_stroke ConvStroke; + typedef agg::conv_transform PathTransform; + typedef agg::conv_transform StrokeTransform; + enum Gradient + { + Solid, + Linear, + Radial + }; + +public: + template friend class Agg2DRenderer; + + typedef ColorType Color; + + + + struct State + { + RectD m_clipBox; + + BlendMode m_blendMode; + BlendMode m_imageBlendMode; + Color m_imageBlendColor; + + double m_masterAlpha; + double m_antiAliasGamma; + + const agg::int8u* m_font; + + Color m_fillColor; + Color m_lineColor; + GradientArray m_fillGradient; + GradientArray m_lineGradient; + + LineCap m_lineCap; + LineJoin m_lineJoin; + + Gradient m_fillGradientFlag; + Gradient m_lineGradientFlag; + agg::trans_affine m_fillGradientMatrix; + agg::trans_affine m_lineGradientMatrix; + double m_fillGradientD1; + double m_lineGradientD1; + double m_fillGradientD2; + double m_lineGradientD2; + + double m_textAngle; + TextAlignment m_textAlignX; + TextAlignment m_textAlignY; + bool m_textHints; + double m_fontHeight; + double m_fontAscent; + double m_fontDescent; + FontCacheType m_fontCacheType; + + double m_lineWidth; + bool m_evenOddFlag; + + agg::trans_affine m_transform; + agg::trans_affine m_affine; + + }; + + + ~Agg2D(); + Agg2D(); + + // Setup + //----------------------- + void attach(unsigned char* buf, unsigned width, unsigned height, int stride); + void attach(MyImage& img); + + void clipBox(double x1, double y1, double x2, double y2); + RectD clipBox() const; + + void clearAll(Color c); + void clearAll(unsigned r, unsigned g, unsigned b, unsigned a = 255); + + void clearClipBox(Color c); + void clearClipBox(unsigned r, unsigned g, unsigned b, unsigned a = 255); + + unsigned width() const { return m_rbuf.width(); } + unsigned height() const { return m_rbuf.height(); } + unsigned stride() const { return m_rbuf.stride(); } + + // Conversions + //----------------------- + void worldToScreen(double& x, double& y) const; + void screenToWorld(double& x, double& y) const; + double worldToScreen(double scalar) const; + double screenToWorld(double scalar) const; + void alignPoint(double& x, double& y) const; + bool inBox(double worldX, double worldY) const; + + // General Attributes + //----------------------- + void blendMode(BlendMode m); + BlendMode blendMode() const; + + void imageBlendMode(BlendMode m); + BlendMode imageBlendMode() const; + + void imageBlendColor(Color c); + void imageBlendColor(unsigned r, unsigned g, unsigned b, unsigned a = 255); + Color imageBlendColor() const; + + void masterAlpha(double a); + double masterAlpha() const; + + void antiAliasGamma(double g); + double antiAliasGamma() const; + + void font(const agg::int8u* font) { m_font = font; } + const agg::int8u* font() { return m_font; } + + void fillColor(Color c); + void fillColor(unsigned r, unsigned g, unsigned b, unsigned a = 255); + void noFill(); + + void lineColor(Color c); + void lineColor(unsigned r, unsigned g, unsigned b, unsigned a = 255); + void noLine(); + + Color fillColor() const; + Color lineColor() const; + + void fillLinearGradient(double x1, double y1, double x2, double y2, Color c1, Color c2, double profile=1.0); + void lineLinearGradient(double x1, double y1, double x2, double y2, Color c1, Color c2, double profile=1.0); + + void fillRadialGradient(double x, double y, double r, Color c1, Color c2, double profile=1.0); + void lineRadialGradient(double x, double y, double r, Color c1, Color c2, double profile=1.0); + + void fillRadialGradient(double x, double y, double r, Color c1, Color c2, Color c3); + void lineRadialGradient(double x, double y, double r, Color c1, Color c2, Color c3); + + void fillRadialGradient(double x, double y, double r); + void lineRadialGradient(double x, double y, double r); + + void lineWidth(double w); + double lineWidth() const; + + void lineCap(LineCap cap); + LineCap lineCap() const; + + void lineJoin(LineJoin join); + LineJoin lineJoin() const; + + void fillEvenOdd(bool evenOddFlag); + bool fillEvenOdd() const; + + // Transformations + //----------------------- + Transformations transformations() const; + void transformations(const Transformations& tr); + + const Affine& affine() const; + void affine(const Affine&); + + void resetTransformations(); + void matrix(const Affine& tr); + void matrix(const Transformations& tr); + void rotate(double angle); + void rotate(double angle, double cx, double cy); + void scale(double s); + void scale(double sx, double sy); + void skew(double sx, double sy); + void translate(double x, double y); + void parallelogram(double x1, double y1, double x2, double y2, const double* para); + void viewport(double worldX1, double worldY1, double worldX2, double worldY2, + double screenX1, double screenY1, double screenX2, double screenY2, + ViewportOption opt=XMidYMid, WindowFitLogic fl = WindowFitLogic_meet); + + // Basic Shapes + //----------------------- + void line(double x1, double y1, double x2, double y2); + void triangle(double x1, double y1, double x2, double y2, double x3, double y3); + void rectangle(double x1, double y1, double x2, double y2); + void roundedRect(double x1, double y1, double x2, double y2, double r); + void roundedRect(double x1, double y1, double x2, double y2, double rx, double ry); + void roundedRect(double x1, double y1, double x2, double y2, + double rxBottom, double ryBottom, + double rxTop, double ryTop); + void ellipse(double cx, double cy, double rx, double ry); + void arc(double cx, double cy, double rx, double ry, double start, double sweep); + void star(double cx, double cy, double r1, double r2, double startAngle, int numRays); + void curve(double x1, double y1, double x2, double y2, double x3, double y3); + void curve(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4); + void polygon(double* xy, int numPoints); + void polyline(double* xy, int numPoints); + + + // Text + //----------------------- +#ifdef AGG2D_USE_VECTORFONTS + void flipText(bool flip); + void font(const char* fileName, double height, + bool bold = false, + bool italic = false, + FontCacheType ch = RasterFontCache, + double angle = 0.0); + double fontHeight() const; + double fontAscent() const; + + void textAlignment(TextAlignment alignX, TextAlignment alignY); + bool textHints() const; + void textHints(bool hints); + double textWidth(const char* str, unsigned int len); + double textWidth(const wchar_t* str, unsigned int len); + void text(double x, double y, const char* str, unsigned int len, bool roundOff=false, double dx=0.0, double dy=0.0); + void text(double x, double y, const wchar_t* str, unsigned int len, bool roundOff=false, double dx=0.0, double dy=0.0); + + double textWidth(const char* str); + void text(double x, double y, const char* str, bool roundOff=false, double dx=0.0, double dy=0.0); +#endif + + // Path commands + //----------------------- + void resetPath(); + + void moveTo(double x, double y); + void moveRel(double dx, double dy); + + void lineTo(double x, double y); + void lineRel(double dx, double dy); + + void horLineTo(double x); + void horLineRel(double dx); + + void verLineTo(double y); + void verLineRel(double dy); + + void arcTo(double rx, double ry, + double angle, + bool largeArcFlag, + bool sweepFlag, + double x, double y); + + void arcRel(double rx, double ry, + double angle, + bool largeArcFlag, + bool sweepFlag, + double dx, double dy); + + void quadricCurveTo(double xCtrl, double yCtrl, + double xTo, double yTo); + void quadricCurveRel(double dxCtrl, double dyCtrl, + double dxTo, double dyTo); + void quadricCurveTo(double xTo, double yTo); + void quadricCurveRel(double dxTo, double dyTo); + + void cubicCurveTo(double xCtrl1, double yCtrl1, + double xCtrl2, double yCtrl2, + double xTo, double yTo); + + void cubicCurveRel(double dxCtrl1, double dyCtrl1, + double dxCtrl2, double dyCtrl2, + double dxTo, double dyTo); + + void cubicCurveTo(double xCtrl2, double yCtrl2, + double xTo, double yTo); + + void cubicCurveRel(double xCtrl2, double yCtrl2, + double xTo, double yTo); + + void addEllipse(double cx, double cy, double rx, double ry, Direction dir); + void closePolygon(); + + void drawPath(DrawPathFlag flag = FillAndStroke); + void drawPathNoTransform(DrawPathFlag flag = FillAndStroke); + + + // Image Transformations + //----------------------- + void imageFilter(ImageFilter f); + ImageFilter imageFilter() const; + + void imageResample(ImageResample f); + ImageResample imageResample() const; + + //--------- + //if anyone can figure out how to put these in the .inl file, theyre more than welcome to. I couldnt declare them correctly to match + //the .h file declaration + + AGG2D_IMAGE_TEMPLATE void transformImage(const TIMAGE& img, + int imgX1, int imgY1, int imgX2, int imgY2, + double dstX1, double dstY1, double dstX2, double dstY2) + { + resetPath(); + moveTo(dstX1, dstY1); + lineTo(dstX2, dstY1); + lineTo(dstX2, dstY2); + lineTo(dstX1, dstY2); + closePolygon(); + double parallelogram[6] = { dstX1, dstY1, dstX2, dstY1, dstX2, dstY2 }; + renderImage (img, imgX1, imgY1, imgX2, imgY2, parallelogram); + } + + AGG2D_IMAGE_TEMPLATE void transformImage(const TIMAGE& img, + double dstX1, double dstY1, double dstX2, double dstY2) + { + resetPath(); + moveTo(dstX1, dstY1); + lineTo(dstX2, dstY1); + lineTo(dstX2, dstY2); + lineTo(dstX1, dstY2); + closePolygon(); + double parallelogram[6] = { dstX1, dstY1, dstX2, dstY1, dstX2, dstY2 }; + renderImage(img, 0, 0, img.renBuf.width(), img.renBuf.height(), parallelogram); + } + + + AGG2D_IMAGE_TEMPLATE void transformImage(const TIMAGE& img, + int imgX1, int imgY1, int imgX2, int imgY2, + const double* parallelogram) + { + resetPath(); + moveTo(parallelogram[0], parallelogram[1]); + lineTo(parallelogram[2], parallelogram[3]); + lineTo(parallelogram[4], parallelogram[5]); + lineTo(parallelogram[0] + parallelogram[4] - parallelogram[2], + parallelogram[1] + parallelogram[5] - parallelogram[3]); + closePolygon(); + renderImage(img, imgX1, imgY1, imgX2, imgY2, parallelogram); + } + + + AGG2D_IMAGE_TEMPLATE void transformImage(const TIMAGE& img, const double* parallelogram) + { + resetPath(); + moveTo(parallelogram[0], parallelogram[1]); + lineTo(parallelogram[2], parallelogram[3]); + lineTo(parallelogram[4], parallelogram[5]); + lineTo(parallelogram[0] + parallelogram[4] - parallelogram[2], + parallelogram[1] + parallelogram[5] - parallelogram[3]); + closePolygon(); + renderImage(img, 0, 0, img.renBuf.width(), img.renBuf.height(), parallelogram); + } + + + + AGG2D_IMAGE_TEMPLATE void transformImagePath(const TIMAGE& img, + int imgX1, int imgY1, int imgX2, int imgY2, + double dstX1, double dstY1, double dstX2, double dstY2) + { + double parallelogram[6] = { dstX1, dstY1, dstX2, dstY1, dstX2, dstY2 }; + renderImage(img, imgX1, imgY1, imgX2, imgY2, parallelogram); + } + + + AGG2D_IMAGE_TEMPLATE void transformImagePath(const TIMAGE& img, + double dstX1, double dstY1, double dstX2, double dstY2) + { + double parallelogram[6] = { dstX1, dstY1, dstX2, dstY1, dstX2, dstY2 }; + renderImage(img, 0, 0, img.renBuf.width(), img.renBuf.height(), parallelogram); + } + + + + AGG2D_IMAGE_TEMPLATE void transformImagePath(const TIMAGE& img, + int imgX1, int imgY1, int imgX2, int imgY2, + const double* parallelogram) + { + renderImage(img, imgX1, imgY1, imgX2, imgY2, parallelogram); + } + + + AGG2D_IMAGE_TEMPLATE void transformImagePath(const TIMAGE& img, const double* parallelogram) + { + renderImage(img, 0, 0, img.renBuf.width(), img.renBuf.height(), parallelogram); + } + + + + // Image Blending (no transformations available) + AGG2D_IMAGE_TEMPLATE void blendImage(TIMAGE& img, + int imgX1, int imgY1, int imgX2, int imgY2, + double dstX, double dstY, unsigned alpha=255) + { + worldToScreen(dstX, dstY); + PixFormat pixF(img.renBuf); + // JME + //agg::rect r(imgX1, imgY1, imgX2, imgY2); + Rect r(imgX1, imgY1, imgX2, imgY2); + if(m_blendMode == BlendAlpha) + { + m_renBasePre.blend_from(pixF, &r, int(dstX)-imgX1, int(dstY)-imgY1, alpha); + } + else + { + m_renBaseCompPre.blend_from(pixF, &r, int(dstX)-imgX1, int(dstY)-imgY1, alpha); + } + } + + + void renderText(double dstX, double dstY, const std::string& str) + { + worldToScreen(dstX, dstY); + PixFormat pixF(m_rbuf); + //Rect r(imgX1, imgY1, imgX2, imgY2); + + typedef agg::glyph_raster_bin glyph_gen; + glyph_gen glyph(0); + + if(m_blendMode == BlendAlpha) + { + typedef agg::renderer_base ren_base; + agg::renderer_raster_htext_solid rt(m_renBasePre,glyph); + rt.color(m_lineColor); + glyph.font(m_font); + rt.render_text(dstX, dstY, str.c_str(), true); //flipy + } + else + { + typedef agg::renderer_base ren_base; + agg::renderer_raster_htext_solid rt(m_renBaseCompPre,glyph); + rt.color(m_lineColor); + glyph.font(m_font); + rt.render_text(dstX, dstY, str.c_str(), true); //flipy + } + } + + + AGG2D_IMAGE_TEMPLATE void blendImage(TIMAGE& img, double dstX, double dstY, unsigned alpha=255) + { + worldToScreen(dstX, dstY); + PixFormat pixF(img.renBuf); + m_renBasePre.blend_from(pixF, 0, int(dstX), int(dstY), alpha); + if(m_blendMode == BlendAlpha) + { + m_renBasePre.blend_from(pixF, 0, int(dstX), int(dstY), alpha); + } + else + { + m_renBaseCompPre.blend_from(pixF, 0, int(dstX), int(dstY), alpha); + } + } + + + + // Copy image directly, together with alpha-channel + AGG2D_IMAGE_TEMPLATE void copyImage(TIMAGE& img, + int imgX1, int imgY1, int imgX2, int imgY2, + double dstX, double dstY) + { + worldToScreen(dstX, dstY); + // JME + //agg::rect r(imgX1, imgY1, imgX2, imgY2); + Rect r(imgX1, imgY1, imgX2, imgY2); + m_renBase.copy_from(img.renBuf, &r, int(dstX)-imgX1, int(dstY)-imgY1); + } + + AGG2D_IMAGE_TEMPLATE void copyImage(TIMAGE& img, double dstX, double dstY) + { + worldToScreen(dstX, dstY); + m_renBase.copy_from(img.renBuf, 0, int(dstX), int(dstY)); + } + + // State + //----------------------- + + void saveStateTo(State& st); + void restoreStateFrom(const State& st); + + + + // Auxiliary + //----------------------- + static double pi() { return agg::pi; } + static double deg2Rad(double v) { return v * agg::pi / 180.0; } + static double rad2Deg(double v) { return v * 180.0 / agg::pi; } + + PixFormat & pixFormat() { return m_pixFormat; } + agg::rendering_buffer & buf() { return m_rbuf; } + +private: + void render(bool fillColor); + +#ifdef AGG2D_USE_VECTORFONTS +#if !defined( UNDER_CE ) + void render(FontRasterizer& ras, FontScanline& sl); +#endif +#endif + + void addLine(double x1, double y1, double x2, double y2); + void updateRasterizerGamma(); + AGG2D_IMAGE_TEMPLATE void renderImage(const TIMAGE& img, int x1, int y1, int x2, int y2, const double* parl) + { + agg::trans_affine mtx((double)x1, + (double)y1, + (double)x2, + (double)y2, + parl); + mtx *= m_transform; + mtx.invert(); + + m_rasterizer.reset(); + m_rasterizer.add_path(m_pathTransform); + + typedef agg::span_interpolator_linear Interpolator; + Interpolator interpolator(mtx); + + if(m_blendMode == BlendAlpha) + { + // JME audit - + Agg2DRenderer::renderImage(*this, img, m_renBasePre, interpolator); + } + else + { + Agg2DRenderer::renderImage(*this, img, m_renBaseCompPre, interpolator); + } + } + + + void updateTransformations(); + + agg::rendering_buffer m_rbuf; + PixFormat m_pixFormat; + PixFormatComp m_pixFormatComp; + PixFormatPre m_pixFormatPre; + PixFormatCompPre m_pixFormatCompPre; + RendererBase m_renBase; + RendererBaseComp m_renBaseComp; + RendererBasePre m_renBasePre; + RendererBaseCompPre m_renBaseCompPre; + RendererSolid m_renSolid; + RendererSolidComp m_renSolidComp; + + SpanAllocator m_allocator; + RectD m_clipBox; + + BlendMode m_blendMode; + BlendMode m_imageBlendMode; + Color m_imageBlendColor; + + agg::scanline_u8 m_scanline; + agg::rasterizer_scanline_aa<> m_rasterizer; + + double m_masterAlpha; + double m_antiAliasGamma; + + const agg::int8u* m_font; + + Color m_fillColor; + Color m_lineColor; + GradientArray m_fillGradient; + GradientArray m_lineGradient; + + LineCap m_lineCap; + LineJoin m_lineJoin; + + Gradient m_fillGradientFlag; + Gradient m_lineGradientFlag; + agg::trans_affine m_fillGradientMatrix; + agg::trans_affine m_lineGradientMatrix; + double m_fillGradientD1; + double m_lineGradientD1; + double m_fillGradientD2; + double m_lineGradientD2; + + double m_textAngle; + TextAlignment m_textAlignX; + TextAlignment m_textAlignY; + bool m_textHints; + double m_fontHeight; + double m_fontAscent; + double m_fontDescent; + FontCacheType m_fontCacheType; + + ImageFilter m_imageFilter; + ImageResample m_imageResample; + agg::image_filter_lut m_imageFilterLut; + + agg::span_interpolator_linear<> m_fillGradientInterpolator; + agg::span_interpolator_linear<> m_lineGradientInterpolator; + + agg::gradient_x m_linearGradientFunction; + agg::gradient_circle m_radialGradientFunction; + + double m_lineWidth; + bool m_evenOddFlag; + + double m_start_x; + double m_start_y; + + agg::path_storage m_path; + agg::trans_affine m_transform; + + agg::trans_affine m_viewport; + agg::trans_affine m_affine; + + ConvCurve m_convCurve; + ConvStroke m_convStroke; + + PathTransform m_pathTransform; + StrokeTransform m_strokeTransform; + +#ifdef AGG2D_USE_VECTORFONTS +#ifndef AGG2D_USE_FREETYPE + HDC m_fontDC; +#endif + FontEngine m_fontEngine; + FontCacheManager m_fontCacheManager; +#endif +}; + + + +#include "agg2d.inl" + +#endif diff --git a/jni/desmume/src/agg2d.inl b/jni/desmume/src/agg2d.inl new file mode 100755 index 0000000..756d193 --- /dev/null +++ b/jni/desmume/src/agg2d.inl @@ -0,0 +1,1979 @@ +//---------------------------------------------------------------------------- +// Agg2D - Version 1.0 +// Based on Anti-Grain Geometry +// Copyright (C) 2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// +// 25 Jan 2007 - Ported to AGG 2.4 Jerry Evans (jerry@novadsp.com) +// 11 Jul 2009 - significant refactors for introduction to desmume +// +//---------------------------------------------------------------------------- +#include "agg2d.h" + +static const double g_approxScale = 2.0; + +#define TAGG2D Agg2D AGG2D_TEMPLATE_ARG +#define TAGG2DRENDERER Agg2DRenderer + +//AGG2D_TEMPLATE inline bool operator == (const TAGG2D::Color& c1, const TAGG2D::Color& c2) +//{ +// return c1.r == c2.r && c1.g == c2.g && c1.b == c2.b && c1.a == c2.a; +//} +// +//AGG2D_TEMPLATE inline bool operator != (const Agg2D::Color& c1, const Agg2D::Color& c2) +//{ +// return !(c1 == c2); +//} + +AGG2D_TEMPLATE inline TAGG2D::~Agg2D() +{ +#ifdef AGG2D_USE_VECTORFONTS +#ifndef AGG2D_USE_FREETYPE + ::ReleaseDC(0, m_fontDC); +#endif +#endif +} + +AGG2D_TEMPLATE inline TAGG2D::Agg2D() : + m_rbuf(), + m_pixFormat(m_rbuf), + m_pixFormatComp(m_rbuf), + m_pixFormatPre(m_rbuf), + m_pixFormatCompPre(m_rbuf), + m_renBase(m_pixFormat), + m_renBaseComp(m_pixFormatComp), + m_renBasePre(m_pixFormatPre), + m_renBaseCompPre(m_pixFormatCompPre), + m_renSolid(m_renBase), + m_renSolidComp(m_renBaseComp), + + m_allocator(), + m_clipBox(0,0,0,0), + + m_blendMode(BlendAlpha), + m_imageBlendMode(BlendDst), + m_imageBlendColor(0,0,0), + + m_scanline(), + m_rasterizer(), + + m_masterAlpha(1.0), + m_antiAliasGamma(1.0), + + m_font(agg::gse4x6), + m_fillColor(255, 255, 255), + m_lineColor(0, 0, 0), + m_fillGradient(), + m_lineGradient(), + + m_lineCap(CAP_ROUND), + m_lineJoin(JOIN_ROUND), + + m_fillGradientFlag(Solid), + m_lineGradientFlag(Solid), + m_fillGradientMatrix(), + m_lineGradientMatrix(), + m_fillGradientD1(0.0), + m_lineGradientD1(0.0), + m_fillGradientD2(100.0), + m_lineGradientD2(100.0), + + m_textAngle(0.0), + m_textAlignX(AlignLeft), + m_textAlignY(AlignBottom), + m_textHints(true), + m_fontHeight(0.0), + m_fontAscent(0.0), + m_fontDescent(0.0), + m_fontCacheType(RasterFontCache), + + //m_imageFilter(Bilinear), //less quality more speed + m_imageFilter(NoFilter), + m_imageResample(NoResample), + m_imageFilterLut(agg::image_filter_bilinear(), true), + + m_fillGradientInterpolator(m_fillGradientMatrix), + m_lineGradientInterpolator(m_lineGradientMatrix), + + m_linearGradientFunction(), + m_radialGradientFunction(), + + m_lineWidth(1), + m_evenOddFlag(false), + + m_start_x(0.0), + m_start_y(0.0), + + m_path(), + m_transform(), + + m_convCurve(m_path), + m_convStroke(m_convCurve), + + m_pathTransform(m_convCurve, m_transform), + m_strokeTransform(m_convStroke, m_transform) + +#ifdef AGG2D_USE_VECTORFONTS +#ifdef AGG2D_USE_FREETYPE + , m_fontEngine(), +#else + m_fontDC(::GetDC(0)), + m_fontEngine(m_fontDC), +#endif + m_fontCacheManager(m_fontEngine) +#endif +{ + lineCap(m_lineCap); + lineJoin(m_lineJoin); +} + +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::saveStateTo(State& st) +{ + + st.m_clipBox = m_clipBox; + + st.m_blendMode = m_blendMode; + st.m_imageBlendMode = m_imageBlendMode; + st.m_imageBlendColor = m_imageBlendColor; + + st.m_masterAlpha = m_masterAlpha; + st.m_antiAliasGamma = m_antiAliasGamma; + + st.m_font = m_font; + st.m_fillColor = m_fillColor; + st.m_lineColor = m_lineColor; + st.m_fillGradient = m_fillGradient; + st.m_lineGradient = m_lineGradient; + + st.m_lineCap = m_lineCap; + st.m_lineJoin = m_lineJoin; + + st.m_fillGradientFlag = m_fillGradientFlag; + st.m_lineGradientFlag = m_lineGradientFlag; + st.m_fillGradientMatrix = m_fillGradientMatrix; + st.m_lineGradientMatrix = m_lineGradientMatrix; + st.m_fillGradientD1 = m_fillGradientD1; + st.m_lineGradientD1 = m_lineGradientD1; + st.m_fillGradientD2 = m_fillGradientD2; + st.m_lineGradientD2 = m_lineGradientD2; + + st.m_textAngle = m_textAngle; + st.m_textAlignX = m_textAlignX; + st.m_textAlignY = m_textAlignY; + st.m_textHints = m_textHints; + st.m_fontHeight = m_fontHeight; + st.m_fontAscent = m_fontAscent; + st.m_fontDescent = m_fontDescent; + st.m_fontCacheType = m_fontCacheType; + + st.m_lineWidth = m_lineWidth; + st.m_evenOddFlag = m_evenOddFlag; + + st.m_transform = m_transform; + st.m_affine = m_affine; + +} + +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::restoreStateFrom(const State& st) +{ + + m_clipBox = st.m_clipBox; + + m_blendMode = st.m_blendMode; + m_imageBlendMode = st.m_imageBlendMode; + m_imageBlendColor = st.m_imageBlendColor; + + m_masterAlpha = st.m_masterAlpha; + m_antiAliasGamma = st.m_antiAliasGamma; + + m_font = st.m_font; + m_fillColor = st.m_fillColor; + m_lineColor = st.m_lineColor; + m_fillGradient = st.m_fillGradient; + m_lineGradient = st.m_lineGradient; + + m_lineCap = st.m_lineCap; + m_lineJoin = st.m_lineJoin; + + m_fillGradientFlag = st.m_fillGradientFlag; + m_lineGradientFlag = st.m_lineGradientFlag; + m_fillGradientMatrix = st.m_fillGradientMatrix; + m_lineGradientMatrix = st.m_lineGradientMatrix; + m_fillGradientD1 = st.m_fillGradientD1; + m_lineGradientD1 = st.m_lineGradientD1; + m_fillGradientD2 = st.m_fillGradientD2; + m_lineGradientD2 = st.m_lineGradientD2; + + m_textAngle = st.m_textAngle; + m_textAlignX = st.m_textAlignX; + m_textAlignY = st.m_textAlignY; + m_textHints = st.m_textHints; + m_fontHeight = st.m_fontHeight; + m_fontAscent = st.m_fontAscent; + m_fontDescent = st.m_fontDescent; + m_fontCacheType = st.m_fontCacheType; + + m_lineWidth = st.m_lineWidth; + m_evenOddFlag = st.m_evenOddFlag; + + m_affine = st.m_affine; + m_transform = st.m_transform; + +} + + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::attach(unsigned char* buf, unsigned width, unsigned height, int stride) +{ + m_rbuf.attach(buf, width, height, stride); + + m_renBase.reset_clipping(true); + m_renBaseComp.reset_clipping(true); + m_renBasePre.reset_clipping(true); + m_renBaseCompPre.reset_clipping(true); + + //why is all this reset here???? seems silly. + + resetTransformations(); + lineWidth(1.0), + lineColor(0,0,0); + fillColor(255,255,255); + clipBox(0, 0, width, height); + lineCap(CAP_ROUND); + lineJoin(JOIN_ROUND); + #ifdef AGG2D_USE_VECTORFONTS + textAlignment(AlignLeft, AlignBottom); + flipText(false); + #endif + //imageFilter(Bilinear); //less quality more speed + imageFilter(NoFilter); + imageResample(NoResample); + m_masterAlpha = 1.0; + m_antiAliasGamma = 1.0; + m_rasterizer.gamma(agg::gamma_none()); + m_blendMode = BlendAlpha; +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::attach(MyImage& img) +{ + attach(img.renBuf.buf(), img.renBuf.width(), img.renBuf.height(), img.renBuf.stride()); +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::clipBox(double x1, double y1, double x2, double y2) +{ + m_viewport.transform(&x1, &y1); // + m_viewport.transform(&x2, &y2); // see: http://article.gmane.org/gmane.comp.graphics.agg/3543 + + m_clipBox = RectD(x1, y1, x2, y2); + + int rx1 = int(x1); + int ry1 = int(y1); + int rx2 = int(x2); + int ry2 = int(y2); + + m_renBase.clip_box(rx1, ry1, rx2, ry2); + m_renBaseComp.clip_box(rx1, ry1, rx2, ry2); + m_renBasePre.clip_box(rx1, ry1, rx2, ry2); + m_renBaseCompPre.clip_box(rx1, ry1, rx2, ry2); + + // m_rasterizer.clip_box(x1, y1, x2, y2); + m_rasterizer.clip_box(m_renBase.xmin(), m_renBase.ymin(), + m_renBase.xmax()+1, m_renBase.ymax()+1); // see link above + +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::blendMode(BlendMode m) +{ + m_blendMode = m; + m_pixFormatComp.comp_op(m); + m_pixFormatCompPre.comp_op(m); +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE typename Agg2D AGG2D_TEMPLATE_ARG ::BlendMode Agg2D AGG2D_TEMPLATE_ARG ::blendMode() const +{ + return m_blendMode; +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::imageBlendMode(BlendMode m) +{ + m_imageBlendMode = m; +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE typename Agg2D AGG2D_TEMPLATE_ARG ::BlendMode Agg2D AGG2D_TEMPLATE_ARG ::imageBlendMode() const +{ + return m_imageBlendMode; +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::imageBlendColor(Color c) +{ + m_imageBlendColor = c; +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::imageBlendColor(unsigned r, unsigned g, unsigned b, unsigned a) +{ + imageBlendColor(Color(r, g, b, a)); +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE typename Agg2D AGG2D_TEMPLATE_ARG ::Color Agg2D AGG2D_TEMPLATE_ARG ::imageBlendColor() const +{ + return m_imageBlendColor; +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::masterAlpha(double a) +{ + m_masterAlpha = a; + updateRasterizerGamma(); +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE double Agg2D AGG2D_TEMPLATE_ARG ::masterAlpha() const +{ + return m_masterAlpha; +} + +//------------------------------------------------------------------------+ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::antiAliasGamma(double g) +{ + m_antiAliasGamma = g; + updateRasterizerGamma(); +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE double Agg2D AGG2D_TEMPLATE_ARG ::antiAliasGamma() const +{ + return m_antiAliasGamma; +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE Agg2DBase::RectD Agg2D AGG2D_TEMPLATE_ARG ::clipBox() const +{ + return m_clipBox; +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::clearAll(Color c) +{ + m_renBase.clear(c); +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::clearAll(unsigned r, unsigned g, unsigned b, unsigned a) +{ + clearAll(Color(r, g, b, a)); +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::clearClipBox(Color c) +{ + m_renBase.copy_bar(0, 0, m_renBase.width(), m_renBase.height(), c); +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::clearClipBox(unsigned r, unsigned g, unsigned b, unsigned a) +{ + clearClipBox(Color(r, g, b, a)); +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::worldToScreen(double& x, double& y) const +{ + m_transform.transform(&x, &y); +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::screenToWorld(double& x, double& y) const +{ + m_transform.inverse_transform(&x, &y); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE double Agg2D AGG2D_TEMPLATE_ARG ::worldToScreen(double scalar) const +{ + double x1 = 0; + double y1 = 0; + double x2 = scalar; + double y2 = scalar; + worldToScreen(x1, y1); + worldToScreen(x2, y2); + return sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) * 0.7071068; +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE double Agg2D AGG2D_TEMPLATE_ARG ::screenToWorld(double scalar) const +{ + double x1 = 0; + double y1 = 0; + double x2 = scalar; + double y2 = scalar; + screenToWorld(x1, y1); + screenToWorld(x2, y2); + return sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) * 0.7071068; +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::alignPoint(double& x, double& y) const +{ + worldToScreen(x, y); + x = floor(x) + 0.5; + y = floor(y) + 0.5; + screenToWorld(x, y); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE bool Agg2D AGG2D_TEMPLATE_ARG ::inBox(double worldX, double worldY) const +{ + worldToScreen(worldX, worldY); + return m_renBase.inbox(int(worldX), int(worldY)); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE Agg2DBase::Transformations Agg2D AGG2D_TEMPLATE_ARG ::transformations() const +{ + Transformations tr; + m_transform.store_to(tr.affineMatrix); + return tr; +} +//------------------------------------------------------------------------ +AGG2D_TEMPLATE const Agg2DBase::Affine& Agg2D AGG2D_TEMPLATE_ARG ::affine() const +{ + return m_affine; +} +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::affine(const Affine& af) +{ + m_affine = af; + updateTransformations(); +} +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::transformations(const Transformations& tr) +{ + m_transform.load_from(tr.affineMatrix); + m_convCurve.approximation_scale(worldToScreen(1.0) * g_approxScale); + m_convStroke.approximation_scale(worldToScreen(1.0) * g_approxScale); +} +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::resetTransformations() +{ + m_transform.reset(); +} +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::updateTransformations() +{ + m_transform = m_affine; + m_transform *= m_viewport; + m_convCurve.approximation_scale(worldToScreen(1.0) * g_approxScale); + m_convStroke.approximation_scale(worldToScreen(1.0) * g_approxScale); +} +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::rotate(double angle) +{ + m_affine.premultiply(agg::trans_affine_rotation(angle)); + updateTransformations(); +} +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::rotate(double angle, double cx, double cy) +{ + agg::trans_affine_translation m(-cx, -cy); + m *= agg::trans_affine_rotation(angle); + m *= agg::trans_affine_translation(cx, cy); + m_affine.premultiply(m); + updateTransformations(); +} +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::skew(double sx, double sy) +{ + m_affine.premultiply(agg::trans_affine_skewing(sx, sy)); + updateTransformations(); +} +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::translate(double x, double y) +{ + m_affine.premultiply(agg::trans_affine_translation(x, y)); + updateTransformations(); +} +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::matrix(const Affine& tr) +{ + m_affine.premultiply(tr); + updateTransformations(); +} +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::matrix(const Transformations& tr) +{ + matrix(agg::trans_affine(tr.affineMatrix[0], tr.affineMatrix[1], tr.affineMatrix[2], + tr.affineMatrix[3], tr.affineMatrix[4], tr.affineMatrix[5])); +} +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::scale(double s) +{ + m_affine.premultiply(agg::trans_affine_scaling(s)); + updateTransformations(); +} +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::scale(double sx, double sy) +{ + m_affine.premultiply(agg::trans_affine_scaling(sx, sy)); + updateTransformations(); +} +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::parallelogram(double x1, double y1, double x2, double y2, const double* para) +{ + m_affine.premultiply(agg::trans_affine(x1, y1, x2, y2, para)); + updateTransformations(); +} +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::viewport(double worldX1, double worldY1, double worldX2, double worldY2, + double screenX1, double screenY1, double screenX2, double screenY2, + ViewportOption opt, WindowFitLogic fl) +{ + agg::trans_viewport vp; + + agg::aspect_ratio_e ar = + (fl == WindowFitLogic_meet) ? agg::aspect_ratio_meet : + agg::aspect_ratio_slice; + switch(opt) + { + case Anisotropic: vp.preserve_aspect_ratio(0.0, 0.0, agg::aspect_ratio_stretch); break; + case XMinYMin: vp.preserve_aspect_ratio(0.0, 0.0, ar); break; + case XMidYMin: vp.preserve_aspect_ratio(0.5, 0.0, ar); break; + case XMaxYMin: vp.preserve_aspect_ratio(1.0, 0.0, ar); break; + case XMinYMid: vp.preserve_aspect_ratio(0.0, 0.5, ar); break; + case XMidYMid: vp.preserve_aspect_ratio(0.5, 0.5, ar); break; + case XMaxYMid: vp.preserve_aspect_ratio(1.0, 0.5, ar); break; + case XMinYMax: vp.preserve_aspect_ratio(0.0, 1.0, ar); break; + case XMidYMax: vp.preserve_aspect_ratio(0.5, 1.0, ar); break; + case XMaxYMax: vp.preserve_aspect_ratio(1.0, 1.0, ar); break; + } + vp.world_viewport(worldX1, worldY1, worldX2, worldY2); + vp.device_viewport(screenX1, screenY1, screenX2, screenY2); + + m_viewport = vp.to_affine(); + updateTransformations(); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::fillColor(Color c) +{ + m_fillColor = c; + m_fillGradientFlag = Solid; +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::fillColor(unsigned r, unsigned g, unsigned b, unsigned a) +{ + fillColor(Color(r, g, b, a)); +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::noFill() +{ + fillColor(Color(0, 0, 0, 0)); +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::lineColor(Color c) +{ + m_lineColor = c; + m_lineGradientFlag = Solid; +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::lineColor(unsigned r, unsigned g, unsigned b, unsigned a) +{ + lineColor(Color(r, g, b, a)); +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void Agg2D AGG2D_TEMPLATE_ARG ::noLine() +{ + lineColor(Color(0, 0, 0, 0)); +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE typename TAGG2D::Color TAGG2D::fillColor() const +{ + return m_fillColor; +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE typename TAGG2D::Color TAGG2D::lineColor() const +{ + return m_lineColor; +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::fillLinearGradient(double x1, double y1, double x2, double y2, Color c1, Color c2, double profile) +{ + int i; + int startGradient = 128 - int(profile * 127.0); + int endGradient = 128 + int(profile * 127.0); + if (endGradient <= startGradient) endGradient = startGradient + 1; + double k = 1.0 / double(endGradient - startGradient); + for (i = 0; i < startGradient; i++) + { + m_fillGradient[i] = c1; + } + for (; i < endGradient; i++) + { + m_fillGradient[i] = c1.gradient(c2, double(i - startGradient) * k); + } + for (; i < 256; i++) + { + m_fillGradient[i] = c2; + } + double angle = atan2(y2-y1, x2-x1); + m_fillGradientMatrix.reset(); + m_fillGradientMatrix *= agg::trans_affine_rotation(angle); + m_fillGradientMatrix *= agg::trans_affine_translation(x1, y1); + m_fillGradientMatrix *= m_transform; + m_fillGradientMatrix.invert(); + m_fillGradientD1 = 0.0; + m_fillGradientD2 = sqrt((x2-x1) * (x2-x1) + (y2-y1) * (y2-y1)); + m_fillGradientFlag = Linear; + m_fillColor = Color(0,0,0); // Set some real color +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::lineLinearGradient(double x1, double y1, double x2, double y2, Color c1, Color c2, double profile) +{ + int i; + int startGradient = 128 - int(profile * 128.0); + int endGradient = 128 + int(profile * 128.0); + if (endGradient <= startGradient) endGradient = startGradient + 1; + double k = 1.0 / double(endGradient - startGradient); + for (i = 0; i < startGradient; i++) + { + m_lineGradient[i] = c1; + } + for (; i < endGradient; i++) + { + m_lineGradient[i] = c1.gradient(c2, double(i - startGradient) * k); + } + for (; i < 256; i++) + { + m_lineGradient[i] = c2; + } + double angle = atan2(y2-y1, x2-x1); + m_lineGradientMatrix.reset(); + m_lineGradientMatrix *= agg::trans_affine_rotation(angle); + m_lineGradientMatrix *= agg::trans_affine_translation(x1, y1); + m_fillGradientMatrix *= m_transform; + m_lineGradientMatrix.invert(); + m_lineGradientD1 = 0; + m_lineGradientD2 = sqrt((x2-x1) * (x2-x1) + (y2-y1) * (y2-y1)); + m_lineGradientFlag = Linear; + m_lineColor = Color(0,0,0); // Set some real color +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::fillRadialGradient(double x, double y, double r, Color c1, Color c2, double profile) +{ + int i; + int startGradient = 128 - int(profile * 127.0); + int endGradient = 128 + int(profile * 127.0); + if (endGradient <= startGradient) endGradient = startGradient + 1; + double k = 1.0 / double(endGradient - startGradient); + for (i = 0; i < startGradient; i++) + { + m_fillGradient[i] = c1; + } + for (; i < endGradient; i++) + { + m_fillGradient[i] = c1.gradient(c2, double(i - startGradient) * k); + } + for (; i < 256; i++) + { + m_fillGradient[i] = c2; + } + m_fillGradientD2 = worldToScreen(r); + worldToScreen(x, y); + m_fillGradientMatrix.reset(); + m_fillGradientMatrix *= agg::trans_affine_translation(x, y); + m_fillGradientMatrix.invert(); + m_fillGradientD1 = 0; + m_fillGradientFlag = Radial; + m_fillColor = Color(0,0,0); // Set some real color +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::lineRadialGradient(double x, double y, double r, Color c1, Color c2, double profile) +{ + int i; + int startGradient = 128 - int(profile * 128.0); + int endGradient = 128 + int(profile * 128.0); + if (endGradient <= startGradient) endGradient = startGradient + 1; + double k = 1.0 / double(endGradient - startGradient); + for (i = 0; i < startGradient; i++) + { + m_lineGradient[i] = c1; + } + for (; i < endGradient; i++) + { + m_lineGradient[i] = c1.gradient(c2, double(i - startGradient) * k); + } + for (; i < 256; i++) + { + m_lineGradient[i] = c2; + } + m_lineGradientD2 = worldToScreen(r); + worldToScreen(x, y); + m_lineGradientMatrix.reset(); + m_lineGradientMatrix *= agg::trans_affine_translation(x, y); + m_lineGradientMatrix.invert(); + m_lineGradientD1 = 0; + m_lineGradientFlag = Radial; + m_lineColor = Color(0,0,0); // Set some real color +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::fillRadialGradient(double x, double y, double r, Color c1, Color c2, Color c3) +{ + int i; + for (i = 0; i < 128; i++) + { + m_fillGradient[i] = c1.gradient(c2, double(i) / 127.0); + } + for (; i < 256; i++) + { + m_fillGradient[i] = c2.gradient(c3, double(i - 128) / 127.0); + } + m_fillGradientD2 = worldToScreen(r); + worldToScreen(x, y); + m_fillGradientMatrix.reset(); + m_fillGradientMatrix *= agg::trans_affine_translation(x, y); + m_fillGradientMatrix.invert(); + m_fillGradientD1 = 0; + m_fillGradientFlag = Radial; + m_fillColor = Color(0,0,0); // Set some real color +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::lineRadialGradient(double x, double y, double r, Color c1, Color c2, Color c3) +{ + int i; + for (i = 0; i < 128; i++) + { + m_lineGradient[i] = c1.gradient(c2, double(i) / 127.0); + } + for (; i < 256; i++) + { + m_lineGradient[i] = c2.gradient(c3, double(i - 128) / 127.0); + } + m_lineGradientD2 = worldToScreen(r); + worldToScreen(x, y); + m_lineGradientMatrix.reset(); + m_lineGradientMatrix *= agg::trans_affine_translation(x, y); + m_lineGradientMatrix.invert(); + m_lineGradientD1 = 0; + m_lineGradientFlag = Radial; + m_lineColor = Color(0,0,0); // Set some real color +} + + +AGG2D_TEMPLATE void TAGG2D::fillRadialGradient(double x, double y, double r) +{ + m_fillGradientD2 = worldToScreen(r); + worldToScreen(x, y); + m_fillGradientMatrix.reset(); + m_fillGradientMatrix *= agg::trans_affine_translation(x, y); + m_fillGradientMatrix.invert(); + m_fillGradientD1 = 0; +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::lineRadialGradient(double x, double y, double r) +{ + m_lineGradientD2 = worldToScreen(r); + worldToScreen(x, y); + m_lineGradientMatrix.reset(); + m_lineGradientMatrix *= agg::trans_affine_translation(x, y); + m_lineGradientMatrix.invert(); + m_lineGradientD1 = 0; +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::lineWidth(double w) +{ + m_lineWidth = w; + m_convStroke.width(w); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE double TAGG2D::lineWidth() const +{ + return m_lineWidth; +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::fillEvenOdd(bool evenOddFlag) +{ + m_evenOddFlag = evenOddFlag; + m_rasterizer.filling_rule(evenOddFlag ? agg::fill_even_odd : agg::fill_non_zero); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE bool TAGG2D::fillEvenOdd() const +{ + return m_evenOddFlag; +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::lineCap(LineCap cap) +{ + m_lineCap = cap; + m_convStroke.line_cap((agg::line_cap_e)cap); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE Agg2DBase::LineCap TAGG2D::lineCap() const +{ + return m_lineCap; +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::lineJoin(LineJoin join) +{ + m_lineJoin = join; + m_convStroke.line_join((agg::line_join_e)join); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE Agg2DBase::LineJoin TAGG2D::lineJoin() const +{ + return m_lineJoin; +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::addLine(double x1, double y1, double x2, double y2) +{ + m_path.move_to(x1, y1); + m_path.line_to(x2, y2); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::line(double x1, double y1, double x2, double y2) +{ + m_path.remove_all(); + addLine(x1, y1, x2, y2); + drawPath(StrokeOnly); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::triangle(double x1, double y1, double x2, double y2, double x3, double y3) +{ + m_path.remove_all(); + m_path.move_to(x1, y1); + m_path.line_to(x2, y2); + m_path.line_to(x3, y3); + m_path.close_polygon(); + drawPath(FillAndStroke); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::rectangle(double x1, double y1, double x2, double y2) +{ + m_path.remove_all(); + m_path.move_to(x1, y1); + m_path.line_to(x2, y1); + m_path.line_to(x2, y2); + m_path.line_to(x1, y2); + m_path.close_polygon(); + drawPath(FillAndStroke); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::roundedRect(double x1, double y1, double x2, double y2, double r) +{ + m_path.remove_all(); + agg::rounded_rect rc(x1, y1, x2, y2, r); + rc.normalize_radius(); + rc.approximation_scale(worldToScreen(1.0) * g_approxScale); + // JME audit + //m_path.add_path(rc, 0, false); + m_path.concat_path(rc,0); + drawPath(FillAndStroke); +} + + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::roundedRect(double x1, double y1, double x2, double y2, double rx, double ry) +{ + m_path.remove_all(); + agg::rounded_rect rc; + rc.rect(x1, y1, x2, y2); + rc.radius(rx, ry); + rc.normalize_radius(); + //m_path.add_path(rc, 0, false); + m_path.concat_path(rc,0); // JME + drawPath(FillAndStroke); +} + + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::roundedRect(double x1, double y1, double x2, double y2, + double rx_bottom, double ry_bottom, + double rx_top, double ry_top) +{ + m_path.remove_all(); + agg::rounded_rect rc; + rc.rect(x1, y1, x2, y2); + rc.radius(rx_bottom, ry_bottom, rx_top, ry_top); + rc.normalize_radius(); + rc.approximation_scale(worldToScreen(1.0) * g_approxScale); + //m_path.add_path(rc, 0, false); + m_path.concat_path(rc,0); // JME + drawPath(FillAndStroke); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::ellipse(double cx, double cy, double rx, double ry) +{ + m_path.remove_all(); + agg::bezier_arc arc(cx, cy, rx, ry, 0, 2*pi()); + //m_path.add_path(arc, 0, false); + m_path.concat_path(arc,0); // JME + m_path.close_polygon(); + drawPath(FillAndStroke); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::arc(double cx, double cy, double rx, double ry, double start, double sweep) +{ + m_path.remove_all(); + agg::bezier_arc arc(cx, cy, rx, ry, start, sweep); + //m_path.add_path(arc, 0, false); + m_path.concat_path(arc,0); // JME + drawPath(StrokeOnly); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::star(double cx, double cy, double r1, double r2, double startAngle, int numRays) +{ + m_path.remove_all(); + double da = agg::pi / double(numRays); + double a = startAngle; + int i; + for (i = 0; i < numRays; i++) + { + double x = cos(a) * r2 + cx; + double y = sin(a) * r2 + cy; + if (i) m_path.line_to(x, y); + else m_path.move_to(x, y); + a += da; + m_path.line_to(cos(a) * r1 + cx, sin(a) * r1 + cy); + a += da; + } + closePolygon(); + drawPath(FillAndStroke); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::curve(double x1, double y1, double x2, double y2, double x3, double y3) +{ + m_path.remove_all(); + m_path.move_to(x1, y1); + m_path.curve3(x2, y2, x3, y3); + drawPath(StrokeOnly); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::curve(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) +{ + m_path.remove_all(); + m_path.move_to(x1, y1); + m_path.curve4(x2, y2, x3, y3, x4, y4); + drawPath(StrokeOnly); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::polygon(double* xy, int numPoints) +{ + m_path.remove_all(); + //m_path.add_poly(xy, numPoints); + m_path.concat_poly(xy,numPoints,true); // JME, AF + closePolygon(); + drawPath(FillAndStroke); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::polyline(double* xy, int numPoints) +{ + m_path.remove_all(); + //m_path.add_poly(xy, numPoints); + m_path.concat_poly(xy,numPoints,true); // JME, AF + drawPath(StrokeOnly); +} + + +//------------------------------------------------------------------------ + +#ifdef AGG2D_USE_VECTORFONTS +AGG2D_TEMPLATE void TAGG2D::flipText(bool flip) +{ + m_fontEngine.flip_y(flip); +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::font(const char* fontName, + double height, + bool bold, + bool italic, + FontCacheType ch, + double angle) +{ + m_textAngle = angle; + m_fontHeight = height; + m_fontCacheType = ch; + + +#ifdef AGG2D_USE_FREETYPE + m_fontEngine.load_font(fontName, + 0, + (ch == VectorFontCache) ? + agg::glyph_ren_outline : + agg::glyph_ren_agg_gray8); + m_fontEngine.hinting(m_textHints); + m_fontEngine.height((ch == VectorFontCache) ? height : worldToScreen(height)); +#else + m_fontEngine.hinting(m_textHints); + + m_fontEngine.create_font(fontName, + (ch == VectorFontCache) ? + agg::glyph_ren_outline : + agg::glyph_ren_agg_gray8, + (ch == VectorFontCache) ? height : worldToScreen(height), + 0.0, + bold ? 700 : 400, + italic); +#endif + +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE double TAGG2D::fontHeight() const +{ + return m_fontHeight; +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE double TAGG2D::fontAscent() const +{ + return m_fontAscent; +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::textAlignment(TextAlignment alignX, TextAlignment alignY) +{ + m_textAlignX = alignX; + m_textAlignY = alignY; +} + +//------------------------------------------------------------------------ + +AGG2D_TEMPLATE double TAGG2D::textWidth(const char* str, unsigned int len) +{ +#if defined( UNDER_CE ) + return 0; +#else + double x = 0; + double y = 0; + bool first = true; + while(*str && len) + { + const agg::glyph_cache* glyph = m_fontCacheManager.glyph(*str); + if(glyph) + { + if(!first) m_fontCacheManager.add_kerning(&x, &y); + x += glyph->advance_x; + y += glyph->advance_y; + first = true; + } + ++str; --len; + } + return (m_fontCacheType == VectorFontCache) ? x : screenToWorld(x); +#endif +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE double TAGG2D::textWidth(const wchar_t* str, unsigned int len) +{ +#if defined( UNDER_CE ) + return 0; +#else + double x = 0; + double y = 0; + bool first = true; + while(*str && len) + { + const agg::glyph_cache* glyph = m_fontCacheManager.glyph(*str); + if(glyph) + { + if(!first) m_fontCacheManager.add_kerning(&x, &y); + x += glyph->advance_x; + y += glyph->advance_y; + first = true; + } + ++str; --len; + } + return (m_fontCacheType == VectorFontCache) ? x : screenToWorld(x); +#endif +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE bool TAGG2D::textHints() const +{ + return m_textHints; +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::textHints(bool hints) +{ + m_textHints = hints; +} + + + +//------------------------------------------------------------------------ + +AGG2D_TEMPLATE void TAGG2D::text(double x, double y, const char* str, unsigned int len, bool roundOff, double ddx, double ddy) +{ + + double dx = 0.0; + double dy = 0.0; + + switch(m_textAlignX) + { + case AlignCenter: dx = -textWidth(str,len) * 0.5; break; + case AlignRight: dx = -textWidth(str,len); break; + default: break; + } + + + double asc = fontHeight(); + const agg::glyph_cache* glyph = m_fontCacheManager.glyph('H'); + if(glyph) + { + asc = glyph->bounds.y2 - glyph->bounds.y1; + } + + if(m_fontCacheType == RasterFontCache) + { + asc = screenToWorld(asc); + } + + switch(m_textAlignY) + { + case AlignCenter: dy = -asc * 0.5; break; + case AlignTop: dy = -asc; break; + case AlignBaseline: dy = -fontAscent(); break; + default: break; + } + + if(m_fontEngine.flip_y()) dy = -dy; + + agg::trans_affine mtx; + + double start_x = x + dx; + double start_y = y + dy; + + if (roundOff) + { + start_x = int(start_x); + start_y = int(start_y); + } + start_x += ddx; + start_y += ddy; + + mtx *= agg::trans_affine_translation(-x, -y); + mtx *= agg::trans_affine_rotation(m_textAngle); + mtx *= agg::trans_affine_translation(x, y); + + agg::conv_transform tr(m_fontCacheManager.path_adaptor(), mtx); + + if(m_fontCacheType == RasterFontCache) + { + worldToScreen(start_x, start_y); + } + + unsigned int i; + for (i = 0; i < len && str[i]; i++) + { + glyph = m_fontCacheManager.glyph(str[i]); + if(glyph) + { + if(i) m_fontCacheManager.add_kerning(&x, &y); + m_fontCacheManager.init_embedded_adaptors(glyph, start_x, start_y); + + if(glyph->data_type == agg::glyph_data_outline) + { + m_path.remove_all(); + m_path.concat_path(tr, 0); + drawPath(); + } + + if(glyph->data_type == agg::glyph_data_gray8) + { + render(m_fontCacheManager.gray8_adaptor(), + m_fontCacheManager.gray8_scanline()); + } + start_x += glyph->advance_x; + start_y += glyph->advance_y; + } + } + +} + +AGG2D_TEMPLATE void TAGG2D::text(double x, double y, const wchar_t* str, unsigned int len, bool roundOff, double ddx, double ddy) +{ + + double dx = 0.0; + double dy = 0.0; + + switch(m_textAlignX) + { + case AlignCenter: dx = -textWidth(str,len) * 0.5; break; + case AlignRight: dx = -textWidth(str,len); break; + default: break; + } + + double asc = fontHeight(); + const agg::glyph_cache* glyph = m_fontCacheManager.glyph('H'); + if(glyph) + { + asc = glyph->bounds.y2 - glyph->bounds.y1; + } + + if(m_fontCacheType == RasterFontCache) + { + asc = screenToWorld(asc); + } + + switch(m_textAlignY) + { + case AlignCenter: dy = -asc * 0.5; break; + case AlignTop: dy = -asc; break; + case AlignBaseline: dy = -fontAscent(); break; + default: break; + } + + if(m_fontEngine.flip_y()) dy = -dy; + + agg::trans_affine mtx; + + double start_x = x + dx; + double start_y = y + dy; + + if (roundOff) + { + start_x = int(start_x); + start_y = int(start_y); + } + start_x += ddx; + start_y += ddy; + + mtx *= agg::trans_affine_translation(-x, -y); + mtx *= agg::trans_affine_rotation(m_textAngle); + mtx *= agg::trans_affine_translation(x, y); + + agg::conv_transform tr(m_fontCacheManager.path_adaptor(), mtx); + + if(m_fontCacheType == RasterFontCache) + { + worldToScreen(start_x, start_y); + } + + unsigned int i; + for (i = 0; i < len && str[i]; i++) + { + glyph = m_fontCacheManager.glyph(str[i]); + if(glyph) + { + if(i) m_fontCacheManager.add_kerning(&x, &y); + m_fontCacheManager.init_embedded_adaptors(glyph, start_x, start_y); + + if(glyph->data_type == agg::glyph_data_outline) + { + m_path.remove_all(); + //m_path.add_path(tr, 0, false); + m_path.concat_path(tr,0); // JME + drawPath(); + } + + if(glyph->data_type == agg::glyph_data_gray8) + { + render(m_fontCacheManager.gray8_adaptor(), + m_fontCacheManager.gray8_scanline()); + } + start_x += glyph->advance_x; + start_y += glyph->advance_y; + } + } + +} +#endif + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::resetPath() { m_path.remove_all(); } + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::moveTo(double x, double y) +{ + m_start_x = x; + m_start_y = y; + + m_path.move_to(x, y); +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::moveRel(double dx, double dy) +{ + if(m_path.vertices().total_vertices()) + { + double x2; + double y2; + m_path.vertices().last_vertex(&x2, &y2); + + dx += x2; + dy += y2; + } + + moveTo(dx, dy); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::lineTo(double x, double y) +{ + m_path.line_to(x, y); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::lineRel(double dx, double dy) +{ + m_path.line_rel(dx, dy); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::horLineTo(double x) +{ + m_path.hline_to(x); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::horLineRel(double dx) +{ + m_path.hline_rel(dx); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::verLineTo(double y) +{ + m_path.vline_to(y); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::verLineRel(double dy) +{ + m_path.vline_rel(dy); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::arcTo(double rx, double ry, + double angle, + bool largeArcFlag, + bool sweepFlag, + double x, double y) +{ + m_path.arc_to(rx, ry, angle, largeArcFlag, sweepFlag, x, y); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::arcRel(double rx, double ry, + double angle, + bool largeArcFlag, + bool sweepFlag, + double dx, double dy) +{ + m_path.arc_rel(rx, ry, angle, largeArcFlag, sweepFlag, dx, dy); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::quadricCurveTo(double xCtrl, double yCtrl, + double xTo, double yTo) +{ + m_path.curve3(xCtrl, yCtrl, xTo, yTo); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::quadricCurveRel(double dxCtrl, double dyCtrl, + double dxTo, double dyTo) +{ + m_path.curve3_rel(dxCtrl, dyCtrl, dxTo, dyTo); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::quadricCurveTo(double xTo, double yTo) +{ + m_path.curve3(xTo, yTo); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::quadricCurveRel(double dxTo, double dyTo) +{ + m_path.curve3_rel(dxTo, dyTo); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::cubicCurveTo(double xCtrl1, double yCtrl1, + double xCtrl2, double yCtrl2, + double xTo, double yTo) +{ + m_path.curve4(xCtrl1, yCtrl1, xCtrl2, yCtrl2, xTo, yTo); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::cubicCurveRel(double dxCtrl1, double dyCtrl1, + double dxCtrl2, double dyCtrl2, + double dxTo, double dyTo) +{ + m_path.curve4_rel(dxCtrl1, dyCtrl1, dxCtrl2, dyCtrl2, dxTo, dyTo); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::cubicCurveTo(double xCtrl2, double yCtrl2, + double xTo, double yTo) +{ + m_path.curve4(xCtrl2, yCtrl2, xTo, yTo); +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::cubicCurveRel(double xCtrl2, double yCtrl2, + double xTo, double yTo) +{ + m_path.curve4_rel(xCtrl2, yCtrl2, xTo, yTo); +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::addEllipse(double cx, double cy, double rx, double ry, Direction dir) +{ + agg::bezier_arc arc(cx, cy, rx, ry, 0, (dir == CCW) ? 2*pi() : -2*pi()); + //m_path.add_path(arc, 0, false); + m_path.concat_path(arc,0); // JME + m_path.close_polygon(); +} + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::closePolygon() +{ + if(agg::is_vertex(m_path.vertices().last_command())) + { + m_path.vertices().add_vertex(m_start_x, m_start_y, + agg::path_cmd_end_poly | agg::path_flags_close); + } +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::imageFilter(ImageFilter f) +{ + m_imageFilter = f; + switch(f) + { + case NoFilter: break; + case Bilinear: m_imageFilterLut.calculate(agg::image_filter_bilinear(), true); break; + case Hanning: m_imageFilterLut.calculate(agg::image_filter_hanning(), true); break; + case Hermite: m_imageFilterLut.calculate(agg::image_filter_hermite(), true); break; + case Quadric: m_imageFilterLut.calculate(agg::image_filter_quadric(), true); break; + case Bicubic: m_imageFilterLut.calculate(agg::image_filter_bicubic(), true); break; + case Catrom: m_imageFilterLut.calculate(agg::image_filter_catrom(), true); break; + case Spline16: m_imageFilterLut.calculate(agg::image_filter_spline16(), true); break; + case Spline36: m_imageFilterLut.calculate(agg::image_filter_spline36(), true); break; + case Blackman144: m_imageFilterLut.calculate(agg::image_filter_blackman144(), true); break; + } +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE Agg2DBase::ImageFilter TAGG2D::imageFilter() const +{ + return m_imageFilter; +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::imageResample(ImageResample f) +{ + m_imageResample = f; +} + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE Agg2DBase::ImageResample TAGG2D::imageResample() const +{ + return m_imageResample; +} + +//==============moved to .h file=========== + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::drawPath(DrawPathFlag flag) +{ + m_rasterizer.reset(); + switch(flag) + { + case FillOnly: + if (m_fillColor.a) + { + m_rasterizer.add_path(m_pathTransform); + render(true); + } + break; + + case StrokeOnly: + if (m_lineColor.a && m_lineWidth > 0.0) + { + m_rasterizer.add_path(m_strokeTransform); + render(false); + } + break; + + case FillAndStroke: + if (m_fillColor.a) + { + m_rasterizer.add_path(m_pathTransform); + render(true); + } + + if (m_lineColor.a && m_lineWidth > 0.0) + { + m_rasterizer.add_path(m_strokeTransform); + render(false); + } + break; + + case FillWithLineColor: + if (m_lineColor.a) + { + m_rasterizer.add_path(m_pathTransform); + render(false); + } + break; + } +} + + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE_WITH_IMAGE class Agg2DRenderer +{ +public: + typedef typename TAGG2D::Color Color; + typedef typename TIMAGE Image; + //-------------------------------------------------------------------- + template + void static render(TAGG2D& gr, BaseRenderer& renBase, SolidRenderer& renSolid, bool fillColor) + { + // JME + typedef agg::span_allocator span_allocator_type; + //- typedef agg::renderer_scanline_aa RendererLinearGradient; + typedef agg::renderer_scanline_aa RendererLinearGradient; + //- typedef agg::renderer_scanline_aa RendererRadialGradient; + typedef agg::renderer_scanline_aa RendererRadialGradient; + + if ((fillColor && gr.m_fillGradientFlag == TAGG2D::Linear) || + (!fillColor && gr.m_lineGradientFlag == TAGG2D::Linear)) + { + if (fillColor) + { + typename TAGG2D::LinearGradientSpan span(/*gr.m_allocator, */ + gr.m_fillGradientInterpolator, + gr.m_linearGradientFunction, + gr.m_fillGradient, + gr.m_fillGradientD1, + gr.m_fillGradientD2); + //-RendererLinearGradient ren(renBase,span); + RendererLinearGradient ren(renBase,gr.m_allocator,span); + agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, ren); + } + else + { + typename TAGG2D::LinearGradientSpan span(/*gr.m_allocator,*/ + gr.m_lineGradientInterpolator, + gr.m_linearGradientFunction, + gr.m_lineGradient, + gr.m_lineGradientD1, + gr.m_lineGradientD2); + //- RendererLinearGradient ren(renBase, span); + RendererLinearGradient ren(renBase,gr.m_allocator,span); + agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, ren); + } + } + else + { + if ((fillColor && gr.m_fillGradientFlag == TAGG2D::Radial) || + (!fillColor && gr.m_lineGradientFlag == TAGG2D::Radial)) + { + if (fillColor) + { + typename TAGG2D::RadialGradientSpan span(/*gr.m_allocator, */ + gr.m_fillGradientInterpolator, + gr.m_radialGradientFunction, + gr.m_fillGradient, + gr.m_fillGradientD1, + gr.m_fillGradientD2); + //-RendererRadialGradient ren(renBase, span); + RendererRadialGradient ren(renBase,gr.m_allocator,span); + agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, ren); + } + else + { + typename TAGG2D::RadialGradientSpan span(/*gr.m_allocator,*/ + gr.m_lineGradientInterpolator, + gr.m_radialGradientFunction, + gr.m_lineGradient, + gr.m_lineGradientD1, + gr.m_lineGradientD2); + //-RendererRadialGradient ren(renBase, span); + RendererRadialGradient ren(renBase,gr.m_allocator,span); + agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, ren); + } + } + else + { + renSolid.color(fillColor ? gr.m_fillColor : gr.m_lineColor); + agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, renSolid); + } + } + } + + + //-------------------------------------------------------------------- + class SpanConvImageBlend + { + public: + SpanConvImageBlend(Agg2DBase::BlendMode m, Color c) : + m_mode(m), m_color(c) + {} + + void convert(Color* span, int x, int y, unsigned len) const + { + unsigned l2; + typename TAGG2D::Color* s2; + if(m_mode != TAGG2D::BlendDst) + { + l2 = len; + s2 = span; + typedef agg::comp_op_adaptor_clip_to_dst_rgba_pre OpType; + do + { + OpType::blend_pix(m_mode, + (typename TAGG2D::Color::value_type*)s2, + m_color.r, + m_color.g, + m_color.b, + TAGG2D::Color::base_mask, + agg::cover_full); + ++s2; + } + while(--l2); + } + if(m_color.a < TAGG2D::Color::base_mask) + { + l2 = len; + s2 = span; + unsigned a = m_color.a; + do + { + s2->r = (s2->r * a) >> TAGG2D::Color::base_shift; + s2->g = (s2->g * a) >> TAGG2D::Color::base_shift; + s2->b = (s2->b * a) >> TAGG2D::Color::base_shift; + s2->a = (s2->a * a) >> TAGG2D::Color::base_shift; + ++s2; + } + while(--l2); + } + } + + private: + Agg2DBase::BlendMode m_mode; + Color m_color; + }; + + + + + //-------------------------------------------------------------------- + template + void static render(TAGG2D& gr, BaseRenderer& renBase, SolidRenderer& renSolid, Rasterizer& ras, Scanline& sl) + { + // JME + typedef agg::span_allocator span_allocator_type; + typedef agg::renderer_scanline_aa RendererLinearGradient; + typedef agg::renderer_scanline_aa RendererRadialGradient; + + if(gr.m_fillGradientFlag == TAGG2D::Linear) + { + typename TAGG2D::LinearGradientSpan span( + gr.m_fillGradientInterpolator, + gr.m_linearGradientFunction, + gr.m_fillGradient, + gr.m_fillGradientD1, + gr.m_fillGradientD2); + RendererLinearGradient ren(renBase,gr.m_allocator,span); + agg::render_scanlines(ras, sl, ren); + } + else + { + if(gr.m_fillGradientFlag == TAGG2D::Radial) + { + typename TAGG2D::RadialGradientSpan span( + gr.m_fillGradientInterpolator, + gr.m_radialGradientFunction, + gr.m_fillGradient, + gr.m_fillGradientD1, + gr.m_fillGradientD2); + RendererRadialGradient ren(renBase,gr.m_allocator,span); + agg::render_scanlines(ras, sl, ren); + } + else + { + renSolid.color(gr.m_fillColor); + agg::render_scanlines(ras, sl, renSolid); + } + } + } + + + + //-------------------------------------------------------------------- + //! JME - this is where the bulk of the changes have taken place. + template + static void renderImage(TAGG2D& gr, const TIMAGE& img, + BaseRenderer& renBase, Interpolator& interpolator) + { + //! JME - have not quite figured which part of this is not const-correct + // hence the cast. + Image& imgc = const_cast(img); + typename ImagePixFormatSet::PixFormat img_pixf(imgc.renBuf); + typedef agg::image_accessor_clone img_source_type; + img_source_type source(img_pixf); + + SpanConvImageBlend blend(gr.m_imageBlendMode, gr.m_imageBlendColor); + if(gr.m_imageFilter == TAGG2D::NoFilter) + { + //original way + typedef agg::span_image_filter_rgba_nn SpanGenType; + typedef agg::renderer_scanline_aa RendererType; + SpanGenType sg(source,interpolator); + RendererType ri(renBase,gr.m_allocator,sg); + agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, ri); + + //our way, using our own span generator to support 555 + //but, it isnt working yet + //typedef ImagePixFormatSet::SpanGenerator SpanGenType; + //typedef agg::renderer_scanline_aa RendererType; + //SpanGenType sg(imgc.renBuf); + //RendererType ri(renBase,gr.m_allocator,sg); + //agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, ri); + } + //else + // { + // bool resample = (gr.m_imageResample == TAGG2D::ResampleAlways); + // if(gr.m_imageResample == TAGG2D::ResampleOnZoomOut) + // { + // double sx, sy; + // interpolator.transformer().scaling_abs(&sx, &sy); + // if (sx > 1.125 || sy > 1.125) + // { + // resample = true; + // } + // } + + // if(resample) + // { + // typedef agg::span_image_resample_rgba_affine SpanGenType; + // typedef agg::span_converter SpanConvType; + // typedef agg::renderer_scanline_aa RendererType; + + // SpanGenType sg(source,interpolator,gr.m_imageFilterLut); + // SpanConvType sc(sg, blend); + // RendererType ri(renBase,gr.m_allocator,sg); + // agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, ri); + // } + // else + // { + //// this is the AGG2D default + // if(gr.m_imageFilter == TAGG2D::Bilinear) + // { + // typedef agg::span_image_filter_rgba_bilinear SpanGenType; + // typedef agg::span_converter SpanConvType; + // typedef agg::renderer_scanline_aa RendererType; + + // SpanGenType sg(source,interpolator); + // SpanConvType sc(sg, blend); + // RendererType ri(renBase,gr.m_allocator,sg); + // agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, ri); + // } + // else + // { + // if(gr.m_imageFilterLut.diameter() == 2) + // { + // typedef agg::span_image_filter_rgba_2x2 SpanGenType; + // typedef agg::span_converter SpanConvType; + // typedef agg::renderer_scanline_aa RendererType; + + // SpanGenType sg(source,interpolator,gr.m_imageFilterLut); + // SpanConvType sc(sg, blend); + // RendererType ri(renBase,gr.m_allocator,sg); + // agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, ri); + // } + // else + // { + // typedef agg::span_image_filter_rgba SpanGenType; + // typedef agg::span_converter SpanConvType; + // typedef agg::renderer_scanline_aa RendererType; + // SpanGenType sg(source,interpolator,gr.m_imageFilterLut); + // SpanConvType sc(sg, blend); + // RendererType ri(renBase,gr.m_allocator,sg); + // agg::render_scanlines(gr.m_rasterizer, gr.m_scanline, ri); + // } + // } + // } + // } + } +}; + + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::render(bool fillColor) +{ + if(m_blendMode == BlendAlpha) + { + TAGG2DRENDERER::render(*this, m_renBase, m_renSolid, fillColor); + } + else + { + TAGG2DRENDERER::render(*this, m_renBaseComp, m_renSolidComp, fillColor); + } +} + +#ifdef AGG2D_USE_VECTORFONTS +#if !defined( UNDER_CE ) + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::render(FontRasterizer& ras, FontScanline& sl) +{ + if(m_blendMode == BlendAlpha) + { + Agg2DRenderer::render(*this, m_renBase, m_renSolid, ras, sl); + } + else + { + Agg2DRenderer::render(*this, m_renBaseComp, m_renSolidComp, ras, sl); + } +} + +#endif +#endif + +//------------------------------------------------------------------------ +struct Agg2DRasterizerGamma +{ + + Agg2DRasterizerGamma(double alpha, double gamma) : + m_alpha(alpha), m_gamma(gamma) {} + + double operator() (double x) const + { + return m_alpha(m_gamma(x)); + } + agg::gamma_multiply m_alpha; + agg::gamma_power m_gamma; +}; + +//------------------------------------------------------------------------ +AGG2D_TEMPLATE void TAGG2D::updateRasterizerGamma() +{ + m_rasterizer.gamma(Agg2DRasterizerGamma(m_masterAlpha, m_antiAliasGamma)); +} + diff --git a/jni/desmume/src/aggdraw.cpp b/jni/desmume/src/aggdraw.cpp new file mode 100755 index 0000000..0aa90d7 --- /dev/null +++ b/jni/desmume/src/aggdraw.cpp @@ -0,0 +1,591 @@ +/* +The MIT License + +Copyright (C) 2009-2010 DeSmuME team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include + +#include "GPU.h" +#include "NDSSystem.h" + +#include "aggdraw.h" + +#include "agg_renderer_base.h" +#include "agg_renderer_primitives.h" +#include "agg_renderer_scanline.h" +#include "agg_bounding_rect.h" +#include "agg_trans_affine.h" +#include "agg_path_storage.h" +#include "agg_color_rgba.h" + +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_scanline_p.h" + +//raster text +#include "agg_glyph_raster_bin.h" +#include "agg_embedded_raster_fonts.h" +#include "agg_renderer_raster_text.h" + +#include "ctrl/agg_bezier_ctrl.h" +#include "platform/agg_platform_support.h" +#include "agg_pattern_filters_rgba.h" +#include "agg_renderer_outline_image.h" +#include "agg_rasterizer_outline_aa.h" + +#include "agg_image_accessors.h" +#include "agg_span_interpolator_linear.h" +#include "agg_span_image_filter_rgb.h" +#include "agg_span_image_filter_rgba.h" +#include "agg_span_image_filter_gray.h" + +#include "agg_span_allocator.h" + +typedef std::map TAgg_Font_Table; +static TAgg_Font_Table font_table; + +font_type fonts_list[] = +{ + { agg::gse4x6, "gse4x6" }, + { agg::gse4x8, "gse4x8" }, + { agg::gse5x7, "gse5x7" }, + { agg::gse5x9, "gse5x9" }, + { agg::gse6x9, "gse6x9" }, + { agg::gse6x12, "gse6x12" }, + { agg::gse7x11, "gse7x11" }, + { agg::gse7x11_bold, "gse7x11_bold" }, + { agg::gse7x15, "gse7x15" }, + { agg::gse7x15_bold, "gse7x15_bold" }, + { agg::gse8x16, "gse8x16" }, + { agg::gse8x16_bold, "gse8x16_bold" }, + { agg::mcs11_prop, "mcs11_prop" }, + { agg::mcs11_prop_condensed, "mcs11_prop_condensed" }, + { agg::mcs12_prop, "mcs12_prop" }, + { agg::mcs13_prop, "mcs13_prop" }, + { agg::mcs5x10_mono, "mcs5x10_mono" }, + { agg::mcs5x11_mono, "mcs5x11_mono" }, + { agg::mcs6x10_mono, "mcs6x10_mono" }, + { agg::mcs6x11_mono, "mcs6x11_mono" }, + { agg::mcs7x12_mono_high, "mcs7x12_mono_high" }, + { agg::mcs7x12_mono_low, "mcs7x12_mono_low" }, + { agg::verdana12, "verdana12" }, + { agg::verdana12_bold, "verdana12_bold" }, + { agg::verdana13, "verdana13" }, + { agg::verdana13_bold, "verdana13_bold" }, + { agg::verdana14, "verdana14" }, + { agg::verdana14_bold, "verdana14_bold" }, + { agg::verdana16, "verdana16" }, + { agg::verdana16_bold, "verdana16_bold" }, + { agg::verdana17, "verdana17" }, + { agg::verdana17_bold, "verdana17_bold" }, + { agg::verdana18, "verdana18" }, + { agg::verdana18_bold, "verdana18_bold" }, +}; +int font_Nums = ARRAY_SIZE(fonts_list); + +const agg::int8u* AggDrawTarget::lookupFont(const std::string& name) +{ + TAgg_Font_Table::iterator it(font_table.find(name)); + if(it == font_table.end()) return NULL; + else return it->second; +} + +static void Agg_init_fonts() +{ + for(u32 i=0;isetFont("verdana18_bold"); +} + +void AggDraw_Desmume::setTarget(AggTarget newTarget) +{ + target = targets[newTarget]; +} + + + +////temporary, just for testing the lib +//void AGGDraw() { +//// +// aggDraw.setTarget(AggTarget_Screen); +// +//// aggDraw.target->clear(); +//// +//// aggDraw.target->clipBox(0,0,255,383); +//// +// aggDraw.target->lineColor(0, 0, 255, 128); +// aggDraw.target->fillColor(0, 0, 255, 128); +//// //aggDraw.target->noFill(); +// aggDraw.target->lineWidth(1.0); +// aggDraw.target->roundedRect(10,30,256-10,192-10,4); +//// +//// aggDraw.target->setFont("verdana18_bold"); +//// aggDraw.target->renderText(60,60, "testing testing testing"); +//// +//// // Gradients (Aqua Buttons) +//// //======================================= +////// m_graphics.font("Verdana", 20.0, false, false, TAGG2D::VectorFontCache); +//// double xb1 = 10; +//// double yb1 = 80; +//// double xb2 = xb1 + 150; +//// double yb2 = yb1 + 36; +//// +//// aggDraw.target->fillColor(0,50,180,180); +//// aggDraw.target->lineColor(0,0,80, 255); +//// aggDraw.target->lineWidth(1.0); +//// aggDraw.target->roundedRect(xb1, yb1, xb2, yb2, 12, 18); +//// +//// aggDraw.target->lineColor(0,0,0,0); +//// aggDraw.target->fillLinearGradient(xb1, yb1, xb1, yb1+30, +//// agg::rgba8(100,200,255,255), +//// agg::rgba8(255,255,255,0)); +//// aggDraw.target->roundedRect(xb1+3, yb1+2.5, xb2-3, yb1+30, 9, 18, 1, 1); +//// +//// aggDraw.target->fillColor(0,0,50, 200); +//// aggDraw.target->noLine(); +/////* m_graphics.textAlignment(TAGG2D::AlignCenter, TAGG2D::AlignCenter); +//// m_graphics.text((xb1 + xb2) / 2.0, (yb1 + yb2) / 2.0, "Aqua Button", true, 0.0, 0.0); +////*/ +//// aggDraw.target->fillLinearGradient(xb1, yb2-20, xb1, yb2-3, +//// agg::rgba8(0, 0, 255,0), +//// agg::rgba8(100,255,255,255)); +//// aggDraw.target->roundedRect(xb1+3, yb2-20, xb2-3, yb2-2, 1, 1, 9, 18); +//// +//// // Basic Shapes -- Ellipse +//// //=========================================== +//// aggDraw.target->lineWidth(3.5); +//// aggDraw.target->lineColor(20, 80, 80); +//// aggDraw.target->fillColor(200, 255, 80, 200); +//// aggDraw.target->ellipse(150, 200, 50, 90); +//// +//// // Paths +//// //=========================================== +//// aggDraw.target->resetPath(); +//// aggDraw.target->fillColor(255, 0, 0, 100); +//// aggDraw.target->lineColor(0, 0, 255, 100); +//// aggDraw.target->lineWidth(2); +//// aggDraw.target->moveTo(300/2, 200/2); +//// aggDraw.target->horLineRel(-150/2); +//// aggDraw.target->arcRel(150/2, 150/2, 0, 1, 0, 150/2, -150/2); +//// aggDraw.target->closePolygon(); +//// aggDraw.target->drawPath(); +//// +//// aggDraw.target->resetPath(); +//// aggDraw.target->fillColor(255, 255, 0, 100); +//// aggDraw.target->lineColor(0, 0, 255, 100); +//// aggDraw.target->lineWidth(2); +//// aggDraw.target->moveTo(275/2, 175/2); +//// aggDraw.target->verLineRel(-150/2); +//// aggDraw.target->arcRel(150/2, 150/2, 0, 0, 0, -150/2, 150/2); +//// aggDraw.target->closePolygon(); +//// aggDraw.target->drawPath(); +//// +//// aggDraw.target->resetPath(); +//// aggDraw.target->noFill(); +//// aggDraw.target->lineColor(127, 0, 0); +//// aggDraw.target->lineWidth(5); +//// aggDraw.target->moveTo(600/2, 350/2); +//// aggDraw.target->lineRel(50/2, -25/2); +//// aggDraw.target->arcRel(25/2, 25/2, aggDraw.target->deg2Rad(-30), 0, 1, 50/2, -25/2); +//// aggDraw.target->lineRel(50/2, -25/2); +//// aggDraw.target->arcRel(25/2, 50/2, aggDraw.target->deg2Rad(-30), 0, 1, 50/2, -25/2); +//// aggDraw.target->lineRel(50/2, -25/2); +//// aggDraw.target->arcRel(25/2, 75/2, aggDraw.target->deg2Rad(-30), 0, 1, 50/2, -25/2); +//// aggDraw.target->lineRel(50, -25); +//// aggDraw.target->arcRel(25/2, 100/2, aggDraw.target->deg2Rad(-30), 0, 1, 50/2, -25/2); +//// aggDraw.target->lineRel(50/2, -25/2); +//// aggDraw.target->drawPath(); +//} +//// + + +// +////======================== +////testing stufff +// +//int width = 256; +//int height = 384; +// +//Agg2D m_graphics; +// +//void AGGDraw(unsigned char * buffer) +// { +// m_graphics.attach(buffer, +// 256, +// 384, +// 512); +// +// m_graphics.clearAll(255, 255, 255); +// //m_graphics.clearAll(0, 0, 0); +// +// //m_graphics.blendMode(TAGG2D::BlendSub); +// //m_graphics.blendMode(TAGG2D::BlendAdd); +// +// m_graphics.antiAliasGamma(1.4); +// +// // Set flipText(true) if you have the Y axis upside down. +// //m_graphics.flipText(true); +// +// +// // ClipBox. +// //m_graphics.clipBox(50, 50, rbuf_window().width() - 50, rbuf_window().height() - 50); +// +// // Transfornations - Rotate around (300,300) to 5 degree +// //m_graphics.translate(-300, -300); +// //m_graphics.rotate(TAGG2D::deg2Rad(5.0)); +// //m_graphics.translate(300, 300); +// +// // Viewport - set 0,0,600,600 to the actual window size +// // preserving aspect ratio and placing the viewport in the center. +// // To ignore aspect ratio use TAGG2D::Anisotropic +// // Note that the viewport just adds transformations to the current +// // affine matrix. So that, set the viewport *after* all transformations! +// m_graphics.viewport(0, 0, 600, 600, +// 0, 0, width, height, +// //TAGG2D::Anisotropic); +// TAGG2D::XMidYMid); +// +// +// // Rounded Rect +// m_graphics.lineColor(0, 0, 0); +// m_graphics.noFill(); +// m_graphics.roundedRect(0.5, 0.5, 600-0.5, 600-0.5, 20.0); +///* +// +// // Reglar Text +// m_graphics.font("Times New Roman", 14.0, false, false); +// m_graphics.fillColor(0, 0, 0); +// m_graphics.noLine(); +// m_graphics.text(100, 20, "Regular Raster Text -- Fast, but can't be rotated"); +// +// // Outlined Text +// m_graphics.font("Times New Roman", 50.0, false, false, TAGG2D::VectorFontCache); +// m_graphics.lineColor(50, 0, 0); +// m_graphics.fillColor(180, 200, 100); +// m_graphics.lineWidth(1.0); +// m_graphics.text(100.5, 50.5, "Outlined Text"); +// +// // Text Alignment +// m_graphics.line(250.5-150, 150.5, 250.5+150, 150.5); +// m_graphics.line(250.5, 150.5-20, 250.5, 150.5+20); +// m_graphics.line(250.5-150, 200.5, 250.5+150, 200.5); +// m_graphics.line(250.5, 200.5-20, 250.5, 200.5+20); +// m_graphics.line(250.5-150, 250.5, 250.5+150, 250.5); +// m_graphics.line(250.5, 250.5-20, 250.5, 250.5+20); +// m_graphics.line(250.5-150, 300.5, 250.5+150, 300.5); +// m_graphics.line(250.5, 300.5-20, 250.5, 300.5+20); +// m_graphics.line(250.5-150, 350.5, 250.5+150, 350.5); +// m_graphics.line(250.5, 350.5-20, 250.5, 350.5+20); +// m_graphics.line(250.5-150, 400.5, 250.5+150, 400.5); +// m_graphics.line(250.5, 400.5-20, 250.5, 400.5+20); +// m_graphics.line(250.5-150, 450.5, 250.5+150, 450.5); +// m_graphics.line(250.5, 450.5-20, 250.5, 450.5+20); +// m_graphics.line(250.5-150, 500.5, 250.5+150, 500.5); +// m_graphics.line(250.5, 500.5-20, 250.5, 500.5+20); +// m_graphics.line(250.5-150, 550.5, 250.5+150, 550.5); +// m_graphics.line(250.5, 550.5-20, 250.5, 550.5+20); +//*/ +///* +// m_graphics.fillColor(100, 50, 50); +// m_graphics.noLine(); +// //m_graphics.textHints(false); +// m_graphics.font("Times New Roman", 40.0, false, false, TAGG2D::VectorFontCache); +// +// m_graphics.textAlignment(TAGG2D::AlignLeft, TAGG2D::AlignBottom); +// m_graphics.text(250.0, 150.0, "Left-Bottom", true, 0, 0); +// +// m_graphics.textAlignment(TAGG2D::AlignCenter, TAGG2D::AlignBottom); +// m_graphics.text(250.0, 200.0, "Center-Bottom", true, 0, 0); +// +// m_graphics.textAlignment(TAGG2D::AlignRight, TAGG2D::AlignBottom); +// m_graphics.text(250.0, 250.0, "Right-Bottom", true, 0, 0); +// +// m_graphics.textAlignment(TAGG2D::AlignLeft, TAGG2D::AlignCenter); +// m_graphics.text(250.0, 300.0, "Left-Center", true, 0, 0); +// +// m_graphics.textAlignment(TAGG2D::AlignCenter, TAGG2D::AlignCenter); +// m_graphics.text(250.0, 350.0, "Center-Center", true, 0, 0); +// +// m_graphics.textAlignment(TAGG2D::AlignRight, TAGG2D::AlignCenter); +// m_graphics.text(250.0, 400.0, "Right-Center", true, 0, 0); +// +// m_graphics.textAlignment(TAGG2D::AlignLeft, TAGG2D::AlignTop); +// m_graphics.text(250.0, 450.0, "Left-Top", true, 0, 0); +// +// m_graphics.textAlignment(TAGG2D::AlignCenter, TAGG2D::AlignTop); +// m_graphics.text(250.0, 500.0, "Center-Top", true, 0, 0); +// +// m_graphics.textAlignment(TAGG2D::AlignRight, TAGG2D::AlignTop); +// m_graphics.text(250.0, 550.0, "Right-Top", true, 0, 0); +// +//*/ +// // Gradients (Aqua Buttons) +// //======================================= +// m_graphics.font("Verdana", 20.0, false, false, TAGG2D::VectorFontCache); +// double xb1 = 400; +// double yb1 = 80; +// double xb2 = xb1 + 150; +// double yb2 = yb1 + 36; +// +// m_graphics.fillColor(TAGG2D::Color(0,50,180,180)); +// m_graphics.lineColor(TAGG2D::Color(0,0,80, 255)); +// m_graphics.lineWidth(1.0); +// m_graphics.roundedRect(xb1, yb1, xb2, yb2, 12, 18); +// +// m_graphics.lineColor(TAGG2D::Color(0,0,0,0)); +// m_graphics.fillLinearGradient(xb1, yb1, xb1, yb1+30, +// TAGG2D::Color(100,200,255,255), +// TAGG2D::Color(255,255,255,0)); +// m_graphics.roundedRect(xb1+3, yb1+2.5, xb2-3, yb1+30, 9, 18, 1, 1); +// +// m_graphics.fillColor(TAGG2D::Color(0,0,50, 200)); +// m_graphics.noLine(); +///* m_graphics.textAlignment(TAGG2D::AlignCenter, TAGG2D::AlignCenter); +// m_graphics.text((xb1 + xb2) / 2.0, (yb1 + yb2) / 2.0, "Aqua Button", true, 0.0, 0.0); +//*/ +// m_graphics.fillLinearGradient(xb1, yb2-20, xb1, yb2-3, +// TAGG2D::Color(0, 0, 255,0), +// TAGG2D::Color(100,255,255,255)); +// m_graphics.roundedRect(xb1+3, yb2-20, xb2-3, yb2-2, 1, 1, 9, 18); +// +// +// // Aqua Button Pressed +// xb1 = 400; +// yb1 = 30; +// xb2 = xb1 + 150; +// yb2 = yb1 + 36; +// +// m_graphics.fillColor(TAGG2D::Color(0,50,180,180)); +// m_graphics.lineColor(TAGG2D::Color(0,0,0, 255)); +// m_graphics.lineWidth(2.0); +// m_graphics.roundedRect(xb1, yb1, xb2, yb2, 12, 18); +// +// m_graphics.lineColor(TAGG2D::Color(0,0,0,0)); +// m_graphics.fillLinearGradient(xb1, yb1+2, xb1, yb1+25, +// TAGG2D::Color(60, 160,255,255), +// TAGG2D::Color(100,255,255,0)); +// m_graphics.roundedRect(xb1+3, yb1+2.5, xb2-3, yb1+30, 9, 18, 1, 1); +// +// m_graphics.fillColor(TAGG2D::Color(0,0,50, 255)); +// m_graphics.noLine(); +///* m_graphics.textAlignment(TAGG2D::AlignCenter, TAGG2D::AlignCenter); +// m_graphics.text((xb1 + xb2) / 2.0, (yb1 + yb2) / 2.0, "Aqua Pressed", 0.0, 0.0); +//*/ +// m_graphics.fillLinearGradient(xb1, yb2-25, xb1, yb2-5, +// TAGG2D::Color(0, 180,255,0), +// TAGG2D::Color(0, 200,255,255)); +// m_graphics.roundedRect(xb1+3, yb2-25, xb2-3, yb2-2, 1, 1, 9, 18); +// +// +// +// +// // Basic Shapes -- Ellipse +// //=========================================== +// m_graphics.lineWidth(3.5); +// m_graphics.lineColor(20, 80, 80); +// m_graphics.fillColor(200, 255, 80, 200); +// m_graphics.ellipse(450, 200, 50, 90); +// +// +// // Paths +// //=========================================== +// m_graphics.resetPath(); +// m_graphics.fillColor(255, 0, 0, 100); +// m_graphics.lineColor(0, 0, 255, 100); +// m_graphics.lineWidth(2); +// m_graphics.moveTo(300/2, 200/2); +// m_graphics.horLineRel(-150/2); +// m_graphics.arcRel(150/2, 150/2, 0, 1, 0, 150/2, -150/2); +// m_graphics.closePolygon(); +// m_graphics.drawPath(); +// +// m_graphics.resetPath(); +// m_graphics.fillColor(255, 255, 0, 100); +// m_graphics.lineColor(0, 0, 255, 100); +// m_graphics.lineWidth(2); +// m_graphics.moveTo(275/2, 175/2); +// m_graphics.verLineRel(-150/2); +// m_graphics.arcRel(150/2, 150/2, 0, 0, 0, -150/2, 150/2); +// m_graphics.closePolygon(); +// m_graphics.drawPath(); +// +// +// m_graphics.resetPath(); +// m_graphics.noFill(); +// m_graphics.lineColor(127, 0, 0); +// m_graphics.lineWidth(5); +// m_graphics.moveTo(600/2, 350/2); +// m_graphics.lineRel(50/2, -25/2); +// m_graphics.arcRel(25/2, 25/2, TAGG2D::deg2Rad(-30), 0, 1, 50/2, -25/2); +// m_graphics.lineRel(50/2, -25/2); +// m_graphics.arcRel(25/2, 50/2, TAGG2D::deg2Rad(-30), 0, 1, 50/2, -25/2); +// m_graphics.lineRel(50/2, -25/2); +// m_graphics.arcRel(25/2, 75/2, TAGG2D::deg2Rad(-30), 0, 1, 50/2, -25/2); +// m_graphics.lineRel(50, -25); +// m_graphics.arcRel(25/2, 100/2, TAGG2D::deg2Rad(-30), 0, 1, 50/2, -25/2); +// m_graphics.lineRel(50/2, -25/2); +// m_graphics.drawPath(); +// +// +// // Master Alpha. From now on everything will be translucent +// //=========================================== +// m_graphics.masterAlpha(0.85); +// +// +// // Image Transformations +// //=========================================== +///* TAGG2D::Image img(rbuf_img(0).buf(), +// rbuf_img(0).width(), +// rbuf_img(0).height(), +// rbuf_img(0).stride()); +// m_graphics.imageFilter(TAGG2D::Bilinear); +// +// //m_graphics.imageResample(TAGG2D::NoResample); +// //m_graphics.imageResample(TAGG2D::ResampleAlways); +// m_graphics.imageResample(TAGG2D::ResampleOnZoomOut); +// +// // Set the initial image blending operation as BlendDst, that actually +// // does nothing. +// //----------------- +// m_graphics.imageBlendMode(TAGG2D::BlendDst); +// +// +// // Transform the whole image to the destination rectangle +// //----------------- +// //m_graphics.transformImage(img, 450, 200, 595, 350); +// +// // Transform the rectangular part of the image to the destination rectangle +// //----------------- +// //m_graphics.transformImage(img, 60, 60, img.width()-60, img.height()-60, +// // 450, 200, 595, 350); +// +// // Transform the whole image to the destination parallelogram +// //----------------- +// //double parl[6] = { 450, 200, 595, 220, 575, 350 }; +// //m_graphics.transformImage(img, parl); +// +// // Transform the rectangular part of the image to the destination parallelogram +// //----------------- +// //double parl[6] = { 450, 200, 595, 220, 575, 350 }; +// //m_graphics.transformImage(img, 60, 60, img.width()-60, img.height()-60, parl); +// +// // Transform image to the destination path. The scale is determined by a rectangle +// //----------------- +// //m_graphics.resetPath(); +// //m_graphics.moveTo(450, 200); +// //m_graphics.cubicCurveTo(595, 220, 575, 350, 595, 350); +// //m_graphics.lineTo(470, 340); +// //m_graphics.transformImagePath(img, 450, 200, 595, 350); +// +// +// // Transform image to the destination path. +// // The scale is determined by a rectangle +// //----------------- +// m_graphics.resetPath(); +// m_graphics.moveTo(450, 200); +// m_graphics.cubicCurveTo(595, 220, 575, 350, 595, 350); +// m_graphics.lineTo(470, 340); +// m_graphics.transformImagePath(img, 60, 60, img.width()-60, img.height()-60, +// 450, 200, 595, 350); +// +// // Transform image to the destination path. +// // The transformation is determined by a parallelogram +// //m_graphics.resetPath(); +// //m_graphics.moveTo(450, 200); +// //m_graphics.cubicCurveTo(595, 220, 575, 350, 595, 350); +// //m_graphics.lineTo(470, 340); +// //double parl[6] = { 450, 200, 595, 220, 575, 350 }; +// //m_graphics.transformImagePath(img, parl); +// +// // Transform the rectangular part of the image to the destination path. +// // The transformation is determined by a parallelogram +// //m_graphics.resetPath(); +// //m_graphics.moveTo(450, 200); +// //m_graphics.cubicCurveTo(595, 220, 575, 350, 595, 350); +// //m_graphics.lineTo(470, 340); +// //double parl[6] = { 450, 200, 595, 220, 575, 350 }; +// //m_graphics.transformImagePath(img, 60, 60, img.width()-60, img.height()-60, parl); +//*/ +// +// // Add/Sub/Contrast Blending Modes +// m_graphics.noLine(); +// m_graphics.fillColor(70, 70, 0); +// m_graphics.blendMode(TAGG2D::BlendAdd); +// m_graphics.ellipse(500, 280, 20, 40); +// +// m_graphics.fillColor(255, 255, 255); +// m_graphics.blendMode(TAGG2D::BlendContrast); +// m_graphics.ellipse(500+40, 280, 20, 40); +// +// +// +// // Radial gradient. +// m_graphics.blendMode(TAGG2D::BlendAlpha); +// m_graphics.fillRadialGradient(400, 500, 40, +// TAGG2D::Color(255, 255, 0, 0), +// TAGG2D::Color(0, 0, 127), +// TAGG2D::Color(0, 255, 0, 0)); +// m_graphics.ellipse(400, 500, 40, 40); +// +// } +// diff --git a/jni/desmume/src/aggdraw.h b/jni/desmume/src/aggdraw.h new file mode 100755 index 0000000..8910373 --- /dev/null +++ b/jni/desmume/src/aggdraw.h @@ -0,0 +1,674 @@ +/* +The MIT License + +Copyright (C) 2009-2010 DeSmuME team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + + +//This file contains code designed to be used by hud and lua systems in any emulator + + +#ifndef _AGGDRAW_H_ +#define _AGGDRAW_H_ + +#include "agg_color_rgba.h" +#include "agg_rendering_buffer.h" + +#include "agg_renderer_base.h" +#include "agg_renderer_primitives.h" +#include "agg_renderer_scanline.h" +#include "agg_bounding_rect.h" + +#include "agg_renderer_mclip.h" +#include "agg_renderer_outline_aa.h" +#include "agg_renderer_markers.h" + +#include "agg_pixfmt_rgb.h" +#include "agg_pixfmt_rgba.h" +#include "agg_pixfmt_rgb_packed.h" + +#include "agg2d.h" + +typedef agg::rgba8 AggColor; + +namespace agg +{ + //NOTE - these blenders are necessary to change the rgb order from the defaults, which are incorrect for us + + //this custom blender does more correct blending math than the default + //which is necessary or else drawing transparent pixels on (31,31,31) will yield (30,30,30) + struct my_blender_rgb555_pre + { + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + //not sure whether this is right... + alpha = color_type::base_mask - alpha; + pixel_type rgb = *p; + calc_type b = (rgb >> 10) & 31; + calc_type g = (rgb >> 5) & 31; + calc_type r = (rgb ) & 31; + b = ((b+1)*(alpha+1) + (cb)*(cover)-1)>>8; + g = ((g+1)*(alpha+1) + (cg)*(cover)-1)>>8; + r = ((r+1)*(alpha+1) + (cr)*(cover)-1)>>8; + *p = (b<<10)|(g<<5)|r; + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xF8) << 7) | + ((g & 0xF8) << 2) | + (r >> 3) | 0x8000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 3) & 0xF8, + (p >> 2) & 0xF8, + (p >> 7) & 0xF8); + } + }; + + struct my_blender_rgb555 + { + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type b = (rgb >> 7) & 0xF8; + calc_type g = (rgb >> 2) & 0xF8; + calc_type r = (rgb << 3) & 0xF8; + *p = (pixel_type) + (((((cb - b) * alpha + (b << 8)) >> 1) & 0x7C00) | + ((((cg - g) * alpha + (g << 8)) >> 6) & 0x03E0) | + (((cr - r) * alpha + (r << 8)) >> 11) | 0x8000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xF8) << 7) | + ((g & 0xF8) << 2) | + (r >> 3) | 0x8000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 3) & 0xF8, + (p >> 2) & 0xF8, + (p >> 7) & 0xF8); + + } + }; + + //this is a prototype span generator which should be able to generate 8888 and 555 spans + //it would be used in agg2d.inl renderImage() + //but it isn't being used yet. + //this will need to be completed before we can use 555 as a source imge + template class span_simple_blur_rgb24 + { + public: + //-------------------------------------------------------------------- + typedef rgba8 color_type; + + //-------------------------------------------------------------------- + span_simple_blur_rgb24() : m_source_image(0) {} + + //-------------------------------------------------------------------- + span_simple_blur_rgb24(const rendering_buffer& src) : + m_source_image(&src) {} + + //-------------------------------------------------------------------- + void source_image(const rendering_buffer& src) { m_source_image = &src; } + const rendering_buffer& source_image() const { return *m_source_image; } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, int len) + { + if(y < 1 || y >= int(m_source_image->height() - 1)) + { + do + { + *span++ = rgba8(0,0,0,0); + } + while(--len); + return; + } + + do + { + int color[4]; + color[0] = color[1] = color[2] = color[3] = 0; + if(x > 0 && x < int(m_source_image->width()-1)) + { + int i = 3; + do + { + const int8u* ptr = m_source_image->row_ptr(y - i + 2) + (x - 1) * 3; + + color[0] += *ptr++; + color[1] += *ptr++; + color[2] += *ptr++; + color[3] += 255; + + color[0] += *ptr++; + color[1] += *ptr++; + color[2] += *ptr++; + color[3] += 255; + + color[0] += *ptr++; + color[1] += *ptr++; + color[2] += *ptr++; + color[3] += 255; + } + while(--i); + color[0] /= 9; + color[1] /= 9; + color[2] /= 9; + color[3] /= 9; + } + *span++ = rgba8(color[Order::R], color[Order::G], color[Order::B], color[3]); + ++x; + } + while(--len); + } + + private: + const rendering_buffer* m_source_image; + }; + + typedef pixfmt_alpha_blend_rgb_packed my_pixfmt_rgb555_pre; //----pixfmt_rgb555_pre + + typedef pixfmt_alpha_blend_rgb_packed my_pixfmt_rgb555; //----pixfmt_rgb555_pre +} + + + +typedef PixFormatSetDeclaration > T_AGG_PF_RGB555; +typedef PixFormatSetDeclaration > T_AGG_PF_RGBA; +class AggDrawTarget +{ +public: + AggDrawTarget() + : empty(true) + { + } + +protected: + void dirty() { empty = false; } + void undirty() { empty = true; } + +public: + + bool empty; + + virtual void clear() = 0; + + virtual agg::rendering_buffer & buf() = 0; + + //returns an image for this target. you must provide the pixel type, but if it is wrong, + //then you have just created trouble for yourself + AGG2D_IMAGE_TEMPLATE TIMAGE image() { return TIMAGE(buf()); } + + // Setup + virtual void attach(unsigned char* buf, unsigned width, unsigned height, int stride) = 0; +// virtual void attach(Agg2DBase::Image& img) {attach(img);}; + + virtual void clipBox(double x1, double y1, double x2, double y2) = 0; + virtual Agg2DBase::RectD clipBox() const = 0; + + virtual void clearAll(AggColor c) = 0; + virtual void clearAll(unsigned r, unsigned g, unsigned b, unsigned a = 255) = 0; + + virtual void clearClipBox(AggColor c) = 0; + virtual void clearClipBox(unsigned r, unsigned g, unsigned b, unsigned a = 255) = 0; + +// virtual unsigned width() const { return Agg2DBase::m_rbuf.width(); } +// virtual unsigned height() const { return Agg2DBase::m_rbuf.height(); } + + // Conversions + virtual void worldToScreen(double& x, double& y) const = 0; + virtual void screenToWorld(double& x, double& y) const = 0; + virtual double worldToScreen(double scalar) const = 0; + virtual double screenToWorld(double scalar) const = 0; + virtual void alignPoint(double& x, double& y) const = 0; + virtual bool inBox(double worldX, double worldY) const = 0; + + // General Attributes + virtual void blendMode(Agg2DBase::BlendMode m) = 0; + virtual Agg2DBase::BlendMode blendMode() = 0; + + virtual void imageBlendMode(Agg2DBase::BlendMode m) = 0; + virtual Agg2DBase::BlendMode imageBlendMode() = 0; + + virtual void imageBlendColor(AggColor c) = 0; + virtual void imageBlendColor(unsigned r, unsigned g, unsigned b, unsigned a = 255) = 0; + virtual AggColor imageBlendColor() = 0; + + virtual void masterAlpha(double a) = 0; + virtual double masterAlpha() = 0; + + virtual void antiAliasGamma(double g) = 0; + virtual double antiAliasGamma() = 0; + +// virtual void font(const agg::int8u* font) { m_font = font; } +// const agg::int8u* font() { return m_font; } + + virtual void fillColor(AggColor c) = 0; + virtual void fillColor(unsigned r, unsigned g, unsigned b, unsigned a = 255) = 0; + virtual void noFill() = 0; + + virtual void lineColor(AggColor c) = 0; + virtual void lineColor(unsigned r, unsigned g, unsigned b, unsigned a = 255) = 0; + virtual void noLine() = 0; + + virtual void transformImage(const Agg2DBase::Image &img, double dstX1, double dstY1, double dstX2, double dstY2) = 0; + //virtual void transformImage(const Agg2DBase::Image &img, double dstX1, double dstY1, double dstX2, double dstY2) = 0; + + virtual AggColor fillColor() = 0; + virtual AggColor lineColor() = 0; + + virtual void fillLinearGradient(double x1, double y1, double x2, double y2, AggColor c1, AggColor c2, double profile=1.0) = 0; + virtual void lineLinearGradient(double x1, double y1, double x2, double y2, AggColor c1, AggColor c2, double profile=1.0) = 0; + + virtual void fillRadialGradient(double x, double y, double r, AggColor c1, AggColor c2, double profile=1.0) = 0; + virtual void lineRadialGradient(double x, double y, double r, AggColor c1, AggColor c2, double profile=1.0) = 0; + + virtual void fillRadialGradient(double x, double y, double r, AggColor c1, AggColor c2, AggColor c3) = 0; + virtual void lineRadialGradient(double x, double y, double r, AggColor c1, AggColor c2, AggColor c3) = 0; + + virtual void fillRadialGradient(double x, double y, double r) = 0; + virtual void lineRadialGradient(double x, double y, double r) = 0; + + virtual void lineWidth(double w) = 0; + virtual double lineWidth() = 0; + + virtual void lineCap(Agg2DBase::LineCap cap) = 0; + virtual Agg2DBase::LineCap lineCap() = 0; + + virtual void lineJoin(Agg2DBase::LineJoin join) = 0; + virtual Agg2DBase::LineJoin lineJoin() = 0; + + virtual void fillEvenOdd(bool evenOddFlag) = 0; + virtual bool fillEvenOdd() = 0; + + // Transformations + virtual Agg2DBase::Transformations transformations() = 0; + virtual void transformations(const Agg2DBase::Transformations& tr) = 0; + + virtual const Agg2DBase::Affine& affine() = 0; +// virtual void affine(const Agg2DBase::Affine&) = 0; + + virtual void resetTransformations() = 0; + virtual void matrix(const Agg2DBase::Affine& tr) = 0; + virtual void matrix(const Agg2DBase::Transformations& tr) = 0; + virtual void rotate(double angle) = 0; + virtual void rotate(double angle, double cx, double cy) = 0; + virtual void scale(double s) = 0; + virtual void scale(double sx, double sy) = 0; + virtual void skew(double sx, double sy) = 0; + virtual void translate(double x, double y) = 0; + virtual void parallelogram(double x1, double y1, double x2, double y2, const double* para) = 0; + virtual void viewport(double worldX1, double worldY1, double worldX2, double worldY2, double screenX1, double screenY1, double screenX2, double screenY2, Agg2DBase::ViewportOption opt=Agg2DBase::XMidYMid, Agg2DBase::WindowFitLogic fl = Agg2DBase::WindowFitLogic_meet) = 0; + + // Basic Shapes + virtual void line(double x1, double y1, double x2, double y2) = 0; + virtual void triangle(double x1, double y1, double x2, double y2, double x3, double y3) = 0; + virtual void rectangle(double x1, double y1, double x2, double y2) = 0; + virtual void roundedRect(double x1, double y1, double x2, double y2, double r) = 0; + virtual void roundedRect(double x1, double y1, double x2, double y2, double rx, double ry) = 0; + virtual void roundedRect(double x1, double y1, double x2, double y2, double rxBottom, double ryBottom, double rxTop, double ryTop) = 0; + virtual void ellipse(double cx, double cy, double rx, double ry) = 0; + virtual void arc(double cx, double cy, double rx, double ry, double start, double sweep) = 0; + virtual void star(double cx, double cy, double r1, double r2, double startAngle, int numRays) = 0; + virtual void curve(double x1, double y1, double x2, double y2, double x3, double y3) = 0; + virtual void curve(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) = 0; + virtual void polygon(double* xy, int numPoints) = 0; + virtual void polyline(double* xy, int numPoints) = 0; + + // Path commands + virtual void resetPath() = 0; + + virtual void moveTo(double x, double y)= 0; + virtual void moveRel(double dx, double dy) = 0; + + virtual void lineTo(double x, double y) = 0; + virtual void lineRel(double dx, double dy) = 0; + + virtual void horLineTo(double x) = 0; + virtual void horLineRel(double dx) = 0; + + virtual void verLineTo(double y) = 0; + virtual void verLineRel(double dy) = 0; + + virtual void arcTo(double rx, double ry,double angle, bool largeArcFlag,bool sweepFlag,double x, double y) = 0; + + virtual void arcRel(double rx, double ry,double angle, bool largeArcFlag,bool sweepFlag,double dx, double dy) = 0; + + virtual void quadricCurveTo(double xCtrl, double yCtrl,double xTo, double yTo) = 0; + virtual void quadricCurveRel(double dxCtrl, double dyCtrl,double dxTo, double dyTo) = 0; + virtual void quadricCurveTo(double xTo, double yTo) = 0; + virtual void quadricCurveRel(double dxTo, double dyTo) = 0; + + virtual void cubicCurveTo(double xCtrl1, double yCtrl1,double xCtrl2, double yCtrl2,double xTo, double yTo) = 0; + virtual void cubicCurveRel(double dxCtrl1, double dyCtrl1,double dxCtrl2, double dyCtrl2,double dxTo, double dyTo) = 0; + virtual void cubicCurveTo(double xCtrl2, double yCtrl2,double xTo, double yTo) = 0; + virtual void cubicCurveRel(double xCtrl2, double yCtrl2,double xTo, double yTo) = 0; + + virtual void addEllipse(double cx, double cy, double rx, double ry, Agg2DBase::Direction dir) = 0; + virtual void closePolygon() = 0; + + virtual void drawPath(Agg2DBase::DrawPathFlag flag = Agg2DBase::FillAndStroke) = 0; +// virtual void drawPathNoTransform(Agg2DBase::DrawPathFlag flag = Agg2DBase::FillAndStroke) = 0; + + // Image Transformations + virtual void imageFilter(Agg2DBase::ImageFilter f) = 0; + virtual Agg2DBase::ImageFilter imageFilter() = 0; + + virtual void imageResample(Agg2DBase::ImageResample f) = 0; + virtual Agg2DBase::ImageResample imageResample() = 0; + static const agg::int8u* lookupFont(const std::string& name); + virtual void setFont(const std::string& name) = 0; + virtual void renderText(double dstX, double dstY, const std::string& str) = 0; + virtual void renderTextDropshadowed(double dstX, double dstY, const std::string& str) + { + AggColor lineColorOld = lineColor(); + if(lineColorOld.r+lineColorOld.g+lineColorOld.b<192) + lineColor(255-lineColorOld.r,255-lineColorOld.g,255-lineColorOld.b); + else + lineColor(0,0,0); + renderText(dstX-1,dstY-1,str); + renderText(dstX,dstY-1,str); + renderText(dstX+1,dstY-1,str); + renderText(dstX-1,dstY,str); + renderText(dstX+1,dstY,str); + renderText(dstX-1,dstY+1,str); + renderText(dstX,dstY+1,str); + renderText(dstX+1,dstY+1,str); + lineColor(lineColorOld); + renderText(dstX,dstY,str); + } + + + // Auxiliary + virtual double pi() { return agg::pi; } + virtual double deg2Rad(double v) { return v * agg::pi / 180.0; } + virtual double rad2Deg(double v) { return v * 180.0 / agg::pi; } +}; + + +template +class AggDrawTargetImplementation : public AggDrawTarget, public Agg2D +{ +public: + typedef typename PixFormatSet::PixFormat pixfmt; + typedef typename pixfmt::color_type color_type; + + typedef Agg2D BASE; + AggDrawTargetImplementation(agg::int8u* buf, int width, int height, int stride) + { + BASE::attach(buf,width,height,stride); + + BASE::viewport(0, 0, width-1, height-1, 0, 0, width-1, height-1, TAGG2D::Anisotropic); + } + + virtual void clear() { + if(!empty) + { + BASE::clearAll(0,0,0,0); + undirty(); + } + } + + virtual agg::rendering_buffer & buf() { dirty(); return BASE::buf(); } // buf() might not always require calling dirty() + typename BASE::MyImage image() { return BASE::MyImage(buf()); } + + // Setup + virtual void attach(unsigned char* buf, unsigned width, unsigned height, int stride) {BASE::attach(buf, width, height, stride);}; +// virtual void attach(Agg2DBase::Image& img) {attach(img);}; + + virtual void clipBox(double x1, double y1, double x2, double y2) { BASE::clipBox(x1,y1,x2,y2); } + virtual Agg2DBase::RectD clipBox() const {return BASE::clipBox();}; + + virtual void clearAll(AggColor c) {BASE::clearAll(c);}; + virtual void clearAll(unsigned r, unsigned g, unsigned b, unsigned a = 255) {BASE::clearAll(r, g, b, a);}; + + virtual void clearClipBox(AggColor c) {BASE::clearClipBox(c);}; + virtual void clearClipBox(unsigned r, unsigned g, unsigned b, unsigned a = 255) {BASE::clearClipBox(r, g, b, a);}; + +// virtual unsigned width() const { return Agg2DBase::m_rbuf.width(); } +// virtual unsigned height() const { return Agg2DBase::m_rbuf.height(); } + + // Conversions + virtual void worldToScreen(double& x, double& y) const {BASE::worldToScreen(x, y);}; + virtual void screenToWorld(double& x, double& y) const {BASE::screenToWorld(x, y);}; + virtual double worldToScreen(double scalar) const {return BASE::worldToScreen(scalar);}; + virtual double screenToWorld(double scalar) const {return BASE::screenToWorld(scalar);}; + virtual void alignPoint(double& x, double& y) const {BASE::alignPoint(x, y);}; + virtual bool inBox(double worldX, double worldY) const {return BASE::inBox(worldX, worldY);}; + + // General Attributes + virtual void blendMode(Agg2DBase::BlendMode m) {BASE::blendMode(m);}; + virtual Agg2DBase::BlendMode blendMode() {return BASE::blendMode();}; + + virtual void imageBlendMode(Agg2DBase::BlendMode m) {BASE::imageBlendMode(m);}; + virtual Agg2DBase::BlendMode imageBlendMode() {return BASE::imageBlendMode();}; + + virtual void imageBlendColor(AggColor c) {BASE::imageBlendColor(c);}; + virtual void imageBlendColor(unsigned r, unsigned g, unsigned b, unsigned a = 255) {BASE::imageBlendColor(r, g, b, a);}; + virtual AggColor imageBlendColor() {return BASE::imageBlendColor();}; + + virtual void masterAlpha(double a) {BASE::masterAlpha(a);}; + virtual double masterAlpha() {return BASE::masterAlpha();}; + + virtual void antiAliasGamma(double g) {BASE::antiAliasGamma(g);}; + virtual double antiAliasGamma() {return BASE::antiAliasGamma();}; + +// virtual void font(const agg::int8u* font) { m_font = font; } +// const agg::int8u* font() { return m_font; } + + virtual void fillColor(AggColor c) {BASE::fillColor(c);}; + virtual void fillColor(unsigned r, unsigned g, unsigned b, unsigned a = 255) {BASE::fillColor(r,g,b,a);}; + virtual void noFill() {BASE::noFill();}; + + virtual void lineColor(AggColor c) {BASE::lineColor(c);}; + virtual void lineColor(unsigned r, unsigned g, unsigned b, unsigned a = 255) {BASE::lineColor(r,g,b,a);}; + virtual void noLine() {BASE::noLine();}; + + virtual AggColor fillColor() {return BASE::fillColor();}; + virtual AggColor lineColor() {return BASE::lineColor();}; + + virtual void fillLinearGradient(double x1, double y1, double x2, double y2, AggColor c1, AggColor c2, double profile=1.0) {dirty(); BASE::fillLinearGradient(x1, y1, x2, y2, c1, c2, profile);}; + virtual void lineLinearGradient(double x1, double y1, double x2, double y2, AggColor c1, AggColor c2, double profile=1.0) {dirty(); BASE::lineLinearGradient(x1, y1, x2, y2, c1, c2, profile);}; + + virtual void fillRadialGradient(double x, double y, double r, AggColor c1, AggColor c2, double profile=1.0) {dirty(); BASE::fillRadialGradient(x, y, r, c1, c2, profile);}; + virtual void lineRadialGradient(double x, double y, double r, AggColor c1, AggColor c2, double profile=1.0) {dirty(); BASE::lineRadialGradient(x, y, r, c1, c2, profile);}; + + virtual void fillRadialGradient(double x, double y, double r, AggColor c1, AggColor c2, AggColor c3) {dirty(); BASE::fillRadialGradient(x, y, r, c1, c2, c3);}; + virtual void lineRadialGradient(double x, double y, double r, AggColor c1, AggColor c2, AggColor c3) {dirty(); BASE::lineRadialGradient(x, y, r, c1, c2, c3);}; + virtual void fillRadialGradient(double x, double y, double r) {dirty(); BASE::fillRadialGradient(x, y, r);}; + virtual void lineRadialGradient(double x, double y, double r) {dirty(); BASE::lineRadialGradient(x, y, r);}; + + virtual void lineWidth(double w) {BASE::lineWidth(w);}; + virtual double lineWidth() {return BASE::lineWidth();}; + + virtual void lineCap(Agg2DBase::LineCap cap) {BASE::lineCap(cap);}; + virtual Agg2DBase::LineCap lineCap() {return BASE::lineCap();}; + + virtual void lineJoin(Agg2DBase::LineJoin join) {BASE::lineJoin(join);}; + virtual Agg2DBase::LineJoin lineJoin() {return BASE::lineJoin();}; + + virtual void fillEvenOdd(bool evenOddFlag) {BASE::fillEvenOdd(evenOddFlag);}; + virtual bool fillEvenOdd() {return BASE::fillEvenOdd();}; + + virtual void transformImage(const Agg2DBase::Image& img, double dstX1, double dstY1, double dstX2, double dstY2) { BASE::transformImage(img,dstX1,dstY1,dstX2,dstY2); } + //virtual void transformImage(const Agg2DBase::Image &img, double dstX1, double dstY1, double dstX2, double dstY2) { BASE::transformImage(img,dstX1,dstY1,dstX2,dstY2); } + + // Transformations + virtual Agg2DBase::Transformations transformations() {return BASE::transformations();}; + virtual void transformations(const Agg2DBase::Transformations& tr) {BASE::transformations(tr);}; + + virtual const Agg2DBase::Affine& affine() {return BASE::affine();}; +// virtual void affine(const Agg2DBase::Affine&) {BASE::affine();}; + + virtual void resetTransformations() {BASE::resetTransformations();}; + virtual void matrix(const Agg2DBase::Affine& tr) {BASE::matrix(tr);}; + virtual void matrix(const Agg2DBase::Transformations& tr) {BASE::matrix(tr);}; + virtual void rotate(double angle) {BASE::rotate(angle);}; + virtual void rotate(double angle, double cx, double cy) {BASE::rotate(angle, cx, cy);}; + virtual void scale(double s) {BASE::scale(s);}; + virtual void scale(double sx, double sy) {BASE::scale(sx, sy);}; + virtual void skew(double sx, double sy) {BASE::skew(sx, sy);}; + virtual void translate(double x, double y) {BASE::translate(x, y);}; + virtual void parallelogram(double x1, double y1, double x2, double y2, const double* para) {BASE::parallelogram(x1, y1, x2, y2, para);}; + virtual void viewport(double worldX1, double worldY1, double worldX2, double worldY2, double screenX1, double screenY1, double screenX2, double screenY2, Agg2DBase::ViewportOption opt=Agg2DBase::XMidYMid, Agg2DBase::WindowFitLogic fl = Agg2DBase::WindowFitLogic_meet) {BASE::viewport(worldX1, worldY1, worldX2, worldY2, screenX1, screenY1, screenX2, screenY2, opt, fl);}; + + // Basic Shapes + virtual void line(double x1, double y1, double x2, double y2) {dirty(); BASE::line(x1, y1, x2, y2);}; + virtual void triangle(double x1, double y1, double x2, double y2, double x3, double y3) {dirty(); BASE::triangle(x1, y1, x2, y2, x3, y3);}; + virtual void rectangle(double x1, double y1, double x2, double y2) {dirty(); BASE::rectangle(x1, y1, x2, y2);}; + virtual void roundedRect(double x1, double y1, double x2, double y2, double r) { dirty(); BASE::roundedRect(x1,y1,x2,y2,r); } + virtual void roundedRect(double x1, double y1, double x2, double y2, double rx, double ry) { dirty(); BASE::roundedRect(x1,y1,x2,y2,rx,ry); } + virtual void roundedRect(double x1, double y1, double x2, double y2,double rx_bottom, double ry_bottom,double rx_top,double ry_top) { dirty(); BASE::roundedRect(x1,y1,x2,y2,rx_bottom,ry_bottom,rx_top,ry_top); } + virtual void ellipse(double cx, double cy, double rx, double ry) {dirty(); BASE::ellipse(cx, cy, rx, ry);} + virtual void arc(double cx, double cy, double rx, double ry, double start, double sweep) {dirty(); BASE::arc(cx, cy, rx, ry, start, sweep);}; + virtual void star(double cx, double cy, double r1, double r2, double startAngle, int numRays) {dirty(); BASE::star(cx, cy, r1, r2, startAngle, numRays);}; + virtual void curve(double x1, double y1, double x2, double y2, double x3, double y3) {dirty(); BASE::curve(x1, y1, x2, y2, x3, y3);}; + virtual void curve(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) {dirty(); BASE::curve(x1, y1, x2, y2, x3, y3, x4, y4);}; + virtual void polygon(double* xy, int numPoints) {dirty(); BASE::polygon(xy, numPoints);}; + virtual void polyline(double* xy, int numPoints) {dirty(); BASE::polyline(xy, numPoints);}; + + virtual void setFont(const std::string& name) { BASE::font(lookupFont(name)); } + virtual void renderText(double dstX, double dstY, const std::string& str) { + dirty(); + int height = BASE::font()[0]; + int base = BASE::font()[1]; + int offset = height-base*2; + BASE::renderText(dstX, dstY + offset, str); + } + + // Path commands + virtual void resetPath() {BASE::resetPath();}; + + virtual void moveTo(double x, double y) {BASE::moveTo(x, y);} + virtual void moveRel(double dx, double dy) {BASE::moveRel(dx,dy);}; + + virtual void lineTo(double x, double y) {BASE::lineTo(x, y);}; + virtual void lineRel(double dx, double dy) {BASE::lineRel(dx, dy);}; + + virtual void horLineTo(double x) {BASE::horLineTo(x);}; + virtual void horLineRel(double dx) {BASE::horLineRel(dx);}; + + virtual void verLineTo(double y) {BASE::verLineTo(y);}; + virtual void verLineRel(double dy) {BASE::verLineRel(dy);}; + + virtual void arcTo(double rx, double ry, double angle, bool largeArcFlag, bool sweepFlag, double x, double y) {BASE::arcTo(rx, ry, angle, largeArcFlag, sweepFlag, x, y);}; + + virtual void arcRel(double rx, double ry, double angle, bool largeArcFlag, bool sweepFlag, double dx, double dy) {BASE::arcRel(rx, ry, angle, largeArcFlag, sweepFlag, dx, dy);}; + + virtual void quadricCurveTo(double xCtrl, double yCtrl, double xTo, double yTo) {BASE::quadricCurveTo(xCtrl, yCtrl, xTo, yTo);}; + virtual void quadricCurveRel(double dxCtrl, double dyCtrl, double dxTo, double dyTo) {BASE::quadricCurveRel(dxCtrl, dyCtrl, dxTo, dyTo);}; + virtual void quadricCurveTo(double xTo, double yTo) {BASE::quadricCurveTo(xTo, yTo);}; + virtual void quadricCurveRel(double dxTo, double dyTo) {BASE::quadricCurveRel(dxTo, dyTo);}; + + virtual void cubicCurveTo(double xCtrl1, double yCtrl1, double xCtrl2, double yCtrl2, double xTo, double yTo) {BASE::cubicCurveTo(xCtrl1, yCtrl1, xCtrl2, yCtrl2, xTo, yTo);}; + virtual void cubicCurveRel(double dxCtrl1, double dyCtrl1, double dxCtrl2, double dyCtrl2, double dxTo, double dyTo) {BASE::cubicCurveRel(dxCtrl1, dyCtrl1, dxCtrl2, dyCtrl2, dxTo, dyTo);}; + virtual void cubicCurveTo(double xCtrl2, double yCtrl2, double xTo, double yTo) {BASE::cubicCurveTo(xCtrl2, yCtrl2, xTo, yTo);}; + virtual void cubicCurveRel(double xCtrl2, double yCtrl2, double xTo, double yTo) {BASE::cubicCurveRel(xCtrl2, yCtrl2, xTo, yTo);}; + + virtual void addEllipse(double cx, double cy, double rx, double ry, Agg2DBase::Direction dir) {BASE::addEllipse(cx, cy, rx, ry, dir);}; + virtual void closePolygon() {BASE::closePolygon();}; + + virtual void drawPath(Agg2DBase::DrawPathFlag flag = Agg2DBase::FillAndStroke) {dirty(); BASE::drawPath(flag);}; +// virtual void drawPathNoTransform(DrawPathFlag flag = FillAndStroke) {dirty(); BASE::drawPathNoTransform(flag);}; + + // Image Transformations + virtual void imageFilter(Agg2DBase::ImageFilter f) {BASE::imageFilter(f);}; + virtual Agg2DBase::ImageFilter imageFilter() {return BASE::imageFilter();}; + + virtual void imageResample(Agg2DBase::ImageResample f) {BASE::imageResample(f);}; + virtual Agg2DBase::ImageResample imageResample() {return BASE::imageResample();}; + + // Auxiliary + virtual double pi() { return agg::pi; } + virtual double deg2Rad(double v) { return v * agg::pi / 180.0; } + virtual double rad2Deg(double v) { return v * 180.0 / agg::pi; } +}; + +//the main aggdraw targets for different pixel formats +typedef AggDrawTargetImplementation T_AGG_RGB555; +typedef AggDrawTargetImplementation T_AGG_RGBA; + + +class AggDraw +{ +public: + AggDraw() + : target(NULL) + {} + AggDrawTarget *target; +}; + +enum AggTarget +{ + AggTarget_Screen = 0, + AggTarget_Hud = 1, + AggTarget_Lua = 2, +}; + +//specialized instance for desmume; should eventually move to another file +class AggDraw_Desmume : public AggDraw +{ +public: + void setTarget(AggTarget newTarget); + //void composite(void* dest); + + AggDrawTarget *screen, *hud, *lua; +}; + +extern AggDraw_Desmume aggDraw; + +void Agg_init(); + +struct font_type +{ + const agg::int8u* font; + const char* name; +}; +extern font_type fonts_list[]; +extern int font_Nums; +#endif diff --git a/jni/desmume/src/android/agg/.goutputstream-22I3IW b/jni/desmume/src/android/agg/.goutputstream-22I3IW new file mode 100755 index 0000000..c9988d3 --- /dev/null +++ b/jni/desmume/src/android/agg/.goutputstream-22I3IW @@ -0,0 +1,5 @@ +# Android ndk for agg-2.5 +# http://www.antigrain.com/ + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) diff --git a/jni/desmume/src/android/agg/.goutputstream-28N3IW b/jni/desmume/src/android/agg/.goutputstream-28N3IW new file mode 100755 index 0000000..102dfa5 --- /dev/null +++ b/jni/desmume/src/android/agg/.goutputstream-28N3IW @@ -0,0 +1,46 @@ +# Android ndk for agg-2.5 +# http://www.antigrain.com/ + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := agg +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include +LOCAL_SRC_FILES := src/agg_arc.cpp \ + src/agg_arrowhead.cpp \ + src/agg_bezier_arc.cpp \ + src/agg_bspline.cpp \ + src/agg_curves.cpp \ + src/agg_embedded_raster_fonts.cpp \ + src/agg_gsv_text.cpp \ + src/agg_image_filters.cpp \ + src/agg_line_aa_basics.cpp \ + src/agg_line_profile_aa.cpp \ + src/agg_rounded_rect.cpp \ + src/agg_sqrt_tables.cpp \ + src/agg_trans_affine.cpp \ + src/agg_trans_double_path.cpp \ + src/agg_trans_single_path.cpp \ + src/agg_trans_warp_magnifier.cpp \ + src/agg_vcgen_bspline.cpp \ + src/agg_vcgen_contour.cpp \ + src/agg_vcgen_dash.cpp \ + src/agg_vcgen_markers_term.cpp \ + src/agg_vcgen_smooth_poly1.cpp \ + src/agg_vcgen_stroke.cpp \ + src/agg_vpgen_clip_polygon.cpp \ + src/agg_vpgen_clip_polyline.cpp \ + src/agg_vpgen_segmentator.cpp \ + src/ctrl/agg_bezier_ctrl.cpp \ + src/ctrl/agg_cbox_ctrl.cpp \ + src/ctrl/agg_gamma_ctrl.cpp \ + src/ctrl/agg_gamma_spline.cpp \ + src/ctrl/agg_polygon_ctrl.cpp \ + src/ctrl/agg_rbox_ctrl.cpp \ + src/ctrl/agg_scale_ctrl.cpp \ + src/ctrl/agg_slider_ctrl.cpp \ + src/ctrl/agg_spline_ctrl.cpp +include $(BUILD_STATIC_LIBRARY) + + + diff --git a/jni/desmume/src/android/agg/.goutputstream-2CUYIW b/jni/desmume/src/android/agg/.goutputstream-2CUYIW new file mode 100755 index 0000000..eaf1808 --- /dev/null +++ b/jni/desmume/src/android/agg/.goutputstream-2CUYIW @@ -0,0 +1,46 @@ +# Android ndk for agg-2.5 +# http://www.antigrain.com/ + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := agg +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include +LOCAL_SRC_FILES := src/agg_arc.cpp \ + src/agg_arrowhead.cpp \ + src/agg_bezier_arc.cpp \ + src/agg_bspline.cpp \ + src/agg_curves.cpp \ + src/agg_embedded_raster_fonts.cpp \ + src/agg_gsv_text.cpp \ + src/agg_image_filters.cpp \ + src/agg_line_aa_basics.cpp \ + src/agg_line_profile_aa.cpp \ + src/agg_rounded_rect.cpp \ + src/agg_sqrt_tables.cpp \ + src/agg_trans_affine.cpp \ + src/agg_trans_double_path.cpp \ + src/agg_trans_single_path.cpp \ + src/agg_trans_warp_magnifier.cpp \ + src/agg_vcgen_bspline.cpp \ + src/agg_vcgen_contour.cpp \ + src/agg_vcgen_dash.cpp \ + src/agg_vcgen_markers_term.cpp \ + src/agg_vcgen_smooth_poly1.cpp \ + src/agg_vcgen_stroke.cpp \ + src/agg_vpgen_clip_polygon.cpp \ + src/agg_vpgen_clip_polyline.cpp \ + src/agg_vpgen_segmentator.cpp \ + src/ctrl/agg_bezier_ctrl.cpp \ + src/ctrl/agg_cbox_ctrl.cpp \ + src/ctrl/agg_gamma_ctrl.cpp \ + src/ctrl/agg_gamma_spline.cpp \ + src/ctrl/agg_polygon_ctrl.cpp \ + src/ctrl/agg_rbox_ctrl.cpp \ + src/ctrl/agg_scale_ctrl.cpp \ + src/ctrl/agg_slider_ctrl.cpp \ + src/ctrl/agg_spline_ctrl.cpp + + + + diff --git a/jni/desmume/src/android/agg/.goutputstream-8XDWIW b/jni/desmume/src/android/agg/.goutputstream-8XDWIW new file mode 100755 index 0000000..8a05be9 --- /dev/null +++ b/jni/desmume/src/android/agg/.goutputstream-8XDWIW @@ -0,0 +1,46 @@ +# Android ndk for agg-2.5 +# http://www.antigrain.com/ + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := agg +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include +LOCAL_SRC_FILES := src/agg_arc.cpp \ + src/agg_arrowhead.cpp \ + src/agg_bezier_arc.cpp \ + src/agg_bspline.cpp \ + src/agg_curves.cpp \ + src/agg_embedded_raster_fonts.cpp \ + src/agg_gsv_text.cpp \ + src/agg_image_filters.cpp \ + src/agg_line_aa_basics.cpp \ + src/agg_line_profile_aa.cpp \ + src/agg_rounded_rect.cpp \ + src/agg_sqrt_tables.cpp \ + src/agg_trans_affine.cpp \ + src/agg_trans_double_path.cpp \ + src/agg_trans_single_path.cpp \ + src/agg_trans_warp_magnifier.cpp \ + src/agg_vcgen_bspline.cpp \ + src/agg_vcgen_contour.cpp \ + src/agg_vcgen_dash.cpp \ + src/agg_vcgen_markers_term.cpp \ + src/agg_vcgen_smooth_poly1.cpp \ + src/agg_vcgen_stroke.cpp \ + src/agg_vpgen_clip_polygon.cpp \ + src/agg_vpgen_clip_polyline.cpp \ + src/agg_vpgen_segmentator.cpp \ + src/ctrl/agg_bezier_ctrl.cpp \ + src/ctrl/agg_cbox_ctrl.cpp \ + src/ctrl/agg_gamma_ctrl.cpp \ + src/ctrl/agg_gamma_spline.cpp \ + src/ctrl/agg_polygon_ctrl.cpp \ + src/ctrl/agg_rbox_ctrl.cpp \ + src/ctrl/agg_scale_ctrl.cpp \ + src/ctrl/agg_slider_ctrl.cpp \ + src/ctrl/agg_spline_ctrl.cpp + +$include (BUILD_STATIC_LIBRARY) + + diff --git a/jni/desmume/src/android/agg/.goutputstream-GGU6IW b/jni/desmume/src/android/agg/.goutputstream-GGU6IW new file mode 100755 index 0000000..8aa7c21 --- /dev/null +++ b/jni/desmume/src/android/agg/.goutputstream-GGU6IW @@ -0,0 +1,46 @@ +# Android ndk for agg-2.5 +# http://www.antigrain.com/ + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := agg +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include +LOCAL_SRC_FILES := src/agg_arc.cpp \ + src/agg_arrowhead.cpp \ + src/agg_bezier_arc.cpp \ + src/agg_bspline.cpp \ + src/agg_curves.cpp \ + src/agg_embedded_raster_fonts.cpp \ + src/agg_gsv_text.cpp \ + src/agg_image_filters.cpp \ + src/agg_line_aa_basics.cpp \ + src/agg_line_profile_aa.cpp \ + src/agg_rounded_rect.cpp \ + src/agg_sqrt_tables.cpp \ + src/agg_trans_affine.cpp \ + src/agg_trans_double_path.cpp \ + src/agg_trans_single_path.cpp \ + src/agg_trans_warp_magnifier.cpp \ + src/agg_vcgen_bspline.cpp \ + src/agg_vcgen_contour.cpp \ + src/agg_vcgen_dash.cpp \ + src/agg_vcgen_markers_term.cpp \ + src/agg_vcgen_smooth_poly1.cpp \ + src/agg_vcgen_stroke.cpp \ + src/agg_vpgen_clip_polygon.cpp \ + src/agg_vpgen_clip_polyline.cpp \ + src/agg_vpgen_segmentator.cpp \ + src/ctrl/agg_bezier_ctrl.cpp \ + src/ctrl/agg_cbox_ctrl.cpp \ + src/ctrl/agg_gamma_ctrl.cpp \ + src/ctrl/agg_gamma_spline.cpp \ + src/ctrl/agg_polygon_ctrl.cpp \ + src/ctrl/agg_rbox_ctrl.cpp \ + src/ctrl/agg_scale_ctrl.cpp \ + src/ctrl/agg_slider_ctrl.cpp \ + src/ctrl/agg_spline_ctrl.cpp + +$include (BUILD_STATIC_LIBRARY) + + diff --git a/jni/desmume/src/android/agg/.goutputstream-I0SOIW b/jni/desmume/src/android/agg/.goutputstream-I0SOIW new file mode 100755 index 0000000..e18a3b0 --- /dev/null +++ b/jni/desmume/src/android/agg/.goutputstream-I0SOIW @@ -0,0 +1,46 @@ +# Android ndk for agg-2.5 +# http://www.antigrain.com/ + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := agg +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include +LOCAL_SRC_FILES := src/agg_arc.cpp \ + src/agg_arrowhead.cpp \ + src/agg_bezier_arc.cpp \ + src/agg_bspline.cpp \ + src/agg_curves.cpp \ + src/agg_embedded_raster_fonts.cpp \ + src/agg_gsv_text.cpp \ + src/agg_image_filters.cpp \ + src/agg_line_aa_basics.cpp \ + src/agg_line_profile_aa.cpp \ + src/agg_rounded_rect.cpp \ + src/agg_sqrt_tables.cpp \ + src/agg_trans_affine.cpp \ + src/agg_trans_double_path.cpp \ + src/agg_trans_single_path.cpp \ + src/agg_trans_warp_magnifier.cpp \ + src/agg_vcgen_bspline.cpp \ + src/agg_vcgen_contour.cpp \ + src/agg_vcgen_dash.cpp \ + src/agg_vcgen_markers_term.cpp \ + src/agg_vcgen_smooth_poly1.cpp \ + src/agg_vcgen_stroke.cpp \ + src/agg_vpgen_clip_polygon.cpp \ + src/agg_vpgen_clip_polyline.cpp \ + src/agg_vpgen_segmentator.cpp \ + src/ctrl/agg_bezier_ctrl.cpp \ + src/ctrl/agg_cbox_ctrl.cpp \ + src/ctrl/agg_gamma_ctrl.cpp \ + src/ctrl/agg_gamma_spline.cpp \ + src/ctrl/agg_polygon_ctrl.cpp \ + src/ctrl/agg_rbox_ctrl.cpp \ + src/ctrl/agg_scale_ctrl.cpp \ + src/ctrl/agg_slider_ctrl.cpp \ + src/ctrl/agg_spline_ctrl.cpp +include $(BUILD_SHARED_LIBRARY) + + + diff --git a/jni/desmume/src/android/agg/.goutputstream-JURNIW b/jni/desmume/src/android/agg/.goutputstream-JURNIW new file mode 100755 index 0000000..ed3fa43 --- /dev/null +++ b/jni/desmume/src/android/agg/.goutputstream-JURNIW @@ -0,0 +1,4 @@ +# Android ndk for agg-2.5 +# http://www.antigrain.com/ + + diff --git a/jni/desmume/src/android/agg/.goutputstream-KXM1IW b/jni/desmume/src/android/agg/.goutputstream-KXM1IW new file mode 100755 index 0000000..8a05be9 --- /dev/null +++ b/jni/desmume/src/android/agg/.goutputstream-KXM1IW @@ -0,0 +1,46 @@ +# Android ndk for agg-2.5 +# http://www.antigrain.com/ + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := agg +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include +LOCAL_SRC_FILES := src/agg_arc.cpp \ + src/agg_arrowhead.cpp \ + src/agg_bezier_arc.cpp \ + src/agg_bspline.cpp \ + src/agg_curves.cpp \ + src/agg_embedded_raster_fonts.cpp \ + src/agg_gsv_text.cpp \ + src/agg_image_filters.cpp \ + src/agg_line_aa_basics.cpp \ + src/agg_line_profile_aa.cpp \ + src/agg_rounded_rect.cpp \ + src/agg_sqrt_tables.cpp \ + src/agg_trans_affine.cpp \ + src/agg_trans_double_path.cpp \ + src/agg_trans_single_path.cpp \ + src/agg_trans_warp_magnifier.cpp \ + src/agg_vcgen_bspline.cpp \ + src/agg_vcgen_contour.cpp \ + src/agg_vcgen_dash.cpp \ + src/agg_vcgen_markers_term.cpp \ + src/agg_vcgen_smooth_poly1.cpp \ + src/agg_vcgen_stroke.cpp \ + src/agg_vpgen_clip_polygon.cpp \ + src/agg_vpgen_clip_polyline.cpp \ + src/agg_vpgen_segmentator.cpp \ + src/ctrl/agg_bezier_ctrl.cpp \ + src/ctrl/agg_cbox_ctrl.cpp \ + src/ctrl/agg_gamma_ctrl.cpp \ + src/ctrl/agg_gamma_spline.cpp \ + src/ctrl/agg_polygon_ctrl.cpp \ + src/ctrl/agg_rbox_ctrl.cpp \ + src/ctrl/agg_scale_ctrl.cpp \ + src/ctrl/agg_slider_ctrl.cpp \ + src/ctrl/agg_spline_ctrl.cpp + +$include (BUILD_STATIC_LIBRARY) + + diff --git a/jni/desmume/src/android/agg/.goutputstream-MN80IW b/jni/desmume/src/android/agg/.goutputstream-MN80IW new file mode 100755 index 0000000..8341e86 --- /dev/null +++ b/jni/desmume/src/android/agg/.goutputstream-MN80IW @@ -0,0 +1,44 @@ +# Android ndk for agg-2.5 +# http://www.antigrain.com/ + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := agg +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include +LOCAL_SRC_FILES := src/agg_arc.cpp \ + src/agg_arrowhead.cpp \ + src/agg_bezier_arc.cpp \ + src/agg_bspline.cpp \ + src/agg_curves.cpp \ + src/agg_embedded_raster_fonts.cpp \ + src/agg_gsv_text.cpp \ + src/agg_image_filters.cpp \ + src/agg_line_aa_basics.cpp \ + src/agg_line_profile_aa.cpp \ + src/agg_rounded_rect.cpp \ + src/agg_sqrt_tables.cpp \ + src/agg_trans_affine.cpp \ + src/agg_trans_double_path.cpp \ + src/agg_trans_single_path.cpp \ + src/agg_trans_warp_magnifier.cpp \ + src/agg_vcgen_bspline.cpp \ + src/agg_vcgen_contour.cpp \ + src/agg_vcgen_dash.cpp \ + src/agg_vcgen_markers_term.cpp \ + src/agg_vcgen_smooth_poly1.cpp \ + src/agg_vcgen_stroke.cpp \ + src/agg_vpgen_clip_polygon.cpp \ + src/agg_vpgen_clip_polyline.cpp \ + src/agg_vpgen_segmentator.cpp \ + src/ctrl/agg_bezier_ctrl.cpp \ + src/ctrl/agg_cbox_ctrl.cpp \ + src/ctrl/agg_gamma_ctrl.cpp \ + src/ctrl/agg_gamma_spline.cpp \ + src/ctrl/agg_polygon_ctrl.cpp \ + src/ctrl/agg_rbox_ctrl.cpp \ + src/ctrl/agg_scale_ctrl.cpp \ + src/ctrl/agg_slider_ctrl.cpp \ + src/ctrl/agg_spline_ctrl.cpp + + diff --git a/jni/desmume/src/android/agg/.goutputstream-PI2TIW b/jni/desmume/src/android/agg/.goutputstream-PI2TIW new file mode 100755 index 0000000..7eff1cd --- /dev/null +++ b/jni/desmume/src/android/agg/.goutputstream-PI2TIW @@ -0,0 +1,9 @@ +# Android ndk for agg-2.5 +# http://www.antigrain.com/ + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := agg +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include +LOCAL_SRC_FILES := diff --git a/jni/desmume/src/android/agg/ChangeLog b/jni/desmume/src/android/agg/ChangeLog new file mode 100755 index 0000000..9bc083f --- /dev/null +++ b/jni/desmume/src/android/agg/ChangeLog @@ -0,0 +1 @@ +Visit http://antigrain.com/news \ No newline at end of file diff --git a/jni/desmume/src/android/agg/Makefile b/jni/desmume/src/android/agg/Makefile new file mode 100755 index 0000000..fe0fe4c --- /dev/null +++ b/jni/desmume/src/android/agg/Makefile @@ -0,0 +1,9 @@ +all: lib + +src/libagg.a: + cd src; make + +lib: src/libagg.a + +clean: + cd src; make clean diff --git a/jni/desmume/src/android/agg/Makefile.AmigaOS b/jni/desmume/src/android/agg/Makefile.AmigaOS new file mode 100755 index 0000000..31011ec --- /dev/null +++ b/jni/desmume/src/android/agg/Makefile.AmigaOS @@ -0,0 +1,398 @@ +# +# Makefile for AmigaOS 4.0 +# + +CXX = g++ +CXXFLAGS = -mcrt=clib2 -O3 -Iinclude -Igpc -Ifont_freetype +CXXLIBS = -Llib -lagg +CC = gcc +CFLAGS = -mcrt=clib2 -O3 -Igpc +AR = ar +ARFLAGS = cr +STRIP = strip -R.comment + +LIBNAME = lib/libagg.a +SVGNAME = bin/svg_test + +EXAMPLES =\ +bin/aa_demo \ +bin/aa_test \ +bin/alpha_gradient \ +bin/alpha_mask \ +bin/alpha_mask2 \ +bin/alpha_mask3 \ +bin/bezier_div \ +bin/bspline \ +bin/circles \ +bin/component_rendering \ +bin/compositing \ +bin/compositing2 \ +bin/conv_contour \ +bin/conv_dash_marker \ +bin/conv_stroke \ +bin/distortions \ +bin/flash_rasterizer \ +bin/flash_rasterizer2 \ +bin/gamma_correction \ +bin/gamma_ctrl \ +bin/gamma_tuner \ +bin/gouraud \ +bin/gouraud_mesh \ +bin/gpc_test \ +bin/gradients \ +bin/graph_test \ +bin/idea \ +bin/image_alpha \ +bin/image_filters \ +bin/image_filters2 \ +bin/image_fltr_graph \ +bin/image_perspective \ +bin/image_resample \ +bin/image_transforms \ +bin/image1 \ +bin/line_patterns_clip \ +bin/line_patterns \ +bin/lion \ +bin/lion_lens \ +bin/lion_outline \ +bin/mol_view \ +bin/multi_clip \ +bin/pattern_fill \ +bin/pattern_perspective \ +bin/pattern_resample \ +bin/perspective \ +bin/polymorphic_renderer \ +bin/raster_text \ +bin/rasterizers \ +bin/rasterizers2 \ +bin/rounded_rect \ +bin/scanline_boolean \ +bin/scanline_boolean2 \ +bin/simple_blur \ +bin/trans_polar + +FREETYPE_EXAMPLES=\ +bin/freetype_test \ +bin/trans_curve1_ft \ +bin/trans_curve2_ft + +PLATFORM_SRC=\ +src/platform/AmigaOS/agg_platform_support.cpp + +FREETYPE_SRC=\ +font_freetype/agg_font_freetype.cpp + +LIB_CXXSRC=\ +src/agg_arc.cpp \ +src/agg_arrowhead.cpp \ +src/agg_bezier_arc.cpp \ +src/agg_bspline.cpp \ +src/agg_curves.cpp \ +src/agg_embedded_raster_fonts.cpp \ +src/agg_gsv_text.cpp \ +src/agg_image_filters.cpp \ +src/agg_line_aa_basics.cpp \ +src/agg_line_profile_aa.cpp \ +src/agg_rounded_rect.cpp \ +src/agg_sqrt_tables.cpp \ +src/agg_trans_affine.cpp \ +src/agg_trans_double_path.cpp \ +src/agg_trans_single_path.cpp \ +src/agg_trans_warp_magnifier.cpp \ +src/agg_vcgen_bspline.cpp \ +src/agg_vcgen_contour.cpp \ +src/agg_vcgen_dash.cpp \ +src/agg_vcgen_markers_term.cpp \ +src/agg_vcgen_smooth_poly1.cpp \ +src/agg_vcgen_stroke.cpp \ +src/agg_vpgen_clip_polygon.cpp \ +src/agg_vpgen_clip_polyline.cpp \ +src/agg_vpgen_segmentator.cpp \ +src/ctrl/agg_bezier_ctrl.cpp \ +src/ctrl/agg_cbox_ctrl.cpp \ +src/ctrl/agg_gamma_ctrl.cpp \ +src/ctrl/agg_gamma_spline.cpp \ +src/ctrl/agg_polygon_ctrl.cpp \ +src/ctrl/agg_rbox_ctrl.cpp \ +src/ctrl/agg_scale_ctrl.cpp \ +src/ctrl/agg_slider_ctrl.cpp \ +src/ctrl/agg_spline_ctrl.cpp + +LIB_CSRC=\ +gpc/gpc.c + +SVG_SRC=\ +examples/svg_viewer/agg_svg_parser.cpp \ +examples/svg_viewer/agg_svg_path_renderer.cpp \ +examples/svg_viewer/agg_svg_path_tokenizer.cpp \ +examples/svg_viewer/svg_test.cpp \ +$(PLATFORM_SRC) + +PLATFORM_OBJ = $(PLATFORM_SRC:.cpp=.o) +FREETYPE_OBJ = $(FREETYPE_SRC:.cpp=.o) +LIB_OBJ = $(LIB_CXXSRC:.cpp=.o) $(LIB_CSRC:.c=.o) +SVG_OBJ = $(SVG_SRC:.cpp=.o) + + +# +# Targets +# +.PHONY : help all lib examples svg freetype clean install wget + +help: + @Echo Requirements: + @Echo - AmigaOS 4.0 + @Echo - SDK 51.22 + @Echo - optional: libexpat.a for SVG viewer + @Echo - optional: libft2.a for FreeType examples + @Echo "" + @Echo Targets: + @Echo all - build AGG library and all tests/examples + @Echo lib - build AGG library only + @Echo examples - build AGG library and examples + @Echo svg - build AGG library and SVG viewer + @Echo freetype - build AGG library and FreeType examples + @Echo clean - clean all build files + @Echo install - build AGG library and install into SDK + @Echo wget - download and install example test files with wget + +all: lib examples svg freetype + $(STRIP) $(EXAMPLES) $(SVGNAME) $(FREETYPE_EXAMPLES) + +lib: $(LIBNAME) + +examples: lib $(EXAMPLES) + +svg: lib $(SVGNAME) + +freetype: lib $(FREETYPE_EXAMPLES) + +clean: + -@Delete *>NIL: FORCE QUIET examples/#?.o + -@Delete *>NIL: FORCE QUIET $(PLATFORM_OBJ) $(FREETYPE_OBJ) $(LIB_OBJ) $(SVG_OBJ) + -@Delete *>NIL: FORCE QUIET ALL lib bin + +install: lib + -@Copy CLONE $(LIBNAME) SDK:Local/clib2/lib + -@Copy CLONE ALL include/#?.h SDK:Local/common/include/agg + -@Copy CLONE ALL gpc/#?.h SDK:Local/common/include/gpc + +$(LIBNAME): $(LIB_OBJ) + $(AR) $(ARFLAGS) $@ $^ + +$(SVGNAME): $(SVG_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) -lexpat + + +# +# Examples binaries +# +bin/aa_test: examples/aa_test.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/aa_demo: examples/aa_demo.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/alpha_gradient: examples/alpha_gradient.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/alpha_mask: examples/alpha_mask.o examples/parse_lion.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/alpha_mask2: examples/alpha_mask2.o examples/parse_lion.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/alpha_mask3: examples/alpha_mask3.o examples/make_arrows.o examples/make_gb_poly.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/bezier_div: examples/bezier_div.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/bspline: examples/bspline.o examples/interactive_polygon.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/circles: examples/circles.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/component_rendering: examples/component_rendering.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/compositing: examples/compositing.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/compositing2: examples/compositing2.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/conv_contour: examples/conv_contour.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/conv_dash_marker: examples/conv_dash_marker.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/conv_stroke: examples/conv_stroke.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/distortions: examples/distortions.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/flash_rasterizer: examples/flash_rasterizer.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/flash_rasterizer2: examples/flash_rasterizer2.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/gamma_correction: examples/gamma_correction.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/gamma_ctrl: examples/gamma_ctrl.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/gamma_tuner: examples/gamma_tuner.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/gouraud: examples/gouraud.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/gouraud_mesh: examples/gouraud_mesh.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/gpc_test: examples/gpc_test.o examples/make_arrows.o examples/make_gb_poly.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/gradients: examples/gradients.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/graph_test: examples/graph_test.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/idea: examples/idea.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/image1: examples/image1.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/image_alpha: examples/image_alpha.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/image_filters: examples/image_filters.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/image_filters2: examples/image_filters2.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/image_fltr_graph: examples/image_fltr_graph.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/image_perspective: examples/image_perspective.o examples/interactive_polygon.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/image_resample: examples/image_resample.o examples/interactive_polygon.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/image_transforms: examples/image_transforms.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/line_patterns: examples/line_patterns.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/line_patterns_clip: examples/line_patterns_clip.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/lion: examples/lion.o examples/parse_lion.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/lion_lens: examples/lion_lens.o examples/parse_lion.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/lion_outline: examples/lion_outline.o examples/parse_lion.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/mol_view: examples/mol_view.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/multi_clip: examples/multi_clip.o examples/parse_lion.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/pattern_fill: examples/pattern_fill.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/pattern_perspective: examples/pattern_perspective.o examples/interactive_polygon.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/pattern_resample: examples/pattern_resample.o examples/interactive_polygon.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/perspective: examples/perspective.o examples/interactive_polygon.o examples/parse_lion.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/polymorphic_renderer: examples/polymorphic_renderer.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/rasterizers: examples/rasterizers.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/rasterizers2: examples/rasterizers2.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/raster_text: examples/raster_text.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/rounded_rect: examples/rounded_rect.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/scanline_boolean: examples/scanline_boolean.o examples/interactive_polygon.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/scanline_boolean2: examples/scanline_boolean2.o examples/make_arrows.o examples/make_gb_poly.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/simple_blur: examples/simple_blur.o examples/parse_lion.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/trans_polar: examples/trans_polar.o $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) + +bin/freetype_test: examples/freetype_test.o $(FREETYPE_OBJ) $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) -lft2 + +bin/trans_curve1_ft: examples/trans_curve1_ft.o examples/interactive_polygon.o $(FREETYPE_OBJ) $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) -lft2 + +bin/trans_curve2_ft: examples/trans_curve2_ft.o examples/interactive_polygon.o $(FREETYPE_OBJ) $(PLATFORM_OBJ) + $(CXX) $(CXXFLAGS) $^ -o $@ $(CXXLIBS) -lft2 + + +# +# Examples files +# +wget: + wget http://www.antigrain.com/svg/tiger.svg + move tiger.svg bin + wget http://www.antigrain.com/agg.bmp + move agg.bmp bin + wget http://www.antigrain.com/compositing.bmp + move compositing.bmp bin + wget http://www.antigrain.com/spheres.bmp + move spheres.bmp bin + wget http://www.antigrain.com/shapes.txt + move shapes.txt bin + wget http://www.antigrain.com/1.sdf + move 1.sdf bin + wget http://www.antigrain.com/line_patterns.bmp.zip + xadunfile line_patterns.bmp.zip bin overwrite + delete line_patterns.bmp.zip + wget http://www.antigrain.com/timesi.zip + xadunfile timesi.zip bin overwrite + delete timesi.zip + + +# +# Pattern Rules +# +%.o: %.cpp + @MakeDir lib bin force + $(CXX) -c $(CXXFLAGS) $< -o $@ + +%.o: %.c + @MakeDir lib bin force + $(CC) -c $(CFLAGS) $< -o $@ diff --git a/jni/desmume/src/android/agg/Makefile.am b/jni/desmume/src/android/agg/Makefile.am new file mode 100755 index 0000000..f1750c1 --- /dev/null +++ b/jni/desmume/src/android/agg/Makefile.am @@ -0,0 +1,21 @@ +SUBDIRS = gpc src font_freetype font_win32_tt include examples + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libagg.pc + +EXTRA_DIST = Makefile.AmigaOS \ + Makefile.in.BeOS \ + Makefile.in.CYGWIN_NT-5.0 \ + Makefile.in.CYGWIN_NT-5.1 \ + Makefile.in.Darwin \ + Makefile.in.Darwin.SDL \ + Makefile.in.IRIX64 \ + Makefile.in.Linux \ + Makefile.in.Linux.SDL \ + Makefile.in.MINGW32_NT-5.0 \ + Makefile.in.MINGW32_NT-5.1 \ + Makefile.in.SunOS + +# M4 macro file for inclusion with autoconf +m4datadir = $(datadir)/aclocal +m4data_DATA = libagg.m4 diff --git a/jni/desmume/src/android/agg/Makefile.in.BeOS b/jni/desmume/src/android/agg/Makefile.in.BeOS new file mode 100755 index 0000000..a923265 --- /dev/null +++ b/jni/desmume/src/android/agg/Makefile.in.BeOS @@ -0,0 +1,7 @@ +AGGLIBS= -lagg +AGGCXXFLAGS = -O1 +CXX = g++ +C = cc +LIB = ar -cru + +.PHONY : clean diff --git a/jni/desmume/src/android/agg/Makefile.in.CYGWIN_NT-5.0 b/jni/desmume/src/android/agg/Makefile.in.CYGWIN_NT-5.0 new file mode 100755 index 0000000..fa0795c --- /dev/null +++ b/jni/desmume/src/android/agg/Makefile.in.CYGWIN_NT-5.0 @@ -0,0 +1,8 @@ +AGGLIBS= -lagg +AGGCXXFLAGS = -O3 -I/usr/X11R6/include -L/usr/X11R6/lib +CXX = g++ +C = gcc +#CXX = icc +LIB = ar cr + +.PHONY : clean diff --git a/jni/desmume/src/android/agg/Makefile.in.CYGWIN_NT-5.1 b/jni/desmume/src/android/agg/Makefile.in.CYGWIN_NT-5.1 new file mode 100755 index 0000000..fa0795c --- /dev/null +++ b/jni/desmume/src/android/agg/Makefile.in.CYGWIN_NT-5.1 @@ -0,0 +1,8 @@ +AGGLIBS= -lagg +AGGCXXFLAGS = -O3 -I/usr/X11R6/include -L/usr/X11R6/lib +CXX = g++ +C = gcc +#CXX = icc +LIB = ar cr + +.PHONY : clean diff --git a/jni/desmume/src/android/agg/Makefile.in.Darwin b/jni/desmume/src/android/agg/Makefile.in.Darwin new file mode 100755 index 0000000..05ecef7 --- /dev/null +++ b/jni/desmume/src/android/agg/Makefile.in.Darwin @@ -0,0 +1,8 @@ +AGGLIBS= -lagg +AGGCXXFLAGS = -O3 -I/usr/X11R6/include -L/usr/X11R6/lib +CXX = g++ +C = gcc +#CXX = icc +LIB = ar cr -s + +.PHONY : clean diff --git a/jni/desmume/src/android/agg/Makefile.in.Darwin.SDL b/jni/desmume/src/android/agg/Makefile.in.Darwin.SDL new file mode 100755 index 0000000..22b2b94 --- /dev/null +++ b/jni/desmume/src/android/agg/Makefile.in.Darwin.SDL @@ -0,0 +1,8 @@ +AGGLIBS= -lagg -L/usr/local/lib -lSDLmain -lSDL -framework Cocoa -framework OpenGL +AGGCXXFLAGS = -O3 -I/Library/Frameworks/SDL.framework/Headers -L/usr/lib +CXX = g++ +C = gcc +#CXX = icc +LIB = ar cr -s + +.PHONY : clean diff --git a/jni/desmume/src/android/agg/Makefile.in.IRIX64 b/jni/desmume/src/android/agg/Makefile.in.IRIX64 new file mode 100755 index 0000000..c2ea173 --- /dev/null +++ b/jni/desmume/src/android/agg/Makefile.in.IRIX64 @@ -0,0 +1,7 @@ +AGGLIBS= -lagg +AGGCXXFLAGS = +CXX = CC +C = cc +LIB = CC -ar -o + +.PHONY : clean diff --git a/jni/desmume/src/android/agg/Makefile.in.Linux b/jni/desmume/src/android/agg/Makefile.in.Linux new file mode 100755 index 0000000..fa0795c --- /dev/null +++ b/jni/desmume/src/android/agg/Makefile.in.Linux @@ -0,0 +1,8 @@ +AGGLIBS= -lagg +AGGCXXFLAGS = -O3 -I/usr/X11R6/include -L/usr/X11R6/lib +CXX = g++ +C = gcc +#CXX = icc +LIB = ar cr + +.PHONY : clean diff --git a/jni/desmume/src/android/agg/Makefile.in.Linux.SDL b/jni/desmume/src/android/agg/Makefile.in.Linux.SDL new file mode 100755 index 0000000..e90b1e8 --- /dev/null +++ b/jni/desmume/src/android/agg/Makefile.in.Linux.SDL @@ -0,0 +1,8 @@ +AGGLIBS= -lagg -lSDL +AGGCXXFLAGS = -O3 -I/usr/include/SDL -L/usr/lib +CXX = g++ +C = gcc +#CXX = icc +LIB = ar cr + +.PHONY : clean diff --git a/jni/desmume/src/android/agg/Makefile.in.MINGW32_NT-5.0 b/jni/desmume/src/android/agg/Makefile.in.MINGW32_NT-5.0 new file mode 100755 index 0000000..31358f4 --- /dev/null +++ b/jni/desmume/src/android/agg/Makefile.in.MINGW32_NT-5.0 @@ -0,0 +1,8 @@ +AGGLIBS= -lagg +AGGCXXFLAGS = -O3 +CXX = g++ +C = gcc +#CXX = icc +LIB = ar cr + +.PHONY : clean diff --git a/jni/desmume/src/android/agg/Makefile.in.MINGW32_NT-5.1 b/jni/desmume/src/android/agg/Makefile.in.MINGW32_NT-5.1 new file mode 100755 index 0000000..31358f4 --- /dev/null +++ b/jni/desmume/src/android/agg/Makefile.in.MINGW32_NT-5.1 @@ -0,0 +1,8 @@ +AGGLIBS= -lagg +AGGCXXFLAGS = -O3 +CXX = g++ +C = gcc +#CXX = icc +LIB = ar cr + +.PHONY : clean diff --git a/jni/desmume/src/android/agg/Makefile.in.SunOS b/jni/desmume/src/android/agg/Makefile.in.SunOS new file mode 100755 index 0000000..2b3697f --- /dev/null +++ b/jni/desmume/src/android/agg/Makefile.in.SunOS @@ -0,0 +1,7 @@ +AGGLIBS= -lagg +AGGCXXFLAGS = -O3 -I/usr/openwin/include -L/usr/openwin/lib +CXX = CC +C = cc +LIB = CC -xar -o + +.PHONY : clean diff --git a/jni/desmume/src/android/agg/agg_compat.mk b/jni/desmume/src/android/agg/agg_compat.mk new file mode 100755 index 0000000..596422e --- /dev/null +++ b/jni/desmume/src/android/agg/agg_compat.mk @@ -0,0 +1,48 @@ +# Android ndk for agg-2.5 +# http://www.antigrain.com/ + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := libaggcompat +LOCAL_ARM_MODE := thumb +LOCAL_ARM_NEON := false +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include +LOCAL_SRC_FILES := src/agg_arc.cpp \ + src/agg_arrowhead.cpp \ + src/agg_bezier_arc.cpp \ + src/agg_bspline.cpp \ + src/agg_curves.cpp \ + src/agg_embedded_raster_fonts.cpp \ + src/agg_gsv_text.cpp \ + src/agg_image_filters.cpp \ + src/agg_line_aa_basics.cpp \ + src/agg_line_profile_aa.cpp \ + src/agg_rounded_rect.cpp \ + src/agg_sqrt_tables.cpp \ + src/agg_trans_affine.cpp \ + src/agg_trans_double_path.cpp \ + src/agg_trans_single_path.cpp \ + src/agg_trans_warp_magnifier.cpp \ + src/agg_vcgen_bspline.cpp \ + src/agg_vcgen_contour.cpp \ + src/agg_vcgen_dash.cpp \ + src/agg_vcgen_markers_term.cpp \ + src/agg_vcgen_smooth_poly1.cpp \ + src/agg_vcgen_stroke.cpp \ + src/agg_vpgen_clip_polygon.cpp \ + src/agg_vpgen_clip_polyline.cpp \ + src/agg_vpgen_segmentator.cpp \ + src/ctrl/agg_bezier_ctrl.cpp \ + src/ctrl/agg_cbox_ctrl.cpp \ + src/ctrl/agg_gamma_ctrl.cpp \ + src/ctrl/agg_gamma_spline.cpp \ + src/ctrl/agg_polygon_ctrl.cpp \ + src/ctrl/agg_rbox_ctrl.cpp \ + src/ctrl/agg_scale_ctrl.cpp \ + src/ctrl/agg_slider_ctrl.cpp \ + src/ctrl/agg_spline_ctrl.cpp +include $(BUILD_STATIC_LIBRARY) + + + diff --git a/jni/desmume/src/android/agg/agg_neon.mk b/jni/desmume/src/android/agg/agg_neon.mk new file mode 100755 index 0000000..cc3796b --- /dev/null +++ b/jni/desmume/src/android/agg/agg_neon.mk @@ -0,0 +1,49 @@ +# Android ndk for agg-2.5 +# http://www.antigrain.com/ + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := libaggneon +LOCAL_ARM_MODE := arm +LOCAL_ARM_NEON := true +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include +LOCAL_CFLAGS := -DHAVE_NEON=1 -march=armv6 -marm -mfloat-abi=softfp -mfpu=neon +LOCAL_SRC_FILES := src/agg_arc.cpp \ + src/agg_arrowhead.cpp \ + src/agg_bezier_arc.cpp \ + src/agg_bspline.cpp \ + src/agg_curves.cpp \ + src/agg_embedded_raster_fonts.cpp \ + src/agg_gsv_text.cpp \ + src/agg_image_filters.cpp \ + src/agg_line_aa_basics.cpp \ + src/agg_line_profile_aa.cpp \ + src/agg_rounded_rect.cpp \ + src/agg_sqrt_tables.cpp \ + src/agg_trans_affine.cpp \ + src/agg_trans_double_path.cpp \ + src/agg_trans_single_path.cpp \ + src/agg_trans_warp_magnifier.cpp \ + src/agg_vcgen_bspline.cpp \ + src/agg_vcgen_contour.cpp \ + src/agg_vcgen_dash.cpp \ + src/agg_vcgen_markers_term.cpp \ + src/agg_vcgen_smooth_poly1.cpp \ + src/agg_vcgen_stroke.cpp \ + src/agg_vpgen_clip_polygon.cpp \ + src/agg_vpgen_clip_polyline.cpp \ + src/agg_vpgen_segmentator.cpp \ + src/ctrl/agg_bezier_ctrl.cpp \ + src/ctrl/agg_cbox_ctrl.cpp \ + src/ctrl/agg_gamma_ctrl.cpp \ + src/ctrl/agg_gamma_spline.cpp \ + src/ctrl/agg_polygon_ctrl.cpp \ + src/ctrl/agg_rbox_ctrl.cpp \ + src/ctrl/agg_scale_ctrl.cpp \ + src/ctrl/agg_slider_ctrl.cpp \ + src/ctrl/agg_spline_ctrl.cpp +include $(BUILD_STATIC_LIBRARY) + + + diff --git a/jni/desmume/src/android/agg/authors b/jni/desmume/src/android/agg/authors new file mode 100755 index 0000000..c0c4ea3 --- /dev/null +++ b/jni/desmume/src/android/agg/authors @@ -0,0 +1,3 @@ +Anti-Grain Geometry (AGG) - Version 2.5 +A high quality rendering engine for C++ +Copyright (C) 2002-2006 Maxim Shemanarev diff --git a/jni/desmume/src/android/agg/autogen.sh b/jni/desmume/src/android/agg/autogen.sh new file mode 100755 index 0000000..a476cff --- /dev/null +++ b/jni/desmume/src/android/agg/autogen.sh @@ -0,0 +1,23 @@ +# autogen.sh +# +# invoke the auto* tools to create the configuration/build system + +# build aclocal.m4 +aclocal + +# build config.h +autoheader + +# build the configure script +autoconf + +# set up libtool +libtoolize --force + +# invoke automake +automake --foreign --add-missing --ignore-deps + +# and finally invoke our new configure +./configure $* + +# end diff --git a/jni/desmume/src/android/agg/configure.in b/jni/desmume/src/android/agg/configure.in new file mode 100755 index 0000000..fceca82 --- /dev/null +++ b/jni/desmume/src/android/agg/configure.in @@ -0,0 +1,165 @@ +AC_INIT(src/agg_arc.cpp) # give me a source file, any source file... +AC_CANONICAL_TARGET +AC_CONFIG_HEADERS(include/config.h) +AM_INIT_AUTOMAKE(agg, 2.5.0) + + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_CXX +AC_ISC_POSIX +AM_C_PROTOTYPES +if test "x$U" != "x"; then + AC_MSG_ERROR(Compiler not ANSI compliant) +fi +AM_PROG_LIBTOOL +AC_PROG_INSTALL + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST + +AC_ARG_ENABLE(examples, + AC_HELP_STRING([--enable-examples],[Antigrain examples])) +AM_CONDITIONAL(ENABLE_EXAMPLES,test x$enable_examples != xno) + +AC_ARG_ENABLE(ctrl, + AC_HELP_STRING([--enable-ctrl],[a gui libray used in examples])) + +AC_ARG_ENABLE(platform, + AC_HELP_STRING([--enable-platform],[portable platform layers])) + +if test x$enable_examples != xno ; then + enable_platform="yes" +fi +if test x$enable_platform != xno ; then + enable_ctrl="yes" +fi +AM_CONDITIONAL(ENABLE_CTRL,test x$enable_ctrl != xno) + +# used as platform library in examples: +# todo, make the PREFERED_PLATFORM selectable, after the set of possible +# Platforms to link the examples have been evaluated. +PREFERED_PLATFORM=X11 +case "$host" in + *darwin* ) + OSX_LIBS="-framework Carbon -framework QuickTime" + OSX_CFLAGS="-I/System/Library/Frameworks/Carbon.framework/Headers -I/System/Library/Frameworks/QuickTime.framework/Headers " + AC_SUBST(OSX_CFLAGS) + AC_SUBST(OSX_LIBS) + osx_host=yes + PREFERED_PLATFORM=mac + ;; +dnl #### Check if we are compiling for win32 ##### + *mingw*) + win32_host=yes + WINDOWS_LIBS=-lgdi32 + WINDOWS_CFLAGS= + AC_SUBST(WINDOWS_CFLAGS) + AC_SUBST(WINDOWS_LIBS) + PREFERED_PLATFORM=win32 + ;; +esac +AM_CONDITIONAL(ENABLE_WIN32,[test x$win32_host = xyes -a x$enable_platform != xno ]) +AM_CONDITIONAL(ENABLE_OSX,[test x$osx_host = xyes -a x$enable_platform != xno ]) +dnl then enable font_win32tt +AC_ARG_ENABLE(win32tt, + AC_HELP_STRING([--enable-win32tt],[Win32 TrueType font support library]), + enable_tt=$enable_win32tt, + enable_tt=$win32_host) +AM_CONDITIONAL(ENABLE_WIN32_TT, test x$enable_tt = xyes ) + +dnl ######### Check for FT2: ##################### +ft_enabled="" +PKG_CHECK_MODULES([FREETYPE], + freetype2, + [ft_enabled="yes"], + AC_MSG_WARN([*** Freetype2 not found! Building without font library.]) + ) +AC_ARG_ENABLE(freetype, + AC_HELP_STRING([--enable-freetype],[freetype font support library]), + ft_enabled=$enable_freetype) + +AM_CONDITIONAL(ENABLE_FT,[test xyes = x$ft_enabled]) +dnl ############################################### + + +dnl ######### Ask for GPC: ####################### +AC_ARG_ENABLE(gpc, + AC_HELP_STRING([--enable-gpc],[gpc polygon clipper library]) ) + +AM_CONDITIONAL(ENABLE_GPC,[test xyes = x$enable_gpc]) +dnl ############################################### + + + + +dnl ######### Check for SDL: ##################### +dnl the sdl script pollutes our global values: +temp_LIBS="$LIBS" +temp_CFLAGS="$CFLAGS" +temp_CXXFLAGS="$CXXFLAGS" +sdl_enabled="" +SDL_VERSION=1.2.0 +AM_PATH_SDL($SDL_VERSION, + [sdl_enabled="yes"], + AC_MSG_WARN([*** SDL version $SDL_VERSION not found! Omitting sdl layer.]) + ) +dnl ### Restore old values +CFLAGS=$temp_CFLAGS +CXXFLAGS=$temp_CXXFLAGS +LIBS=$temp_LIBS +dnl ### the sdl script already does that: +dnl AC_SUBST(SDL_CFLAGS) +dnl AC_SUBST(SDL_LIBS) +AM_CONDITIONAL(ENABLE_SDL,[test xyes = x$sdl_enabled -a xno != x$enable_platform -a x$win32_host != xyes]) +dnl ############################################### + + +dnl ######### Checking for X11: ################## +AC_PATH_X +if test "$no_x" = "yes"; then + AC_MSG_WARN([*** X11 not found! Omitting X11 layer.]) +fi +AM_CONDITIONAL(ENABLE_X11,[test x$no_x = x -a xno != x$enable_platform -a x$win32_host != xyes]) +AC_SUBST(x_includes) +AC_SUBST(x_libraries) +dnl ############################################### + +dnl Settung up library version +AGG_LIB_VERSION="2:4:0" +dnl current-´ / / +dnl revision--´ / +dnl age---´ +dnl Update the version information only immediately before a public release of antigrain +dnl If the library source code has changed, increment revision (c:r:a becomes c:r+1:a). +dnl If any interfaces have been added, removed, or changed since the last update, +dnl increment current, and set revision to 0. +dnl If any interfaces have been added since the last public release, then increment age. +dnl If any interfaces have been removed since the last public release, then set age to 0. + +AC_SUBST(AGG_LIB_VERSION) +AC_SUBST(PREFERED_PLATFORM) + + +AC_OUTPUT( + Makefile + libagg.pc + gpc/Makefile + font_freetype/Makefile + font_win32_tt/Makefile + src/Makefile + src/ctrl/Makefile + src/platform/Makefile + src/platform/X11/Makefile + src/platform/sdl/Makefile + src/platform/mac/Makefile + src/platform/win32/Makefile + src/platform/BeOS/Makefile + src/platform/AmigaOS/Makefile + include/Makefile + include/ctrl/Makefile + include/util/Makefile + include/platform/Makefile + examples/Makefile +) + diff --git a/jni/desmume/src/android/agg/copying b/jni/desmume/src/android/agg/copying new file mode 100755 index 0000000..d511905 --- /dev/null +++ b/jni/desmume/src/android/agg/copying @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/jni/desmume/src/android/agg/distclean b/jni/desmume/src/android/agg/distclean new file mode 100755 index 0000000..88c8daa --- /dev/null +++ b/jni/desmume/src/android/agg/distclean @@ -0,0 +1,24 @@ +#! /bin/sh + +find . -iname '*.[oa]' -exec \rm -f {} \; +find . -iname '*.ppm' -exec \rm -f {} \; +find . -iname '*~' -exec \rm -f {} \; +find . -iname 'gamma.*' -exec \rm -f {} \; +find . -iname Debug -exec \rm -rf {} \; +find . -iname Release -exec \rm -rf {} \; +find . -iname '*.exe' -exec \rm -rf {} \; +find . -iname '*.lib' -exec \rm -rf {} \; +find . -iname '*.dll' -exec \rm -rf {} \; +find . -iname '*.obj' -exec \rm -rf {} \; +find . -iname '*.aps' -exec \rm -rf {} \; +find . -iname '*.clw' -exec \rm -rf {} \; +find . -iname '*.ilk' -exec \rm -rf {} \; +find . -iname '*.ncb' -exec \rm -rf {} \; +find . -iname '*.opt' -exec \rm -rf {} \; +find . -iname '*.plg' -exec \rm -rf {} \; +find . -iname '*.pch' -exec \rm -rf {} \; +find . -iname '*.idb' -exec \rm -rf {} \; +find . -iname '*.pdb' -exec \rm -rf {} \; +find . -iname '*.res' -exec \rm -rf {} \; + + diff --git a/jni/desmume/src/android/agg/examples/BeOS/Makefile b/jni/desmume/src/android/agg/examples/BeOS/Makefile new file mode 100755 index 0000000..7bf90c0 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/BeOS/Makefile @@ -0,0 +1,412 @@ +include ../../Makefile.in.$(shell uname) + +PLATFORM=BeOS + +PLATFORMSOURCES=../../src/platform/$(PLATFORM)/agg_platform_support.o + +CXXFLAGS= $(AGGCXXFLAGS) -I../../include \ +-L../../src \ +$(PIXFMT) + +CXXFREETYPEFLAGS= $(AGGCXXFLAGS) -Wall \ +-I../../include \ +-I../../font_freetype \ +-I/boot/home/config/include/ \ +-L../../src \ +-L/boot/home/config/lib/ \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lroot -lbe -ltranslation + +base: + cd ../../src/; make + make aa_demo + make aa_test + make alpha_gradient + make alpha_mask + make alpha_mask2 + make alpha_mask3 + make bezier_div + make blur + make blend_color + make bspline + make circles + make component_rendering + make conv_contour + make conv_dash_marker + make conv_stroke + make flash_rasterizer + make flash_rasterizer2 + make gamma_correction + make gamma_ctrl + make gamma_tuner + make gouraud + make gouraud_mesh + make gradient_focal + make gradients + make graph_test + make idea + make lion + make lion_lens + make lion_outline + make multi_clip + make pattern_fill + make perspective + make polymorphic_renderer + make raster_text + make rasterizers + make rasterizers2 + make rasterizer_compound + make rounded_rect + make scanline_boolean + make scanline_boolean2 + make simple_blur + make trans_polar + make image_alpha + make image_filters + make image_filters2 + make image_fltr_graph + make image_perspective + make image_resample + make image_transforms + make image1 + make distortions + make pattern_perspective + make compositing + make compositing2 + make line_patterns + make line_patterns_clip + make mol_view + +freetype: + make freetype_test + make trans_curve1_ft + make trans_curve2_ft + +gpc: + make gpc_test + +all: + make base + make freetype + make gpc + +aa_demo: ../aa_demo.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o aa_demo $(LIBS) + +aa_test: ../aa_test.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o aa_test $(LIBS) + +alpha_gradient: ../alpha_gradient.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o alpha_gradient $(LIBS) + +alpha_mask: ../alpha_mask.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o alpha_mask $(LIBS) + +alpha_mask2: ../alpha_mask2.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o alpha_mask2 $(LIBS) + +alpha_mask3: ../alpha_mask3.o ../make_arrows.o ../make_gb_poly.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o alpha_mask3 $(LIBS) + +bezier_div: ../bezier_div.o ../interactive_polygon.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o bezier_div $(LIBS) + +blur: ../blur.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o blur $(LIBS) + +blend_color: ../blend_color.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o blend_color $(LIBS) + +bspline: ../bspline.o ../interactive_polygon.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o bspline $(LIBS) + +circles: ../circles.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o circles $(LIBS) + +component_rendering: ../component_rendering.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o component_rendering $(LIBS) + +compositing: ../compositing.o $(PLATFORMSOURCES) compositing.ppm + $(CXX) $(CXXFLAGS) ../compositing.o $(PLATFORMSOURCES) -o compositing $(LIBS) + +compositing2: ../compositing2.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o compositing2 $(LIBS) + +conv_contour: ../conv_contour.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o conv_contour $(LIBS) + +conv_dash_marker: ../conv_dash_marker.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o conv_dash_marker $(LIBS) + +conv_stroke: ../conv_stroke.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o conv_stroke $(LIBS) + +distortions: ../distortions.o $(PLATFORMSOURCES) spheres.ppm + $(CXX) $(CXXFLAGS) ../distortions.o $(PLATFORMSOURCES) -o distortions $(LIBS) + +flash_rasterizer: ../flash_rasterizer.o $(PLATFORMSOURCES) shapes.txt + $(CXX) $(CXXFLAGS) ../flash_rasterizer.o $(PLATFORMSOURCES) -o flash_rasterizer $(LIBS) + +flash_rasterizer2: ../flash_rasterizer2.o $(PLATFORMSOURCES) shapes.txt + $(CXX) $(CXXFLAGS) ../flash_rasterizer2.o $(PLATFORMSOURCES) -o flash_rasterizer2 $(LIBS) + +gamma_correction: ../gamma_correction.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gamma_correction $(LIBS) + +gamma_ctrl: ../gamma_ctrl.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gamma_ctrl $(LIBS) + +gamma_tuner: ../gamma_tuner.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gamma_tuner $(LIBS) + +gouraud: ../gouraud.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gouraud $(LIBS) + +gouraud_mesh: ../gouraud_mesh.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gouraud_mesh $(LIBS) + +gradient_focal: ../gradient_focal.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gradient_focal $(LIBS) + +gradients: ../gradients.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gradients $(LIBS) + +graph_test: ../graph_test.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o graph_test $(LIBS) + +idea: ../idea.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o idea $(LIBS) + +image_alpha: ../image_alpha.o $(PLATFORMSOURCES) spheres.ppm + $(CXX) $(CXXFLAGS) ../image_alpha.o $(PLATFORMSOURCES) -o image_alpha $(LIBS) + +image_filters: ../image_filters.o $(PLATFORMSOURCES) spheres.ppm + $(CXX) $(CXXFLAGS) ../image_filters.o $(PLATFORMSOURCES) -o image_filters $(LIBS) + +image_filters2: ../image_filters2.o $(PLATFORMSOURCES) spheres.ppm + $(CXX) $(CXXFLAGS) ../image_filters2.o $(PLATFORMSOURCES) -o image_filters2 $(LIBS) + +image_fltr_graph: ../image_fltr_graph.o $(PLATFORMSOURCES) spheres.ppm + $(CXX) $(CXXFLAGS) ../image_fltr_graph.o $(PLATFORMSOURCES) -o image_fltr_graph $(LIBS) + +image_perspective: ../image_perspective.o ../interactive_polygon.o $(PLATFORMSOURCES) spheres.ppm + $(CXX) $(CXXFLAGS) ../image_perspective.o ../interactive_polygon.o $(PLATFORMSOURCES) -o image_perspective $(LIBS) + +image_resample: ../image_resample.o ../interactive_polygon.o $(PLATFORMSOURCES) spheres.ppm + $(CXX) $(CXXFLAGS) ../image_resample.o ../interactive_polygon.o $(PLATFORMSOURCES) -o image_resample $(LIBS) + +image_transforms: ../image_transforms.o $(PLATFORMSOURCES) spheres.ppm + $(CXX) $(CXXFLAGS) ../image_transforms.o $(PLATFORMSOURCES) -o image_transforms $(LIBS) + +image1: ../image1.o $(PLATFORMSOURCES) spheres.ppm + $(CXX) $(CXXFLAGS) ../image1.o $(PLATFORMSOURCES) -o image1 $(LIBS) + +line_patterns: ../line_patterns.o $(PLATFORMSOURCES) 1.ppm 2.ppm 3.ppm 4.ppm 5.ppm 6.ppm 7.ppm 8.ppm 9.ppm + $(CXX) $(CXXFLAGS) ../line_patterns.o $(PLATFORMSOURCES) -o line_patterns $(LIBS) + +line_patterns_clip: ../line_patterns_clip.o $(PLATFORMSOURCES) 1.ppm + $(CXX) $(CXXFLAGS) ../line_patterns_clip.o $(PLATFORMSOURCES) -o line_patterns_clip $(LIBS) + +lion: ../lion.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o lion $(LIBS) + +lion_lens: ../lion_lens.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o lion_lens $(LIBS) + +lion_outline: ../lion_outline.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o lion_outline $(LIBS) + +mol_view: ../mol_view.o $(PLATFORMSOURCES) 1.sdf + $(CXX) $(CXXFLAGS) ../mol_view.o $(PLATFORMSOURCES) -o mol_view $(LIBS) + +multi_clip: ../multi_clip.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o multi_clip $(LIBS) + +pattern_fill: ../pattern_fill.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o pattern_fill $(LIBS) + +pattern_perspective: ../pattern_perspective.o ../interactive_polygon.o $(PLATFORMSOURCES) agg.ppm + $(CXX) $(CXXFLAGS) ../pattern_perspective.o ../interactive_polygon.o $(PLATFORMSOURCES) -o pattern_perspective $(LIBS) + +perspective: ../perspective.o ../interactive_polygon.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o perspective $(LIBS) + +polymorphic_renderer: ../polymorphic_renderer.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o polymorphic_renderer $(LIBS) + +raster_text: ../raster_text.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o raster_text $(LIBS) + +rasterizers: ../rasterizers.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o rasterizers $(LIBS) + +rasterizers2: ../rasterizers2.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o rasterizers2 $(LIBS) + +rasterizer_compound: ../rasterizer_compound.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o rasterizer_compound $(LIBS) + +rounded_rect: ../rounded_rect.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o rounded_rect $(LIBS) + +scanline_boolean: ../scanline_boolean.o ../interactive_polygon.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o scanline_boolean $(LIBS) + +scanline_boolean2: ../scanline_boolean2.o ../make_arrows.o ../make_gb_poly.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o scanline_boolean2 $(LIBS) + +simple_blur: ../simple_blur.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o simple_blur $(LIBS) + +trans_polar: ../trans_polar.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o trans_polar $(LIBS) + +freetype_test: ../freetype_test.o ../../font_freetype/agg_font_freetype.o $(PLATFORMSOURCES) timesi.ttf + $(CXX) $(CXXFREETYPEFLAGS) ../freetype_test.o ../../font_freetype/agg_font_freetype.o $(PLATFORMSOURCES) -o freetype_test $(LIBS) -lfreetype + +trans_curve1_ft: ../trans_curve1_ft.o ../../font_freetype/agg_font_freetype.o ../interactive_polygon.o $(PLATFORMSOURCES) timesi.ttf + $(CXX) $(CXXFLAGS) ../trans_curve1_ft.o ../../font_freetype/agg_font_freetype.o ../interactive_polygon.o $(PLATFORMSOURCES) -o trans_curve1_ft $(LIBS) -lfreetype + +trans_curve2_ft: ../trans_curve2_ft.o ../../font_freetype/agg_font_freetype.o ../interactive_polygon.o $(PLATFORMSOURCES) timesi.ttf + $(CXX) $(CXXFLAGS) ../trans_curve2_ft.o ../../font_freetype/agg_font_freetype.o ../interactive_polygon.o $(PLATFORMSOURCES) -o trans_curve2_ft $(LIBS) -lfreetype + +gpc_test: ../gpc_test.o ../make_arrows.o ../make_gb_poly.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gpc_test $(LIBS) + +clean: + rm -f ../*.o + rm -f ../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -rf aa_demo + rm -rf aa_test + rm -rf alpha_gradient + rm -rf alpha_mask + rm -rf alpha_mask2 + rm -rf alpha_mask3 + rm -rf bezier_div + rm -rf bspline + rm -rf blur + rn -rf blend_color + rm -rf circles + rm -rf component_rendering + rm -rf conv_contour + rm -rf conv_dash_marker + rm -rf conv_stroke + rm -rf flash_rasterizer + rm -rf flash_rasterizer2 + rm -rf gamma_correction + rm -rf gamma_ctrl + rm -rf gamma_tuner + rm -rf gouraud + rm -rf gouraud_mesh + rm -rf gradient_focal + rm -rf gradients + rm -rf graph_test + rm -rf idea + rm -rf lion + rm -rf lion_lens + rm -rf lion_outline + rm -rf multi_clip + rm -rf pattern_fill + rm -rf perspective + rm -rf polymorphic_renderer + rm -rf raster_text + rm -rf rasterizers + rm -rf rasterizers2 + rm -rf rounded_rect + rm -rf scanline_boolean + rm -rf scanline_boolean2 + rm -rf simple_blur + rm -rf trans_polar + rm -rf image_alpha + rm -rf image_filters + rm -rf image_filters2 + rm -rf image_fltr_graph + rm -rf image_perspective + rm -rf image_resample + rm -rf image_transforms + rm -rf image1 + rm -rf distortions + rm -rf pattern_perspective + rm -rf compositing + rm -rf line_patterns + rm -rf line_patterns_clip + rm -rf mol_view + rm -rf freetype_test + rm -rf trans_curve1_ft + rm -rf trans_curve2_ft + rm -rf gpc_test + +agg.ppm: + @echo "Required file missing!!" + @echo "Please download http://www.antigrain.com/agg.ppm to /examples/X11/" + @echo "Attempting to retrieve via wget: (will fail if wget is not installed)" + wget http://www.antigrain.com/agg.ppm + +compositing.ppm: + @echo "Required file missing!!" + @echo "Please download http://www.antigrain.com/compositing.ppm to /examples/X11/" + @echo "Attempting to retrieve via wget: (will fail if wget is not installed)" + wget http://www.antigrain.com/compositing.ppm + +spheres.ppm: + @echo "Required file missing!!" + @echo "Please download http://www.antigrain.com/spheres.ppm to /examples/X11/" + @echo "Attempting to retrieve file: (will fail if wget is not installed)" + wget http://www.antigrain.com/spheres.ppm + +shapes.txt: + @echo "Required file missing!!" + @echo "Please download http://www.antigrain.com/shapes.txt to /examples/X11/" + @echo "Attempting to retrieve file: (will fail if wget is not installed)" + wget http://www.antigrain.com/shapes.txt + +1.sdf: + @echo "Required file missing!!" + @echo "Please download http://www.antigrain.com/1.sdf to /examples/macosx_carbon/" + @echo "Attempting to retrieve file: (will fail if wget is not installed)" + wget http://www.antigrain.com/1.sdf + +1.ppm: + @echo "Required file missing!!" + @echo "Please download http://www.antigrain.com/line_patterns.tar.gz to /examples/X11/ and decompress it" + @echo "Attempting to retrieve file: (will fail if wget is not installed)" + wget http://www.antigrain.com/line_patterns.tar.gz + gunzip line_patterns.tar.gz + tar -xvf line_patterns.tar + +timesi.ttf: + @echo "Required file missing!!" + @echo "Please download http://www.antigrain.com/timesi.zip to /examples/X11/ and decompress it" + @echo "Attempting to retrieve file: (will fail if wget is not installed)" + wget http://www.antigrain.com/timesi.zip + unzip -o timesi.zip + +../freetype_test.o: ../freetype_test.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFREETYPEFLAGS) $*.cpp -o $@ + +../trans_curve1_ft.o: ../trans_curve1_ft.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFREETYPEFLAGS) $*.cpp -o $@ + +../trans_curve2_ft.o: ../trans_curve2_ft.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFREETYPEFLAGS) $*.cpp -o $@ + +../../font_freetype/agg_font_freetype.o: ../../font_freetype/agg_font_freetype.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFREETYPEFLAGS) $*.cpp -o $@ + +../gpc_test.o: ../gpc_test.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) -I../../gpc $*.cpp -o $@ + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + +.PHONY : clean + + diff --git a/jni/desmume/src/android/agg/examples/BeOS/readme.txt b/jni/desmume/src/android/agg/examples/BeOS/readme.txt new file mode 100755 index 0000000..e691517 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/BeOS/readme.txt @@ -0,0 +1,36 @@ +The Anti-Grain Geometry Project +A high quality rendering engine for C++ +http://antigrain.com + +Anti-Grain Geometry +Copyright (C) 2002-2005 Maxim Shemanarev (McSeem) + +Permission to copy, use, modify, sell and distribute this software +is granted provided this copyright notice appears in all copies. +This software is provided "as is" without express or implied +warranty, and with no claim as to its suitability for any purpose. + +By default only the examples that do not require extra dependancies are built. +with the following commands: + +cd (AGGDIRECTORY)/examples/BeOS +make clean +make + +Some examples (freetype_test, trans_curve1_ft and trans_curve2_ft) require the Freetype Library, and can be built with: + +make freetype + +There is also an example (gpc_test) that requires the GPC library, build it with: + +make gpc + +Of course, to build ALL examples run: + +make all + +Alternatively you can also build the examples one by one, using the example name directly: + +make aa_demo +make aa_test +... diff --git a/jni/desmume/src/android/agg/examples/Makefile.am b/jni/desmume/src/android/agg/examples/Makefile.am new file mode 100755 index 0000000..8040b6a --- /dev/null +++ b/jni/desmume/src/android/agg/examples/Makefile.am @@ -0,0 +1,248 @@ +EXTRA_DIST= X11/Makefile interactive_polygon.h pixel_formats.h win32_api/aa_demo/Makefile win32_api/aa_demo/aa_demo.dsp win32_api/aa_demo/aa_demo.dsw win32_api/Makefile win32_api/examples.dsw win32_api/aa_test/Makefile win32_api/aa_test/aa_test.dsp win32_api/aa_test/aa_test.dsw win32_api/alpha_gradient/Makefile win32_api/alpha_gradient/alpha_gradient.dsp win32_api/alpha_gradient/alpha_gradient.dsw win32_api/alpha_mask/Makefile win32_api/alpha_mask/alpha_mask.dsp win32_api/alpha_mask/alpha_mask.dsw win32_api/alpha_mask2/Makefile win32_api/alpha_mask2/alpha_mask2.dsp win32_api/alpha_mask2/alpha_mask2.dsw win32_api/alpha_mask3/Makefile win32_api/alpha_mask3/alpha_mask3.dsp win32_api/alpha_mask3/alpha_mask3.dsw win32_api/bezier_div/Makefile win32_api/bezier_div/bezier_div.dsp win32_api/bezier_div/bezier_div.dsw win32_api/bspline/Makefile win32_api/bspline/bspline.dsp win32_api/bspline/bspline.dsw win32_api/circles/Makefile win32_api/circles/circles.dsp win32_api/circles/circles.dsw win32_api/component_rendering/Makefile win32_api/component_rendering/component_rendering.dsp win32_api/component_rendering/component_rendering.dsw win32_api/compositing/Makefile win32_api/compositing/compositing.dsp win32_api/compositing/compositing.dsw win32_api/compositing/readme win32_api/conv_contour/Makefile win32_api/conv_contour/conv_contour.dsp win32_api/conv_contour/conv_contour.dsw win32_api/conv_dash_marker/Makefile win32_api/conv_dash_marker/conv_dash_marker.dsp win32_api/conv_dash_marker/conv_dash_marker.dsw win32_api/conv_stroke/Makefile win32_api/conv_stroke/conv_stroke.dsp win32_api/conv_stroke/conv_stroke.dsw win32_api/distortions/Makefile win32_api/distortions/distortions.dsp win32_api/distortions/distortions.dsw win32_api/distortions/readme win32_api/freetype_test/Makefile win32_api/freetype_test/freetype_test.dsp win32_api/freetype_test/freetype_test.dsw win32_api/freetype_test/readme win32_api/gamma_correction/Makefile win32_api/gamma_correction/gamma_correction.dsp win32_api/gamma_correction/gamma_correction.dsw win32_api/gamma_ctrl/Makefile win32_api/gamma_ctrl/gamma_ctrl.dsp win32_api/gamma_ctrl/gamma_ctrl.dsw win32_api/gouraud/Makefile win32_api/gouraud/gouraud.dsp win32_api/gouraud/gouraud.dsw win32_api/gpc_test/Makefile win32_api/gpc_test/gpc_test.dsp win32_api/gpc_test/gpc_test.dsw win32_api/gradients/Makefile win32_api/gradients/gradients.dsp win32_api/gradients/gradients.dsw win32_api/gradients/settings.dat win32_api/graph_test/Makefile win32_api/graph_test/graph_test.dsp win32_api/graph_test/graph_test.dsw win32_api/idea/Makefile win32_api/idea/idea.dsp win32_api/idea/idea.dsw win32_api/image1/Makefile win32_api/image1/image1.dsp win32_api/image1/image1.dsw win32_api/image1/readme win32_api/image_alpha/Makefile win32_api/image_alpha/image_alpha.dsp win32_api/image_alpha/image_alpha.dsw win32_api/image_alpha/readme win32_api/image_filters/Makefile win32_api/image_filters/image_filters.dsp win32_api/image_filters/image_filters.dsw win32_api/image_filters/readme win32_api/image_filters2/Makefile win32_api/image_filters2/image_filters2.dsp win32_api/image_filters2/image_filters2.dsw win32_api/image_filters2/readme win32_api/image_fltr_graph/Makefile win32_api/image_fltr_graph/image_fltr_graph.dsp win32_api/image_fltr_graph/image_fltr_graph.dsw win32_api/image_perspective/Makefile win32_api/image_perspective/image_perspective.dsp win32_api/image_perspective/image_perspective.dsw win32_api/image_perspective/readme win32_api/image_resample/Makefile win32_api/image_resample/image_resample.dsp win32_api/image_resample/image_resample.dsw win32_api/image_resample/readme win32_api/image_transforms/Makefile win32_api/image_transforms/image_transforms.dsp win32_api/image_transforms/image_transforms.dsw win32_api/image_transforms/readme! win32_api/line_patterns/Makefile win32_api/line_patterns/line_patterns.dsp win32_api/line_patterns/line_patterns.dsw win32_api/lion/Makefile win32_api/lion/lion.dsp win32_api/lion/lion.dsw win32_api/lion_lens/Makefile win32_api/lion_lens/lion_lens.dsp win32_api/lion_lens/lion_lens.dsw win32_api/lion_outline/Makefile win32_api/lion_outline/lion_outline.dsp win32_api/lion_outline/lion_outline.dsw win32_api/mol_view/Makefile win32_api/mol_view/mol_view.dsp win32_api/mol_view/mol_view.dsw win32_api/mol_view/readme win32_api/multi_clip/Makefile win32_api/multi_clip/multi_clip.dsp win32_api/multi_clip/multi_clip.dsw win32_api/pattern_fill/Makefile win32_api/pattern_fill/pattern_fill.dsp win32_api/pattern_fill/pattern_fill.dsw win32_api/pattern_perspective/pattern_perspective.dsp win32_api/pattern_perspective/pattern_perspective.dsw win32_api/pattern_resample/Makefile win32_api/pattern_resample/pattern_resample.dsp win32_api/pattern_resample/pattern_resample.dsw win32_api/perspective/Makefile win32_api/perspective/perspective.dsp win32_api/perspective/perspective.dsw win32_api/polymorphic_renderer/Makefile win32_api/polymorphic_renderer/polymorphic_renderer.dsp win32_api/polymorphic_renderer/polymorphic_renderer.dsw win32_api/pure_api/StdAfx.cpp win32_api/pure_api/StdAfx.h win32_api/pure_api/pure_api.cpp win32_api/pure_api/pure_api.dsp win32_api/pure_api/pure_api.dsw win32_api/pure_api/pure_api.h win32_api/pure_api/pure_api.ico win32_api/pure_api/pure_api.rc win32_api/pure_api/resource.h win32_api/pure_api/small.ico win32_api/raster_text/Makefile win32_api/raster_text/raster_text.dsp win32_api/raster_text/raster_text.dsw win32_api/rasterizers/Makefile win32_api/rasterizers/rasterizers.dsp win32_api/rasterizers/rasterizers.dsw win32_api/rasterizers2/Makefile win32_api/rasterizers2/rasterizers2.dsp win32_api/rasterizers2/rasterizers2.dsw win32_api/rounded_rect/Makefile win32_api/rounded_rect/rounded_rect.dsp win32_api/rounded_rect/rounded_rect.dsw win32_api/scanline_boolean/Makefile win32_api/scanline_boolean/scanline_boolean.dsp win32_api/scanline_boolean/scanline_boolean.dsw win32_api/scanline_boolean2/Makefile win32_api/scanline_boolean2/scanline_boolean2.dsp win32_api/scanline_boolean2/scanline_boolean2.dsw win32_api/simple_blur/Makefile win32_api/simple_blur/simple_blur.dsp win32_api/simple_blur/simple_blur.dsw win32_api/trans_curve1/Makefile win32_api/trans_curve1/trans_curve1.dsp win32_api/trans_curve1/trans_curve1.dsw win32_api/trans_curve2/Makefile win32_api/trans_curve2/trans_curve2.dsp win32_api/trans_curve2/trans_curve2.dsw win32_api/trans_polar/Makefile win32_api/trans_polar/trans_polar.dsp win32_api/trans_polar/trans_polar.dsw win32_api/truetype_test/Makefile win32_api/truetype_test/truetype_test.dsp win32_api/truetype_test/truetype_test.dsw + +if ENABLE_EXAMPLES + +if ENABLE_WIN32_TT +W32TTP=truetype_test trans_curve1 trans_curve2 +endif + +if ENABLE_FT +FTP=freetype_test ### these dont work : trans_curve2_ft trans_curve1_ft +endif + +if ENABLE_GPC +GPCP=gpc_test +endif + +INCLUDES=-I$(top_srcdir)/include -I$(top_srcdir)/font_freetype/ -I$(top_srcdir)/gpc -I$(top_srcdir)/font_win32_tt + +noinst_LTLIBRARIES=libexamples.la +libexamples_la_SOURCES=parse_lion.cpp make_gb_poly.cpp make_arrows.cpp interactive_polygon.cpp + +noinst_PROGRAMS=aa_demo aa_test alpha_gradient alpha_mask2 alpha_mask3 alpha_mask bezier_div bspline circles component_rendering compositing conv_contour conv_dash_marker conv_stroke distortions gamma_correction gamma_ctrl gouraud gradients graph_test idea image1 image_alpha image_filters2 image_filters image_fltr_graph image_perspective image_resample image_transforms line_patterns lion lion_lens lion_outline mol_view multi_clip pattern_fill pattern_perspective pattern_resample perspective polymorphic_renderer rasterizers2 rasterizers raster_text rounded_rect scanline_boolean2 scanline_boolean simple_blur trans_polar $(GPCP) $(W32TTP) $(FTP) + + +aa_demo_SOURCES=aa_demo.cpp +aa_demo_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +aa_test_SOURCES=aa_test.cpp +aa_test_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +alpha_gradient_SOURCES=alpha_gradient.cpp +alpha_gradient_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +alpha_mask2_SOURCES=alpha_mask2.cpp +alpha_mask2_LDFLAGS= libexamples.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +alpha_mask3_SOURCES=alpha_mask3.cpp +alpha_mask3_LDFLAGS= libexamples.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +alpha_mask_SOURCES=alpha_mask.cpp +alpha_mask_LDFLAGS= libexamples.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +bezier_div_SOURCES=bezier_div.cpp +bezier_div_LDFLAGS= libexamples.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +bspline_SOURCES=bspline.cpp +bspline_LDFLAGS= libexamples.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +circles_SOURCES=circles.cpp +circles_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +component_rendering_SOURCES=component_rendering.cpp +component_rendering_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +compositing_SOURCES=compositing.cpp +compositing_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +conv_contour_SOURCES=conv_contour.cpp +conv_contour_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +conv_dash_marker_SOURCES=conv_dash_marker.cpp +conv_dash_marker_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +conv_stroke_SOURCES=conv_stroke.cpp +conv_stroke_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +distortions_SOURCES=distortions.cpp +distortions_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +gamma_correction_SOURCES=gamma_correction.cpp +gamma_correction_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +gamma_ctrl_SOURCES=gamma_ctrl.cpp +gamma_ctrl_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +gouraud_SOURCES=gouraud.cpp +gouraud_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +gradients_SOURCES=gradients.cpp +gradients_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +graph_test_SOURCES=graph_test.cpp +graph_test_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +idea_SOURCES=idea.cpp +idea_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +image1_SOURCES=image1.cpp +image1_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +image_alpha_SOURCES=image_alpha.cpp +image_alpha_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +image_filters2_SOURCES=image_filters2.cpp +image_filters2_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +image_filters_SOURCES=image_filters.cpp +image_filters_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +image_fltr_graph_SOURCES=image_fltr_graph.cpp +image_fltr_graph_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +image_perspective_SOURCES=image_perspective.cpp +image_perspective_LDFLAGS= libexamples.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +image_resample_SOURCES=image_resample.cpp +image_resample_LDFLAGS= libexamples.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +image_transforms_SOURCES=image_transforms.cpp +image_transforms_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +line_patterns_SOURCES=line_patterns.cpp +line_patterns_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +lion_SOURCES=lion.cpp +lion_LDFLAGS= libexamples.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +lion_lens_SOURCES=lion_lens.cpp +lion_lens_LDFLAGS= libexamples.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +lion_outline_SOURCES=lion_outline.cpp +lion_outline_LDFLAGS= libexamples.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +mol_view_SOURCES=mol_view.cpp +mol_view_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +multi_clip_SOURCES=multi_clip.cpp +multi_clip_LDFLAGS= libexamples.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +pattern_fill_SOURCES=pattern_fill.cpp +pattern_fill_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +pattern_perspective_SOURCES=pattern_perspective.cpp +pattern_perspective_LDFLAGS= libexamples.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +pattern_resample_SOURCES=pattern_resample.cpp +pattern_resample_LDFLAGS= libexamples.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +perspective_SOURCES=perspective.cpp +perspective_LDFLAGS= libexamples.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +polymorphic_renderer_SOURCES=polymorphic_renderer.cpp +polymorphic_renderer_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +rasterizers2_SOURCES=rasterizers2.cpp +rasterizers2_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +rasterizers_SOURCES=rasterizers.cpp +rasterizers_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +raster_text_SOURCES=raster_text.cpp +raster_text_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +rounded_rect_SOURCES=rounded_rect.cpp +rounded_rect_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +scanline_boolean2_SOURCES=scanline_boolean2.cpp +scanline_boolean2_LDFLAGS= libexamples.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +scanline_boolean_SOURCES=scanline_boolean.cpp +scanline_boolean_LDFLAGS= libexamples.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +simple_blur_SOURCES=simple_blur.cpp +simple_blur_LDFLAGS= libexamples.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +trans_polar_SOURCES=trans_polar.cpp +trans_polar_LDFLAGS= $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +freetype_test_SOURCES=freetype_test.cpp +freetype_test_CXXFLAGS=@FREETYPE_CFLAGS@ +freetype_test_LDFLAGS= $(top_builddir)/font_freetype/libaggfontfreetype.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +trans_curve2_ft_SOURCES=trans_curve2_ft.cpp +trans_curve2_ft_CXXFLAGS=@FREETYPE_CFLAGS@ +trans_curve2_ft_LDFLAGS= $(top_builddir)/font_freetype/libaggfontfreetype.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +trans_curve1_ft_SOURCES=trans_curve1_ft.cpp +trans_curve1_ft_CXXFLAGS=@FREETYPE_CFLAGS@ +trans_curve1_ft_LDFLAGS= $(top_builddir)/font_freetype/libaggfontfreetype.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +gpc_test_SOURCES=gpc_test.cpp +gpc_test_LDFLAGS= libexamples.la $(top_builddir)/gpc/libagggpc.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +truetype_test_SOURCES=truetype_test.cpp +truetype_test_LDFLAGS= $(top_builddir)/font_win32_tt/libaggfontwin32tt.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +trans_curve1_SOURCES=trans_curve1.cpp +trans_curve1_LDFLAGS= libexamples.la $(top_builddir)/font_win32_tt/libaggfontwin32tt.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +trans_curve2_SOURCES=trans_curve2.cpp +trans_curve2_LDFLAGS= libexamples.la $(top_builddir)/font_win32_tt/libaggfontwin32tt.la $(top_builddir)/src/platform/@PREFERED_PLATFORM@/libaggplatform@PREFERED_PLATFORM@.la $(top_builddir)/src/libagg.la + + +endif diff --git a/jni/desmume/src/android/agg/examples/X11/Makefile b/jni/desmume/src/android/agg/examples/X11/Makefile new file mode 100755 index 0000000..d53bf93 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/X11/Makefile @@ -0,0 +1,355 @@ +include ../../Makefile.in.$(shell uname) + +PLATFORM=X11 + +PLATFORMSOURCES=../../src/platform/$(PLATFORM)/agg_platform_support.o + +CXXFLAGS= $(AGGCXXFLAGS) -I../../include \ +-L../../src \ +$(PIXFMT) + +CXXFREETYPEFLAGS= $(AGGCXXFLAGS) -Wall \ +-I../../include \ +-I../../font_freetype \ +-I/usr/local/include/freetype2 \ +-L../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lX11 + +base: + cd ../../src/; make + make aa_demo + make aa_test + make alpha_gradient + make alpha_mask + make alpha_mask2 + make alpha_mask3 + make bezier_div + make bspline + make circles + make component_rendering + make conv_contour + make conv_dash_marker + make conv_stroke + make flash_rasterizer + make flash_rasterizer2 + make gamma_correction + make gamma_ctrl + make gamma_tuner + make gouraud + make gouraud_mesh + make gradient_focal + make gradients + make graph_test + make idea + make lion + make lion_lens + make lion_outline + make multi_clip + make pattern_fill + make perspective + make polymorphic_renderer + make raster_text + make rasterizers + make rasterizers2 + make rounded_rect + make scanline_boolean + make scanline_boolean2 + make simple_blur + make trans_polar + make image_alpha + make image_filters + make image_filters2 + make image_fltr_graph + make image_perspective + make image_resample + make image_transforms + make image1 + make distortions + make pattern_perspective + make compositing + make compositing2 + make line_patterns + make line_patterns_clip + make mol_view + make blur + make rasterizer_compound + make blend_color + +freetype: + make freetype_test + make trans_curve1_ft + make trans_curve2_ft + +gpc: + make gpc_test + +all: + make base + make freetype + make gpc + make svg_test + +aa_demo: ../aa_demo.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o aa_demo $(LIBS) + +aa_test: ../aa_test.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o aa_test $(LIBS) + +alpha_gradient: ../alpha_gradient.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o alpha_gradient $(LIBS) + +alpha_mask: ../alpha_mask.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o alpha_mask $(LIBS) + +alpha_mask2: ../alpha_mask2.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o alpha_mask2 $(LIBS) + +alpha_mask3: ../alpha_mask3.o ../make_arrows.o ../make_gb_poly.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o alpha_mask3 $(LIBS) + +bezier_div: ../bezier_div.o ../interactive_polygon.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o bezier_div $(LIBS) + +blur: ../blur.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o blur $(LIBS) + +bspline: ../bspline.o ../interactive_polygon.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o bspline $(LIBS) + +circles: ../circles.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o circles $(LIBS) + +component_rendering: ../component_rendering.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o component_rendering $(LIBS) + +compositing: ../compositing.o $(PLATFORMSOURCES) compositing.ppm + $(CXX) $(CXXFLAGS) ../compositing.o $(PLATFORMSOURCES) -o compositing $(LIBS) + +compositing2: ../compositing2.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o compositing2 $(LIBS) + +conv_contour: ../conv_contour.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o conv_contour $(LIBS) + +conv_dash_marker: ../conv_dash_marker.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o conv_dash_marker $(LIBS) + +conv_stroke: ../conv_stroke.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o conv_stroke $(LIBS) + +distortions: ../distortions.o $(PLATFORMSOURCES) spheres.ppm + $(CXX) $(CXXFLAGS) ../distortions.o $(PLATFORMSOURCES) -o distortions $(LIBS) + +flash_rasterizer: ../flash_rasterizer.o $(PLATFORMSOURCES) shapes.txt + $(CXX) $(CXXFLAGS) ../flash_rasterizer.o $(PLATFORMSOURCES) -o flash_rasterizer $(LIBS) + +flash_rasterizer2: ../flash_rasterizer2.o $(PLATFORMSOURCES) shapes.txt + $(CXX) $(CXXFLAGS) ../flash_rasterizer2.o $(PLATFORMSOURCES) -o flash_rasterizer2 $(LIBS) + +gamma_correction: ../gamma_correction.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gamma_correction $(LIBS) + +gamma_ctrl: ../gamma_ctrl.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gamma_ctrl $(LIBS) + +gamma_tuner: ../gamma_tuner.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gamma_tuner $(LIBS) + +gouraud: ../gouraud.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gouraud $(LIBS) + +gouraud_mesh: ../gouraud_mesh.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gouraud_mesh $(LIBS) + +gradient_focal: ../gradient_focal.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gradient_focal $(LIBS) + +gradients: ../gradients.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gradients $(LIBS) + +graph_test: ../graph_test.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o graph_test $(LIBS) + +idea: ../idea.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o idea $(LIBS) + +image_alpha: ../image_alpha.o $(PLATFORMSOURCES) spheres.ppm + $(CXX) $(CXXFLAGS) ../image_alpha.o $(PLATFORMSOURCES) -o image_alpha $(LIBS) + +image_filters: ../image_filters.o $(PLATFORMSOURCES) spheres.ppm + $(CXX) $(CXXFLAGS) ../image_filters.o $(PLATFORMSOURCES) -o image_filters $(LIBS) + +image_filters2: ../image_filters2.o $(PLATFORMSOURCES) spheres.ppm + $(CXX) $(CXXFLAGS) ../image_filters2.o $(PLATFORMSOURCES) -o image_filters2 $(LIBS) + +image_fltr_graph: ../image_fltr_graph.o $(PLATFORMSOURCES) spheres.ppm + $(CXX) $(CXXFLAGS) ../image_fltr_graph.o $(PLATFORMSOURCES) -o image_fltr_graph $(LIBS) + +image_perspective: ../image_perspective.o ../interactive_polygon.o $(PLATFORMSOURCES) spheres.ppm + $(CXX) $(CXXFLAGS) ../image_perspective.o ../interactive_polygon.o $(PLATFORMSOURCES) -o image_perspective $(LIBS) + +image_resample: ../image_resample.o ../interactive_polygon.o $(PLATFORMSOURCES) spheres.ppm + $(CXX) $(CXXFLAGS) ../image_resample.o ../interactive_polygon.o $(PLATFORMSOURCES) -o image_resample $(LIBS) + +image_transforms: ../image_transforms.o $(PLATFORMSOURCES) spheres.ppm + $(CXX) $(CXXFLAGS) ../image_transforms.o $(PLATFORMSOURCES) -o image_transforms $(LIBS) + +image1: ../image1.o $(PLATFORMSOURCES) spheres.ppm + $(CXX) $(CXXFLAGS) ../image1.o $(PLATFORMSOURCES) -o image1 $(LIBS) + +line_patterns: ../line_patterns.o $(PLATFORMSOURCES) 1.ppm 2.ppm 3.ppm 4.ppm 5.ppm 6.ppm 7.ppm 8.ppm 9.ppm + $(CXX) $(CXXFLAGS) ../line_patterns.o $(PLATFORMSOURCES) -o line_patterns $(LIBS) + +line_patterns_clip: ../line_patterns_clip.o $(PLATFORMSOURCES) 1.ppm + $(CXX) $(CXXFLAGS) ../line_patterns_clip.o $(PLATFORMSOURCES) -o line_patterns_clip $(LIBS) + +lion: ../lion.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o lion $(LIBS) + +lion_lens: ../lion_lens.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o lion_lens $(LIBS) + +lion_outline: ../lion_outline.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o lion_outline $(LIBS) + +mol_view: ../mol_view.o $(PLATFORMSOURCES) 1.sdf + $(CXX) $(CXXFLAGS) ../mol_view.o $(PLATFORMSOURCES) -o mol_view $(LIBS) + +multi_clip: ../multi_clip.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o multi_clip $(LIBS) + +pattern_fill: ../pattern_fill.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o pattern_fill $(LIBS) + +pattern_perspective: ../pattern_perspective.o ../interactive_polygon.o $(PLATFORMSOURCES) agg.ppm + $(CXX) $(CXXFLAGS) ../pattern_perspective.o ../interactive_polygon.o $(PLATFORMSOURCES) -o pattern_perspective $(LIBS) + +perspective: ../perspective.o ../interactive_polygon.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o perspective $(LIBS) + +polymorphic_renderer: ../polymorphic_renderer.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o polymorphic_renderer $(LIBS) + +raster_text: ../raster_text.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o raster_text $(LIBS) + +rasterizers: ../rasterizers.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o rasterizers $(LIBS) + +rasterizers2: ../rasterizers2.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o rasterizers2 $(LIBS) + +rasterizer_compound: ../rasterizer_compound.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o rasterizer_compound $(LIBS) + +blend_color: ../blend_color.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o blend_color $(LIBS) + +rounded_rect: ../rounded_rect.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o rounded_rect $(LIBS) + +scanline_boolean: ../scanline_boolean.o ../interactive_polygon.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o scanline_boolean $(LIBS) + +scanline_boolean2: ../scanline_boolean2.o ../make_arrows.o ../make_gb_poly.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o scanline_boolean2 $(LIBS) + +simple_blur: ../simple_blur.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o simple_blur $(LIBS) + +trans_polar: ../trans_polar.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o trans_polar $(LIBS) + +freetype_test: ../freetype_test.o ../../font_freetype/agg_font_freetype.o $(PLATFORMSOURCES) timesi.ttf + $(CXX) $(CXXFREETYPEFLAGS) ../freetype_test.o ../../font_freetype/agg_font_freetype.o $(PLATFORMSOURCES) -o freetype_test $(LIBS) -lfreetype + +trans_curve1_ft: ../trans_curve1_ft.o ../../font_freetype/agg_font_freetype.o ../interactive_polygon.o $(PLATFORMSOURCES) timesi.ttf + $(CXX) $(CXXFLAGS) ../trans_curve1_ft.o ../../font_freetype/agg_font_freetype.o ../interactive_polygon.o $(PLATFORMSOURCES) -o trans_curve1_ft $(LIBS) -lfreetype + +trans_curve2_ft: ../trans_curve2_ft.o ../../font_freetype/agg_font_freetype.o ../interactive_polygon.o $(PLATFORMSOURCES) timesi.ttf + $(CXX) $(CXXFLAGS) ../trans_curve2_ft.o ../../font_freetype/agg_font_freetype.o ../interactive_polygon.o $(PLATFORMSOURCES) -o trans_curve2_ft $(LIBS) -lfreetype + +gpc_test: ../gpc_test.o ../make_arrows.o ../make_gb_poly.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gpc_test $(LIBS) + +svg_test: ../svg_viewer/agg_svg_parser.o ../svg_viewer/agg_svg_path_renderer.o ../svg_viewer/agg_svg_path_tokenizer.o ../svg_viewer/svg_test.o $(PLATFORMSOURCES) tiger.svg + $(CXX) $(CXXFLAGS) ../svg_viewer/agg_svg_parser.o ../svg_viewer/agg_svg_path_renderer.o ../svg_viewer/agg_svg_path_tokenizer.o ../svg_viewer/svg_test.o $(PLATFORMSOURCES) -o svg_test $(LIBS) -lfreetype -lexpat + +clean: + rm -f ../*.o + rm -f ../svg_viewer/*.o + rm -f ../../src/platform/$(PLATFORM)/agg_platform_support.o + +agg.ppm: + @echo "Please download http://www.antigrain.com/agg.ppm" + @echo "Attempting to retrieve via wget: (will fail if wget is not installed)" + wget http://www.antigrain.com/agg.ppm + +compositing.ppm: + @echo "Please download http://www.antigrain.com/compositing.ppm" + @echo "Attempting to retrieve via wget: (will fail if wget is not installed)" + wget http://www.antigrain.com/compositing.ppm + +spheres.ppm: + @echo "Please download http://www.antigrain.com/spheres.ppm" + @echo "Attempting to retrieve file: (will fail if wget is not installed)" + wget http://www.antigrain.com/spheres.ppm + +shapes.txt: + @echo "Please download http://www.antigrain.com/shapes.txt" + @echo "Attempting to retrieve file: (will fail if wget is not installed)" + wget http://www.antigrain.com/shapes.txt + +1.sdf: + @echo "Please download http://www.antigrain.com/1.sdf" + @echo "Attempting to retrieve file: (will fail if wget is not installed)" + wget http://www.antigrain.com/1.sdf + +1.ppm: + @echo "Please download http://www.antigrain.com/line_patterns.tar.gz and decompress it" + @echo "Attempting to retrieve file: (will fail if wget is not installed)" + wget http://www.antigrain.com/line_patterns.tar.gz + gunzip line_patterns.tar.gz + tar -xvf line_patterns.tar + +timesi.ttf: + @echo "Please download http://www.antigrain.com/timesi.zip and decompress it" + @echo "Attempting to retrieve file: (will fail if wget is not installed)" + wget http://www.antigrain.com/timesi.zip + unzip -o timesi.zip + +tiger.svg: + @echo "Please download http://www.antigrain.com/svg/tiger.svg" + @echo "Attempting to retrieve file: (will fail if wget is not installed)" + wget http://www.antigrain.com/svg/tiger.svg + +../freetype_test.o: ../freetype_test.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFREETYPEFLAGS) $*.cpp -o $@ + +../trans_curve1_ft.o: ../trans_curve1_ft.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFREETYPEFLAGS) $*.cpp -o $@ + +../trans_curve2_ft.o: ../trans_curve2_ft.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFREETYPEFLAGS) $*.cpp -o $@ + +../../font_freetype/agg_font_freetype.o: ../../font_freetype/agg_font_freetype.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFREETYPEFLAGS) $*.cpp -o $@ + +../gpc_test.o: ../gpc_test.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) -I../../gpc $*.cpp -o $@ + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + +.PHONY : clean + + diff --git a/jni/desmume/src/android/agg/examples/X11/readme.txt b/jni/desmume/src/android/agg/examples/X11/readme.txt new file mode 100755 index 0000000..74034c9 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/X11/readme.txt @@ -0,0 +1,36 @@ +The Anti-Grain Geometry Project +A high quality rendering engine for C++ +http://antigrain.com + +Anti-Grain Geometry +Copyright (C) 2002-2005 Maxim Shemanarev (McSeem) + +Permission to copy, use, modify, sell and distribute this software +is granted provided this copyright notice appears in all copies. +This software is provided "as is" without express or implied +warranty, and with no claim as to its suitability for any purpose. + +By default only the examples that do not require extra dependancies are built. +with the following commands: + +cd (AGGDIRECTORY)/examples/X11 +make clean +make + +Some examples (freetype_test, trans_curve1_ft and trans_curve2_ft) require the Freetype Library, and can be built with: + +make freetype + +There is also an example (gpc_test) that requires the GPC library, build it with: + +make gpc + +Of course, to build ALL examples run: + +make all + +Alternatively you can also build the examples one by one, using the example name directly: + +make aa_demo +make aa_test +... \ No newline at end of file diff --git a/jni/desmume/src/android/agg/examples/aa_demo.cpp b/jni/desmume/src/android/agg/examples/aa_demo.cpp new file mode 100755 index 0000000..8bafc62 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/aa_demo.cpp @@ -0,0 +1,305 @@ +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_pixfmt_rgb.h" +#include "platform/agg_platform_support.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" + + +enum flip_y_e { flip_y = true }; + + +namespace agg +{ + + class square + { + public: + square(double size) : m_size(size) {} + + template + void draw(Rasterizer& ras, Scanline& sl, Renderer& ren, ColorT color, + double x, double y) + { + ras.reset(); + ras.move_to_d(x*m_size, y*m_size); + ras.line_to_d(x*m_size+m_size, y*m_size); + ras.line_to_d(x*m_size+m_size, y*m_size+m_size); + ras.line_to_d(x*m_size, y*m_size+m_size); + agg::render_scanlines_aa_solid(ras, sl, ren, color); + } + + private: + double m_size; + }; + + + + template class renderer_enlarged + { + public: + renderer_enlarged(Renderer& ren, double size) : + m_ren(ren), + m_square(size), + m_size(size) {} + + //-------------------------------------------------------------------- + void color(rgba8 c) { m_color = c; } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + template void render(const Scanline& sl) + { + int y = sl.y(); + + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + + do + { + int x = span->x; + const typename Scanline::cover_type* covers = span->covers; + int num_pix = span->len; + + do + { + int a = (*covers++ * m_color.a) >> 8; + m_square.draw(m_ras, m_sl, m_ren, + rgba8(m_color.r, m_color.g, m_color.b, a), + x, y); + ++x; + } + while(--num_pix); + } + while(--num_spans); + } + + private: + rasterizer_scanline_aa<> m_ras; + scanline_u8 m_sl; + Renderer& m_ren; + square m_square; + rgba8 m_color; + double m_size; + }; + + + +}; + + + + + + + + + + + + + + + + + + + +class the_application : public agg::platform_support +{ + double m_x[3]; + double m_y[3]; + double m_dx; + double m_dy; + int m_idx; + + agg::slider_ctrl m_slider1; + agg::slider_ctrl m_slider2; + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_slider1(80, 10, 600-10, 19, !flip_y), + m_slider2(80, 10+20, 600-10, 19+20, !flip_y) + { + m_idx = -1; + m_x[0] = 57; m_y[0] = 100; + m_x[1] = 369; m_y[1] = 170; + m_x[2] = 143; m_y[2] = 310; + + add_ctrl(m_slider1); + add_ctrl(m_slider2); + + m_slider1.range(8.0, 100.0); + m_slider1.num_steps(23); + m_slider1.value(32.0); + + m_slider2.range(0.1, 3.0); + m_slider2.value(1.0); + + m_slider1.label("Pixel size=%1.0f"); + m_slider2.label("Gamma=%4.3f"); + + m_slider1.no_transform(); + m_slider2.no_transform(); + } + + + virtual ~the_application() + { + } + + + virtual void on_init() + { + } + + + virtual void on_draw() + { + typedef agg::renderer_base ren_base; + + agg::pixfmt_bgr24 pixf(rbuf_window()); + ren_base ren(pixf); + agg::scanline_u8 sl; + + ren.clear(agg::rgba(1,1,1)); + + agg::rasterizer_scanline_aa<> ras; + + int size_mul = int(m_slider1.value()); + + ras.gamma(agg::gamma_power(m_slider2.value())); + + + agg::renderer_enlarged ren_en(ren, size_mul); + + ras.reset(); + ras.move_to_d(m_x[0]/size_mul, m_y[0]/size_mul); + ras.line_to_d(m_x[1]/size_mul, m_y[1]/size_mul); + ras.line_to_d(m_x[2]/size_mul, m_y[2]/size_mul); + ren_en.color(agg::rgba8(0,0,0, 255)); + agg::render_scanlines(ras, sl, ren_en); + + + agg::render_scanlines_aa_solid(ras, sl, ren, agg::rgba8(0,0,0)); + + ras.gamma(agg::gamma_none()); + + agg::path_storage ps; + agg::conv_stroke pg(ps); + pg.width(2.0); + + ps.remove_all(); + ps.move_to(m_x[0], m_y[0]); + ps.line_to(m_x[1], m_y[1]); + ras.add_path(pg); + agg::render_scanlines_aa_solid(ras, sl, ren, agg::rgba8(0,150,160, 200)); + + ps.remove_all(); + ps.move_to(m_x[1], m_y[1]); + ps.line_to(m_x[2], m_y[2]); + ras.add_path(pg); + agg::render_scanlines_aa_solid(ras, sl, ren, agg::rgba8(0,150,160, 200)); + + ps.remove_all(); + ps.move_to(m_x[2], m_y[2]); + ps.line_to(m_x[0], m_y[0]); + ras.add_path(pg); + agg::render_scanlines_aa_solid(ras, sl, ren, agg::rgba8(0,150,160, 200)); + + // Render the controls + agg::render_ctrl(ras, sl, ren, m_slider1); + agg::render_ctrl(ras, sl, ren, m_slider2); + } + + + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + unsigned i; + for (i = 0; i < 3; i++) + { + if(sqrt( (x-m_x[i]) * (x-m_x[i]) + (y-m_y[i]) * (y-m_y[i]) ) < 10.0) + { + m_dx = x - m_x[i]; + m_dy = y - m_y[i]; + m_idx = i; + break; + } + } + if(i == 3) + { + if(agg::point_in_triangle(m_x[0], m_y[0], + m_x[1], m_y[1], + m_x[2], m_y[2], + x, y)) + { + m_dx = x - m_x[0]; + m_dy = y - m_y[0]; + m_idx = 3; + } + } + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_idx == 3) + { + double dx = x - m_dx; + double dy = y - m_dy; + m_x[1] -= m_x[0] - dx; + m_y[1] -= m_y[0] - dy; + m_x[2] -= m_x[0] - dx; + m_y[2] -= m_y[0] - dy; + m_x[0] = dx; + m_y[0] = dy; + force_redraw(); + return; + } + + if(m_idx >= 0) + { + m_x[m_idx] = x - m_dx; + m_y[m_idx] = y - m_dy; + force_redraw(); + } + } + else + { + on_mouse_button_up(x, y, flags); + } + } + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + m_idx = -1; + } +}; + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("AGG Example. Anti-Aliasing Demo"); + + if(app.init(600, 400, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/aa_test.cpp b/jni/desmume/src/android/agg/examples/aa_test.cpp new file mode 100755 index 0000000..d475b0a --- /dev/null +++ b/jni/desmume/src/android/agg/examples/aa_test.cpp @@ -0,0 +1,600 @@ +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_pixfmt_rgb.h" +#include "agg_gamma_lut.h" +#include "agg_conv_dash.h" +#include "agg_conv_stroke.h" +#include "agg_span_gradient.h" +#include "agg_span_interpolator_linear.h" +#include "agg_span_gouraud_rgba.h" +#include "agg_span_allocator.h" +#include "platform/agg_platform_support.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" + + +enum flip_y_e { flip_y = false }; + + + +typedef agg::gamma_lut gamma_lut_type; +typedef agg::pixfmt_bgr24_gamma pixfmt_type; +typedef pixfmt_type::color_type color_type; +typedef agg::renderer_base renderer_base_type; +typedef agg::renderer_scanline_aa_solid renderer_scanline_type; +typedef agg::scanline_u8 scanline_type; +typedef agg::rasterizer_scanline_aa<> rasterizer_type; + +template T min(T a, T b) { return (a < b) ? a : b; } + +inline double frand(double x) +{ + return ((((rand() << 15) | rand()) & 0x3FFFFFFF) % 1000000) * x / 1000000.0; +} + + + + +class simple_vertex_source +{ +public: + simple_vertex_source() : m_num_vertices(0), m_count(0) + { + m_cmd[0] = agg::path_cmd_stop; + } + + + simple_vertex_source(double x1, double y1, double x2, double y2) + { + init(x1, y1, x2, y2); + } + + + simple_vertex_source(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + init(x1, y1, x2, y2, x3, y3); + } + + void init(double x1, double y1, double x2, double y2) + { + m_num_vertices = 2; + m_count = 0; + m_x[0] = x1; + m_y[0] = y1; + m_x[1] = x2; + m_y[1] = y2; + m_cmd[0] = agg::path_cmd_move_to; + m_cmd[1] = agg::path_cmd_line_to; + m_cmd[2] = agg::path_cmd_stop; + } + + + + void init(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + m_num_vertices = 3; + m_count = 0; + m_x[0] = x1; + m_y[0] = y1; + m_x[1] = x2; + m_y[1] = y2; + m_x[2] = x3; + m_y[2] = y3; + m_x[3] = m_y[3] = m_x[4] = m_y[4] = 0.0; + m_cmd[0] = agg::path_cmd_move_to; + m_cmd[1] = agg::path_cmd_line_to; + m_cmd[2] = agg::path_cmd_line_to; + m_cmd[3] = agg::path_cmd_end_poly | agg::path_flags_close; + m_cmd[4] = agg::path_cmd_stop; + } + + + void rewind(unsigned) + { + m_count = 0; + } + + unsigned vertex(double* x, double* y) + { + *x = m_x[m_count]; + *y = m_y[m_count]; + return m_cmd[m_count++]; + } + +private: + unsigned m_num_vertices; + unsigned m_count; + double m_x[8]; + double m_y[8]; + unsigned m_cmd[8]; +}; + + + + + +template class dashed_line +{ +public: + dashed_line(Ras& ras, Ren& ren, Scanline& sl) : + m_ras(ras), m_ren(ren), m_sl(sl), + m_src(), + m_dash(m_src), + m_stroke(m_src), + m_dash_stroke(m_dash) + {} + + void draw(double x1, double y1, double x2, double y2, + double line_width, double dash_length) + { + m_src.init(x1 + 0.5, y1 + 0.5, x2 + 0.5, y2 + 0.5); + m_ras.reset(); + if(dash_length > 0.0) + { + m_dash.remove_all_dashes(); + m_dash.add_dash(dash_length, dash_length); + m_dash_stroke.width(line_width); + m_dash_stroke.line_cap(agg::round_cap); + m_ras.add_path(m_dash_stroke); + } + else + { + m_stroke.width(line_width); + m_stroke.line_cap(agg::round_cap); + m_ras.add_path(m_stroke); + } + agg::render_scanlines(m_ras, m_sl, m_ren); + } + +private: + Ras& m_ras; + Ren& m_ren; + Scanline& m_sl; + simple_vertex_source m_src; + agg::conv_dash m_dash; + agg::conv_stroke m_stroke; + agg::conv_stroke > m_dash_stroke; +}; + + + +// Calculate the affine transformation matrix for the linear gradient +// from (x1, y1) to (x2, y2). gradient_d2 is the "base" to scale the +// gradient. Here d1 must be 0.0, and d2 must equal gradient_d2. +//--------------------------------------------------------------- +void calc_linear_gradient_transform(double x1, double y1, double x2, double y2, + agg::trans_affine& mtx, + double gradient_d2 = 100.0) +{ + double dx = x2 - x1; + double dy = y2 - y1; + mtx.reset(); + mtx *= agg::trans_affine_scaling(sqrt(dx * dx + dy * dy) / gradient_d2); + mtx *= agg::trans_affine_rotation(atan2(dy, dx)); + mtx *= agg::trans_affine_translation(x1 + 0.5, y1 + 0.5); + mtx.invert(); +} + + +// A simple function to form the gradient color array +// consisting of 3 colors, "begin", "middle", "end" +//--------------------------------------------------- +template +void fill_color_array(ColorArrayT& array, + color_type begin, + color_type end) +{ + unsigned i; + for(i = 0; i < 256; ++i) + { + array[i] = begin.gradient(end, i / 255.0); + } +} + + + + + + +class the_application : public agg::platform_support +{ + gamma_lut_type m_gamma; + agg::slider_ctrl m_slider_gamma; + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_gamma(1.0), + m_slider_gamma(3, 3, 480-3, 8, !flip_y) + { + add_ctrl(m_slider_gamma); + m_slider_gamma.range(0.1, 3.0); + m_slider_gamma.value(1.6); + m_slider_gamma.label("Gamma=%4.3f"); + } + + + virtual ~the_application() + { + } + + + virtual void on_init() + { + } + + + virtual void on_draw() + { + pixfmt_type pixf(rbuf_window(), m_gamma); + renderer_base_type ren_base(pixf); + renderer_scanline_type ren_sl(ren_base); + scanline_type sl; + rasterizer_type ras; + + ren_base.clear(agg::rgba(0,0,0)); + + + // gamma correction + //ras.gamma(agg::gamma_power()); + m_gamma.gamma(m_slider_gamma.value()); + + int i; + + // radial line test + //------------------------- + dashed_line dash(ras, ren_sl, sl); + + double cx = width() / 2.0; + double cy = height() / 2.0; + + ren_sl.color(agg::rgba(1.0, 1.0, 1.0, 0.2)); + for(i = 180; i > 0; i--) + { + double n = 2.0 * agg::pi * i / 180.0; + dash.draw(cx + min(cx, cy) * sin(n), cy + min(cx, cy) * cos(n), + cx, cy, + 1.0, (i < 90) ? i : 0.0); + } + + + typedef agg::gradient_x gradient_func_type; + typedef agg::span_interpolator_linear<> interpolator_type; + typedef agg::span_allocator span_allocator_type; + typedef agg::pod_auto_array color_array_type; + typedef agg::span_gradient span_gradient_type; + + typedef agg::renderer_scanline_aa renderer_gradient_type; + + gradient_func_type gradient_func; // The gradient function + agg::trans_affine gradient_mtx; // Affine transformer + interpolator_type span_interpolator(gradient_mtx); // Span interpolator + span_allocator_type span_allocator; // Span Allocator + color_array_type gradient_colors; // The gradient colors + span_gradient_type span_gradient(span_interpolator, + gradient_func, + gradient_colors, + 0, 100); + + renderer_gradient_type ren_gradient(ren_base, span_allocator, span_gradient); + + dashed_line dash_gradient(ras, ren_gradient, sl); + + double x1, y1, x2, y2; + + for(i = 1; i <= 20; i++) + { + ren_sl.color(agg::rgba(1,1,1)); + + // integral point sizes 1..20 + //---------------- + agg::ellipse ell; + + ell.init(20 + i * (i + 1) + 0.5, + 20.5, + i / 2.0, + i / 2.0, + 8 + i); + ras.reset(); + ras.add_path(ell); + agg::render_scanlines(ras, sl, ren_sl); + + + // fractional point sizes 0..2 + //---------------- + ell.init(18 + i * 4 + 0.5, 33 + 0.5, + i/20.0, i/20.0, + 8); + ras.reset(); + ras.add_path(ell); + agg::render_scanlines(ras, sl, ren_sl); + + + // fractional point positioning + //--------------- + ell.init(18 + i * 4 + (i-1) / 10.0 + 0.5, + 27 + (i - 1) / 10.0 + 0.5, + 0.5, 0.5, 8); + ras.reset(); + ras.add_path(ell); + agg::render_scanlines(ras, sl, ren_sl); + + + // integral line widths 1..20 + //---------------- + fill_color_array(gradient_colors, + agg::rgba(1,1,1), + agg::rgba(i % 2, (i % 3) * 0.5, (i % 5) * 0.25)); + + x1 = 20 + i* (i + 1); + y1 = 40.5; + x2 = 20 + i * (i + 1) + (i - 1) * 4; + y2 = 100.5; + calc_linear_gradient_transform(x1, y1, x2, y2, gradient_mtx); + dash_gradient.draw(x1, y1, x2, y2, i, 0); + + + fill_color_array(gradient_colors, + agg::rgba(1,0,0), + agg::rgba(0,0,1)); + + // fractional line lengths H (red/blue) + //---------------- + x1 = 17.5 + i * 4; + y1 = 107; + x2 = 17.5 + i * 4 + i/6.66666667; + y2 = 107; + calc_linear_gradient_transform(x1, y1, x2, y2, gradient_mtx); + dash_gradient.draw(x1, y1, x2, y2, 1.0, 0); + + + // fractional line lengths V (red/blue) + //--------------- + x1 = 18 + i * 4; + y1 = 112.5; + x2 = 18 + i * 4; + y2 = 112.5 + i / 6.66666667; + calc_linear_gradient_transform(x1, y1, x2, y2, gradient_mtx); + dash_gradient.draw(x1, y1, x2, y2, 1.0, 0); + + // fractional line positioning (red) + //--------------- + fill_color_array(gradient_colors, + agg::rgba(1,0,0), + agg::rgba(1,1,1)); + x1 = 21.5; + y1 = 120 + (i - 1) * 3.1; + x2 = 52.5; + y2 = 120 + (i - 1) * 3.1; + calc_linear_gradient_transform(x1, y1, x2, y2, gradient_mtx); + dash_gradient.draw(x1, y1, x2, y2, 1.0, 0); + + + // fractional line width 2..0 (green) + fill_color_array(gradient_colors, + agg::rgba(0,1,0), + agg::rgba(1,1,1)); + x1 = 52.5; + y1 = 118 + i * 3; + x2 = 83.5; + y2 = 118 + i * 3; + calc_linear_gradient_transform(x1, y1, x2, y2, gradient_mtx); + dash_gradient.draw(x1, y1, x2, y2, 2.0 - (i - 1) / 10.0, 0); + + // stippled fractional width 2..0 (blue) + fill_color_array(gradient_colors, + agg::rgba(0,0,1), + agg::rgba(1,1,1)); + x1 = 83.5; + y1 = 119 + i * 3; + x2 = 114.5; + y2 = 119 + i * 3; + calc_linear_gradient_transform(x1, y1, x2, y2, gradient_mtx); + dash_gradient.draw(x1, y1, x2, y2, 2.0 - (i - 1) / 10.0, 3.0); + + + ren_sl.color(agg::rgba(1,1,1)); + if(i <= 10) + { + // integral line width, horz aligned (mipmap test) + //------------------- + dash.draw(125.5, 119.5 + (i + 2) * (i / 2.0), + 135.5, 119.5 + (i + 2) * (i / 2.0), + i, 0.0); + } + + // fractional line width 0..2, 1 px H + //----------------- + dash.draw(17.5 + i * 4, 192, 18.5 + i * 4, 192, i / 10.0, 0); + + // fractional line positioning, 1 px H + //----------------- + dash.draw(17.5 + i * 4 + (i - 1) / 10.0, 186, + 18.5 + i * 4 + (i - 1) / 10.0, 186, + 1.0, 0); + } + + + // Triangles + //--------------- + for (i = 1; i <= 13; i++) + { + fill_color_array(gradient_colors, + agg::rgba(1,1,1), + agg::rgba(i % 2, (i % 3) * 0.5, (i % 5) * 0.25)); + calc_linear_gradient_transform(width() - 150, + height() - 20 - i * (i + 1.5), + width() - 20, + height() - 20 - i * (i + 1), + gradient_mtx); + ras.reset(); + ras.move_to_d(width() - 150, height() - 20 - i * (i + 1.5)); + ras.line_to_d(width() - 20, height() - 20 - i * (i + 1)); + ras.line_to_d(width() - 20, height() - 20 - i * (i + 2)); + agg::render_scanlines(ras, sl, ren_gradient); + } + + + // Reset AA Gamma and render the controls + ras.gamma(agg::gamma_power(1.0)); + agg::render_ctrl(ras, sl, ren_base, m_slider_gamma); + } + + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + srand(123); + pixfmt_type pixf(rbuf_window(), m_gamma); + renderer_base_type ren_base(pixf); + renderer_scanline_type ren_sl(ren_base); + scanline_type sl; + rasterizer_type ras; + + ren_base.clear(agg::rgba(0,0,0)); + + int i; + + double w = width(); + double h = height(); + + agg::ellipse ell; + + start_timer(); + for(i = 0; i < 20000; i++) + { + double r = frand(20.0) + 1.0; + ell.init(frand(w), frand(h), r/2, r/2, int(r) + 10); + ras.reset(); + ras.add_path(ell); + agg::render_scanlines(ras, sl, ren_sl); + ren_sl.color(agg::rgba(frand(1.0), frand(1.0), frand(1.0), 0.5+frand(0.5))); + } + double t1 = elapsed_time(); + + typedef agg::gradient_x gradient_func_type; + typedef agg::span_interpolator_linear<> interpolator_type; + typedef agg::span_allocator span_allocator_type; + typedef agg::pod_auto_array color_array_type; + typedef agg::span_gradient span_gradient_type; + typedef agg::renderer_scanline_aa renderer_gradient_type; + + gradient_func_type gradient_func; // The gradient function + agg::trans_affine gradient_mtx; // Affine transformer + interpolator_type span_interpolator(gradient_mtx); // Span interpolator + span_allocator_type span_allocator; // Span Allocator + color_array_type gradient_colors; + span_gradient_type span_gradient(span_interpolator, + gradient_func, + gradient_colors, + 0, 100); + renderer_gradient_type ren_gradient(ren_base, + span_allocator, + span_gradient); + dashed_line dash_gradient(ras, ren_gradient, sl); + + double x1, y1, x2, y2, x3, y3; + + start_timer(); + for(i = 0; i < 2000; i++) + { + x1 = frand(w); + y1 = frand(h); + x2 = x1 + frand(w * 0.5) - w * 0.25; + y2 = y1 + frand(h * 0.5) - h * 0.25; + + fill_color_array(gradient_colors, + agg::rgba(frand(1.0), frand(1.0), frand(1.0), 0.5+frand(0.5)), + agg::rgba(frand(1.0), frand(1.0), frand(1.0), frand(1.0))); + calc_linear_gradient_transform(x1, y1, x2, y2, gradient_mtx); + dash_gradient.draw(x1, y1, x2, y2, 10.0, 0); + } + double t2 = elapsed_time(); + + + + typedef agg::span_gouraud_rgba gouraud_span_gen_type; + typedef agg::renderer_scanline_aa renderer_gouraud_type; + + gouraud_span_gen_type span_gouraud; + renderer_gouraud_type ren_gouraud(ren_base, span_allocator, span_gouraud); + + + start_timer(); + for(i = 0; i < 2000; i++) + { + x1 = frand(w); + y1 = frand(h); + x2 = x1 + frand(w * 0.4) - w * 0.2; + y2 = y1 + frand(h * 0.4) - h * 0.2; + x3 = x1 + frand(w * 0.4) - w * 0.2; + y3 = y1 + frand(h * 0.4) - h * 0.2; + + span_gouraud.colors(agg::rgba(frand(1.0), frand(1.0), frand(1.0), 0.5+frand(0.5)), + agg::rgba(frand(1.0), frand(1.0), frand(1.0), frand(1.0)), + agg::rgba(frand(1.0), frand(1.0), frand(1.0), frand(1.0))); + span_gouraud.triangle(x1, y1, x2, y2, x3, y3, 0.0); + ras.add_path(span_gouraud); + agg::render_scanlines(ras, sl, ren_gouraud); + } + + double t3 = elapsed_time(); + + char buf[256]; + sprintf(buf, "Points=%.2fK/sec, Lines=%.2fK/sec, Triangles=%.2fK/sec", 20000.0/t1, 2000.0/t2, 2000.0/t3); + message(buf); + update_window(); + } + + + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + } + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + } +}; + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("AGG Example. Anti-Aliasing Test"); + + if(app.init(480, 350, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/alpha_gradient.cpp b/jni/desmume/src/android/agg/examples/alpha_gradient.cpp new file mode 100755 index 0000000..991103d --- /dev/null +++ b/jni/desmume/src/android/agg/examples/alpha_gradient.cpp @@ -0,0 +1,375 @@ +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_span_gradient.h" +#include "agg_span_gradient_alpha.h" +#include "agg_span_interpolator_linear.h" +#include "agg_span_allocator.h" +#include "agg_span_converter.h" +#include "agg_ellipse.h" +#include "agg_pixfmt_rgb.h" +#include "agg_vcgen_stroke.h" +#include "platform/agg_platform_support.h" + +#include "ctrl/agg_spline_ctrl.h" + +enum flip_y_e { flip_y = true }; + + + +#define pix_format agg::pix_format_bgr24 +typedef agg::pixfmt_bgr24 pixfmt_type; +typedef pixfmt_type::color_type color_type; +typedef color_type::value_type color_value_type; + + +class the_application : public agg::platform_support +{ + double m_x[3]; + double m_y[3]; + double m_dx; + double m_dy; + int m_idx; + agg::spline_ctrl m_alpha; + + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_idx(-1), + m_alpha(2, 2, 200, 30, 6, !flip_y) + { + m_x[0] = 257; m_y[0] = 60; + m_x[1] = 369; m_y[1] = 170; + m_x[2] = 143; m_y[2] = 310; + + m_alpha.point(0, 0.0, 0.0); + m_alpha.point(1, 1.0/5.0, 1.0 - 4.0/5.0); + m_alpha.point(2, 2.0/5.0, 1.0 - 3.0/5.0); + m_alpha.point(3, 3.0/5.0, 1.0 - 2.0/5.0); + m_alpha.point(4, 4.0/5.0, 1.0 - 1.0/5.0); + m_alpha.point(5, 1.0, 1.0); + m_alpha.update_spline(); + add_ctrl(m_alpha); + } + + + + // A simple function to form the gradient color array + // consisting of 3 colors, "begin", "middle", "end" + //--------------------------------------------------- + template + static void fill_color_array(ColorArrayT& array, + color_type begin, + color_type middle, + color_type end) + { + unsigned i; + for(i = 0; i < 128; ++i) + { + array[i] = begin.gradient(middle, i / 128.0); + } + for(; i < 256; ++i) + { + array[i] = middle.gradient(end, (i - 128) / 128.0); + } + } + + + + virtual void on_draw() + { + typedef agg::renderer_base base_ren_type; + + pixfmt_type pf(rbuf_window()); + base_ren_type ren_base(pf); + ren_base.clear(agg::rgba(1,1,1)); + + agg::scanline_u8 sl; + agg::rasterizer_scanline_aa<> ras; + + + // Draw some background + agg::ellipse ell; + srand(1234); + unsigned i; + unsigned w = unsigned(width()); + unsigned h = unsigned(height()); + for(i = 0; i < 100; i++) + { + ell.init(rand() % w, rand() % h, rand() % 60 + 5, rand() % 60 + 5, 50); + ras.add_path(ell); + agg::render_scanlines_aa_solid(ras, sl, ren_base, + agg::rgba(rand() / double(RAND_MAX), + rand() / double(RAND_MAX), + rand() / double(RAND_MAX), + rand() / double(RAND_MAX) / 2.0)); + } + + + + double parallelogram[6]; + parallelogram[0] = m_x[0]; + parallelogram[1] = m_y[0]; + parallelogram[2] = m_x[1]; + parallelogram[3] = m_y[1]; + parallelogram[4] = m_x[2]; + parallelogram[5] = m_y[2]; + + + // Gradient shape function (linear, radial, custom, etc) + //----------------- + typedef agg::gradient_circle gradient_func_type; + + // Alpha gradient shape function (linear, radial, custom, etc) + //----------------- + typedef agg::gradient_xy gradient_alpha_func_type; + + // Span interpolator. This object is used in all span generators + // that operate with transformations during iterating of the spans, + // for example, image transformers use the interpolator too. + //----------------- + typedef agg::span_interpolator_linear<> interpolator_type; + + + // Span allocator is an object that allocates memory for + // the array of colors that will be used to render the + // color spans. One object can be shared between different + // span generators. + //----------------- + typedef agg::span_allocator span_allocator_type; + + + // Gradient colors array adaptor + //----------------- + typedef agg::pod_auto_array gradient_colors_type; + + + // Finally, the gradient span generator working with the color_type + // color type. + //----------------- + typedef agg::span_gradient span_gradient_type; + + + // Gradient alpha array adaptor + //----------------- + typedef agg::pod_auto_array gradient_alpha_type; + + // The alpha gradient span converter working with the color_type + // color type. + //----------------- + typedef agg::span_gradient_alpha span_gradient_alpha_type; + + + // Span converter type + //----------------- + typedef agg::span_converter span_conv_type; + + + // The gradient objects declarations + //---------------- + gradient_func_type gradient_func; // The gradient function + gradient_alpha_func_type alpha_func; // The gradient function + agg::trans_affine gradient_mtx; // Gradient affine transformer + agg::trans_affine alpha_mtx; // Alpha affine transformer + interpolator_type span_interpolator(gradient_mtx); // Span gradient interpolator + interpolator_type span_interpolator_alpha(alpha_mtx); // Span alpha interpolator + span_allocator_type span_allocator; // Span Allocator + gradient_colors_type color_array; // The gradient colors + + // Declare the gradient span itself. + // The last two arguments are so called "d1" and "d2" + // defining two distances in pixels, where the gradient starts + // and where it ends. The actual meaning of "d1" and "d2" depands + // on the gradient function. + //---------------- + span_gradient_type span_gradient(span_interpolator, + gradient_func, + color_array, + 0, 150); + + // Declare the gradient span itself. + // The last two arguments are so called "d1" and "d2" + // defining two distances in pixels, where the gradient starts + // and where it ends. The actual meaning of "d1" and "d2" depands + // on the gradient function. + //---------------- + gradient_alpha_type alpha_array; + span_gradient_alpha_type span_gradient_alpha(span_interpolator_alpha, + alpha_func, + alpha_array, + 0, 100); + + // Span converter declaration + span_conv_type span_conv(span_gradient, span_gradient_alpha); + + + // Finally we can draw a circle. + //---------------- + gradient_mtx *= agg::trans_affine_scaling(0.75, 1.2); + gradient_mtx *= agg::trans_affine_rotation(-agg::pi/3.0); + gradient_mtx *= agg::trans_affine_translation(width()/2, height()/2); + gradient_mtx.invert(); + alpha_mtx.parl_to_rect(parallelogram, -100, -100, 100, 100); + fill_color_array(color_array, + agg::rgba(0, 0.19, 0.19), + agg::rgba(0.7, 0.7, 0.19), + agg::rgba(0.31, 0, 0)); + + // Fill Alpha array + //---------------- + for(i = 0; i < 256; i++) + { + alpha_array[i] = color_value_type(m_alpha.value(i / 255.0) * double(color_type::base_mask)); + } + + ell.init(width()/2, height()/2, 150, 150, 100); + ras.add_path(ell); + + // Render the circle with gradient plus alpha-gradient + agg::render_scanlines_aa(ras, sl, ren_base, span_allocator, span_conv); + + + // Draw the control points and the parallelogram + //----------------- + agg::rgba color_pnt(0, 0.4, 0.4, 0.31); + ell.init(m_x[0], m_y[0], 5, 5, 20); + ras.add_path(ell); + agg::render_scanlines_aa_solid(ras, sl, ren_base, color_pnt); + ell.init(m_x[1], m_y[1], 5, 5, 20); + ras.add_path(ell); + agg::render_scanlines_aa_solid(ras, sl, ren_base, color_pnt); + ell.init(m_x[2], m_y[2], 5, 5, 20); + ras.add_path(ell); + agg::render_scanlines_aa_solid(ras, sl, ren_base, color_pnt); + + agg::vcgen_stroke stroke; + stroke.add_vertex(m_x[0], m_y[0], agg::path_cmd_move_to); + stroke.add_vertex(m_x[1], m_y[1], agg::path_cmd_line_to); + stroke.add_vertex(m_x[2], m_y[2], agg::path_cmd_line_to); + stroke.add_vertex(m_x[0]+m_x[2]-m_x[1], m_y[0]+m_y[2]-m_y[1], agg::path_cmd_line_to); + stroke.add_vertex(0, 0, agg::path_cmd_end_poly | agg::path_flags_close); + ras.add_path(stroke); + agg::render_scanlines_aa_solid(ras, sl, ren_base, agg::rgba(0, 0, 0)); + + agg::render_ctrl(ras, sl, ren_base, m_alpha); + } + + + + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + unsigned i; + if(flags & agg::mouse_left) + { + for (i = 0; i < 3; i++) + { + if(sqrt( (x-m_x[i]) * (x-m_x[i]) + (y-m_y[i]) * (y-m_y[i]) ) < 10.0) + { + m_dx = x - m_x[i]; + m_dy = y - m_y[i]; + m_idx = i; + break; + } + } + if(i == 3) + { + if(agg::point_in_triangle(m_x[0], m_y[0], + m_x[1], m_y[1], + m_x[2], m_y[2], + x, y)) + { + m_dx = x - m_x[0]; + m_dy = y - m_y[0]; + m_idx = 3; + } + + } + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_idx == 3) + { + double dx = x - m_dx; + double dy = y - m_dy; + m_x[1] -= m_x[0] - dx; + m_y[1] -= m_y[0] - dy; + m_x[2] -= m_x[0] - dx; + m_y[2] -= m_y[0] - dy; + m_x[0] = dx; + m_y[0] = dy; + force_redraw(); + return; + } + + if(m_idx >= 0) + { + m_x[m_idx] = x - m_dx; + m_y[m_idx] = y - m_dy; + force_redraw(); + } + } + else + { + on_mouse_button_up(x, y, flags); + } + } + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + m_idx = -1; + } + + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + double dx = 0; + double dy = 0; + switch(key) + { + case agg::key_left: dx = -0.1; break; + case agg::key_right: dx = 0.1; break; + case agg::key_up: dy = 0.1; break; + case agg::key_down: dy = -0.1; break; + } + m_x[0] += dx; + m_y[0] += dy; + m_x[1] += dx; + m_y[1] += dy; + force_redraw(); + } + + +}; + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Alpha channel gradient"); + + if(app.init(400, 320, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/alpha_mask.cpp b/jni/desmume/src/android/agg/examples/alpha_mask.cpp new file mode 100755 index 0000000..14e7d2a --- /dev/null +++ b/jni/desmume/src/android/agg/examples/alpha_mask.cpp @@ -0,0 +1,198 @@ +#include +#include +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_path_storage.h" +#include "agg_conv_transform.h" +#include "agg_bounding_rect.h" +#include "agg_renderer_scanline.h" +#include "agg_pixfmt_rgb.h" +#include "agg_pixfmt_gray.h" +#include "agg_alpha_mask_u8.h" +#include "agg_scanline_u.h" +#include "agg_scanline_p.h" +#include "agg_ellipse.h" +#include "platform/agg_platform_support.h" + +enum flip_y_e { flip_y = true }; + +agg::path_storage g_path; +agg::rgba8 g_colors[100]; +unsigned g_path_idx[100]; +unsigned g_npaths = 0; +double g_x1 = 0; +double g_y1 = 0; +double g_x2 = 0; +double g_y2 = 0; +double g_base_dx = 0; +double g_base_dy = 0; +double g_angle = 0; +double g_scale = 1.0; +double g_skew_x = 0; +double g_skew_y = 0; +int g_nclick = 0; + + +unsigned parse_lion(agg::path_storage& ps, agg::rgba8* colors, unsigned* path_idx); +void parse_lion() +{ + g_npaths = parse_lion(g_path, g_colors, g_path_idx); + agg::pod_array_adaptor path_idx(g_path_idx, 100); + agg::bounding_rect(g_path, path_idx, 0, g_npaths, &g_x1, &g_y1, &g_x2, &g_y2); + g_base_dx = (g_x2 - g_x1) / 2.0; + g_base_dy = (g_y2 - g_y1) / 2.0; +} + + +agg::rendering_buffer g_alpha_mask_rbuf; +agg::alpha_mask_gray8 g_alpha_mask(g_alpha_mask_rbuf); +agg::rasterizer_scanline_aa<> g_rasterizer; + + +class the_application : public agg::platform_support +{ + unsigned char* m_alpha_buf; + agg::rendering_buffer m_alpha_rbuf; + +public: + virtual ~the_application() + { + delete [] m_alpha_buf; + } + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_alpha_buf(0) + { + parse_lion(); + } + + + void generate_alpha_mask(int cx, int cy) + { + delete [] m_alpha_buf; + m_alpha_buf = new unsigned char[cx * cy]; + g_alpha_mask_rbuf.attach(m_alpha_buf, cx, cy, cx); + + typedef agg::renderer_base ren_base; + typedef agg::renderer_scanline_aa_solid renderer; + + agg::pixfmt_gray8 pixf(g_alpha_mask_rbuf); + ren_base rb(pixf); + renderer r(rb); + agg::scanline_p8 sl; + + rb.clear(agg::gray8(0)); + + agg::ellipse ell; + + int i; + for(i = 0; i < 10; i++) + { + ell.init(rand() % cx, + rand() % cy, + rand() % 100 + 20, + rand() % 100 + 20, + 100); + + g_rasterizer.add_path(ell); + r.color(agg::gray8(rand() & 0xFF, rand() & 0xFF)); + agg::render_scanlines(g_rasterizer, sl, r); + } + } + + + virtual void on_resize(int cx, int cy) + { + generate_alpha_mask(cx, cy); + } + + virtual void on_draw() + { + int width = rbuf_window().width(); + int height = rbuf_window().height(); + + typedef agg::scanline_u8_am scanline_type; + typedef agg::renderer_base ren_base; + typedef agg::renderer_scanline_aa_solid renderer; + + agg::pixfmt_bgr24 pixf(rbuf_window()); + ren_base rb(pixf); + renderer r(rb); + + scanline_type sl(g_alpha_mask); + rb.clear(agg::rgba8(255, 255, 255)); + + agg::trans_affine mtx; + mtx *= agg::trans_affine_translation(-g_base_dx, -g_base_dy); + mtx *= agg::trans_affine_scaling(g_scale, g_scale); + mtx *= agg::trans_affine_rotation(g_angle + agg::pi); + mtx *= agg::trans_affine_skewing(g_skew_x/1000.0, g_skew_y/1000.0); + mtx *= agg::trans_affine_translation(width/2, height/2); + + agg::conv_transform trans(g_path, mtx); + + agg::render_all_paths(g_rasterizer, sl, r, trans, g_colors, g_path_idx, g_npaths); + } + + + void transform(double width, double height, double x, double y) + { + x -= width / 2; + y -= height / 2; + g_angle = atan2(y, x); + g_scale = sqrt(y * y + x * x) / 100.0; + } + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + int width = rbuf_window().width(); + int height = rbuf_window().height(); + transform(width, height, x, y); + force_redraw(); + } + + if(flags & agg::mouse_right) + { + g_skew_x = x; + g_skew_y = y; + force_redraw(); + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + on_mouse_button_down(x, y, flags); + } + + +}; + + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("AGG Example. Lion with Alpha-Masking"); + + if(app.init(512, 400, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + + + + + diff --git a/jni/desmume/src/android/agg/examples/alpha_mask2.cpp b/jni/desmume/src/android/agg/examples/alpha_mask2.cpp new file mode 100755 index 0000000..f657932 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/alpha_mask2.cpp @@ -0,0 +1,416 @@ +#include +#include +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_scanline_p.h" +#include "agg_color_gray.h" +#include "agg_renderer_mclip.h" +#include "agg_renderer_scanline.h" +#include "agg_path_storage.h" +#include "agg_conv_transform.h" +#include "agg_bounding_rect.h" +#include "agg_renderer_outline_aa.h" +#include "agg_pixfmt_gray.h" +#include "agg_pixfmt_amask_adaptor.h" +#include "agg_renderer_primitives.h" +#include "agg_renderer_markers.h" +#include "agg_span_allocator.h" +#include "agg_span_gradient.h" +#include "agg_span_interpolator_linear.h" +#include "agg_rasterizer_outline_aa.h" +#include "agg_alpha_mask_u8.h" +#include "agg_ellipse.h" +#include "ctrl/agg_slider_ctrl.h" +#include "platform/agg_platform_support.h" + + +//#define AGG_GRAY8 +//#define AGG_BGR24 +//#define AGG_RGB24 +#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + +enum flip_y_e { flip_y = true }; + +agg::rasterizer_scanline_aa<> g_rasterizer; +agg::scanline_u8 g_scanline; +agg::path_storage g_path; +agg::rgba8 g_colors[100]; +unsigned g_path_idx[100]; +unsigned g_npaths = 0; +double g_x1 = 0; +double g_y1 = 0; +double g_x2 = 0; +double g_y2 = 0; +double g_base_dx = 0; +double g_base_dy = 0; +double g_angle = 0; +double g_scale = 1.0; +double g_skew_x = 0; +double g_skew_y = 0; +int g_nclick = 0; + + +unsigned parse_lion(agg::path_storage& ps, agg::rgba8* colors, unsigned* path_idx); +void parse_lion() +{ + g_npaths = parse_lion(g_path, g_colors, g_path_idx); + agg::pod_array_adaptor path_idx(g_path_idx, 100); + agg::bounding_rect(g_path, path_idx, 0, g_npaths, &g_x1, &g_y1, &g_x2, &g_y2); + g_base_dx = (g_x2 - g_x1) / 2.0; + g_base_dy = (g_y2 - g_y1) / 2.0; +} + + +namespace agg +{ + // Specializations of the gradient_linear_color for rgba8 and gray8 + // color types. Only for the sake of performance. + + //======================================================================== + template<> struct gradient_linear_color + { + typedef rgba8 color_type; + + gradient_linear_color() {} + gradient_linear_color(const color_type& c1, const color_type& c2) : + m_c1(c1), m_c2(c2) {} + + static unsigned size() { return 256; } + color_type operator [] (unsigned v) const + { + color_type c; + c.r = (int8u)((((m_c2.r - m_c1.r) * int(v)) + (m_c1.r << 8)) >> 8); + c.g = (int8u)((((m_c2.g - m_c1.g) * int(v)) + (m_c1.g << 8)) >> 8); + c.b = (int8u)((((m_c2.b - m_c1.b) * int(v)) + (m_c1.b << 8)) >> 8); + c.a = (int8u)((((m_c2.a - m_c1.a) * int(v)) + (m_c1.a << 8)) >> 8); + return c; + } + + void colors(const color_type& c1, const color_type& c2) + { + m_c1 = c1; + m_c2 = c2; + } + + color_type m_c1; + color_type m_c2; + }; + + + //======================================================================== + template<> struct gradient_linear_color + { + typedef gray8 color_type; + + gradient_linear_color() {} + gradient_linear_color(const color_type& c1, const color_type& c2) : + m_c1(c1), m_c2(c2) {} + + static unsigned size() { return 256; } + color_type operator [] (unsigned v) const + { + color_type c; + c.v = (int8u)((((m_c2.v - m_c1.v) * int(v)) + (m_c1.v << 8)) >> 8); + c.a = (int8u)((((m_c2.a - m_c1.a) * int(v)) + (m_c1.a << 8)) >> 8); + return c; + } + + void colors(const color_type& c1, const color_type& c2) + { + m_c1 = c1; + m_c2 = c2; + } + + color_type m_c1; + color_type m_c2; + }; + +} + + + + + + + + +class the_application : public agg::platform_support +{ + agg::slider_ctrl m_num_cb; + + typedef agg::amask_no_clip_gray8 alpha_mask_type; + //typedef agg::alpha_mask_gray8 alpha_mask_type; + + unsigned char* m_alpha_buf; + agg::rendering_buffer m_alpha_mask_rbuf; + alpha_mask_type m_alpha_mask; + + double m_slider_value; + + +public: + ~the_application() + { + delete [] m_alpha_buf; + } + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_num_cb(5, 5, 150, 12, !flip_y), + + m_alpha_buf(0), + m_alpha_mask_rbuf(), + m_alpha_mask(m_alpha_mask_rbuf), + m_slider_value(0.0) + { + parse_lion(); + add_ctrl(m_num_cb); + m_num_cb.range(5, 100); + m_num_cb.value(10); + m_num_cb.label("N=%.2f"); + m_num_cb.no_transform(); + } + + + + void generate_alpha_mask(int cx, int cy) + { + delete [] m_alpha_buf; + m_alpha_buf = new unsigned char[cx * cy]; + m_alpha_mask_rbuf.attach(m_alpha_buf, cx, cy, cx); + + typedef agg::renderer_base ren_base; + typedef agg::renderer_scanline_aa_solid renderer; + + agg::pixfmt_gray8 pixf(m_alpha_mask_rbuf); + ren_base rb(pixf); + renderer r(rb); + agg::scanline_p8 sl; + + rb.clear(agg::gray8(0)); + + agg::ellipse ell; + + srand(1432); + + int i; + for(i = 0; i < (int)m_num_cb.value(); i++) + { + ell.init(rand() % cx, + rand() % cy, + rand() % 100 + 20, + rand() % 100 + 20, + 100); + + g_rasterizer.add_path(ell); + r.color(agg::gray8((rand() & 127) + 128, (rand() & 127) + 128)); + agg::render_scanlines(g_rasterizer, sl, r); + } + } + + + virtual void on_resize(int cx, int cy) + { + generate_alpha_mask(cx, cy); + } + + + + + virtual void on_draw() + { + unsigned i; + int width = rbuf_window().width(); + int height = rbuf_window().height(); + + if(m_num_cb.value() != m_slider_value) + { + generate_alpha_mask(width, height); + m_slider_value = m_num_cb.value(); + } + + + pixfmt pf(rbuf_window()); + + typedef agg::pixfmt_amask_adaptor pixfmt_amask_type; + typedef agg::renderer_base amask_ren_type; + typedef agg::renderer_base base_ren_type; + + pixfmt_amask_type pfa(pf, m_alpha_mask); + amask_ren_type r(pfa); + base_ren_type rbase(pf); + + agg::renderer_scanline_aa_solid rs(r); + agg::renderer_scanline_aa_solid rb(rbase); + + agg::trans_affine mtx; + mtx *= agg::trans_affine_translation(-g_base_dx, -g_base_dy); + mtx *= agg::trans_affine_scaling(g_scale, g_scale); + mtx *= agg::trans_affine_rotation(g_angle + agg::pi); + mtx *= agg::trans_affine_skewing(g_skew_x/1000.0, g_skew_y/1000.0); + mtx *= agg::trans_affine_translation(width/2, height/2); + + rbase.clear(agg::rgba(1, 1, 1)); + + int x, y; + + // Render the lion + agg::conv_transform trans(g_path, mtx); + agg::render_all_paths(g_rasterizer, g_scanline, rs, trans, g_colors, g_path_idx, g_npaths); + + + // Render random Bresenham lines and markers + agg::renderer_markers m(r); + for(i = 0; i < 50; i++) + { + m.line_color(agg::rgba8(rand() & 0x7F, + rand() & 0x7F, + rand() & 0x7F, + (rand() & 0x7F) + 0x7F)); + m.fill_color(agg::rgba8(rand() & 0x7F, + rand() & 0x7F, + rand() & 0x7F, + (rand() & 0x7F) + 0x7F)); + + m.line(m.coord(rand() % width), m.coord(rand() % height), + m.coord(rand() % width), m.coord(rand() % height)); + + m.marker(rand() % width, rand() % height, rand() % 10 + 5, + agg::marker_e(rand() % agg::end_of_markers)); + } + + + // Render random anti-aliased lines + double w = 5.0; + agg::line_profile_aa profile; + profile.width(w); + + typedef agg::renderer_outline_aa renderer_type; + renderer_type ren(r, profile); + + typedef agg::rasterizer_outline_aa rasterizer_type; + rasterizer_type ras(ren); + ras.round_cap(true); + + for(i = 0; i < 50; i++) + { + ren.color(agg::rgba8(rand() & 0x7F, + rand() & 0x7F, + rand() & 0x7F, + //255)); + (rand() & 0x7F) + 0x7F)); + ras.move_to_d(rand() % width, rand() % height); + ras.line_to_d(rand() % width, rand() % height); + ras.render(false); + } + + + // Render random circles with gradient + typedef agg::gradient_linear_color grad_color; + typedef agg::gradient_circle grad_func; + typedef agg::span_interpolator_linear<> interpolator_type; + typedef agg::span_gradient span_grad_type; + + agg::trans_affine grm; + grad_func grf; + grad_color grc(agg::rgba8(0,0,0), agg::rgba8(0,0,0)); + agg::ellipse ell; + agg::span_allocator sa; + interpolator_type inter(grm); + span_grad_type sg(inter, grf, grc, 0, 10); + agg::renderer_scanline_aa, + span_grad_type> rg(r, sa, sg); + for(i = 0; i < 50; i++) + { + x = rand() % width; + y = rand() % height; + double r = rand() % 10 + 5; + grm.reset(); + grm *= agg::trans_affine_scaling(r / 10.0); + grm *= agg::trans_affine_translation(x, y); + grm.invert(); + grc.colors(agg::rgba8(255, 255, 255, 0), + agg::rgba8(rand() & 0x7F, + rand() & 0x7F, + rand() & 0x7F, + 255)); + sg.color_function(grc); + ell.init(x, y, r, r, 32); + g_rasterizer.add_path(ell); + agg::render_scanlines(g_rasterizer, g_scanline, rg); + } + + agg::render_ctrl(g_rasterizer, g_scanline, rbase, m_num_cb); + } + + + void transform(double width, double height, double x, double y) + { + x -= width / 2; + y -= height / 2; + g_angle = atan2(y, x); + g_scale = sqrt(y * y + x * x) / 100.0; + } + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + int width = rbuf_window().width(); + int height = rbuf_window().height(); + transform(width, height, x, y); + force_redraw(); + } + + if(flags & agg::mouse_right) + { + g_skew_x = x; + g_skew_y = y; + force_redraw(); + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + on_mouse_button_down(x, y, flags); + } + +}; + + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Clipping to multiple rectangle regions"); + + if(app.init(512, 400, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + + + + + diff --git a/jni/desmume/src/android/agg/examples/alpha_mask3.cpp b/jni/desmume/src/android/agg/examples/alpha_mask3.cpp new file mode 100755 index 0000000..55ad354 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/alpha_mask3.cpp @@ -0,0 +1,562 @@ +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_renderer_primitives.h" +#include "agg_conv_curve.h" +#include "agg_conv_stroke.h" +#include "agg_gsv_text.h" +#include "agg_pixfmt_rgb.h" +#include "agg_pixfmt_gray.h" +#include "agg_pixfmt_amask_adaptor.h" +#include "agg_span_allocator.h" +#include "agg_alpha_mask_u8.h" + +#include "platform/agg_platform_support.h" + +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" + + +enum flip_y_e { flip_y = true }; + + + + +class spiral +{ +public: + spiral(double x, double y, double r1, double r2, double step, double start_angle=0) : + m_x(x), + m_y(y), + m_r1(r1), + m_r2(r2), + m_step(step), + m_start_angle(start_angle), + m_angle(start_angle), + m_da(agg::deg2rad(4.0)), + m_dr(m_step / 90.0) + { + } + + void rewind(unsigned) + { + m_angle = m_start_angle; + m_curr_r = m_r1; + m_start = true; + } + + unsigned vertex(double* x, double* y) + { + if(m_curr_r > m_r2) return agg::path_cmd_stop; + + *x = m_x + cos(m_angle) * m_curr_r; + *y = m_y + sin(m_angle) * m_curr_r; + m_curr_r += m_dr; + m_angle += m_da; + if(m_start) + { + m_start = false; + return agg::path_cmd_move_to; + } + return agg::path_cmd_line_to; + } + +private: + double m_x; + double m_y; + double m_r1; + double m_r2; + double m_step; + double m_start_angle; + + double m_angle; + double m_curr_r; + double m_da; + double m_dr; + bool m_start; +}; + + + + + +void make_gb_poly(agg::path_storage& ps); +void make_arrows(agg::path_storage& ps); + + +class the_application : public agg::platform_support +{ + agg::rbox_ctrl m_polygons; + agg::rbox_ctrl m_operation; + + typedef agg::amask_no_clip_gray8 alpha_mask_type; + //typedef agg::alpha_mask_gray8 alpha_mask_type; + + typedef agg::pixfmt_bgr24 pixfmt_type; + + unsigned char* m_alpha_buf; + agg::rendering_buffer m_alpha_mask_rbuf; + alpha_mask_type m_alpha_mask; + agg::rasterizer_scanline_aa<> m_ras; + agg::scanline_p8 m_sl; + + double m_x; + double m_y; + +public: + ~the_application() + { + delete [] m_alpha_buf; + } + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_polygons (5.0, 5.0, 5.0+205.0, 110.0, !flip_y), + m_operation(555.0, 5.0, 555.0+80.0, 55.0, !flip_y), + m_alpha_buf(0), + m_alpha_mask_rbuf(), + m_alpha_mask(m_alpha_mask_rbuf), + m_x(0), + m_y(0) + { + m_operation.add_item("AND"); + m_operation.add_item("SUB"); + m_operation.cur_item(0); + add_ctrl(m_operation); + m_operation.no_transform(); + + m_polygons.add_item("Two Simple Paths"); + m_polygons.add_item("Closed Stroke"); + m_polygons.add_item("Great Britain and Arrows"); + m_polygons.add_item("Great Britain and Spiral"); + m_polygons.add_item("Spiral and Glyph"); + m_polygons.cur_item(3); + add_ctrl(m_polygons); + m_polygons.no_transform(); + } + + + void draw_text(double x, double y, const char* str) + { + pixfmt_type pf(rbuf_window()); + agg::renderer_base rb(pf); + agg::renderer_scanline_aa_solid > ren(rb); + + agg::gsv_text txt; + agg::conv_stroke txt_stroke(txt); + txt_stroke.width(1.5); + txt_stroke.line_cap(agg::round_cap); + txt.size(10.0); + txt.start_point(x, y); + txt.text(str); + m_ras.add_path(txt_stroke); + ren.color(agg::rgba(0.0, 0.0, 0.0)); + agg::render_scanlines(m_ras, m_sl, ren); + } + + + template void generate_alpha_mask(VertexSource& vs) + { + unsigned cx = (unsigned)width(); + unsigned cy = (unsigned)height(); + + delete [] m_alpha_buf; + m_alpha_buf = new unsigned char[cx * cy]; + m_alpha_mask_rbuf.attach(m_alpha_buf, cx, cy, cx); + + typedef agg::renderer_base ren_base; + typedef agg::renderer_scanline_aa_solid renderer; + + agg::pixfmt_gray8 pixf(m_alpha_mask_rbuf); + ren_base rb(pixf); + renderer ren(rb); + + start_timer(); + if(m_operation.cur_item() == 0) + { + rb.clear(agg::gray8(0)); + ren.color(agg::gray8(255)); + } + else + { + rb.clear(agg::gray8(255)); + ren.color(agg::gray8(0)); + } + m_ras.add_path(vs); + agg::render_scanlines(m_ras, m_sl, ren); + double t1 = elapsed_time(); + + char buf[100]; + sprintf(buf, "Generate AlphaMask: %.3fms", t1); + draw_text(250, 20, buf); + } + + + template + void perform_rendering(VertexSource& vs) + { + pixfmt_type pixf(rbuf_window()); + + typedef agg::pixfmt_amask_adaptor pixfmt_amask_type; + typedef agg::renderer_base amask_ren_type; + + + pixfmt_amask_type pixfa(pixf, m_alpha_mask); + amask_ren_type rbase(pixfa); + agg::renderer_scanline_aa_solid ren(rbase); + + ren.color(agg::rgba(0.5, 0.0, 0, 0.5)); + + start_timer(); + m_ras.reset(); + m_ras.add_path(vs); + agg::render_scanlines(m_ras, m_sl, ren); + double t1 = elapsed_time(); + + + char buf[100]; + sprintf(buf, "Render with AlphaMask: %.3fms", t1); + draw_text(250, 5, buf); + } + + + unsigned render() + { + pixfmt_type pf(rbuf_window()); + agg::renderer_base rb(pf); + agg::renderer_scanline_aa_solid > ren(rb); + + switch(m_polygons.cur_item()) + { + case 0: + { + //------------------------------------ + // Two simple paths + // + agg::path_storage ps1; + agg::path_storage ps2; + + double x = m_x - initial_width()/2 + 100; + double y = m_y - initial_height()/2 + 100; + ps1.move_to(x+140, y+145); + ps1.line_to(x+225, y+44); + ps1.line_to(x+296, y+219); + ps1.close_polygon(); + + ps1.line_to(x+226, y+289); + ps1.line_to(x+82, y+292); + + ps1.move_to(x+220, y+222); + ps1.line_to(x+363, y+249); + ps1.line_to(x+265, y+331); + + ps1.move_to(x+242, y+243); + ps1.line_to(x+268, y+309); + ps1.line_to(x+325, y+261); + + ps1.move_to(x+259, y+259); + ps1.line_to(x+273, y+288); + ps1.line_to(x+298, y+266); + + ps2.move_to(100+32, 100+77); + ps2.line_to(100+473, 100+263); + ps2.line_to(100+351, 100+290); + ps2.line_to(100+354, 100+374); + + m_ras.reset(); + m_ras.add_path(ps1); + ren.color(agg::rgba(0, 0, 0, 0.1)); + agg::render_scanlines(m_ras, m_sl, ren); + + m_ras.reset(); + m_ras.add_path(ps2); + ren.color(agg::rgba(0, 0.6, 0, 0.1)); + agg::render_scanlines(m_ras, m_sl, ren); + + generate_alpha_mask(ps1); + perform_rendering(ps2); + } + break; + + case 1: + { + //------------------------------------ + // Closed stroke + // + agg::path_storage ps1; + agg::path_storage ps2; + agg::conv_stroke stroke(ps2); + stroke.width(10.0); + + double x = m_x - initial_width()/2 + 100; + double y = m_y - initial_height()/2 + 100; + ps1.move_to(x+140, y+145); + ps1.line_to(x+225, y+44); + ps1.line_to(x+296, y+219); + ps1.close_polygon(); + + ps1.line_to(x+226, y+289); + ps1.line_to(x+82, y+292); + + ps1.move_to(x+220-50, y+222); + ps1.line_to(x+265-50, y+331); + ps1.line_to(x+363-50, y+249); + ps1.close_polygon(agg::path_flags_ccw); + + ps2.move_to(100+32, 100+77); + ps2.line_to(100+473, 100+263); + ps2.line_to(100+351, 100+290); + ps2.line_to(100+354, 100+374); + ps2.close_polygon(); + + m_ras.reset(); + m_ras.add_path(ps1); + ren.color(agg::rgba(0, 0, 0, 0.1)); + agg::render_scanlines(m_ras, m_sl, ren); + + m_ras.reset(); + m_ras.add_path(stroke); + ren.color(agg::rgba(0, 0.6, 0, 0.1)); + agg::render_scanlines(m_ras, m_sl, ren); + + generate_alpha_mask(ps1); + perform_rendering(stroke); + } + break; + + + case 2: + { + //------------------------------------ + // Great Britain and Arrows + // + agg::path_storage gb_poly; + agg::path_storage arrows; + make_gb_poly(gb_poly); + make_arrows(arrows); + + agg::trans_affine mtx1; + agg::trans_affine mtx2; + mtx1 *= agg::trans_affine_translation(-1150, -1150); + mtx1 *= agg::trans_affine_scaling(2.0); + + mtx2 = mtx1; + mtx2 *= agg::trans_affine_translation(m_x - initial_width()/2, + m_y - initial_height()/2); + + agg::conv_transform trans_gb_poly(gb_poly, mtx1); + agg::conv_transform trans_arrows(arrows, mtx2); + + m_ras.add_path(trans_gb_poly); + ren.color(agg::rgba(0.5, 0.5, 0, 0.1)); + agg::render_scanlines(m_ras, m_sl, ren); + + agg::conv_stroke > stroke_gb_poly(trans_gb_poly); + stroke_gb_poly.width(0.1); + m_ras.add_path(stroke_gb_poly); + ren.color(agg::rgba(0, 0, 0)); + agg::render_scanlines(m_ras, m_sl, ren); + + m_ras.add_path(trans_arrows); + ren.color(agg::rgba(0.0, 0.5, 0.5, 0.1)); + agg::render_scanlines(m_ras, m_sl, ren); + + generate_alpha_mask(trans_gb_poly); + perform_rendering(trans_arrows); + } + break; + + + case 3: + { + //------------------------------------ + // Great Britain and a Spiral + // + spiral sp(m_x, m_y, 10, 150, 30, 0.0); + agg::conv_stroke stroke(sp); + stroke.width(15.0); + + agg::path_storage gb_poly; + make_gb_poly(gb_poly); + + agg::trans_affine mtx; + mtx *= agg::trans_affine_translation(-1150, -1150); + mtx *= agg::trans_affine_scaling(2.0); + + agg::conv_transform trans_gb_poly(gb_poly, mtx); + + m_ras.add_path(trans_gb_poly); + ren.color(agg::rgba(0.5, 0.5, 0, 0.1)); + agg::render_scanlines(m_ras, m_sl, ren); + + agg::conv_stroke > stroke_gb_poly(trans_gb_poly); + stroke_gb_poly.width(0.1); + m_ras.add_path(stroke_gb_poly); + ren.color(agg::rgba(0, 0, 0)); + agg::render_scanlines(m_ras, m_sl, ren); + + m_ras.add_path(stroke); + ren.color(agg::rgba(0.0, 0.5, 0.5, 0.1)); + agg::render_scanlines(m_ras, m_sl, ren); + + generate_alpha_mask(trans_gb_poly); + perform_rendering(stroke); + } + break; + + + case 4: + { + //------------------------------------ + // Spiral and glyph + // + spiral sp(m_x, m_y, 10, 150, 30, 0.0); + agg::conv_stroke stroke(sp); + stroke.width(15.0); + + agg::path_storage glyph; + glyph.move_to(28.47, 6.45); + glyph.curve3(21.58, 1.12, 19.82, 0.29); + glyph.curve3(17.19, -0.93, 14.21, -0.93); + glyph.curve3(9.57, -0.93, 6.57, 2.25); + glyph.curve3(3.56, 5.42, 3.56, 10.60); + glyph.curve3(3.56, 13.87, 5.03, 16.26); + glyph.curve3(7.03, 19.58, 11.99, 22.51); + glyph.curve3(16.94, 25.44, 28.47, 29.64); + glyph.line_to(28.47, 31.40); + glyph.curve3(28.47, 38.09, 26.34, 40.58); + glyph.curve3(24.22, 43.07, 20.17, 43.07); + glyph.curve3(17.09, 43.07, 15.28, 41.41); + glyph.curve3(13.43, 39.75, 13.43, 37.60); + glyph.line_to(13.53, 34.77); + glyph.curve3(13.53, 32.52, 12.38, 31.30); + glyph.curve3(11.23, 30.08, 9.38, 30.08); + glyph.curve3(7.57, 30.08, 6.42, 31.35); + glyph.curve3(5.27, 32.62, 5.27, 34.81); + glyph.curve3(5.27, 39.01, 9.57, 42.53); + glyph.curve3(13.87, 46.04, 21.63, 46.04); + glyph.curve3(27.59, 46.04, 31.40, 44.04); + glyph.curve3(34.28, 42.53, 35.64, 39.31); + glyph.curve3(36.52, 37.21, 36.52, 30.71); + glyph.line_to(36.52, 15.53); + glyph.curve3(36.52, 9.13, 36.77, 7.69); + glyph.curve3(37.01, 6.25, 37.57, 5.76); + glyph.curve3(38.13, 5.27, 38.87, 5.27); + glyph.curve3(39.65, 5.27, 40.23, 5.62); + glyph.curve3(41.26, 6.25, 44.19, 9.18); + glyph.line_to(44.19, 6.45); + glyph.curve3(38.72, -0.88, 33.74, -0.88); + glyph.curve3(31.35, -0.88, 29.93, 0.78); + glyph.curve3(28.52, 2.44, 28.47, 6.45); + glyph.close_polygon(); + + glyph.move_to(28.47, 9.62); + glyph.line_to(28.47, 26.66); + glyph.curve3(21.09, 23.73, 18.95, 22.51); + glyph.curve3(15.09, 20.36, 13.43, 18.02); + glyph.curve3(11.77, 15.67, 11.77, 12.89); + glyph.curve3(11.77, 9.38, 13.87, 7.06); + glyph.curve3(15.97, 4.74, 18.70, 4.74); + glyph.curve3(22.41, 4.74, 28.47, 9.62); + glyph.close_polygon(); + + agg::trans_affine mtx; + mtx *= agg::trans_affine_scaling(4.0); + mtx *= agg::trans_affine_translation(220, 200); + agg::conv_transform trans(glyph, mtx); + agg::conv_curve > curve(trans); + + m_ras.reset(); + m_ras.add_path(stroke); + ren.color(agg::rgba(0, 0, 0, 0.1)); + agg::render_scanlines(m_ras, m_sl, ren); + + m_ras.reset(); + m_ras.add_path(curve); + ren.color(agg::rgba(0, 0.6, 0, 0.1)); + agg::render_scanlines(m_ras, m_sl, ren); + + generate_alpha_mask(stroke); + perform_rendering(curve); + } + break; + } + + return 0; + } + + + virtual void on_init() + { + m_x = width() / 2.0; + m_y = height() / 2.0; + } + + virtual void on_draw() + { + typedef agg::renderer_base base_ren_type; + + pixfmt_type pf(rbuf_window()); + base_ren_type ren_base(pf); + ren_base.clear(agg::rgba(1,1,1)); + + render(); + + agg::render_ctrl(m_ras, m_sl, ren_base, m_polygons); + agg::render_ctrl(m_ras, m_sl, ren_base, m_operation); + } + + + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + m_x = x; + m_y = y; + force_redraw(); + } + + if(flags & agg::mouse_right) + { + char buf[100]; + sprintf(buf, "%d %d", x, y); + message(buf); + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + m_x = x; + m_y = y; + force_redraw(); + } + } + + + +}; + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("AGG Example. Alpha-Mask as a Polygon Clipper"); + + if(app.init(640, 520, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/bezier_div.cpp b/jni/desmume/src/android/agg/examples/bezier_div.cpp new file mode 100755 index 0000000..95d39e7 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/bezier_div.cpp @@ -0,0 +1,567 @@ +#include +#include +#include +#include "agg_rendering_buffer.h" +#include "agg_conv_transform.h" +#include "agg_conv_stroke.h" +#include "agg_conv_dash.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_rasterizer_outline_aa.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_pattern_filters_rgba.h" +#include "agg_renderer_outline_aa.h" +#include "agg_renderer_outline_image.h" +#include "agg_arc.h" +#include "agg_bezier_arc.h" +#include "agg_pixfmt_rgb.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_bezier_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "platform/agg_platform_support.h" + + +enum flip_y_e { flip_y = true }; + +typedef agg::pixfmt_bgr24 pixfmt; + + +void bezier4_point(double x1, double y1, double x2, double y2, + double x3, double y3, double x4, double y4, + double mu, + double* x, double* y) +{ + double mum1, mum13, mu3; + + mum1 = 1 - mu; + mum13 = mum1 * mum1 * mum1; + mu3 = mu * mu * mu; + + *x = mum13*x1 + 3*mu*mum1*mum1*x2 + 3*mu*mu*mum1*x3 + mu3*x4; + *y = mum13*y1 + 3*mu*mum1*mum1*y2 + 3*mu*mu*mum1*y3 + mu3*y4; +} + + + + +class the_application : public agg::platform_support +{ + agg::rgba8 m_ctrl_color; + agg::bezier_ctrl m_curve1; + agg::slider_ctrl m_angle_tolerance; + agg::slider_ctrl m_approximation_scale; + agg::slider_ctrl m_cusp_limit; + agg::slider_ctrl m_width; + agg::cbox_ctrl m_show_points; + agg::cbox_ctrl m_show_outline; + agg::rbox_ctrl m_curve_type; + agg::rbox_ctrl m_case_type; + agg::rbox_ctrl m_inner_join; + agg::rbox_ctrl m_line_join; + agg::rbox_ctrl m_line_cap; + + int m_cur_case_type; + +public: + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_scanline; + typedef agg::rasterizer_scanline_aa<> rasterizer_scanline; + typedef agg::scanline_u8 scanline; + + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_ctrl_color(agg::rgba(0, 0.3, 0.5, 0.8)), + m_angle_tolerance (5.0, 5.0, 240.0, 12.0, !flip_y), + m_approximation_scale(5.0, 17+5.0, 240.0, 17+12.0, !flip_y), + m_cusp_limit (5.0, 17+17+5.0, 240.0, 17+17+12.0, !flip_y), + m_width (245.0, 5.0, 495.0, 12.0, !flip_y), + m_show_points (250.0, 15+5, "Show Points", !flip_y), + m_show_outline (250.0, 30+5, "Show Stroke Outline", !flip_y), + m_curve_type (535.0, 5.0, 535.0+115.0, 55.0, !flip_y), + m_case_type (535.0, 60.0, 535.0+115.0, 195.0, !flip_y), + m_inner_join (535.0, 200.0, 535.0+115.0, 290.0, !flip_y), + m_line_join (535.0, 295.0, 535.0+115.0, 385.0, !flip_y), + m_line_cap (535.0, 395.0, 535.0+115.0, 455.0, !flip_y), + m_cur_case_type(-1) + { + m_curve1.line_color(m_ctrl_color); + + m_curve1.curve(170, 424, 13, 87, 488, 423, 26, 333); + //m_curve1.curve(26.000, 333.000, 276.000, 126.000, 402.000, 479.000, 26.000, 333.000); // Loop with p1==p4 + //m_curve1.curve(378.000, 439.000, 378.000, 497.000, 487.000, 432.000, 14.000, 338.000); // Narrow loop + //m_curve1.curve(288.000, 283.000, 232.000, 89.000, 66.000, 197.000, 456.000, 241.000); // Loop + //m_curve1.curve(519.000, 142.000, 97.000, 147.000, 69.000, 147.000, 30.000, 144.000); // Almost straight + //m_curve1.curve(100, 100, 200, 100, 100, 200, 200, 200); // A "Z" case + //m_curve1.curve(150, 150, 350, 150, 150, 150, 350, 150); // Degenerate + //m_curve1.curve(409, 330, 300, 200, 200, 200, 401, 263); // Strange cusp + //m_curve1.curve(129, 233, 172, 320, 414, 253, 344, 236); // Curve cap + //m_curve1.curve(100,100, 100,200, 100,100, 110,100); // A "boot" + //m_curve1.curve(225, 150, 60, 150, 460, 150, 295, 150); // 2----1----4----3 + //m_curve1.curve(162.2, 248.801, 162.2, 248.801, 266, 284, 394, 335); // Coinciding 1-2 + //m_curve1.curve(162.200, 248.801, 162.200, 248.801, 257.000, 301.000, 394.000, 335.000); // Coinciding 1-2 + //m_curve1.curve(394.000, 335.000, 257.000, 301.000, 162.200, 248.801, 162.200, 248.801); // Coinciding 3-4 + //m_curve1.curve(84.200000,302.80100, 84.200000,302.80100, 79.000000,292.40100, 97.001000,304.40100); // From tiger.svg + //m_curve1.curve(97.001000,304.40100, 79.000000,292.40100, 84.200000,302.80100, 84.200000,302.80100); // From tiger.svg opposite dir + //m_curve1.curve(475, 157, 200, 100, 453, 100, 222, 157); // Cusp, failure for Adobe SVG + add_ctrl(m_curve1); + m_curve1.no_transform(); + + m_angle_tolerance.label("Angle Tolerance=%.0f deg"); + m_angle_tolerance.range(0, 90); + m_angle_tolerance.value(15); + add_ctrl(m_angle_tolerance); + m_angle_tolerance.no_transform(); + + m_approximation_scale.label("Approximation Scale=%.3f"); + m_approximation_scale.range(0.1, 5); + m_approximation_scale.value(1.0); + add_ctrl(m_approximation_scale); + m_approximation_scale.no_transform(); + + m_cusp_limit.label("Cusp Limit=%.0f deg"); + m_cusp_limit.range(0, 90); + m_cusp_limit.value(0); + add_ctrl(m_cusp_limit); + m_cusp_limit.no_transform(); + + m_width.label("Width=%.2f"); + m_width.range(-50, 100); + m_width.value(50.0); + add_ctrl(m_width); + m_width.no_transform(); + + add_ctrl(m_show_points); + m_show_points.no_transform(); + m_show_points.status(true); + + add_ctrl(m_show_outline); + m_show_outline.no_transform(); + m_show_outline.status(true); + + m_curve_type.add_item("Incremental"); + m_curve_type.add_item("Subdiv"); + m_curve_type.cur_item(1); + add_ctrl(m_curve_type); + m_curve_type.no_transform(); + + m_case_type.text_size(7); + m_case_type.text_thickness(1.0); + m_case_type.add_item("Random"); + m_case_type.add_item("13---24"); + m_case_type.add_item("Smooth Cusp 1"); + m_case_type.add_item("Smooth Cusp 2"); + m_case_type.add_item("Real Cusp 1"); + m_case_type.add_item("Real Cusp 2"); + m_case_type.add_item("Fancy Stroke"); + m_case_type.add_item("Jaw"); + m_case_type.add_item("Ugly Jaw"); + add_ctrl(m_case_type); + m_case_type.no_transform(); + + m_inner_join.text_size(8); + m_inner_join.add_item("Inner Bevel"); + m_inner_join.add_item("Inner Miter"); + m_inner_join.add_item("Inner Jag"); + m_inner_join.add_item("Inner Round"); + m_inner_join.cur_item(3); + add_ctrl(m_inner_join); + m_inner_join.no_transform(); + + m_line_join.text_size(8); + m_line_join.add_item("Miter Join"); + m_line_join.add_item("Miter Revert"); + m_line_join.add_item("Round Join"); + m_line_join.add_item("Bevel Join"); + m_line_join.add_item("Miter Round"); + + m_line_join.cur_item(1); + add_ctrl(m_line_join); + m_line_join.no_transform(); + + m_line_cap.text_size(8); + m_line_cap.add_item("Butt Cap"); + m_line_cap.add_item("Square Cap"); + m_line_cap.add_item("Round Cap"); + m_line_cap.cur_item(0); + add_ctrl(m_line_cap); + m_line_cap.no_transform(); + } + + + template double measure_time(Curve& curve) + { + start_timer(); + for(int i = 0; i < 100; i++) + { + double x, y; + curve.init(m_curve1.x1(), m_curve1.y1(), + m_curve1.x2(), m_curve1.y2(), + m_curve1.x3(), m_curve1.y3(), + m_curve1.x4(), m_curve1.y4()); + curve.rewind(0); + while(!agg::is_stop(curve.vertex(&x, &y))); + } + return elapsed_time() * 10; + } + + + template + bool find_point(const Path& path, double dist, unsigned* i, unsigned* j) + { + int k; + *j = path.size() - 1; + + for(*i = 0; (*j - *i) > 1; ) + { + if(dist < path[k = (*i + *j) >> 1].dist) *j = k; + else *i = k; + } + return true; + } + + struct curve_point + { + curve_point() {} + curve_point(double x1, double y1, double mu1) : x(x1), y(y1), mu(mu1) {} + double x, y, dist, mu; + }; + + template double calc_max_error(Curve& curve, double scale, + double* max_angle_error) + { + curve.approximation_scale(m_approximation_scale.value() * scale); + curve.init(m_curve1.x1(), m_curve1.y1(), + m_curve1.x2(), m_curve1.y2(), + m_curve1.x3(), m_curve1.y3(), + m_curve1.x4(), m_curve1.y4()); + + agg::pod_bvector curve_points; + unsigned cmd; + double x, y; + curve.rewind(0); + while(!agg::is_stop(cmd = curve.vertex(&x, &y))) + { + if(agg::is_vertex(cmd)) + { + curve_points.add(agg::vertex_dist(x, y)); + } + } + unsigned i; + double curve_dist = 0; + for(i = 1; i < curve_points.size(); i++) + { + curve_points[i - 1].dist = curve_dist; + curve_dist += agg::calc_distance(curve_points[i-1].x, curve_points[i-1].y, + curve_points[i].x, curve_points[i].y); + } + curve_points[curve_points.size() - 1].dist = curve_dist; + + agg::pod_bvector reference_points; + for(i = 0; i < 4096; i++) + { + double mu = i / 4095.0; + bezier4_point(m_curve1.x1(), m_curve1.y1(), + m_curve1.x2(), m_curve1.y2(), + m_curve1.x3(), m_curve1.y3(), + m_curve1.x4(), m_curve1.y4(), + mu, &x, &y); + reference_points.add(curve_point(x, y, mu)); + } + + double reference_dist = 0; + for(i = 1; i < reference_points.size(); i++) + { + reference_points[i - 1].dist = reference_dist; + reference_dist += agg::calc_distance(reference_points[i-1].x, reference_points[i-1].y, + reference_points[i].x, reference_points[i].y); + } + reference_points[reference_points.size() - 1].dist = reference_dist; + + + unsigned idx1 = 0; + unsigned idx2 = 1; + double max_error = 0; + for(i = 0; i < reference_points.size(); i++) + { + if(find_point(curve_points, reference_points[i].dist, &idx1, &idx2)) + { + double err = fabs(agg::calc_line_point_distance(curve_points[idx1].x, curve_points[idx1].y, + curve_points[idx2].x, curve_points[idx2].y, + reference_points[i].x, reference_points[i].y)); + if(err > max_error) max_error = err; + } + } + + double aerr = 0; + for(i = 2; i < curve_points.size(); i++) + { + double a1 = atan2(curve_points[i-1].y - curve_points[i-2].y, + curve_points[i-1].x - curve_points[i-2].x); + double a2 = atan2(curve_points[i].y - curve_points[i-1].y, + curve_points[i].x - curve_points[i-1].x); + + double da = fabs(a1 - a2); + if(da >= agg::pi) da = 2*agg::pi - da; + if(da > aerr) aerr = da; + } + + + *max_angle_error = aerr * 180.0 / agg::pi; + return max_error * scale; + } + + + + virtual void on_draw() + { + pixfmt pf(rbuf_window()); + renderer_base ren_base(pf); + ren_base.clear(agg::rgba(1.0, 1.0, 0.95)); + renderer_scanline ren(ren_base); + + rasterizer_scanline ras; + scanline sl; + + agg::path_storage path; + + double x, y; + double curve_time = 0; + + path.remove_all(); + agg::curve4 curve; + curve.approximation_method(agg::curve_approximation_method_e(m_curve_type.cur_item())); + curve.approximation_scale(m_approximation_scale.value()); + curve.angle_tolerance(agg::deg2rad(m_angle_tolerance.value())); + curve.cusp_limit(agg::deg2rad(m_cusp_limit.value())); + curve_time = measure_time(curve); + double max_angle_error_01 = 0; + double max_angle_error_1 = 0; + double max_angle_error1 = 0; + double max_angle_error_10 = 0; + double max_angle_error_100 = 0; + double max_error_01 = 0; + double max_error_1 = 0; + double max_error1 = 0; + double max_error_10 = 0; + double max_error_100 = 0; + + max_error_01 = calc_max_error(curve, 0.01, &max_angle_error_01); + max_error_1 = calc_max_error(curve, 0.1, &max_angle_error_1); + max_error1 = calc_max_error(curve, 1, &max_angle_error1); + max_error_10 = calc_max_error(curve, 10, &max_angle_error_10); + max_error_100 = calc_max_error(curve, 100, &max_angle_error_100); + + curve.approximation_scale(m_approximation_scale.value()); + curve.angle_tolerance(agg::deg2rad(m_angle_tolerance.value())); + curve.cusp_limit(agg::deg2rad(m_cusp_limit.value())); + curve.init(m_curve1.x1(), m_curve1.y1(), + m_curve1.x2(), m_curve1.y2(), + m_curve1.x3(), m_curve1.y3(), + m_curve1.x4(), m_curve1.y4()); + + path.concat_path(curve); +//path.move_to(m_curve1.x1(), m_curve1.y1()); +//path.line_to(m_curve1.x2(), m_curve1.y2()); +//path.line_to(m_curve1.x3(), m_curve1.y3()); +//path.line_to(m_curve1.x4(), m_curve1.y4()); + + + agg::conv_stroke stroke(path); + stroke.width(m_width.value()); + stroke.line_join(agg::line_join_e(m_line_join.cur_item())); + stroke.line_cap(agg::line_cap_e(m_line_cap.cur_item())); + stroke.inner_join(agg::inner_join_e(m_inner_join.cur_item())); + stroke.inner_miter_limit(1.01); + + ras.add_path(stroke); + ren.color(agg::rgba(0, 0.5, 0, 0.5)); + agg::render_scanlines(ras, sl, ren); + + unsigned cmd; + unsigned num_points1 = 0; + path.rewind(0); + while(!agg::is_stop(cmd = path.vertex(&x, &y))) + { + if(m_show_points.status()) + { + agg::ellipse ell(x, y, 1.5, 1.5, 8); + ras.add_path(ell); + ren.color(agg::rgba(0,0,0, 0.5)); + agg::render_scanlines(ras, sl, ren); + } + ++num_points1; + } + + if(m_show_outline.status()) + { + // Draw a stroke of the stroke to see the internals + //-------------- + agg::conv_stroke > stroke2(stroke); + ras.add_path(stroke2); + ren.color(agg::rgba(0,0,0, 0.5)); + agg::render_scanlines(ras, sl, ren); + } + + // Check ellipse and arc for the number of points + //--------------- + //agg::ellipse a(100, 100, m_width.value(), m_width.value(), 0); + //ras.add_path(a); + //ren.color(agg::rgba(0.5,0,0, 0.5)); + //agg::render_scanlines(ras, sl, ren); + //a.rewind(0); + //while(!agg::is_stop(cmd = a.vertex(&x, &y))) + //{ + // if(agg::is_vertex(cmd)) + // { + // agg::ellipse ell(x, y, 1.5, 1.5, 8); + // ras.add_path(ell); + // ren.color(agg::rgba(0,0,0,0.5)); + // agg::render_scanlines(ras, sl, ren); + // } + //} + + + // Check a circle with huge radius (10,000,000) and high approximation accuracy + //--------------- + //double circle_pnt_count = 0; + //agg::bezier_arc ell(0,0, 10000000, 10000000, 0, 2*agg::pi); + //agg::conv_curve crv(ell); + //crv.approximation_scale(10.0); + //crv.rewind(0); + //while(crv.vertex(&x, &y)) ++circle_pnt_count; + + + char buf[512]; + agg::gsv_text t; + t.size(8.0); + + agg::conv_stroke pt(t); + pt.line_cap(agg::round_cap); + pt.line_join(agg::round_join); + pt.width(1.5); + + sprintf(buf, "Num Points=%d Time=%.2fmks\n\n" + " Dist Error: x0.01=%.5f x0.1=%.5f x1=%.5f x10=%.5f x100=%.5f\n\n" + "Angle Error: x0.01=%.1f x0.1=%.1f x1=%.1f x10=%.1f x100=%.1f", + num_points1, curve_time, + max_error_01, + max_error_1, + max_error1, + max_error_10, + max_error_100, + max_angle_error_01, + max_angle_error_1, + max_angle_error1, + max_angle_error_10, + max_angle_error_100); + + t.start_point(10.0, 85.0); + t.text(buf); + + ras.add_path(pt); + ren.color(agg::rgba(0,0,0)); + agg::render_scanlines(ras, sl, ren); + + agg::render_ctrl(ras, sl, ren_base, m_curve1); + agg::render_ctrl(ras, sl, ren_base, m_angle_tolerance); + agg::render_ctrl(ras, sl, ren_base, m_approximation_scale); + agg::render_ctrl(ras, sl, ren_base, m_cusp_limit); + agg::render_ctrl(ras, sl, ren_base, m_width); + agg::render_ctrl(ras, sl, ren_base, m_show_points); + agg::render_ctrl(ras, sl, ren_base, m_show_outline); + agg::render_ctrl(ras, sl, ren_base, m_curve_type); + agg::render_ctrl(ras, sl, ren_base, m_case_type); + agg::render_ctrl(ras, sl, ren_base, m_inner_join); + agg::render_ctrl(ras, sl, ren_base, m_line_join); + agg::render_ctrl(ras, sl, ren_base, m_line_cap); + } + + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + if(key == ' ') + { + FILE* fd = fopen(full_file_name("coord"), "w"); + fprintf(fd, "%.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f", + m_curve1.x1(), m_curve1.y1(), + m_curve1.x2(), m_curve1.y2(), + m_curve1.x3(), m_curve1.y3(), + m_curve1.x4(), m_curve1.y4()); + fclose(fd); + } + } + + virtual void on_ctrl_change() + { + if(m_case_type.cur_item() != m_cur_case_type) + { + switch(m_case_type.cur_item()) + { + case 0: //m_case_type.add_item("Random"); + { + int w = int(width() - 120); + int h = int(height() - 80); + m_curve1.curve(rand() % w, rand() % h + 80, rand() % w, rand() % h + 80, + rand() % w, rand() % h + 80, rand() % w, rand() % h + 80); + } + break; + + case 1: //m_case_type.add_item("13---24"); + m_curve1.curve(150, 150, 350, 150, 150, 150, 350, 150); + //m_curve1.curve(252, 227, 16, 227, 506, 227, 285, 227); + //m_curve1.curve(252, 227, 16, 227, 387, 227, 285, 227); + break; + + case 2: //m_case_type.add_item("Smooth Cusp 1"); + m_curve1.curve(50, 142, 483, 251, 496, 62, 26, 333); + break; + + case 3: //m_case_type.add_item("Smooth Cusp 2"); + m_curve1.curve(50, 142, 484, 251, 496, 62, 26, 333); + break; + + case 4: //m_case_type.add_item("Real Cusp 1"); + m_curve1.curve(100, 100, 300, 200, 200, 200, 200, 100); + break; + + case 5: //m_case_type.add_item("Real Cusp 2"); + m_curve1.curve(475, 157, 200, 100, 453, 100, 222, 157); + break; + + case 6: //m_case_type.add_item("Fancy Stroke"); + m_curve1.curve(129, 233, 32, 283, 258, 285, 159, 232); + m_width.value(100); + break; + + case 7: //m_case_type.add_item("Jaw"); + m_curve1.curve(100, 100, 300, 200, 264, 286, 264, 284); + break; + + case 8: //m_case_type.add_item("Ugly Jaw"); + m_curve1.curve(100, 100, 413, 304, 264, 286, 264, 284); + break; + } + force_redraw(); + m_cur_case_type = m_case_type.cur_item(); + } + } +}; + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("AGG Example"); + if(app.init(655, 520, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + + + + diff --git a/jni/desmume/src/android/agg/examples/blend_color.cpp b/jni/desmume/src/android/agg/examples/blend_color.cpp new file mode 100755 index 0000000..c16b37e --- /dev/null +++ b/jni/desmume/src/android/agg/examples/blend_color.cpp @@ -0,0 +1,542 @@ +#include +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_conv_curve.h" +#include "agg_conv_contour.h" +#include "agg_conv_stroke.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_pixfmt_rgb.h" +#include "agg_pixfmt_rgba.h" +#include "agg_pixfmt_gray.h" +#include "agg_bounding_rect.h" +#include "agg_trans_perspective.h" +#include "agg_blur.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "ctrl/agg_polygon_ctrl.h" +#include "platform/agg_platform_support.h" + +//#define AGG_GRAY8 +#define AGG_BGR24 +//#define AGG_BGR48 +//#define AGG_RGB_AAA +//#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + + +static agg::int8u g_gradient_colors[] = +{ + 255, 255, 255, 255, + 255, 255, 254, 255, + 255, 255, 254, 255, + 255, 255, 254, 255, + 255, 255, 253, 255, + 255, 255, 253, 255, + 255, 255, 252, 255, + 255, 255, 251, 255, + 255, 255, 250, 255, + 255, 255, 248, 255, + 255, 255, 246, 255, + 255, 255, 244, 255, + 255, 255, 241, 255, + 255, 255, 238, 255, + 255, 255, 235, 255, + 255, 255, 231, 255, + 255, 255, 227, 255, + 255, 255, 222, 255, + 255, 255, 217, 255, + 255, 255, 211, 255, + 255, 255, 206, 255, + 255, 255, 200, 255, + 255, 254, 194, 255, + 255, 253, 188, 255, + 255, 252, 182, 255, + 255, 250, 176, 255, + 255, 249, 170, 255, + 255, 247, 164, 255, + 255, 246, 158, 255, + 255, 244, 152, 255, + 254, 242, 146, 255, + 254, 240, 141, 255, + 254, 238, 136, 255, + 254, 236, 131, 255, + 253, 234, 126, 255, + 253, 232, 121, 255, + 253, 229, 116, 255, + 252, 227, 112, 255, + 252, 224, 108, 255, + 251, 222, 104, 255, + 251, 219, 100, 255, + 251, 216, 96, 255, + 250, 214, 93, 255, + 250, 211, 89, 255, + 249, 208, 86, 255, + 249, 205, 83, 255, + 248, 202, 80, 255, + 247, 199, 77, 255, + 247, 196, 74, 255, + 246, 193, 72, 255, + 246, 190, 69, 255, + 245, 187, 67, 255, + 244, 183, 64, 255, + 244, 180, 62, 255, + 243, 177, 60, 255, + 242, 174, 58, 255, + 242, 170, 56, 255, + 241, 167, 54, 255, + 240, 164, 52, 255, + 239, 161, 51, 255, + 239, 157, 49, 255, + 238, 154, 47, 255, + 237, 151, 46, 255, + 236, 147, 44, 255, + 235, 144, 43, 255, + 235, 141, 41, 255, + 234, 138, 40, 255, + 233, 134, 39, 255, + 232, 131, 37, 255, + 231, 128, 36, 255, + 230, 125, 35, 255, + 229, 122, 34, 255, + 228, 119, 33, 255, + 227, 116, 31, 255, + 226, 113, 30, 255, + 225, 110, 29, 255, + 224, 107, 28, 255, + 223, 104, 27, 255, + 222, 101, 26, 255, + 221, 99, 25, 255, + 220, 96, 24, 255, + 219, 93, 23, 255, + 218, 91, 22, 255, + 217, 88, 21, 255, + 216, 86, 20, 255, + 215, 83, 19, 255, + 214, 81, 18, 255, + 213, 79, 17, 255, + 212, 77, 17, 255, + 211, 74, 16, 255, + 210, 72, 15, 255, + 209, 70, 14, 255, + 207, 68, 13, 255, + 206, 66, 13, 255, + 205, 64, 12, 255, + 204, 62, 11, 255, + 203, 60, 10, 255, + 202, 58, 10, 255, + 201, 56, 9, 255, + 199, 55, 9, 255, + 198, 53, 8, 255, + 197, 51, 7, 255, + 196, 50, 7, 255, + 195, 48, 6, 255, + 193, 46, 6, 255, + 192, 45, 5, 255, + 191, 43, 5, 255, + 190, 42, 4, 255, + 188, 41, 4, 255, + 187, 39, 3, 255, + 186, 38, 3, 255, + 185, 37, 2, 255, + 183, 35, 2, 255, + 182, 34, 1, 255, + 181, 33, 1, 255, + 179, 32, 1, 255, + 178, 30, 0, 255, + 177, 29, 0, 255, + 175, 28, 0, 255, + 174, 27, 0, 255, + 173, 26, 0, 255, + 171, 25, 0, 255, + 170, 24, 0, 255, + 168, 23, 0, 255, + 167, 22, 0, 255, + 165, 21, 0, 255, + 164, 21, 0, 255, + 163, 20, 0, 255, + 161, 19, 0, 255, + 160, 18, 0, 255, + 158, 17, 0, 255, + 156, 17, 0, 255, + 155, 16, 0, 255, + 153, 15, 0, 255, + 152, 14, 0, 255, + 150, 14, 0, 255, + 149, 13, 0, 255, + 147, 12, 0, 255, + 145, 12, 0, 255, + 144, 11, 0, 255, + 142, 11, 0, 255, + 140, 10, 0, 255, + 139, 10, 0, 255, + 137, 9, 0, 255, + 135, 9, 0, 255, + 134, 8, 0, 255, + 132, 8, 0, 255, + 130, 7, 0, 255, + 128, 7, 0, 255, + 126, 6, 0, 255, + 125, 6, 0, 255, + 123, 5, 0, 255, + 121, 5, 0, 255, + 119, 4, 0, 255, + 117, 4, 0, 255, + 115, 4, 0, 255, + 113, 3, 0, 255, + 111, 3, 0, 255, + 109, 2, 0, 255, + 107, 2, 0, 255, + 105, 2, 0, 255, + 103, 1, 0, 255, + 101, 1, 0, 255, + 99, 1, 0, 255, + 97, 0, 0, 255, + 95, 0, 0, 255, + 93, 0, 0, 255, + 91, 0, 0, 255, + 90, 0, 0, 255, + 88, 0, 0, 255, + 86, 0, 0, 255, + 84, 0, 0, 255, + 82, 0, 0, 255, + 80, 0, 0, 255, + 78, 0, 0, 255, + 77, 0, 0, 255, + 75, 0, 0, 255, + 73, 0, 0, 255, + 72, 0, 0, 255, + 70, 0, 0, 255, + 68, 0, 0, 255, + 67, 0, 0, 255, + 65, 0, 0, 255, + 64, 0, 0, 255, + 63, 0, 0, 255, + 61, 0, 0, 255, + 60, 0, 0, 255, + 59, 0, 0, 255, + 58, 0, 0, 255, + 57, 0, 0, 255, + 56, 0, 0, 255, + 55, 0, 0, 255, + 54, 0, 0, 255, + 53, 0, 0, 255, + 53, 0, 0, 255, + 52, 0, 0, 255, + 52, 0, 0, 255, + 51, 0, 0, 255, + 51, 0, 0, 255, + 51, 0, 0, 255, + 50, 0, 0, 255, + 50, 0, 0, 255, + 51, 0, 0, 255, + 51, 0, 0, 255, + 51, 0, 0, 255, + 51, 0, 0, 255, + 52, 0, 0, 255, + 52, 0, 0, 255, + 53, 0, 0, 255, + 54, 1, 0, 255, + 55, 2, 0, 255, + 56, 3, 0, 255, + 57, 4, 0, 255, + 58, 5, 0, 255, + 59, 6, 0, 255, + 60, 7, 0, 255, + 62, 8, 0, 255, + 63, 9, 0, 255, + 64, 11, 0, 255, + 66, 12, 0, 255, + 68, 13, 0, 255, + 69, 14, 0, 255, + 71, 16, 0, 255, + 73, 17, 0, 255, + 75, 18, 0, 255, + 77, 20, 0, 255, + 79, 21, 0, 255, + 81, 23, 0, 255, + 83, 24, 0, 255, + 85, 26, 0, 255, + 87, 28, 0, 255, + 90, 29, 0, 255, + 92, 31, 0, 255, + 94, 33, 0, 255, + 97, 34, 0, 255, + 99, 36, 0, 255, + 102, 38, 0, 255, + 104, 40, 0, 255, + 107, 41, 0, 255, + 109, 43, 0, 255, + 112, 45, 0, 255, + 115, 47, 0, 255, + 117, 49, 0, 255, + 120, 51, 0, 255, + 123, 52, 0, 255, + 126, 54, 0, 255, + 128, 56, 0, 255, + 131, 58, 0, 255, + 134, 60, 0, 255, + 137, 62, 0, 255, + 140, 64, 0, 255, + 143, 66, 0, 255, + 145, 68, 0, 255, + 148, 70, 0, 255, + 151, 72, 0, 255, + 154, 74, 0, 255 +}; + + +enum flip_y_e { flip_y = true }; + + +class the_application : public agg::platform_support +{ + agg::rbox_ctrl m_method; + agg::slider_ctrl m_radius; + agg::polygon_ctrl m_shadow_ctrl; + + agg::path_storage m_path; + typedef agg::conv_curve shape_type; + shape_type m_shape; + + agg::rasterizer_scanline_aa<> m_ras; + agg::scanline_p8 m_sl; + + agg::rect_d m_shape_bounds; + + agg::pod_array m_gray8_buf; + agg::rendering_buffer m_gray8_rbuf; + agg::rendering_buffer m_gray8_rbuf2; + + agg::pod_array m_color_lut; +public: + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_method (10.0, 10.0, 130.0, 55.0, !flip_y), + m_radius (130 + 10.0, 10.0 + 4.0, 130 + 300.0, 10.0 + 8.0 + 4.0, !flip_y), + m_shadow_ctrl(4), + m_shape(m_path) + { + add_ctrl(m_method); + m_method.text_size(8); + m_method.add_item("Single Color"); + m_method.add_item("Color LUT"); + m_method.cur_item(1); + + add_ctrl(m_radius); + m_radius.range(0.0, 40.0); + m_radius.value(15.0); + m_radius.label("Blur Radius=%1.2f"); + + add_ctrl(m_shadow_ctrl); + + m_path.remove_all(); + m_path.move_to(28.47, 6.45); + m_path.curve3(21.58, 1.12, 19.82, 0.29); + m_path.curve3(17.19, -0.93, 14.21, -0.93); + m_path.curve3(9.57, -0.93, 6.57, 2.25); + m_path.curve3(3.56, 5.42, 3.56, 10.60); + m_path.curve3(3.56, 13.87, 5.03, 16.26); + m_path.curve3(7.03, 19.58, 11.99, 22.51); + m_path.curve3(16.94, 25.44, 28.47, 29.64); + m_path.line_to(28.47, 31.40); + m_path.curve3(28.47, 38.09, 26.34, 40.58); + m_path.curve3(24.22, 43.07, 20.17, 43.07); + m_path.curve3(17.09, 43.07, 15.28, 41.41); + m_path.curve3(13.43, 39.75, 13.43, 37.60); + m_path.line_to(13.53, 34.77); + m_path.curve3(13.53, 32.52, 12.38, 31.30); + m_path.curve3(11.23, 30.08, 9.38, 30.08); + m_path.curve3(7.57, 30.08, 6.42, 31.35); + m_path.curve3(5.27, 32.62, 5.27, 34.81); + m_path.curve3(5.27, 39.01, 9.57, 42.53); + m_path.curve3(13.87, 46.04, 21.63, 46.04); + m_path.curve3(27.59, 46.04, 31.40, 44.04); + m_path.curve3(34.28, 42.53, 35.64, 39.31); + m_path.curve3(36.52, 37.21, 36.52, 30.71); + m_path.line_to(36.52, 15.53); + m_path.curve3(36.52, 9.13, 36.77, 7.69); + m_path.curve3(37.01, 6.25, 37.57, 5.76); + m_path.curve3(38.13, 5.27, 38.87, 5.27); + m_path.curve3(39.65, 5.27, 40.23, 5.62); + m_path.curve3(41.26, 6.25, 44.19, 9.18); + m_path.line_to(44.19, 6.45); + m_path.curve3(38.72, -0.88, 33.74, -0.88); + m_path.curve3(31.35, -0.88, 29.93, 0.78); + m_path.curve3(28.52, 2.44, 28.47, 6.45); + m_path.close_polygon(); + + m_path.move_to(28.47, 9.62); + m_path.line_to(28.47, 26.66); + m_path.curve3(21.09, 23.73, 18.95, 22.51); + m_path.curve3(15.09, 20.36, 13.43, 18.02); + m_path.curve3(11.77, 15.67, 11.77, 12.89); + m_path.curve3(11.77, 9.38, 13.87, 7.06); + m_path.curve3(15.97, 4.74, 18.70, 4.74); + m_path.curve3(22.41, 4.74, 28.47, 9.62); + m_path.close_polygon(); + + agg::trans_affine shape_mtx; + shape_mtx *= agg::trans_affine_scaling(4.0); + shape_mtx *= agg::trans_affine_translation(150, 100); + m_path.transform(shape_mtx); + + agg::bounding_rect_single(m_shape, 0, + &m_shape_bounds.x1, &m_shape_bounds.y1, + &m_shape_bounds.x2, &m_shape_bounds.y2); + + m_shadow_ctrl.xn(0) = m_shape_bounds.x1; + m_shadow_ctrl.yn(0) = m_shape_bounds.y1; + m_shadow_ctrl.xn(1) = m_shape_bounds.x2; + m_shadow_ctrl.yn(1) = m_shape_bounds.y1; + m_shadow_ctrl.xn(2) = m_shape_bounds.x2; + m_shadow_ctrl.yn(2) = m_shape_bounds.y2; + m_shadow_ctrl.xn(3) = m_shape_bounds.x1; + m_shadow_ctrl.yn(3) = m_shape_bounds.y2; + m_shadow_ctrl.line_color(agg::rgba(0, 0.3, 0.5, 0.3)); + + + m_color_lut.resize(256); + unsigned i; + const agg::int8u* p = g_gradient_colors; + for(i = 0; i < 256; i++) + { + m_color_lut[i] = agg::rgba8(p[0], p[1], p[2], (i > 63) ? 255 : i * 4);//p[3]); + //m_color_lut[i].premultiply(); + p += 4; + } + } + + + virtual void on_resize(int sx, int sy) + { + m_gray8_buf.resize(sx * sy); + m_gray8_rbuf.attach(m_gray8_buf.data(), sx, sy, sx); + } + + + virtual void on_draw() + { + typedef agg::pixfmt_gray8 pixfmt_gray8; + typedef agg::renderer_base ren_base_gray8; + + m_ras.clip_box(0,0, width(), height()); + + pixfmt_gray8 pixf_gray8(m_gray8_rbuf); + ren_base_gray8 renb_gray8(pixf_gray8); + renb_gray8.clear(agg::gray8(0)); + + // Testing enhanced compositing operations. + // Uncomment and replace renb.blend_from_* to renb_blend.blend_from_* + //---------------- + //typedef agg::comp_op_rgba_minus blender_type; + //typedef agg::comp_adaptor_rgba blend_adaptor_type; + //typedef agg::pixfmt_custom_blend_rgba pixfmt_type; + //typedef agg::renderer_base ren_base; + //pixfmt_type pixf_blend(rbuf_window()); + //agg::renderer_base renb_blend(pixf_blend); + + pixfmt pixf(rbuf_window()); + agg::renderer_base renb(pixf); + renb.clear(agg::rgba(1, 0.95, 0.95)); + + agg::trans_perspective shadow_persp(m_shape_bounds.x1, m_shape_bounds.y1, + m_shape_bounds.x2, m_shape_bounds.y2, + m_shadow_ctrl.polygon()); + + agg::conv_transform shadow_trans(m_shape, + shadow_persp); + + start_timer(); + + // Render shadow + m_ras.add_path(shadow_trans); + agg::render_scanlines_aa_solid(m_ras, m_sl, renb_gray8, agg::gray8(255)); + + // Calculate the bounding box and extend it by the blur radius + agg::rect_d bbox; + agg::bounding_rect_single(shadow_trans, 0, &bbox.x1, &bbox.y1, &bbox.x2, &bbox.y2); + + bbox.x1 -= m_radius.value(); + bbox.y1 -= m_radius.value(); + bbox.x2 += m_radius.value(); + bbox.y2 += m_radius.value(); + + if(bbox.clip(agg::rect_d(0, 0, width(), height()))) + { + // Create a new pixel renderer and attach it to the main one as a child image. + // It returns true if the attachment suceeded. It fails if the rectangle + // (bbox) is fully clipped. + //------------------ + pixfmt_gray8 pixf2(m_gray8_rbuf2); + if(pixf2.attach(pixf_gray8, int(bbox.x1), int(bbox.y1), int(bbox.x2), int(bbox.y2))) + { + // Blur it + agg::stack_blur_gray8(pixf2, agg::uround(m_radius.value()), + agg::uround(m_radius.value())); + } + if(m_method.cur_item() == 0) + { + renb.blend_from_color(pixf2, + agg::rgba8(0, 100, 0), + 0, + int(bbox.x1), + int(bbox.y1)); + } + else + { + renb.blend_from_lut(pixf2, + m_color_lut.data(), + 0, + int(bbox.x1), + int(bbox.y1)); + } + } + double tm = elapsed_time(); + + char buf[64]; + agg::gsv_text t; + t.size(10.0); + + agg::conv_stroke st(t); + st.width(1.5); + + sprintf(buf, "%3.2f ms", tm); + t.start_point(140.0, 30.0); + t.text(buf); + + m_ras.add_path(st); + agg::render_scanlines_aa_solid(m_ras, m_sl, renb, agg::rgba(0,0,0)); + + agg::render_ctrl(m_ras, m_sl, renb, m_method); + agg::render_ctrl(m_ras, m_sl, renb, m_radius); + agg::render_ctrl(m_ras, m_sl, renb, m_shadow_ctrl); + } + +}; + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Gaussian and Stack Blur"); + + if(app.init(440, 330, 0)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/blur.cpp b/jni/desmume/src/android/agg/examples/blur.cpp new file mode 100755 index 0000000..2b58f4f --- /dev/null +++ b/jni/desmume/src/android/agg/examples/blur.cpp @@ -0,0 +1,319 @@ +#include +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_conv_curve.h" +#include "agg_conv_contour.h" +#include "agg_conv_stroke.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_pixfmt_rgb.h" +#include "agg_pixfmt_rgba.h" +#include "agg_pixfmt_gray.h" +#include "agg_bounding_rect.h" +#include "agg_trans_perspective.h" +#include "agg_blur.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "ctrl/agg_polygon_ctrl.h" +#include "platform/agg_platform_support.h" + + +enum flip_y_e { flip_y = true }; + + +class the_application : public agg::platform_support +{ + agg::rbox_ctrl m_method; + agg::slider_ctrl m_radius; + agg::polygon_ctrl m_shadow_ctrl; + agg::cbox_ctrl m_channel_r; + agg::cbox_ctrl m_channel_g; + agg::cbox_ctrl m_channel_b; + + agg::path_storage m_path; + typedef agg::conv_curve shape_type; + shape_type m_shape; + + agg::rasterizer_scanline_aa<> m_ras; + agg::scanline_p8 m_sl; + agg::rendering_buffer m_rbuf2; + + agg::stack_blur > m_stack_blur; + agg::recursive_blur > m_recursive_blur; + + agg::rect_d m_shape_bounds; + + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_method (10.0, 10.0, 130.0, 70.0, !flip_y), + m_radius (130 + 10.0, 10.0 + 4.0, 130 + 300.0, 10.0 + 8.0 + 4.0, !flip_y), + m_shadow_ctrl(4), + m_channel_r (10.0, 80.0, "Red", !flip_y), + m_channel_g (10.0, 95.0, "Green", !flip_y), + m_channel_b (10.0, 110.0, "Blue", !flip_y), + m_shape(m_path) + { + add_ctrl(m_method); + m_method.text_size(8); + m_method.add_item("Stack Blur"); + m_method.add_item("Recursive Blur"); + m_method.add_item("Channels"); + m_method.cur_item(0); + + add_ctrl(m_radius); + m_radius.range(0.0, 40.0); + m_radius.value(15.0); + m_radius.label("Blur Radius=%1.2f"); + + add_ctrl(m_shadow_ctrl); + + add_ctrl(m_channel_r); + add_ctrl(m_channel_g); + add_ctrl(m_channel_b); + m_channel_g.status(true); + + m_path.remove_all(); + m_path.move_to(28.47, 6.45); + m_path.curve3(21.58, 1.12, 19.82, 0.29); + m_path.curve3(17.19, -0.93, 14.21, -0.93); + m_path.curve3(9.57, -0.93, 6.57, 2.25); + m_path.curve3(3.56, 5.42, 3.56, 10.60); + m_path.curve3(3.56, 13.87, 5.03, 16.26); + m_path.curve3(7.03, 19.58, 11.99, 22.51); + m_path.curve3(16.94, 25.44, 28.47, 29.64); + m_path.line_to(28.47, 31.40); + m_path.curve3(28.47, 38.09, 26.34, 40.58); + m_path.curve3(24.22, 43.07, 20.17, 43.07); + m_path.curve3(17.09, 43.07, 15.28, 41.41); + m_path.curve3(13.43, 39.75, 13.43, 37.60); + m_path.line_to(13.53, 34.77); + m_path.curve3(13.53, 32.52, 12.38, 31.30); + m_path.curve3(11.23, 30.08, 9.38, 30.08); + m_path.curve3(7.57, 30.08, 6.42, 31.35); + m_path.curve3(5.27, 32.62, 5.27, 34.81); + m_path.curve3(5.27, 39.01, 9.57, 42.53); + m_path.curve3(13.87, 46.04, 21.63, 46.04); + m_path.curve3(27.59, 46.04, 31.40, 44.04); + m_path.curve3(34.28, 42.53, 35.64, 39.31); + m_path.curve3(36.52, 37.21, 36.52, 30.71); + m_path.line_to(36.52, 15.53); + m_path.curve3(36.52, 9.13, 36.77, 7.69); + m_path.curve3(37.01, 6.25, 37.57, 5.76); + m_path.curve3(38.13, 5.27, 38.87, 5.27); + m_path.curve3(39.65, 5.27, 40.23, 5.62); + m_path.curve3(41.26, 6.25, 44.19, 9.18); + m_path.line_to(44.19, 6.45); + m_path.curve3(38.72, -0.88, 33.74, -0.88); + m_path.curve3(31.35, -0.88, 29.93, 0.78); + m_path.curve3(28.52, 2.44, 28.47, 6.45); + m_path.close_polygon(); + + m_path.move_to(28.47, 9.62); + m_path.line_to(28.47, 26.66); + m_path.curve3(21.09, 23.73, 18.95, 22.51); + m_path.curve3(15.09, 20.36, 13.43, 18.02); + m_path.curve3(11.77, 15.67, 11.77, 12.89); + m_path.curve3(11.77, 9.38, 13.87, 7.06); + m_path.curve3(15.97, 4.74, 18.70, 4.74); + m_path.curve3(22.41, 4.74, 28.47, 9.62); + m_path.close_polygon(); + + agg::trans_affine shape_mtx; + shape_mtx *= agg::trans_affine_scaling(4.0); + shape_mtx *= agg::trans_affine_translation(150, 100); + m_path.transform(shape_mtx); + + agg::bounding_rect_single(m_shape, 0, + &m_shape_bounds.x1, &m_shape_bounds.y1, + &m_shape_bounds.x2, &m_shape_bounds.y2); + + m_shadow_ctrl.xn(0) = m_shape_bounds.x1; + m_shadow_ctrl.yn(0) = m_shape_bounds.y1; + m_shadow_ctrl.xn(1) = m_shape_bounds.x2; + m_shadow_ctrl.yn(1) = m_shape_bounds.y1; + m_shadow_ctrl.xn(2) = m_shape_bounds.x2; + m_shadow_ctrl.yn(2) = m_shape_bounds.y2; + m_shadow_ctrl.xn(3) = m_shape_bounds.x1; + m_shadow_ctrl.yn(3) = m_shape_bounds.y2; + m_shadow_ctrl.line_color(agg::rgba(0, 0.3, 0.5, 0.3)); + } + + + + virtual void on_draw() + { + typedef agg::renderer_base ren_base; + + agg::pixfmt_bgr24 pixf(rbuf_window()); + ren_base renb(pixf); + renb.clear(agg::rgba(1, 1, 1)); + m_ras.clip_box(0,0, width(), height()); + + agg::trans_perspective shadow_persp(m_shape_bounds.x1, m_shape_bounds.y1, + m_shape_bounds.x2, m_shape_bounds.y2, + m_shadow_ctrl.polygon()); + + agg::conv_transform shadow_trans(m_shape, + shadow_persp); + + // Render shadow + m_ras.add_path(shadow_trans); + agg::render_scanlines_aa_solid(m_ras, m_sl, renb, agg::rgba(0.2,0.3,0)); + + // Calculate the bounding box and extend it by the blur radius + agg::rect_d bbox; + agg::bounding_rect_single(shadow_trans, 0, &bbox.x1, &bbox.y1, &bbox.x2, &bbox.y2); + + bbox.x1 -= m_radius.value(); + bbox.y1 -= m_radius.value(); + bbox.x2 += m_radius.value(); + bbox.y2 += m_radius.value(); + + if(m_method.cur_item() == 1) + { + // The recursive blur method represents the true Gussian Blur, + // with theoretically infinite kernel. The restricted window size + // results in extra influence of edge pixels. It's impossible to + // solve correctly, but extending the right and top areas to another + // radius value produces fair result. + //------------------ + bbox.x2 += m_radius.value(); + bbox.y2 += m_radius.value(); + } + + start_timer(); + if(m_method.cur_item() != 2) + { + // Create a new pixel renderer and attach it to the main one as a child image. + // It returns true if the attachment suceeded. It fails if the rectangle + // (bbox) is fully clipped. + //------------------ + agg::pixfmt_bgr24 pixf2(m_rbuf2); + if(pixf2.attach(pixf, int(bbox.x1), int(bbox.y1), int(bbox.x2), int(bbox.y2))) + { + // Blur it + if(m_method.cur_item() == 0) + { + // More general method, but 30-40% slower. + //------------------ + //m_stack_blur.blur(pixf2, agg::uround(m_radius.value())); + + // Faster, but bore specific. + // Works only for 8 bits per channel and only with radii <= 254. + //------------------ + agg::stack_blur_rgb24(pixf2, agg::uround(m_radius.value()), + agg::uround(m_radius.value())); + } + else + { + // True Gaussian Blur, 3-5 times slower than Stack Blur, + // but still constant time of radius. Very sensitive + // to precision, doubles are must here. + //------------------ + m_recursive_blur.blur(pixf2, m_radius.value()); + } + } + } + else + { + // Blur separate channels + //------------------ + if(m_channel_r.status()) + { + typedef agg::pixfmt_alpha_blend_gray< + agg::blender_gray8, + agg::rendering_buffer, + 3, 2> pixfmt_gray8r; + + pixfmt_gray8r pixf2r(m_rbuf2); + if(pixf2r.attach(pixf, int(bbox.x1), int(bbox.y1), int(bbox.x2), int(bbox.y2))) + { + agg::stack_blur_gray8(pixf2r, agg::uround(m_radius.value()), + agg::uround(m_radius.value())); + } + } + + if(m_channel_g.status()) + { + typedef agg::pixfmt_alpha_blend_gray< + agg::blender_gray8, + agg::rendering_buffer, + 3, 1> pixfmt_gray8g; + + pixfmt_gray8g pixf2g(m_rbuf2); + if(pixf2g.attach(pixf, int(bbox.x1), int(bbox.y1), int(bbox.x2), int(bbox.y2))) + { + agg::stack_blur_gray8(pixf2g, agg::uround(m_radius.value()), + agg::uround(m_radius.value())); + } + } + + if(m_channel_b.status()) + { + typedef agg::pixfmt_alpha_blend_gray< + agg::blender_gray8, + agg::rendering_buffer, + 3, 0> pixfmt_gray8b; + + pixfmt_gray8b pixf2b(m_rbuf2); + if(pixf2b.attach(pixf, int(bbox.x1), int(bbox.y1), int(bbox.x2), int(bbox.y2))) + { + agg::stack_blur_gray8(pixf2b, agg::uround(m_radius.value()), + agg::uround(m_radius.value())); + } + } + } + double tm = elapsed_time(); + + agg::render_ctrl(m_ras, m_sl, renb, m_shadow_ctrl); + + // Render the shape itself + //------------------ + m_ras.add_path(m_shape); + agg::render_scanlines_aa_solid(m_ras, m_sl, renb, agg::rgba(0.6,0.9,0.7, 0.8)); + + char buf[64]; + agg::gsv_text t; + t.size(10.0); + + agg::conv_stroke st(t); + st.width(1.5); + + sprintf(buf, "%3.2f ms", tm); + t.start_point(140.0, 30.0); + t.text(buf); + + m_ras.add_path(st); + agg::render_scanlines_aa_solid(m_ras, m_sl, renb, agg::rgba(0,0,0)); + + + agg::render_ctrl(m_ras, m_sl, renb, m_method); + agg::render_ctrl(m_ras, m_sl, renb, m_radius); + agg::render_ctrl(m_ras, m_sl, renb, m_channel_r); + agg::render_ctrl(m_ras, m_sl, renb, m_channel_g); + agg::render_ctrl(m_ras, m_sl, renb, m_channel_b); + } + +}; + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("AGG Example. Gaussian and Stack Blur"); + + if(app.init(440, 330, 0)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/bspline.cpp b/jni/desmume/src/android/agg/examples/bspline.cpp new file mode 100755 index 0000000..ae8f649 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/bspline.cpp @@ -0,0 +1,205 @@ +#include +#include +#include +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_conv_bspline.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "ctrl/agg_slider_ctrl.h" +#include "platform/agg_platform_support.h" +#include "interactive_polygon.h" + +#define AGG_BGR24 +//#define AGG_RGB24 +//#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + +enum flip_y_e { flip_y = true }; + + + + + + +class the_application : public agg::platform_support +{ +public: + typedef agg::renderer_base renderer_base; + typedef agg::scanline_p8 scanline_type; + + agg::interactive_polygon m_poly; + agg::slider_ctrl m_num_points; + agg::cbox_ctrl m_close; + int m_flip; + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_poly(6, 5.0), + m_num_points(5.0, 5.0, 340.0, 12.0, !flip_y), + m_close (350, 5.0, "Close", !flip_y), + m_flip(0) + { + add_ctrl(m_close); + m_num_points.range(1.0, 40.0); + m_num_points.value(20.0); + m_num_points.label("Number of intermediate Points = %.3f"); + add_ctrl(m_num_points); + } + + + virtual void on_init() + { + if(m_flip) + { + m_poly.xn(0) = 100; + m_poly.yn(0) = height() - 100; + m_poly.xn(1) = width() - 100; + m_poly.yn(1) = height() - 100; + m_poly.xn(2) = width() - 100; + m_poly.yn(2) = 100; + m_poly.xn(3) = 100; + m_poly.yn(3) = 100; + } + else + { + m_poly.xn(0) = 100; + m_poly.yn(0) = 100; + m_poly.xn(1) = width() - 100; + m_poly.yn(1) = 100; + m_poly.xn(2) = width() - 100; + m_poly.yn(2) = height() - 100; + m_poly.xn(3) = 100; + m_poly.yn(3) = height() - 100; + } + m_poly.xn(4) = width() / 2; + m_poly.yn(4) = height() / 2; + m_poly.xn(5) = width() / 2; + m_poly.yn(5) = height() / 3; + + } + + + + + virtual void on_draw() + { + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + rb.clear(agg::rgba(1, 1, 1)); + + scanline_type sl; + agg::rasterizer_scanline_aa<> ras; + + agg::simple_polygon_vertex_source path(m_poly.polygon(), + m_poly.num_points(), + false, + m_close.status()); + + typedef agg::conv_bspline conv_bspline_type; + conv_bspline_type bspline(path); + bspline.interpolation_step(1.0 / m_num_points.value()); + + typedef agg::conv_stroke conv_stroke_type; + conv_stroke_type stroke(bspline); + + stroke.width(2.0); + + ras.add_path(stroke); + agg::render_scanlines_aa_solid(ras, sl, rb, agg::rgba(0, 0, 0)); + + + //-------------------------- + // Render the "poly" tool and controls + ras.add_path(m_poly); + agg::render_scanlines_aa_solid(ras, sl, rb, agg::rgba(0, 0.3, 0.5, 0.6)); + + agg::render_ctrl(ras, sl, rb, m_close); + agg::render_ctrl(ras, sl, rb, m_num_points); + //-------------------------- + + } + + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_poly.on_mouse_button_down(x, y)) + { + force_redraw(); + } + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_poly.on_mouse_move(x, y)) + { + force_redraw(); + } + } + if((flags & agg::mouse_left) == 0) + { + on_mouse_button_up(x, y, flags); + } + } + + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + if(m_poly.on_mouse_button_up(x, y)) + { + force_redraw(); + } + } + + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + if(key == ' ') + { + m_flip ^= 1; + on_init(); + force_redraw(); + } + } + +}; + + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. BSpline Interpolator"); + + if(app.init(600, 600, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + + + + + + + + + diff --git a/jni/desmume/src/android/agg/examples/circles.cpp b/jni/desmume/src/android/agg/examples/circles.cpp new file mode 100755 index 0000000..497e214 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/circles.cpp @@ -0,0 +1,266 @@ +#include +#include +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_conv_transform.h" +#include "agg_bspline.h" +#include "agg_ellipse.h" +#include "agg_gsv_text.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_scale_ctrl.h" +#include "platform/agg_platform_support.h" + +#define AGG_BGR24 +//#define AGG_RGB24 +//#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + +enum flip_y_e { flip_y = true }; +enum default_num_points_e { default_num_points = 10000 }; + +enum start_size_e +{ + start_width = 400, + start_height = 400 +}; + +static double spline_r_x[] = { 0.000000, 0.200000, 0.400000, 0.910484, 0.957258, 1.000000 }; +static double spline_r_y[] = { 1.000000, 0.800000, 0.600000, 0.066667, 0.169697, 0.600000 }; + +static double spline_g_x[] = { 0.000000, 0.292244, 0.485655, 0.564859, 0.795607, 1.000000 }; +static double spline_g_y[] = { 0.000000, 0.607260, 0.964065, 0.892558, 0.435571, 0.000000 }; + +static double spline_b_x[] = { 0.000000, 0.055045, 0.143034, 0.433082, 0.764859, 1.000000 }; +static double spline_b_y[] = { 0.385480, 0.128493, 0.021416, 0.271507, 0.713974, 1.000000 }; + + +struct scatter_point +{ + double x; + double y; + double z; + agg::rgba color; +}; + + +double random_dbl(double start, double end) +{ + unsigned r = rand() & 0x7FFF; + return double(r) * (end - start) / 32768.0 + start; +} + + +class the_application : public agg::platform_support +{ + unsigned m_num_points; + scatter_point* m_points; + + agg::scale_ctrl m_scale_ctrl_z; + agg::slider_ctrl m_slider_ctrl_sel; + agg::slider_ctrl m_slider_ctrl_size; + + agg::bspline m_spline_r; + agg::bspline m_spline_g; + agg::bspline m_spline_b; + +public: + virtual ~the_application() + { + delete [] m_points; + } + + the_application(agg::pix_format_e format, bool flip_y, unsigned num_points) : + agg::platform_support(format, flip_y), + m_num_points(num_points), + m_points(new scatter_point [num_points]), + m_scale_ctrl_z (5, 5, start_width-5, 12, !flip_y), + m_slider_ctrl_sel (5, 20, start_width-5, 27, !flip_y), + m_slider_ctrl_size(5, 35, start_width-5, 42, !flip_y) + { + + m_spline_r.init(6, spline_r_x, spline_r_y); + m_spline_g.init(6, spline_g_x, spline_g_y); + m_spline_b.init(6, spline_b_x, spline_b_y); + + add_ctrl(m_scale_ctrl_z); + add_ctrl(m_slider_ctrl_sel); + add_ctrl(m_slider_ctrl_size); + + m_slider_ctrl_size.label("Size"); + m_slider_ctrl_sel.label("Selectivity"); + } + + + void generate() + { + unsigned i; + + double rx = initial_width()/3.5; + double ry = initial_height()/3.5; + + for(i = 0; i < m_num_points; i++) + { + double z = m_points[i].z = random_dbl(0.0, 1.0); + double x = cos(z * 2.0 * agg::pi) * rx; + double y = sin(z * 2.0 * agg::pi) * ry; + + double dist = random_dbl(0.0, rx/2.0); + double angle = random_dbl(0.0, agg::pi * 2.0); + + m_points[i].x = initial_width()/2.0 + x + cos(angle) * dist; + m_points[i].y = initial_height()/2.0 + y + sin(angle) * dist; + m_points[i].color = agg::rgba(m_spline_r.get(z)*0.8, + m_spline_g.get(z)*0.8, + m_spline_b.get(z)*0.8, + 1.0); + } + } + + + virtual void on_init() + { + generate(); + } + + + virtual void on_draw() + { + agg::rasterizer_scanline_aa<> pf; + agg::scanline_p8 sl; + + typedef agg::renderer_base renderer_base; + + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + + rb.clear(agg::rgba(1,1,1)); + + agg::ellipse e1; + agg::conv_transform t1(e1, trans_affine_resizing()); + + + unsigned i; + unsigned n_drawn = 0; + for(i = 0; i < m_num_points; i++) + { + double z = m_points[i].z; + double alpha = 1.0; + if(z < m_scale_ctrl_z.value1()) + { + alpha = + 1.0 - + (m_scale_ctrl_z.value1() - z) * + m_slider_ctrl_sel.value() * 100.0; + } + + if(z > m_scale_ctrl_z.value2()) + { + alpha = + 1.0 - + (z - m_scale_ctrl_z.value2()) * + m_slider_ctrl_sel.value() * 100.0; + } + + + + if(alpha > 1.0) alpha = 1.0; + if(alpha < 0.0) alpha = 0.0; + + if(alpha > 0.0) + { + e1.init(m_points[i].x, + m_points[i].y, + m_slider_ctrl_size.value() * 5.0, + m_slider_ctrl_size.value() * 5.0, + 8); + pf.add_path(t1); + + agg::render_scanlines_aa_solid( + pf, sl, rb, + agg::rgba(m_points[i].color.r, + m_points[i].color.g, + m_points[i].color.b, + alpha)); + n_drawn++; + } + } + + agg::render_ctrl(pf, sl, rb, m_scale_ctrl_z); + agg::render_ctrl(pf, sl, rb, m_slider_ctrl_sel); + agg::render_ctrl(pf, sl, rb, m_slider_ctrl_size); + + char buf[10]; + sprintf(buf, "%08u", n_drawn); + + agg::gsv_text txt; + txt.size(15.0); + txt.text(buf); + txt.start_point(10.0, initial_height() - 20.0); + agg::gsv_text_outline<> txt_o(txt, trans_affine_resizing()); + pf.add_path(txt_o); + agg::render_scanlines_aa_solid(pf, sl, rb, agg::rgba(0,0,0)); + + } + + + virtual void on_idle() + { + unsigned i; + for(i = 0; i < m_num_points; i++) + { + m_points[i].x += random_dbl(0, m_slider_ctrl_sel.value()) - m_slider_ctrl_sel.value()*0.5; + m_points[i].y += random_dbl(0, m_slider_ctrl_sel.value()) - m_slider_ctrl_sel.value()*0.5; + m_points[i].z += random_dbl(0, m_slider_ctrl_sel.value()*0.01) - m_slider_ctrl_sel.value()*0.005; + if(m_points[i].z < 0.0) m_points[i].z = 0.0; + if(m_points[i].z > 1.0) m_points[i].z = 1.0; + } + force_redraw(); + } + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + generate(); + force_redraw(); + } + + if(flags & agg::mouse_right) + { + wait_mode(!wait_mode()); + } + } + +}; + + + +int agg_main(int argc, char* argv[]) +{ + unsigned num_points = default_num_points; + if(argc > 1) + { + num_points = atoi(argv[1]); + if(num_points == 0) num_points = default_num_points; + if(num_points > 20000) num_points = 20000; + } + + the_application app(pix_format, flip_y, num_points); + app.caption("AGG Drawing random circles - A scatter plot prototype"); + + if(app.init(start_width, start_height, agg::window_resize | agg::window_keep_aspect_ratio)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/component_rendering.cpp b/jni/desmume/src/android/agg/examples/component_rendering.cpp new file mode 100755 index 0000000..256c42f --- /dev/null +++ b/jni/desmume/src/android/agg/examples/component_rendering.cpp @@ -0,0 +1,86 @@ +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_ellipse.h" +#include "agg_pixfmt_gray.h" +#include "agg_pixfmt_rgb.h" +#include "ctrl/agg_slider_ctrl.h" +#include "platform/agg_platform_support.h" + +enum flip_y_e { flip_y = true }; + + +class the_application : public agg::platform_support +{ + agg::slider_ctrl m_alpha; + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_alpha(5, 5, 320-5, 10+5, !flip_y) + { + m_alpha.label("Alpha=%1.0f"); + m_alpha.range(0, 255); + m_alpha.value(255); + add_ctrl(m_alpha); + } + + virtual void on_draw() + { + agg::pixfmt_bgr24 pf(rbuf_window()); + + typedef agg::pixfmt_alpha_blend_gray pixfmt_gray8_bgr24r; + typedef agg::pixfmt_alpha_blend_gray pixfmt_gray8_bgr24g; + typedef agg::pixfmt_alpha_blend_gray pixfmt_gray8_bgr24b; + + pixfmt_gray8_bgr24r pfr(rbuf_window()); + pixfmt_gray8_bgr24g pfg(rbuf_window()); + pixfmt_gray8_bgr24b pfb(rbuf_window()); + + agg::renderer_base rbase(pf); + agg::renderer_base rbr(pfr); + agg::renderer_base rbg(pfg); + agg::renderer_base rbb(pfb); + + agg::rasterizer_scanline_aa<> ras; + agg::scanline_p8 sl; + + rbase.clear(agg::rgba(1,1,1)); + + agg::ellipse er(width() / 2 - 0.87*50, height() / 2 - 0.5*50, 100, 100, 100); + ras.add_path(er); + agg::render_scanlines_aa_solid(ras, sl, rbr, + agg::gray8(0, unsigned(m_alpha.value()))); + + agg::ellipse eg(width() / 2 + 0.87*50, height() / 2 - 0.5*50, 100, 100, 100); + ras.add_path(eg); + agg::render_scanlines_aa_solid(ras, sl, rbg, + agg::gray8(0, unsigned(m_alpha.value()))); + + agg::ellipse eb(width() / 2, height() / 2 + 50, 100, 100, 100); + ras.add_path(eb); + agg::render_scanlines_aa_solid(ras, sl, rbb, + agg::gray8(0, unsigned(m_alpha.value()))); + + agg::render_ctrl(ras, sl, rbase, m_alpha); + } + +}; + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("AGG Example. Component Rendering"); + + if(app.init(320, 320, 0)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/compositing.cpp b/jni/desmume/src/android/agg/examples/compositing.cpp new file mode 100755 index 0000000..3bb7dff --- /dev/null +++ b/jni/desmume/src/android/agg/examples/compositing.cpp @@ -0,0 +1,424 @@ +#include +#include "agg_rendering_buffer.h" +#include "agg_renderer_base.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_rounded_rect.h" +#include "agg_pixfmt_rgba.h" +#include "agg_span_allocator.h" +#include "agg_span_gradient.h" +#include "agg_gsv_text.h" +#include "agg_span_interpolator_linear.h" +#include "platform/agg_platform_support.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" + + +enum flip_y_e { flip_y = true }; + +typedef agg::rgba8 color; +typedef color::value_type value_type; +typedef agg::order_bgra order; +typedef agg::int32u pixel_type; +typedef agg::rendering_buffer rbuf_type; +#define pix_format agg::pix_format_bgra32 + +typedef agg::blender_rgba prim_blender_type; +typedef agg::pixfmt_alpha_blend_rgba prim_pixfmt_type; +typedef agg::renderer_base prim_ren_base_type; + +void force_comp_op_link() +{ + // For unknown reason Digital Mars C++ doesn't want to link these + // functions if they are not specified explicitly. + value_type p[4] = {0}; + agg::comp_op_rgba_invert_rgb ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_invert ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_contrast ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_darken ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_lighten ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_color_dodge::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_color_burn ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_hard_light ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_soft_light ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_difference ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_exclusion ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_src_atop ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_dst_atop ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_xor ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_plus ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_minus ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_multiply ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_screen ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_overlay ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_src ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_dst ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_src_over ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_dst_over ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_src_in ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_dst_in ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_src_out ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_dst_out ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_clear ::blend_pix(p,0,0,0,0,0); +} + +namespace agg +{ + + //======================================================================== + template<> struct gradient_linear_color + { + typedef color color_type; + enum base_scale_e { base_shift = color_type::base_shift }; + + gradient_linear_color() {} + gradient_linear_color(const color_type& c1, const color_type& c2) : + m_c1(c1), m_c2(c2) {} + + static unsigned size() { return 256; } + color_type operator [] (unsigned v) const + { + color_type c; + typedef color_type::value_type value_type; + v <<= base_shift - 8; + c.r = (value_type)((((m_c2.r - m_c1.r) * v) + (m_c1.r << base_shift)) >> base_shift); + c.g = (value_type)((((m_c2.g - m_c1.g) * v) + (m_c1.g << base_shift)) >> base_shift); + c.b = (value_type)((((m_c2.b - m_c1.b) * v) + (m_c1.b << base_shift)) >> base_shift); + c.a = (value_type)((((m_c2.a - m_c1.a) * v) + (m_c1.a << base_shift)) >> base_shift); + return c; + } + + void colors(const color_type& c1, const color_type& c2) + { + m_c1 = c1; + m_c2 = c2; + } + + color_type m_c1; + color_type m_c2; + }; + +} + + + + +agg::trans_affine gradient_affine(double x1, double y1, double x2, double y2, + double gradient_d2 = 100.0) +{ + agg::trans_affine mtx; + double dx = x2 - x1; + double dy = y2 - y1; + mtx.reset(); + mtx *= agg::trans_affine_scaling(sqrt(dx * dx + dy * dy) / gradient_d2); + mtx *= agg::trans_affine_rotation(atan2(dy, dx)); + mtx *= agg::trans_affine_translation(x1, y1); + mtx.invert(); + return mtx; +} + + + +template +void circle(RenBase& rbase, color c1, color c2, + double x1, double y1, double x2, double y2, + double shadow_alpha) +{ + typedef RenBase renderer_base_type; + typedef agg::gradient_x gradient_func_type; + typedef agg::gradient_linear_color color_func_type; + typedef agg::span_interpolator_linear<> interpolator_type; + typedef agg::span_allocator span_allocator_type; + typedef agg::span_gradient span_gradient_type; + + gradient_func_type gradient_func; // The gradient function + agg::trans_affine gradient_mtx = gradient_affine(x1, y1, x2, y2, 100); + interpolator_type span_interpolator(gradient_mtx); // Span interpolator + span_allocator_type span_allocator; // Span Allocator + color_func_type color_func(c1, c2); + span_gradient_type span_gradient(span_interpolator, + gradient_func, + color_func, + 0, 100); + agg::rasterizer_scanline_aa<> ras; + agg::scanline_u8 sl; + + double r = agg::calc_distance(x1, y1, x2, y2) / 2; + agg::ellipse ell((x1+x2)/2+5, (y1+y2)/2-3, r, r, 100); + + ras.add_path(ell); + agg::render_scanlines_aa_solid(ras, sl, rbase, + agg::rgba(0.6, 0.6, 0.6, 0.7*shadow_alpha)); + + ell.init((x1+x2)/2, (y1+y2)/2, r, r, 100); + ras.add_path(ell); + agg::render_scanlines_aa(ras, sl, rbase, span_allocator, span_gradient); +} + + + +template +void src_shape(RenBase& rbase, color c1, color c2, + double x1, double y1, double x2, double y2) +{ + typedef RenBase renderer_base_type; + typedef agg::gradient_x gradient_func_type; + typedef agg::gradient_linear_color color_func_type; + typedef agg::span_interpolator_linear<> interpolator_type; + typedef agg::span_allocator span_allocator_type; + typedef agg::span_gradient span_gradient_type; + + gradient_func_type gradient_func; // The gradient function + agg::trans_affine gradient_mtx = gradient_affine(x1, y1, x2, y2, 100); + interpolator_type span_interpolator(gradient_mtx); // Span interpolator + span_allocator_type span_allocator; // Span Allocator + color_func_type color_func(c1, c2); + span_gradient_type span_gradient(span_interpolator, + gradient_func, + color_func, + 0, 100); + agg::rasterizer_scanline_aa<> ras; + agg::scanline_u8 sl; + + agg::rounded_rect shape(x1, y1, x2, y2, 40); +// agg::ellipse shape((x1+x2)/2, (y1+y2)/2, fabs(x2-x1)/2, fabs(y2-y1)/2, 100); + + ras.add_path(shape); + agg::render_scanlines_aa(ras, sl, rbase, span_allocator, span_gradient); +} + + + + + + + +class the_application : public agg::platform_support +{ + agg::slider_ctrl m_alpha_src; + agg::slider_ctrl m_alpha_dst; + agg::rbox_ctrl m_comp_op; + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_alpha_src(5, 5, 400, 11, !flip_y), + m_alpha_dst(5, 5+15, 400, 11+15, !flip_y), + m_comp_op(420, 5.0, 420+170.0, 395.0, !flip_y) + { + m_alpha_src.label("Src Alpha=%.2f"); + m_alpha_src.value(0.75); + add_ctrl(m_alpha_src); + + m_alpha_dst.label("Dst Alpha=%.2f"); + m_alpha_dst.value(1.0); + add_ctrl(m_alpha_dst); + + m_comp_op.text_size(6.8); + m_comp_op.add_item("clear"); + m_comp_op.add_item("src"); + m_comp_op.add_item("dst"); + m_comp_op.add_item("src-over"); + m_comp_op.add_item("dst-over"); + m_comp_op.add_item("src-in"); + m_comp_op.add_item("dst-in"); + m_comp_op.add_item("src-out"); + m_comp_op.add_item("dst-out"); + m_comp_op.add_item("src-atop"); + m_comp_op.add_item("dst-atop"); + m_comp_op.add_item("xor"); + m_comp_op.add_item("plus"); + m_comp_op.add_item("minus"); + m_comp_op.add_item("multiply"); + m_comp_op.add_item("screen"); + m_comp_op.add_item("overlay"); + m_comp_op.add_item("darken"); + m_comp_op.add_item("lighten"); + m_comp_op.add_item("color-dodge"); + m_comp_op.add_item("color-burn"); + m_comp_op.add_item("hard-light"); + m_comp_op.add_item("soft-light"); + m_comp_op.add_item("difference"); + m_comp_op.add_item("exclusion"); + m_comp_op.add_item("contrast"); + m_comp_op.add_item("invert"); + m_comp_op.add_item("invert-rgb"); + m_comp_op.cur_item(3); + add_ctrl(m_comp_op); + } + + virtual ~the_application() + { + } + + virtual void on_init() + { + } + + + void render_scene(rbuf_type& rbuf, prim_pixfmt_type& pixf) + { + typedef agg::comp_op_adaptor_rgba blender_type; + typedef agg::pixfmt_custom_blend_rgba pixfmt_type; + typedef agg::renderer_base renderer_type; + + pixfmt_type ren_pixf(rbuf); + renderer_type renderer(ren_pixf); + + agg::renderer_base rb(pixf); + + rb.blend_from(prim_pixfmt_type(rbuf_img(1)), + 0, 250, 180, + unsigned(m_alpha_dst.value() * 255)); + + circle(rb, + agg::rgba8(0xFD, 0xF0, 0x6F, unsigned(m_alpha_dst.value() * 255)), + agg::rgba8(0xFE, 0x9F, 0x34, unsigned(m_alpha_dst.value() * 255)), + 70*3, 100+24*3, 37*3, 100+79*3, + m_alpha_dst.value()); + + ren_pixf.comp_op(m_comp_op.cur_item()); + + if(m_comp_op.cur_item() == 25) // Contrast + { + double v = m_alpha_src.value(); + src_shape(renderer, + agg::rgba(v, v, v), + agg::rgba(v, v, v), + 300+50, 100+24*3, 107+50, 100+79*3); + } + else + { + + src_shape(renderer, + agg::rgba8(0x7F, 0xC1, 0xFF, unsigned(m_alpha_src.value() * 255)), + agg::rgba8(0x05, 0x00, 0x5F, unsigned(m_alpha_src.value() * 255)), + 300+50, 100+24*3, 107+50, 100+79*3); +/* + src_shape(renderer, + agg::rgba8(0xFF, 0xFF, 0xFF, unsigned(m_alpha_src.value() * 255)), + agg::rgba8(0xFF, 0xFF, 0xFF, unsigned(m_alpha_src.value() * 255)), + 300+50, 100+24*3, 107+50, 100+79*3); +*/ + } + } + + + virtual void on_draw() + { + prim_pixfmt_type pixf(rbuf_window()); + prim_ren_base_type rb(pixf); + rb.clear(agg::rgba8(255, 255, 255)); + + unsigned y; + for(y = 0; y < rb.height(); y += 8) + { + unsigned x; + for(x = ((y >> 3) & 1) << 3; x < rb.width(); x += 16) + { + rb.copy_bar(x, y, x+7, y+7, agg::rgba8(0xdf, 0xdf, 0xdf)); + } + } + + create_img(0, rbuf_window().width(), rbuf_window().height()); // agg_platform_support functionality + + prim_pixfmt_type pixf2(rbuf_img(0)); + prim_ren_base_type rb2(pixf2); + rb2.clear(agg::rgba8(0,0,0,0)); + //rb2.clear(agg::rgba8(255,255,255,255)); + + typedef agg::blender_rgba_pre blender_type_pre; + typedef agg::pixfmt_alpha_blend_rgba pixfmt_pre; + typedef agg::renderer_base ren_base_pre; + + pixfmt_pre pixf_pre(rbuf_window()); + ren_base_pre rb_pre(pixf_pre); + + + start_timer(); + render_scene(rbuf_img(0), pixf2); + double tm = elapsed_time(); + + rb_pre.blend_from(pixf2); + + agg::rasterizer_scanline_aa<> ras; + agg::scanline_u8 sl; + agg::renderer_scanline_aa_solid ren(rb); + + char buf[64]; + agg::gsv_text t; + t.size(10.0); + + agg::conv_stroke pt(t); + pt.width(1.5); + + sprintf(buf, "%3.2f ms", tm); + t.start_point(10.0, 35.0); + t.text(buf); + + ras.add_path(pt); + ren.color(agg::rgba(0,0,0)); + agg::render_scanlines(ras, sl, ren); + + + agg::render_ctrl_rs(ras, sl, ren, m_alpha_src); + agg::render_ctrl_rs(ras, sl, ren, m_alpha_dst); + agg::render_ctrl_rs(ras, sl, ren, m_comp_op); + } + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + } + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + } + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + } +}; + + +int agg_main(int argc, char* argv[]) +{ + force_comp_op_link(); + the_application app(pix_format, flip_y); + app.caption("AGG Example. Compositing Modes"); + + const char* img_name = "compositing"; + if(argc >= 2) img_name = argv[1]; + if(!app.load_img(1, img_name)) + { + char buf[256]; + if(strcmp(img_name, "compositing") == 0) + { + sprintf(buf, "File not found: %s%s. Download http://www.antigrain.com/%s%s\n" + "or copy it from another directory if available.", + img_name, app.img_ext(), img_name, app.img_ext()); + } + else + { + sprintf(buf, "File not found: %s%s", img_name, app.img_ext()); + } + app.message(buf); + return 1; + } + + + if(app.init(600, 400, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/compositing2.cpp b/jni/desmume/src/android/agg/examples/compositing2.cpp new file mode 100755 index 0000000..1f76a65 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/compositing2.cpp @@ -0,0 +1,252 @@ +#include +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_rounded_rect.h" +#include "agg_pixfmt_rgba.h" +#include "agg_span_allocator.h" +#include "agg_span_gradient.h" +#include "agg_gsv_text.h" +#include "agg_span_interpolator_linear.h" +#include "platform/agg_platform_support.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" + + +enum flip_y_e { flip_y = true }; + +typedef agg::rgba8 color; +typedef agg::order_bgra order; +typedef agg::pixel32_type pixel_type; +#define pix_format agg::pix_format_bgra32 + + +typedef agg::blender_rgba prim_blender_type; +typedef agg::pixfmt_alpha_blend_rgba prim_pixfmt_type; +typedef agg::renderer_base prim_ren_base_type; + + +void force_comp_op_link() +{ + // For unknown reason Digital Mars C++ doesn't want to link these + // functions if they are not specified explicitly. + agg::int8u p[4] = {0}; + agg::comp_op_rgba_invert_rgb ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_invert ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_contrast ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_darken ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_lighten ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_color_dodge::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_color_burn ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_hard_light ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_soft_light ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_difference ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_exclusion ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_src_atop ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_dst_atop ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_xor ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_plus ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_minus ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_multiply ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_screen ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_overlay ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_src ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_dst ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_src_over ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_dst_over ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_src_in ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_dst_in ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_src_out ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_dst_out ::blend_pix(p,0,0,0,0,0); + agg::comp_op_rgba_clear ::blend_pix(p,0,0,0,0,0); +} + + +template +void generate_color_ramp(Container& c, + ColorT c1, ColorT c2, ColorT c3, ColorT c4) +{ + unsigned i; + for(i = 0; i < 85; i++) + { + c[i] = c1.gradient(c2, i/85.0); + } + for(; i < 170; i++) + { + c[i] = c2.gradient(c3, (i - 85)/85.0); + } + for(; i < 256; i++) + { + c[i] = c3.gradient(c4, (i - 170)/85.0); + } +} + + +class the_application : public agg::platform_support +{ + agg::slider_ctrl m_alpha_dst; + agg::slider_ctrl m_alpha_src; + agg::rbox_ctrl m_comp_op; + + agg::pod_auto_array m_ramp1; + agg::pod_auto_array m_ramp2; + + agg::rasterizer_scanline_aa<> m_ras; + agg::scanline_u8 m_sl; + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_alpha_dst(5, 5, 400, 11, !flip_y), + m_alpha_src(5, 5+15, 400, 11+15, !flip_y), + m_comp_op(420, 5.0, 420+170.0, 395.0, !flip_y) + { + m_alpha_dst.label("Dst Alpha=%.2f"); + m_alpha_dst.value(1.0); + add_ctrl(m_alpha_dst); + + m_alpha_src.label("Src Alpha=%.2f"); + m_alpha_src.value(1.0); + add_ctrl(m_alpha_src); + + m_comp_op.text_size(6.8); + m_comp_op.add_item("clear"); + m_comp_op.add_item("src"); + m_comp_op.add_item("dst"); + m_comp_op.add_item("src-over"); + m_comp_op.add_item("dst-over"); + m_comp_op.add_item("src-in"); + m_comp_op.add_item("dst-in"); + m_comp_op.add_item("src-out"); + m_comp_op.add_item("dst-out"); + m_comp_op.add_item("src-atop"); + m_comp_op.add_item("dst-atop"); + m_comp_op.add_item("xor"); + m_comp_op.add_item("plus"); + m_comp_op.add_item("minus"); + m_comp_op.add_item("multiply"); + m_comp_op.add_item("screen"); + m_comp_op.add_item("overlay"); + m_comp_op.add_item("darken"); + m_comp_op.add_item("lighten"); + m_comp_op.add_item("color-dodge"); + m_comp_op.add_item("color-burn"); + m_comp_op.add_item("hard-light"); + m_comp_op.add_item("soft-light"); + m_comp_op.add_item("difference"); + m_comp_op.add_item("exclusion"); + m_comp_op.add_item("contrast"); + m_comp_op.add_item("invert"); + m_comp_op.add_item("invert-rgb"); + m_comp_op.cur_item(3); + add_ctrl(m_comp_op); + } + + + template + void radial_shape(RenBase& rbase, const ColorRamp& colors, + double x1, double y1, double x2, double y2) + { + typedef RenBase renderer_base_type; + typedef agg::gradient_radial gradient_func_type; + typedef ColorRamp color_func_type; + typedef agg::span_interpolator_linear<> interpolator_type; + typedef agg::span_allocator span_allocator_type; + typedef agg::span_gradient span_gradient_type; + + gradient_func_type gradient_func; // The gradient function + agg::trans_affine gradient_mtx; + interpolator_type span_interpolator(gradient_mtx); // Span interpolator + span_allocator_type span_allocator; // Span Allocator + span_gradient_type span_gradient(span_interpolator, + gradient_func, + colors, + 0, 100); + + double cx = (x1 + x2) / 2.0; + double cy = (y1 + y2) / 2.0; + double r = 0.5 * (((x2 - x1) < (y2 - y1)) ? (x2 - x1) : (y2 - y1)); + + gradient_mtx *= agg::trans_affine_scaling(r / 100.0); + gradient_mtx *= agg::trans_affine_translation(cx, cy); + gradient_mtx *= trans_affine_resizing(); + gradient_mtx.invert(); + + agg::ellipse ell(cx, cy, r, r, 100); + agg::conv_transform trans(ell, trans_affine_resizing()); + m_ras.add_path(trans); + + agg::render_scanlines_aa(m_ras, m_sl, rbase, span_allocator, span_gradient); + } + + + template void render_scene(RenBase& rb) + { + typedef agg::comp_op_adaptor_rgba blender_type; + typedef agg::pixfmt_custom_blend_rgba pixfmt_type; + typedef agg::renderer_base renderer_type; + + pixfmt_type pixf(rbuf_window()); + renderer_type ren(pixf); + + + pixf.comp_op(agg::comp_op_difference); + radial_shape(ren, m_ramp1, 50, 50, 50+320, 50+320); + + pixf.comp_op(m_comp_op.cur_item()); + double cx = 50; + double cy = 50; + radial_shape(ren, m_ramp2, cx+120-70, cy+120-70, cx+120+70, cy+120+70); + radial_shape(ren, m_ramp2, cx+200-70, cy+120-70, cx+200+70, cy+120+70); + radial_shape(ren, m_ramp2, cx+120-70, cy+200-70, cx+120+70, cy+200+70); + radial_shape(ren, m_ramp2, cx+200-70, cy+200-70, cx+200+70, cy+200+70); + } + + + virtual void on_draw() + { + prim_pixfmt_type pixf(rbuf_window()); + prim_ren_base_type rb(pixf); + rb.clear(agg::rgba8(255, 255, 255)); + + generate_color_ramp(m_ramp1, + agg::rgba(0, 0, 0, m_alpha_dst.value()), + agg::rgba(0, 0, 1, m_alpha_dst.value()), + agg::rgba(0, 1, 0, m_alpha_dst.value()), + agg::rgba(1, 0, 0, 0)); + + generate_color_ramp(m_ramp2, + agg::rgba(0, 0, 0, m_alpha_src.value()), + agg::rgba(0, 0, 1, m_alpha_src.value()), + agg::rgba(0, 1, 0, m_alpha_src.value()), + agg::rgba(1, 0, 0, 0)); + + render_scene(rb); + agg::renderer_scanline_aa_solid ren(rb); + + agg::render_ctrl_rs(m_ras, m_sl, ren, m_alpha_dst); + agg::render_ctrl_rs(m_ras, m_sl, ren, m_alpha_src); + agg::render_ctrl_rs(m_ras, m_sl, ren, m_comp_op); + } + +}; + + +int agg_main(int argc, char* argv[]) +{ + force_comp_op_link(); + the_application app(pix_format, flip_y); + app.caption("AGG Example. Compositing Modes"); + + if(app.init(600, 400, agg::window_resize|agg::window_keep_aspect_ratio)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/conv_contour.cpp b/jni/desmume/src/android/agg/examples/conv_contour.cpp new file mode 100755 index 0000000..5198691 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/conv_contour.cpp @@ -0,0 +1,161 @@ +#include +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_conv_curve.h" +#include "agg_conv_contour.h" +#include "agg_conv_stroke.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_pixfmt_rgb.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "platform/agg_platform_support.h" + + +enum flip_y_e { flip_y = true }; + + + +class the_application : public agg::platform_support +{ + agg::rbox_ctrl m_close; + agg::slider_ctrl m_width; + agg::cbox_ctrl m_auto_detect; + agg::path_storage m_path; + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_close (10.0, 10.0, 130.0, 80.0, !flip_y), + m_width (130 + 10.0, 10.0 + 4.0, 130 + 300.0, 10.0 + 8.0 + 4.0, !flip_y), + m_auto_detect(130 + 10.0, 10.0 + 4.0 + 16.0, "Autodetect orientation if not defined", !flip_y) + { + add_ctrl(m_close); + m_close.add_item("Close"); + m_close.add_item("Close CW"); + m_close.add_item("Close CCW"); + m_close.cur_item(0); + + add_ctrl(m_width); + m_width.range(-100.0, 100.0); + m_width.value(0.0); + m_width.label("Width=%1.2f"); + + add_ctrl(m_auto_detect); + } + + void compose_path() + { + unsigned flag = 0; + if (m_close.cur_item() == 1) flag = agg::path_flags_cw; + if (m_close.cur_item() == 2) flag = agg::path_flags_ccw; + + m_path.remove_all(); + m_path.move_to(28.47, 6.45); + m_path.curve3(21.58, 1.12, 19.82, 0.29); + m_path.curve3(17.19, -0.93, 14.21, -0.93); + m_path.curve3(9.57, -0.93, 6.57, 2.25); + m_path.curve3(3.56, 5.42, 3.56, 10.60); + m_path.curve3(3.56, 13.87, 5.03, 16.26); + m_path.curve3(7.03, 19.58, 11.99, 22.51); + m_path.curve3(16.94, 25.44, 28.47, 29.64); + m_path.line_to(28.47, 31.40); + m_path.curve3(28.47, 38.09, 26.34, 40.58); + m_path.curve3(24.22, 43.07, 20.17, 43.07); + m_path.curve3(17.09, 43.07, 15.28, 41.41); + m_path.curve3(13.43, 39.75, 13.43, 37.60); + m_path.line_to(13.53, 34.77); + m_path.curve3(13.53, 32.52, 12.38, 31.30); + m_path.curve3(11.23, 30.08, 9.38, 30.08); + m_path.curve3(7.57, 30.08, 6.42, 31.35); + m_path.curve3(5.27, 32.62, 5.27, 34.81); + m_path.curve3(5.27, 39.01, 9.57, 42.53); + m_path.curve3(13.87, 46.04, 21.63, 46.04); + m_path.curve3(27.59, 46.04, 31.40, 44.04); + m_path.curve3(34.28, 42.53, 35.64, 39.31); + m_path.curve3(36.52, 37.21, 36.52, 30.71); + m_path.line_to(36.52, 15.53); + m_path.curve3(36.52, 9.13, 36.77, 7.69); + m_path.curve3(37.01, 6.25, 37.57, 5.76); + m_path.curve3(38.13, 5.27, 38.87, 5.27); + m_path.curve3(39.65, 5.27, 40.23, 5.62); + m_path.curve3(41.26, 6.25, 44.19, 9.18); + m_path.line_to(44.19, 6.45); + m_path.curve3(38.72, -0.88, 33.74, -0.88); + m_path.curve3(31.35, -0.88, 29.93, 0.78); + m_path.curve3(28.52, 2.44, 28.47, 6.45); + m_path.close_polygon(flag); + + m_path.move_to(28.47, 9.62); + m_path.line_to(28.47, 26.66); + m_path.curve3(21.09, 23.73, 18.95, 22.51); + m_path.curve3(15.09, 20.36, 13.43, 18.02); + m_path.curve3(11.77, 15.67, 11.77, 12.89); + m_path.curve3(11.77, 9.38, 13.87, 7.06); + m_path.curve3(15.97, 4.74, 18.70, 4.74); + m_path.curve3(22.41, 4.74, 28.47, 9.62); + m_path.close_polygon(flag); + } + + + + virtual void on_draw() + { + typedef agg::renderer_base ren_base; + + agg::pixfmt_bgr24 pixf(rbuf_window()); + ren_base renb(pixf); + renb.clear(agg::rgba(1, 1, 1)); + + agg::rasterizer_scanline_aa<> ras; + agg::scanline_p8 sl; + + agg::trans_affine mtx; + mtx *= agg::trans_affine_scaling(4.0); + mtx *= agg::trans_affine_translation(150, 100); + + + agg::conv_transform trans(m_path, mtx); + agg::conv_curve > curve(trans); + + agg::conv_contour + > > contour(curve); + + contour.width(m_width.value()); + //contour.inner_join(agg::inner_bevel); + //contour.line_join(agg::miter_join); + //contour.inner_line_join(agg::miter_join); + //contour.inner_miter_limit(4.0); + contour.auto_detect_orientation(m_auto_detect.status()); + + compose_path(); + ras.add_path(contour); + agg::render_scanlines_aa_solid(ras, sl, renb, agg::rgba(0,0,0)); + + agg::render_ctrl(ras, sl, renb, m_close); + agg::render_ctrl(ras, sl, renb, m_width); + agg::render_ctrl(ras, sl, renb, m_auto_detect); + } + +}; + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("AGG Example. Contour Tool & Polygon Orientation"); + + if(app.init(440, 330, 0)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/conv_dash_marker.cpp b/jni/desmume/src/android/agg/examples/conv_dash_marker.cpp new file mode 100755 index 0000000..8f55e62 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/conv_dash_marker.cpp @@ -0,0 +1,283 @@ +#include +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_conv_stroke.h" +#include "agg_conv_dash.h" +#include "agg_conv_curve.h" +#include "agg_conv_contour.h" +#include "agg_conv_smooth_poly1.h" +#include "agg_conv_marker.h" +#include "agg_arrowhead.h" +#include "agg_vcgen_markers_term.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_pixfmt_rgb.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "platform/agg_platform_support.h" + + +enum flip_y_e { flip_y = true }; + + + +class the_application : public agg::platform_support +{ + double m_x[3]; + double m_y[3]; + double m_dx; + double m_dy; + int m_idx; + agg::rbox_ctrl m_cap; + agg::slider_ctrl m_width; + agg::slider_ctrl m_smooth; + agg::cbox_ctrl m_close; + agg::cbox_ctrl m_even_odd; + + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_idx(-1), + m_cap(10.0, 10.0, 130.0, 80.0, !flip_y), + m_width(130 + 10.0, 10.0 + 4.0, 130 + 150.0, 10.0 + 8.0 + 4.0, !flip_y), + m_smooth(130 + 150.0 + 10.0, 10.0 + 4.0, 500 - 10.0, 10.0 + 8.0 + 4.0, !flip_y), + m_close(130 + 10.0, 10.0 + 4.0 + 16.0, "Close Polygons", !flip_y), + m_even_odd(130 + 150.0 + 10.0, 10.0 + 4.0 + 16.0, "Even-Odd Fill", !flip_y) + { + m_x[0] = 57 + 100; m_y[0] = 60; + m_x[1] = 369 + 100; m_y[1] = 170; + m_x[2] = 143 + 100; m_y[2] = 310; + + add_ctrl(m_cap); + m_cap.add_item("Butt Cap"); + m_cap.add_item("Square Cap"); + m_cap.add_item("Round Cap"); + m_cap.cur_item(0); + m_cap.no_transform(); + + add_ctrl(m_width); + m_width.range(0.0, 10.0); + m_width.value(3.0); + m_width.label("Width=%1.2f"); + m_width.no_transform(); + + add_ctrl(m_smooth); + m_smooth.range(0.0, 2.0); + m_smooth.value(1.0); + m_smooth.label("Smooth=%1.2f"); + m_smooth.no_transform(); + + add_ctrl(m_close); + m_close.no_transform(); + + add_ctrl(m_even_odd); + m_even_odd.no_transform(); + } + + virtual void on_init() + { + } + + virtual void on_draw() + { + typedef agg::renderer_base ren_base; + + agg::pixfmt_bgr24 pixf(rbuf_window()); + ren_base renb(pixf); + renb.clear(agg::rgba(1, 1, 1)); + + agg::rasterizer_scanline_aa<> ras; + agg::scanline_u8 sl; + + agg::line_cap_e cap = agg::butt_cap; + if(m_cap.cur_item() == 1) cap = agg::square_cap; + if(m_cap.cur_item() == 2) cap = agg::round_cap; + + // Here we declare a very cheap-in-use path storage. + // It allocates space for at most 20 vertices in stack and + // never allocates memory. But be aware that adding more than + // 20 vertices is fatal! + //------------------------ + typedef agg::path_base< + agg::vertex_stl_storage< + agg::pod_auto_vector< + agg::vertex_d, 20> > > path_storage_type; + path_storage_type path; + + path.move_to(m_x[0], m_y[0]); + path.line_to(m_x[1], m_y[1]); + path.line_to((m_x[0]+m_x[1]+m_x[2]) / 3.0, (m_y[0]+m_y[1]+m_y[2]) / 3.0); + path.line_to(m_x[2], m_y[2]); + if(m_close.status()) path.close_polygon(); + + path.move_to((m_x[0] + m_x[1]) / 2, (m_y[0] + m_y[1]) / 2); + path.line_to((m_x[1] + m_x[2]) / 2, (m_y[1] + m_y[2]) / 2); + path.line_to((m_x[2] + m_x[0]) / 2, (m_y[2] + m_y[0]) / 2); + if(m_close.status()) path.close_polygon(); + + if(m_even_odd.status()) ras.filling_rule(agg::fill_even_odd); + + // (1) + ras.add_path(path); + agg::render_scanlines_aa_solid(ras, sl, renb, agg::rgba(0.7, 0.5, 0.1, 0.5)); + // (1) + + // Start of (2, 3, 4) + agg::conv_smooth_poly1 smooth(path); + smooth.smooth_value(m_smooth.value()); + + // (2) + ras.add_path(smooth); + agg::render_scanlines_aa_solid(ras, sl, renb, agg::rgba(0.1, 0.5, 0.7, 0.1)); + // (2) + + + // (3) + agg::conv_stroke > smooth_outline(smooth); + ras.add_path(smooth_outline); + agg::render_scanlines_aa_solid(ras, sl, renb, agg::rgba(0.0, 0.6, 0.0, 0.8)); + // (3) + + // (4) + agg::conv_curve > curve(smooth); + agg::conv_dash >, agg::vcgen_markers_term> dash(curve); + agg::conv_stroke >, agg::vcgen_markers_term> > stroke(dash); + stroke.line_cap(cap); + stroke.width(m_width.value()); + + double k = ::pow(m_width.value(), 0.7); + + agg::arrowhead ah; + ah.head(4 * k, 4 * k, 3 * k, 2 * k); + if(!m_close.status()) ah.tail(1 * k, 1.5 * k, 3 * k, 5 * k); + + agg::conv_marker arrow(dash.markers(), ah); + + dash.add_dash(20.0, 5.0); + dash.add_dash(5.0, 5.0); + dash.add_dash(5.0, 5.0); + dash.dash_start(10); + + ras.add_path(stroke); + ras.add_path(arrow); + agg::render_scanlines_aa_solid(ras, sl, renb, agg::rgba(0.0, 0.0, 0.0)); + // (4) + + + ras.filling_rule(agg::fill_non_zero); + agg::render_ctrl(ras, sl, renb, m_cap); + agg::render_ctrl(ras, sl, renb, m_width); + agg::render_ctrl(ras, sl, renb, m_smooth); + agg::render_ctrl(ras, sl, renb, m_close); + agg::render_ctrl(ras, sl, renb, m_even_odd); + } + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + unsigned i; + for (i = 0; i < 3; i++) + { + if(sqrt( (x-m_x[i]) * (x-m_x[i]) + (y-m_y[i]) * (y-m_y[i]) ) < 20.0) + { + m_dx = x - m_x[i]; + m_dy = y - m_y[i]; + m_idx = i; + break; + } + } + if(i == 3) + { + if(agg::point_in_triangle(m_x[0], m_y[0], + m_x[1], m_y[1], + m_x[2], m_y[2], + x, y)) + { + m_dx = x - m_x[0]; + m_dy = y - m_y[0]; + m_idx = 3; + } + + } + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_idx == 3) + { + double dx = x - m_dx; + double dy = y - m_dy; + m_x[1] -= m_x[0] - dx; + m_y[1] -= m_y[0] - dy; + m_x[2] -= m_x[0] - dx; + m_y[2] -= m_y[0] - dy; + m_x[0] = dx; + m_y[0] = dy; + force_redraw(); + return; + } + + if(m_idx >= 0) + { + m_x[m_idx] = x - m_dx; + m_y[m_idx] = y - m_dy; + force_redraw(); + } + } + else + { + on_mouse_button_up(x, y, flags); + } + } + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + m_idx = -1; + } + + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + double dx = 0; + double dy = 0; + switch(key) + { + case agg::key_left: dx = -0.1; break; + case agg::key_right: dx = 0.1; break; + case agg::key_up: dy = 0.1; break; + case agg::key_down: dy = -0.1; break; + } + m_x[0] += dx; + m_y[0] += dy; + m_x[1] += dx; + m_y[1] += dy; + force_redraw(); + } + +}; + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("AGG Example. Line Join"); + + if(app.init(500, 330, 0)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/conv_stroke.cpp b/jni/desmume/src/android/agg/examples/conv_stroke.cpp new file mode 100755 index 0000000..9477dce --- /dev/null +++ b/jni/desmume/src/android/agg/examples/conv_stroke.cpp @@ -0,0 +1,273 @@ +#include +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_conv_stroke.h" +#include "agg_conv_dash.h" +#include "agg_conv_curve.h" +#include "agg_conv_contour.h" +#include "agg_conv_smooth_poly1.h" +#include "agg_conv_marker.h" +#include "agg_arrowhead.h" +#include "agg_vcgen_markers_term.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_pixfmt_rgb.h" +#include "platform/agg_platform_support.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" + + +enum flip_y_e { flip_y = true }; + + + +class the_application : public agg::platform_support +{ + double m_x[3]; + double m_y[3]; + double m_dx; + double m_dy; + int m_idx; + agg::rbox_ctrl m_join; + agg::rbox_ctrl m_cap; + agg::slider_ctrl m_width; + agg::slider_ctrl m_miter_limit; + + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_idx(-1), + m_join(10.0, 10.0, 133.0, 80.0, !flip_y), + m_cap(10.0, 80.0 + 10.0, 133.0, 80.0 + 80.0, !flip_y), + m_width(130 + 10.0, 10.0 + 4.0, 500.0 - 10.0, 10.0 + 8.0 + 4.0, !flip_y), + m_miter_limit(130 + 10.0, 20.0 + 10.0 + 4.0, 500.0 - 10.0, 20.0 + 10.0 + 8.0 + 4.0, !flip_y) + { + m_x[0] = 57 + 100; m_y[0] = 60; + m_x[1] = 369 + 100; m_y[1] = 170; + m_x[2] = 143 + 100; m_y[2] = 310; + + add_ctrl(m_join); + m_join.text_size(7.5); + m_join.text_thickness(1.0); + m_join.add_item("Miter Join"); + m_join.add_item("Miter Join Revert"); + m_join.add_item("Round Join"); + m_join.add_item("Bevel Join"); + m_join.cur_item(2); + + add_ctrl(m_cap); + m_cap.add_item("Butt Cap"); + m_cap.add_item("Square Cap"); + m_cap.add_item("Round Cap"); + m_cap.cur_item(2); + + add_ctrl(m_width); + m_width.range(3.0, 40.0); + m_width.value(20.0); + m_width.label("Width=%1.2f"); + + add_ctrl(m_miter_limit); + m_miter_limit.range(1.0, 10.0); + m_miter_limit.value(4.0); + m_miter_limit.label("Miter Limit=%1.2f"); + + m_join.no_transform(); + m_cap.no_transform(); + m_width.no_transform(); + m_miter_limit.no_transform(); + } + + virtual void on_init() + { + } + + virtual void on_draw() + { + typedef agg::renderer_base ren_base; + + agg::pixfmt_bgr24 pixf(rbuf_window()); + ren_base renb(pixf); + renb.clear(agg::rgba(1, 1, 1)); + + agg::rasterizer_scanline_aa<> ras; + agg::scanline_p8 sl; + + agg::path_storage path; + + path.move_to(m_x[0], m_y[0]); + path.line_to((m_x[0] + m_x[1]) / 2, (m_y[0] + m_y[1]) / 2); // This point is added only to check for numerical stability + path.line_to(m_x[1], m_y[1]); + path.line_to(m_x[2], m_y[2]); + path.line_to(m_x[2], m_y[2]); // This point is added only to check for numerical stability + + path.move_to((m_x[0] + m_x[1]) / 2, (m_y[0] + m_y[1]) / 2); + path.line_to((m_x[1] + m_x[2]) / 2, (m_y[1] + m_y[2]) / 2); + path.line_to((m_x[2] + m_x[0]) / 2, (m_y[2] + m_y[0]) / 2); + path.close_polygon(); + + agg::line_cap_e cap = agg::butt_cap; + if(m_cap.cur_item() == 1) cap = agg::square_cap; + if(m_cap.cur_item() == 2) cap = agg::round_cap; + + agg::line_join_e join = agg::miter_join; + if(m_join.cur_item() == 1) join = agg::miter_join_revert; + if(m_join.cur_item() == 2) join = agg::round_join; + if(m_join.cur_item() == 3) join = agg::bevel_join; + + + + // (1) + agg::conv_stroke stroke(path); + stroke.line_join(join); + stroke.line_cap(cap); + stroke.miter_limit(m_miter_limit.value()); + stroke.width(m_width.value()); + ras.add_path(stroke); + agg::render_scanlines_aa_solid(ras, sl, renb, agg::rgba(0.8, 0.7, 0.6)); + // (1) + + + // (2) + agg::conv_stroke poly1(path); + poly1.width(1.5); + ras.add_path(poly1); + agg::render_scanlines_aa_solid(ras, sl, renb, agg::rgba(0,0,0)); + // (2) + + + + // (3) + agg::conv_dash > poly2_dash(stroke); + agg::conv_stroke > > poly2(poly2_dash); + poly2.miter_limit(4.0); + poly2.width(m_width.value() / 5.0); + poly2.line_cap(cap); + poly2.line_join(join); + poly2_dash.add_dash(20.0, m_width.value() / 2.5); + ras.add_path(poly2); + agg::render_scanlines_aa_solid(ras, sl, renb, agg::rgba(0,0,0.3)); + // (3) + + + + // (4) + ras.add_path(path); + agg::render_scanlines_aa_solid(ras, sl, renb, agg::rgba(0.0, 0.0, 0.0, 0.2)); + // (4) + + + + agg::render_ctrl(ras, sl, renb, m_join); + agg::render_ctrl(ras, sl, renb, m_cap); + agg::render_ctrl(ras, sl, renb, m_width); + agg::render_ctrl(ras, sl, renb, m_miter_limit); + } + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + unsigned i; + for (i = 0; i < 3; i++) + { + if(sqrt( (x-m_x[i]) * (x-m_x[i]) + (y-m_y[i]) * (y-m_y[i]) ) < 20.0) + { + m_dx = x - m_x[i]; + m_dy = y - m_y[i]; + m_idx = i; + break; + } + } + if(i == 3) + { + if(agg::point_in_triangle(m_x[0], m_y[0], + m_x[1], m_y[1], + m_x[2], m_y[2], + x, y)) + { + m_dx = x - m_x[0]; + m_dy = y - m_y[0]; + m_idx = 3; + } + + } + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_idx == 3) + { + double dx = x - m_dx; + double dy = y - m_dy; + m_x[1] -= m_x[0] - dx; + m_y[1] -= m_y[0] - dy; + m_x[2] -= m_x[0] - dx; + m_y[2] -= m_y[0] - dy; + m_x[0] = dx; + m_y[0] = dy; + force_redraw(); + return; + } + + if(m_idx >= 0) + { + m_x[m_idx] = x - m_dx; + m_y[m_idx] = y - m_dy; + force_redraw(); + } + } + else + { + on_mouse_button_up(x, y, flags); + } + } + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + m_idx = -1; + } + + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + double dx = 0; + double dy = 0; + switch(key) + { + case agg::key_left: dx = -0.1; break; + case agg::key_right: dx = 0.1; break; + case agg::key_up: dy = 0.1; break; + case agg::key_down: dy = -0.1; break; + } + m_x[0] += dx; + m_y[0] += dy; + m_x[1] += dx; + m_y[1] += dy; + force_redraw(); + } + +}; + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("AGG Example. Line Join"); + + if(app.init(500, 330, 0)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/distortions.cpp b/jni/desmume/src/android/agg/examples/distortions.cpp new file mode 100755 index 0000000..b214f07 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/distortions.cpp @@ -0,0 +1,707 @@ +#include +#include +#include +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_ellipse.h" +#include "agg_trans_affine.h" +#include "agg_conv_transform.h" +#include "agg_pixfmt_rgb.h" +#include "agg_span_allocator.h" +#include "agg_span_image_filter_rgb.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_span_interpolator_linear.h" +#include "agg_span_interpolator_adaptor.h" +#include "agg_span_gradient.h" +#include "agg_image_accessors.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "platform/agg_platform_support.h" + + +enum flip_y_e { flip_y = true }; + + +static agg::int8u g_gradient_colors[] = +{ + 255, 255, 255, 255, + 255, 255, 254, 255, + 255, 255, 254, 255, + 255, 255, 254, 255, + 255, 255, 253, 255, + 255, 255, 253, 255, + 255, 255, 252, 255, + 255, 255, 251, 255, + 255, 255, 250, 255, + 255, 255, 248, 255, + 255, 255, 246, 255, + 255, 255, 244, 255, + 255, 255, 241, 255, + 255, 255, 238, 255, + 255, 255, 235, 255, + 255, 255, 231, 255, + 255, 255, 227, 255, + 255, 255, 222, 255, + 255, 255, 217, 255, + 255, 255, 211, 255, + 255, 255, 206, 255, + 255, 255, 200, 255, + 255, 254, 194, 255, + 255, 253, 188, 255, + 255, 252, 182, 255, + 255, 250, 176, 255, + 255, 249, 170, 255, + 255, 247, 164, 255, + 255, 246, 158, 255, + 255, 244, 152, 255, + 254, 242, 146, 255, + 254, 240, 141, 255, + 254, 238, 136, 255, + 254, 236, 131, 255, + 253, 234, 126, 255, + 253, 232, 121, 255, + 253, 229, 116, 255, + 252, 227, 112, 255, + 252, 224, 108, 255, + 251, 222, 104, 255, + 251, 219, 100, 255, + 251, 216, 96, 255, + 250, 214, 93, 255, + 250, 211, 89, 255, + 249, 208, 86, 255, + 249, 205, 83, 255, + 248, 202, 80, 255, + 247, 199, 77, 255, + 247, 196, 74, 255, + 246, 193, 72, 255, + 246, 190, 69, 255, + 245, 187, 67, 255, + 244, 183, 64, 255, + 244, 180, 62, 255, + 243, 177, 60, 255, + 242, 174, 58, 255, + 242, 170, 56, 255, + 241, 167, 54, 255, + 240, 164, 52, 255, + 239, 161, 51, 255, + 239, 157, 49, 255, + 238, 154, 47, 255, + 237, 151, 46, 255, + 236, 147, 44, 255, + 235, 144, 43, 255, + 235, 141, 41, 255, + 234, 138, 40, 255, + 233, 134, 39, 255, + 232, 131, 37, 255, + 231, 128, 36, 255, + 230, 125, 35, 255, + 229, 122, 34, 255, + 228, 119, 33, 255, + 227, 116, 31, 255, + 226, 113, 30, 255, + 225, 110, 29, 255, + 224, 107, 28, 255, + 223, 104, 27, 255, + 222, 101, 26, 255, + 221, 99, 25, 255, + 220, 96, 24, 255, + 219, 93, 23, 255, + 218, 91, 22, 255, + 217, 88, 21, 255, + 216, 86, 20, 255, + 215, 83, 19, 255, + 214, 81, 18, 255, + 213, 79, 17, 255, + 212, 77, 17, 255, + 211, 74, 16, 255, + 210, 72, 15, 255, + 209, 70, 14, 255, + 207, 68, 13, 255, + 206, 66, 13, 255, + 205, 64, 12, 255, + 204, 62, 11, 255, + 203, 60, 10, 255, + 202, 58, 10, 255, + 201, 56, 9, 255, + 199, 55, 9, 255, + 198, 53, 8, 255, + 197, 51, 7, 255, + 196, 50, 7, 255, + 195, 48, 6, 255, + 193, 46, 6, 255, + 192, 45, 5, 255, + 191, 43, 5, 255, + 190, 42, 4, 255, + 188, 41, 4, 255, + 187, 39, 3, 255, + 186, 38, 3, 255, + 185, 37, 2, 255, + 183, 35, 2, 255, + 182, 34, 1, 255, + 181, 33, 1, 255, + 179, 32, 1, 255, + 178, 30, 0, 255, + 177, 29, 0, 255, + 175, 28, 0, 255, + 174, 27, 0, 255, + 173, 26, 0, 255, + 171, 25, 0, 255, + 170, 24, 0, 255, + 168, 23, 0, 255, + 167, 22, 0, 255, + 165, 21, 0, 255, + 164, 21, 0, 255, + 163, 20, 0, 255, + 161, 19, 0, 255, + 160, 18, 0, 255, + 158, 17, 0, 255, + 156, 17, 0, 255, + 155, 16, 0, 255, + 153, 15, 0, 255, + 152, 14, 0, 255, + 150, 14, 0, 255, + 149, 13, 0, 255, + 147, 12, 0, 255, + 145, 12, 0, 255, + 144, 11, 0, 255, + 142, 11, 0, 255, + 140, 10, 0, 255, + 139, 10, 0, 255, + 137, 9, 0, 255, + 135, 9, 0, 255, + 134, 8, 0, 255, + 132, 8, 0, 255, + 130, 7, 0, 255, + 128, 7, 0, 255, + 126, 6, 0, 255, + 125, 6, 0, 255, + 123, 5, 0, 255, + 121, 5, 0, 255, + 119, 4, 0, 255, + 117, 4, 0, 255, + 115, 4, 0, 255, + 113, 3, 0, 255, + 111, 3, 0, 255, + 109, 2, 0, 255, + 107, 2, 0, 255, + 105, 2, 0, 255, + 103, 1, 0, 255, + 101, 1, 0, 255, + 99, 1, 0, 255, + 97, 0, 0, 255, + 95, 0, 0, 255, + 93, 0, 0, 255, + 91, 0, 0, 255, + 90, 0, 0, 255, + 88, 0, 0, 255, + 86, 0, 0, 255, + 84, 0, 0, 255, + 82, 0, 0, 255, + 80, 0, 0, 255, + 78, 0, 0, 255, + 77, 0, 0, 255, + 75, 0, 0, 255, + 73, 0, 0, 255, + 72, 0, 0, 255, + 70, 0, 0, 255, + 68, 0, 0, 255, + 67, 0, 0, 255, + 65, 0, 0, 255, + 64, 0, 0, 255, + 63, 0, 0, 255, + 61, 0, 0, 255, + 60, 0, 0, 255, + 59, 0, 0, 255, + 58, 0, 0, 255, + 57, 0, 0, 255, + 56, 0, 0, 255, + 55, 0, 0, 255, + 54, 0, 0, 255, + 53, 0, 0, 255, + 53, 0, 0, 255, + 52, 0, 0, 255, + 52, 0, 0, 255, + 51, 0, 0, 255, + 51, 0, 0, 255, + 51, 0, 0, 255, + 50, 0, 0, 255, + 50, 0, 0, 255, + 51, 0, 0, 255, + 51, 0, 0, 255, + 51, 0, 0, 255, + 51, 0, 0, 255, + 52, 0, 0, 255, + 52, 0, 0, 255, + 53, 0, 0, 255, + 54, 1, 0, 255, + 55, 2, 0, 255, + 56, 3, 0, 255, + 57, 4, 0, 255, + 58, 5, 0, 255, + 59, 6, 0, 255, + 60, 7, 0, 255, + 62, 8, 0, 255, + 63, 9, 0, 255, + 64, 11, 0, 255, + 66, 12, 0, 255, + 68, 13, 0, 255, + 69, 14, 0, 255, + 71, 16, 0, 255, + 73, 17, 0, 255, + 75, 18, 0, 255, + 77, 20, 0, 255, + 79, 21, 0, 255, + 81, 23, 0, 255, + 83, 24, 0, 255, + 85, 26, 0, 255, + 87, 28, 0, 255, + 90, 29, 0, 255, + 92, 31, 0, 255, + 94, 33, 0, 255, + 97, 34, 0, 255, + 99, 36, 0, 255, + 102, 38, 0, 255, + 104, 40, 0, 255, + 107, 41, 0, 255, + 109, 43, 0, 255, + 112, 45, 0, 255, + 115, 47, 0, 255, + 117, 49, 0, 255, + 120, 51, 0, 255, + 123, 52, 0, 255, + 126, 54, 0, 255, + 128, 56, 0, 255, + 131, 58, 0, 255, + 134, 60, 0, 255, + 137, 62, 0, 255, + 140, 64, 0, 255, + 143, 66, 0, 255, + 145, 68, 0, 255, + 148, 70, 0, 255, + 151, 72, 0, 255, + 154, 74, 0, 255 +}; + + + +class periodic_distortion +{ +public: + periodic_distortion() : + m_cx(0.0), + m_cy(0.0), + m_period(0.5), + m_amplitude(0.5), + m_phase(0.0) + {} + + void center(double x, double y) { m_cx = x; m_cy = y; } + void period(double v) { m_period = v; } + void amplitude(double v) { m_amplitude = 1.0 / v; } + void phase(double v) { m_phase = v; } + + virtual void calculate(int* x, int* y) const = 0; + +protected: + double m_cx; + double m_cy; + double m_period; + double m_amplitude; + double m_phase; +}; + + + +inline void calculate_wave(int* x, int* y, + double cx, double cy, + double period, double amplitude, double phase) +{ + double xd = double(*x) / agg::image_subpixel_scale - cx; + double yd = double(*y) / agg::image_subpixel_scale - cy; + double d = sqrt(xd*xd + yd*yd); + if(d > 1) + { + double a = cos(d / (16.0 * period) - phase) * (1.0 / (amplitude * d)) + 1.0; + *x = int((xd * a + cx) * agg::image_subpixel_scale); + *y = int((yd * a + cy) * agg::image_subpixel_scale); + } +} + + + +inline void calculate_swirl(int* x, int* y, + double cx, double cy, + double amplitude, double phase) +{ + double xd = double(*x) / agg::image_subpixel_scale - cx; + double yd = double(*y) / agg::image_subpixel_scale - cy; + double a = double(100.0 - sqrt(xd * xd + yd * yd)) / 100.0 * (0.1 / -amplitude); + double sa = sin(a - phase/25.0); + double ca = cos(a - phase/25.0); + *x = int((xd * ca - yd * sa + cx) * agg::image_subpixel_scale); + *y = int((xd * sa + yd * ca + cy) * agg::image_subpixel_scale); +} + + + + + +class distortion_wave : public periodic_distortion +{ + virtual void calculate(int* x, int* y) const + { + calculate_wave(x, y, m_cx, m_cy, m_period, m_amplitude, m_phase); + } +}; + +class distortion_swirl : public periodic_distortion +{ + virtual void calculate(int* x, int* y) const + { + calculate_swirl(x, y, m_cx, m_cy, m_amplitude, m_phase); + } +}; + +class distortion_swirl_wave : public periodic_distortion +{ + virtual void calculate(int* x, int* y) const + { + calculate_swirl(x, y, m_cx, m_cy, m_amplitude, m_phase); + calculate_wave(x, y, m_cx, m_cy, m_period, m_amplitude, m_phase); + } +}; + + +class distortion_wave_swirl : public periodic_distortion +{ + virtual void calculate(int* x, int* y) const + { + calculate_wave(x, y, m_cx, m_cy, m_period, m_amplitude, m_phase); + calculate_swirl(x, y, m_cx, m_cy, m_amplitude, m_phase); + } +}; + + + + + + + + + + +class the_application : public agg::platform_support +{ + agg::slider_ctrl m_angle; + agg::slider_ctrl m_scale; + agg::slider_ctrl m_amplitude; + agg::slider_ctrl m_period; + agg::rbox_ctrl m_distortion; + + double m_center_x; + double m_center_y; + double m_phase; + + typedef agg::pod_auto_array color_array_type; + color_array_type m_gradient_colors; + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_angle (5, 5, 150, 12, !flip_y), + m_scale (5, 5+15, 150, 12+15, !flip_y), + m_period (5+170, 5, 150+170, 12, !flip_y), + m_amplitude (5+170, 5+15, 150+170, 12+15, !flip_y), + m_distortion(480, 5, 600, 90, !flip_y), + + m_center_x(0.0), + m_center_y(0.0), + m_phase(0.0) + { + add_ctrl(m_angle); + add_ctrl(m_scale); + add_ctrl(m_amplitude); + add_ctrl(m_period); + add_ctrl(m_distortion); + m_angle.label("Angle=%3.2f"); + m_scale.label("Scale=%3.2f"); + m_angle.range(-180.0, 180.0); + m_angle.value(20.0); + m_scale.range(0.1, 5.0); + m_scale.value(1.0); + + m_amplitude.label("Amplitude=%3.2f"); + m_period.label("Period=%3.2f"); + m_amplitude.range(0.1, 40.0); + m_period.range(0.1, 2.0); + m_amplitude.value(10.0); + m_period.value(1.0); + + m_distortion.add_item("Wave"); + m_distortion.add_item("Swirl"); + m_distortion.add_item("Wave-Swirl"); + m_distortion.add_item("Swirl-Wave"); + m_distortion.cur_item(0); + + unsigned i; + const agg::int8u* p = g_gradient_colors; + for(i = 0; i < 256; i++) + { + m_gradient_colors[i] = agg::rgba8(p[0], p[1], p[2], p[3]); + p += 4; + } + } + + virtual ~the_application() + { + } + + virtual void on_init() + { + m_center_x = rbuf_img(0).width() / 2.0 + 10; + m_center_y = rbuf_img(0).height() / 2.0 + 10 + 40; + } + + virtual void on_draw() + { + double img_width = rbuf_img(0).width(); + double img_height = rbuf_img(0).height(); + + typedef agg::pixfmt_bgr24 pixfmt; + typedef agg::renderer_base renderer_base; + + pixfmt pixf(rbuf_window()); + pixfmt img_pixf(rbuf_img(0)); + + renderer_base rb(pixf); + + rb.clear(agg::rgba(1.0, 1.0, 1.0)); + + agg::trans_affine src_mtx; + src_mtx *= agg::trans_affine_translation(-img_width/2, -img_height/2); + src_mtx *= agg::trans_affine_rotation(m_angle.value() * agg::pi / 180.0); + src_mtx *= agg::trans_affine_translation(img_width/2 + 10, img_height/2 + 10 + 40); + src_mtx *= trans_affine_resizing(); + + agg::trans_affine img_mtx; + img_mtx *= agg::trans_affine_translation(-img_width/2, -img_height/2); + img_mtx *= agg::trans_affine_rotation(m_angle.value() * agg::pi / 180.0); + img_mtx *= agg::trans_affine_scaling(m_scale.value()); + img_mtx *= agg::trans_affine_translation(img_width/2 + 10, img_height/2 + 10 + 40); + img_mtx *= trans_affine_resizing(); + img_mtx.invert(); + + + typedef agg::span_allocator span_alloc_type; + + span_alloc_type sa; + + typedef agg::span_interpolator_adaptor, + periodic_distortion> interpolator_type; + + periodic_distortion* dist = 0; + distortion_wave dist_wave; + distortion_swirl dist_swirl; + distortion_wave_swirl dist_wave_swirl; + distortion_swirl_wave dist_swirl_wave; + + switch(m_distortion.cur_item()) + { + case 0: dist = &dist_wave; break; + case 1: dist = &dist_swirl; break; + case 2: dist = &dist_wave_swirl; break; + case 3: dist = &dist_swirl_wave; break; + } + + dist->period(m_period.value()); + dist->amplitude(m_amplitude.value()); + dist->phase(m_phase); + double cx = m_center_x; + double cy = m_center_y; + img_mtx.transform(&cx, &cy); + dist->center(cx, cy); + + interpolator_type interpolator(img_mtx, *dist); + + typedef agg::image_accessor_clip img_source_type; + img_source_type img_src(img_pixf, agg::rgba(1,1,1)); + +/* + // Version without filtering (nearest neighbor) + //------------------------------------------ + typedef agg::span_image_filter_rgb_nn span_gen_type; + span_gen_type sg(img_src, interpolator); + //------------------------------------------ +*/ + + // Version with "hardcoded" bilinear filter and without + // image_accessor (direct filter, the old variant) + //------------------------------------------ + typedef agg::span_image_filter_rgb_bilinear_clip span_gen_type; + span_gen_type sg(img_pixf, agg::rgba(1,1,1), interpolator); + //------------------------------------------ + +/* + // Version with arbitrary 2x2 filter + //------------------------------------------ + typedef agg::span_image_filter_rgb_2x2 span_gen_type; + agg::image_filter filter; + span_gen_type sg(img_src, interpolator, filter); + //------------------------------------------ +*/ +/* + // Version with arbitrary filter + //------------------------------------------ + typedef agg::span_image_filter_rgb span_gen_type; + agg::image_filter filter; + span_gen_type sg(img_src, interpolator, filter); + //------------------------------------------ +*/ + + + agg::rasterizer_scanline_aa<> ras; + agg::scanline_u8 sl; + double r = img_width; + if(img_height < r) r = img_height; + agg::ellipse ell(img_width / 2.0, + img_height / 2.0, + r / 2.0 - 20.0, + r / 2.0 - 20.0, 200); + + + agg::conv_transform tr(ell, src_mtx); + + ras.add_path(tr); + agg::render_scanlines_aa(ras, sl, rb, sa, sg); + + src_mtx *= ~trans_affine_resizing(); + src_mtx *= agg::trans_affine_translation(img_width - img_width/10, 0.0); + src_mtx *= trans_affine_resizing(); + + ras.add_path(tr); + agg::render_scanlines_aa_solid(ras, sl, rb, agg::rgba8(0,0,0)); + + typedef agg::span_gradient gradient_span_gen; + + agg::gradient_circle gradient_function; + + color_array_type gradient_colors(m_gradient_colors); + gradient_span_gen span_gradient(interpolator, + gradient_function, + gradient_colors, + 0, 180); + + agg::trans_affine gr1_mtx; + gr1_mtx *= agg::trans_affine_translation(-img_width/2, -img_height/2); + gr1_mtx *= agg::trans_affine_scaling(0.8); + gr1_mtx *= agg::trans_affine_rotation(m_angle.value() * agg::pi / 180.0); + gr1_mtx *= agg::trans_affine_translation(img_width - img_width/10 + img_width/2 + 10, + img_height/2 + 10 + 40); + gr1_mtx *= trans_affine_resizing(); + + agg::trans_affine gr2_mtx; + gr2_mtx *= agg::trans_affine_rotation(m_angle.value() * agg::pi / 180.0); + gr2_mtx *= agg::trans_affine_scaling(m_scale.value()); + gr2_mtx *= agg::trans_affine_translation(img_width - img_width/10 + img_width/2 + 10 + 50, + img_height/2 + 10 + 40 + 50); + gr2_mtx *= trans_affine_resizing(); + gr2_mtx.invert(); + + cx = m_center_x + img_width - img_width/10; + cy = m_center_y; + gr2_mtx.transform(&cx, &cy); + dist->center(cx, cy); + + interpolator.transformer(gr2_mtx); + + agg::conv_transform tr2(ell, gr1_mtx); + + ras.add_path(tr2); + agg::render_scanlines_aa(ras, sl, rb, sa, span_gradient); + + agg::render_ctrl(ras, sl, rb, m_angle); + agg::render_ctrl(ras, sl, rb, m_scale); + agg::render_ctrl(ras, sl, rb, m_amplitude); + agg::render_ctrl(ras, sl, rb, m_period); + agg::render_ctrl(ras, sl, rb, m_distortion); + } + + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags) + { + m_center_x = x; + m_center_y = y; + force_redraw(); + } + } + + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & 1) + { + m_center_x = x; + m_center_y = y; + force_redraw(); + } + } + + virtual void on_idle() + { + m_phase += 15.0 * agg::pi / 180.0; + if(m_phase > agg::pi * 200.0) m_phase -= agg::pi * 200.0; + force_redraw(); + } + + +}; + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("Image and Gradient Distortions"); + + const char* img_name = "spheres"; + if(argc >= 2) img_name = argv[1]; + if(!app.load_img(0, img_name)) + { + char buf[256]; + if(strcmp(img_name, "spheres") == 0) + { + sprintf(buf, "File not found: %s%s. Download http://www.antigrain.com/%s%s\n" + "or copy it from another directory if available.", + img_name, app.img_ext(), img_name, app.img_ext()); + } + else + { + sprintf(buf, "File not found: %s%s", img_name, app.img_ext()); + } + app.message(buf); + return 1; + } + + if(app.init(app.rbuf_img(0).width() + 300, app.rbuf_img(0).height() + 40 + 20, agg::window_resize)) + { + app.wait_mode(false); + return app.run(); + } + return 0; +} + + diff --git a/jni/desmume/src/android/agg/examples/flash_rasterizer.cpp b/jni/desmume/src/android/agg/examples/flash_rasterizer.cpp new file mode 100755 index 0000000..a96b9cd --- /dev/null +++ b/jni/desmume/src/android/agg/examples/flash_rasterizer.cpp @@ -0,0 +1,571 @@ +#include +#include +#include +#include +#include "agg_rendering_buffer.h" +#include "agg_trans_viewport.h" +#include "agg_path_storage.h" +#include "agg_conv_transform.h" +#include "agg_conv_curve.h" +#include "agg_conv_stroke.h" +#include "agg_gsv_text.h" +#include "agg_scanline_u.h" +#include "agg_scanline_bin.h" +#include "agg_renderer_scanline.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_rasterizer_compound_aa.h" +#include "agg_span_allocator.h" +#include "agg_gamma_lut.h" +#include "agg_pixfmt_rgba.h" +#include "agg_bounding_rect.h" +#include "agg_color_gray.h" +#include "platform/agg_platform_support.h" + + + +enum { flip_y = false }; + +typedef agg::pixfmt_bgra32_pre pixfmt; + + + +namespace agg +{ + struct path_style + { + unsigned path_id; + int left_fill; + int right_fill; + int line; + }; + + class compound_shape + { + public: + ~compound_shape() + { + if(m_fd) + { + fclose(m_fd); + } + } + + compound_shape() : + m_path(), + m_affine(), + m_curve(m_path), + m_trans(m_curve, m_affine), + m_styles() + {} + + bool open(const char* fname) + { + m_fd = fopen(fname, "r"); + return m_fd != 0; + } + + bool read_next() + { + m_path.remove_all(); + m_styles.remove_all(); + const char space[] = " \t\n\r"; + double ax, ay, cx, cy; + if(m_fd) + { + char buf[1024]; + char* ts; + + for(;;) + { + if(fgets(buf, 1022, m_fd) == 0) return false; + if(buf[0] == '=') break; + } + + while(fgets(buf, 1022, m_fd)) + { + if(buf[0] == '!') break; + if(buf[0] == 'P') + { + // BeginPath + path_style style; + style.path_id = m_path.start_new_path(); + ts = strtok(buf, space); // Path; + ts = strtok(0, space); // left_style + style.left_fill = atoi(ts); + ts = strtok(0, space); // right_style + style.right_fill = atoi(ts); + ts = strtok(0, space); // line_style + style.line = atoi(ts); + ts = strtok(0, space); // ax + ax = atof(ts); + ts = strtok(0, space); // ay + ay = atof(ts); + m_path.move_to(ax, ay); + m_styles.add(style); + } + + + if(buf[0] == 'C') + { + ts = strtok(buf, space); // Curve; + ts = strtok(0, space); // cx + cx = atof(ts); + ts = strtok(0, space); // cy + cy = atof(ts); + ts = strtok(0, space); // ax + ax = atof(ts); + ts = strtok(0, space); // ay + ay = atof(ts); + m_path.curve3(cx, cy, ax, ay); + } + + if(buf[0] == 'L') + { + ts = strtok(buf, space); // Line; + ts = strtok(0, space); // ax + ax = atof(ts); + ts = strtok(0, space); // ay + ay = atof(ts); + m_path.line_to(ax, ay); + } + + + if(buf[0] == '<') + { + // EndPath + } + } + return true; + } + return false; + } + + + unsigned operator [] (unsigned i) const + { + return m_styles[i].path_id; + } + + unsigned paths() const { return m_styles.size(); } + const path_style& style(unsigned i) const + { + return m_styles[i]; + } + + void rewind(unsigned path_id) + { + m_trans.rewind(path_id); + } + + unsigned vertex(double* x, double* y) + { + return m_trans.vertex(x, y); + } + + double scale() const + { + return m_affine.scale(); + } + + void scale(double w, double h) + { + m_affine.reset(); + double x1, y1, x2, y2; + bounding_rect(m_path, *this, 0, m_styles.size(), + &x1, &y1, &x2, &y2); + if(x1 < x2 && y1 < y2) + { + trans_viewport vp; + vp.preserve_aspect_ratio(0.5, 0.5, aspect_ratio_meet); + vp.world_viewport(x1, y1, x2, y2); + vp.device_viewport(0, 0, w, h); + m_affine = vp.to_affine(); + } + m_curve.approximation_scale(m_affine.scale()); + } + + void approximation_scale(double s) + { + m_curve.approximation_scale(m_affine.scale() * s); + } + + int hit_test(double x, double y, double r) + { + m_affine.inverse_transform(&x, &y); + r /= m_affine.scale(); + unsigned i; + for(i = 0; i < m_path.total_vertices(); i++) + { + double vx, vy; + unsigned cmd = m_path.vertex(i, &vx, &vy); + if(is_vertex(cmd)) + { + if(calc_distance(x, y, vx, vy) <= r) + { + return i; + } + } + } + return -1; + } + + void modify_vertex(unsigned i, double x, double y) + { + m_affine.inverse_transform(&x, &y); + m_path.modify_vertex(i, x, y); + } + + private: + path_storage m_path; + trans_affine m_affine; + conv_curve m_curve; + conv_transform > m_trans; + pod_bvector m_styles; + double m_x1, m_y1, m_x2, m_y2; + + FILE* m_fd; + }; + + + + // Testing class, color provider and span generator + //------------------------------------------------- + class test_styles + { + public: + test_styles(const rgba8* solid_colors, + const rgba8* gradient) : + m_solid_colors(solid_colors), + m_gradient(gradient) + {} + + // Suppose that style=1 is a gradient + //--------------------------------------------- + bool is_solid(unsigned style) const + { + return true;//style != 1; + } + + // Just returns a color + //--------------------------------------------- + const rgba8& color(unsigned style) const + { + return m_solid_colors[style]; + } + + // Generate span. In our test case only one style (style=1) + // can be a span generator, so that, parameter "style" + // isn't used here. + //--------------------------------------------- + void generate_span(rgba8* span, int x, int y, unsigned len, unsigned style) + { + memcpy(span, m_gradient + x, sizeof(rgba8) * len); + } + + private: + const rgba8* m_solid_colors; + const rgba8* m_gradient; + }; + + + + +} + + + + + + +class the_application : public agg::platform_support +{ + +public: + agg::compound_shape m_shape; + agg::rgba8 m_colors[100]; + agg::trans_affine m_scale; + agg::gamma_lut<> m_gamma; + agg::pod_array m_gradient; + int m_point_idx; + int m_hit_x; + int m_hit_y; + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_point_idx(-1), + m_hit_x(-1), + m_hit_y(-1) + { + m_gamma.gamma(2.0); + + for(unsigned i = 0; i < 100; i++) + { + m_colors[i] = agg::rgba8( + (rand() & 0xFF), + (rand() & 0xFF), + (rand() & 0xFF), + 230); + + m_colors[i].apply_gamma_dir(m_gamma); + m_colors[i].premultiply(); + } + } + + + + bool open(const char* fname) + { + return m_shape.open(full_file_name(fname)); + } + + void read_next() + { + m_shape.read_next(); + m_shape.scale(width(), height()); + } + + virtual void on_draw() + { + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_scanline; + typedef agg::scanline_u8 scanline; + + pixfmt pixf(rbuf_window()); + renderer_base ren_base(pixf); + ren_base.clear(agg::rgba(1.0, 1.0, 0.95)); + renderer_scanline ren(ren_base); + + unsigned i; + unsigned w = unsigned(width()); + m_gradient.resize(w); + agg::rgba8 c1(255, 0, 0, 180); + agg::rgba8 c2(0, 0, 255, 180); + for(i = 0; i < w; i++) + { + m_gradient[i] = c1.gradient(c2, i / width()); + m_gradient[i].premultiply(); + } + + agg::rasterizer_scanline_aa ras; + agg::rasterizer_compound_aa rasc; + agg::scanline_u8 sl; + agg::scanline_bin sl_bin; + agg::conv_transform shape(m_shape, m_scale); + agg::conv_stroke > stroke(shape); + + agg::test_styles style_handler(m_colors, m_gradient.data()); + agg::span_allocator alloc; + + m_shape.approximation_scale(m_scale.scale()); + + // Fill shape + //---------------------- + rasc.clip_box(0, 0, width(), height()); + rasc.reset(); + //rasc.filling_rule(agg::fill_even_odd); + start_timer(); + for(i = 0; i < m_shape.paths(); i++) + { + + if(m_shape.style(i).left_fill >= 0 || + m_shape.style(i).right_fill >= 0) + { + rasc.styles(m_shape.style(i).left_fill, + m_shape.style(i).right_fill); + rasc.add_path(shape, m_shape.style(i).path_id); + } + } + agg::render_scanlines_compound(rasc, sl, sl_bin, ren_base, alloc, style_handler); + double tfill = elapsed_time(); + + // Hit-test test + bool draw_strokes = true; + if(m_hit_x >= 0 && m_hit_y >= 0) + { + if(rasc.hit_test(m_hit_x, m_hit_y)) + { + draw_strokes = false; + } + } + + // Draw strokes + //---------------------- + start_timer(); + if(draw_strokes) + { + ras.clip_box(0, 0, width(), height()); + stroke.width(sqrt(m_scale.scale())); + stroke.line_join(agg::round_join); + stroke.line_cap(agg::round_cap); + for(i = 0; i < m_shape.paths(); i++) + { + ras.reset(); + if(m_shape.style(i).line >= 0) + { + ras.add_path(stroke, m_shape.style(i).path_id); + ren.color(agg::rgba8(0,0,0, 128)); + agg::render_scanlines(ras, sl, ren); + } + } + } + double tstroke = elapsed_time(); + + + char buf[256]; + agg::gsv_text t; + t.size(8.0); + t.flip(true); + + agg::conv_stroke ts(t); + ts.width(1.6); + ts.line_cap(agg::round_cap); + + sprintf(buf, "Fill=%.2fms (%dFPS) Stroke=%.2fms (%dFPS) Total=%.2fms (%dFPS)\n\n" + "Space: Next Shape\n\n" + "+/- : ZoomIn/ZoomOut (with respect to the mouse pointer)", + tfill, int(1000.0 / tfill), + tstroke, int(1000.0 / tstroke), + tfill+tstroke, int(1000.0 / (tfill+tstroke))); + + t.start_point(10.0, 20.0); + t.text(buf); + + ras.add_path(ts); + ren.color(agg::rgba(0,0,0)); + agg::render_scanlines(ras, sl, ren); + + if(m_gamma.gamma() != 1.0) + { + pixf.apply_gamma_inv(m_gamma); + } + } + + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + if(key == ' ') + { + m_shape.read_next(); + m_shape.scale(width(), height()); + force_redraw(); + } + + if(key == '+' || key == agg::key_kp_plus) + { + m_scale *= agg::trans_affine_translation(-x, -y); + m_scale *= agg::trans_affine_scaling(1.1); + m_scale *= agg::trans_affine_translation(x, y); + force_redraw(); + } + + if(key == '-' || key == agg::key_kp_minus) + { + m_scale *= agg::trans_affine_translation(-x, -y); + m_scale *= agg::trans_affine_scaling(1/1.1); + m_scale *= agg::trans_affine_translation(x, y); + force_redraw(); + } + + if(key == agg::key_left) + { + m_scale *= agg::trans_affine_translation(-x, -y); + m_scale *= agg::trans_affine_rotation(-agg::pi / 20.0); + m_scale *= agg::trans_affine_translation(x, y); + force_redraw(); + } + + if(key == agg::key_right) + { + m_scale *= agg::trans_affine_translation(-x, -y); + m_scale *= agg::trans_affine_rotation(agg::pi / 20.0); + m_scale *= agg::trans_affine_translation(x, y); + force_redraw(); + } + } + + void on_mouse_move(int x, int y, unsigned flags) + { + if((flags & 3) == 0) + { + on_mouse_button_up(x, y, flags); + } + else + { + if(m_point_idx >= 0) + { + double xd = x; + double yd = y; + m_scale.inverse_transform(&xd, &yd); + m_shape.modify_vertex(m_point_idx, xd, yd); + force_redraw(); + } + } + } + + void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & 1) + { + double xd = x; + double yd = y; + double r = 4.0 / m_scale.scale(); + m_scale.inverse_transform(&xd, &yd); + m_point_idx = m_shape.hit_test(xd, yd, r); + force_redraw(); + } + if(flags & 2) + { + m_hit_x = x; + m_hit_y = y; + force_redraw(); + } + } + + void on_mouse_button_up(int x, int y, unsigned flags) + { + m_point_idx = -1; + m_hit_x = -1; + m_hit_y = -1; + force_redraw(); + } + + +}; + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgra32, flip_y); + app.caption("AGG Example - Flash Rasterizer"); + const char* fname = "shapes.txt"; + if(argc > 1) fname = argv[1]; + if(!app.open(fname)) + { + char buf[256]; + if(strcmp(fname, "shapes.txt") == 0) + { + sprintf(buf, "File not found: %s. Download http://www.antigrain.com/%s\n" + "or copy it from another directory if available.", + fname, fname); + } + else + { + sprintf(buf, "File not found: %s", fname); + } + app.message(buf); + return 1; + } + + if(app.init(655, 520, agg::window_resize)) + { + app.read_next(); + return app.run(); + } + return 1; +} + + + + + diff --git a/jni/desmume/src/android/agg/examples/flash_rasterizer2.cpp b/jni/desmume/src/android/agg/examples/flash_rasterizer2.cpp new file mode 100755 index 0000000..bbd5966 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/flash_rasterizer2.cpp @@ -0,0 +1,543 @@ +#include +#include +#include +#include "agg_rendering_buffer.h" +#include "agg_trans_viewport.h" +#include "agg_path_storage.h" +#include "agg_conv_transform.h" +#include "agg_conv_curve.h" +#include "agg_conv_stroke.h" +#include "agg_gsv_text.h" +#include "agg_scanline_u.h" +#include "agg_scanline_bin.h" +#include "agg_renderer_scanline.h" +#include "agg_rasterizer_outline_aa.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_span_allocator.h" +#include "agg_gamma_lut.h" +#include "agg_pixfmt_rgba.h" +#include "agg_bounding_rect.h" +#include "platform/agg_platform_support.h" + + +enum { flip_y = false }; + +typedef agg::pixfmt_bgra32_pre pixfmt; + + + +namespace agg +{ + struct path_style + { + unsigned path_id; + int left_fill; + int right_fill; + int line; + }; + + class compound_shape + { + public: + ~compound_shape() + { + if(m_fd) + { + fclose(m_fd); + } + } + + compound_shape() : + m_path(), + m_affine(), + m_curve(m_path), + m_trans(m_curve, m_affine), + m_styles(), + m_min_style(0x7FFFFFFF), + m_max_style(-0x7FFFFFFF) + {} + + bool open(const char* fname) + { + m_fd = fopen(fname, "r"); + return m_fd != 0; + } + + bool read_next() + { + m_path.remove_all(); + m_styles.remove_all(); + m_min_style = 0x7FFFFFFF; + m_max_style = -0x7FFFFFFF; + + const char space[] = " \t\n\r"; + double ax, ay, cx, cy; + if(m_fd) + { + char buf[1024]; + char* ts; + + for(;;) + { + if(fgets(buf, 1022, m_fd) == 0) return false; + if(buf[0] == '=') break; + } + + while(fgets(buf, 1022, m_fd)) + { + if(buf[0] == '!') break; + if(buf[0] == 'P') + { + // BeginPath + path_style style; + style.path_id = m_path.start_new_path(); + ts = strtok(buf, space); // Path; + ts = strtok(0, space); // left_style + style.left_fill = atoi(ts); + ts = strtok(0, space); // right_style + style.right_fill = atoi(ts); + ts = strtok(0, space); // line_style + style.line = atoi(ts); + ts = strtok(0, space); // ax + ax = atof(ts); + ts = strtok(0, space); // ay + ay = atof(ts); + m_path.move_to(ax, ay); + m_styles.add(style); + if(style.left_fill >= 0) + { + if(style.left_fill < m_min_style) m_min_style = style.left_fill; + if(style.left_fill > m_max_style) m_max_style = style.left_fill; + } + if(style.right_fill >= 0) + { + if(style.right_fill < m_min_style) m_min_style = style.right_fill; + if(style.right_fill > m_max_style) m_max_style = style.right_fill; + } + } + + + if(buf[0] == 'C') + { + ts = strtok(buf, space); // Curve; + ts = strtok(0, space); // cx + cx = atof(ts); + ts = strtok(0, space); // cy + cy = atof(ts); + ts = strtok(0, space); // ax + ax = atof(ts); + ts = strtok(0, space); // ay + ay = atof(ts); + m_path.curve3(cx, cy, ax, ay); + } + + if(buf[0] == 'L') + { + ts = strtok(buf, space); // Line; + ts = strtok(0, space); // ax + ax = atof(ts); + ts = strtok(0, space); // ay + ay = atof(ts); + m_path.line_to(ax, ay); + } + + if(buf[0] == '<') + { + // EndPath + } + } + return true; + } + return false; + } + + unsigned operator [] (unsigned i) const + { + return m_styles[i].path_id; + } + + unsigned paths() const { return m_styles.size(); } + const path_style& style(unsigned i) const + { + return m_styles[i]; + } + + int min_style() const { return m_min_style; } + int max_style() const { return m_max_style; } + + void rewind(unsigned path_id) + { + m_trans.rewind(path_id); + } + + unsigned vertex(double* x, double* y) + { + return m_trans.vertex(x, y); + } + + double scale() const + { + return m_affine.scale(); + } + + void scale(double w, double h) + { + m_affine.reset(); + double x1, y1, x2, y2; + bounding_rect(m_path, *this, 0, m_styles.size(), + &x1, &y1, &x2, &y2); + if(x1 < x2 && y1 < y2) + { + trans_viewport vp; + vp.preserve_aspect_ratio(0.5, 0.5, aspect_ratio_meet); + vp.world_viewport(x1, y1, x2, y2); + vp.device_viewport(0, 0, w, h); + m_affine = vp.to_affine(); + } + m_curve.approximation_scale(m_affine.scale()); + } + + void approximation_scale(double s) + { + m_curve.approximation_scale(m_affine.scale() * s); + } + + int hit_test(double x, double y, double r) + { + m_affine.inverse_transform(&x, &y); + r /= m_affine.scale(); + unsigned i; + for(i = 0; i < m_path.total_vertices(); i++) + { + double vx, vy; + unsigned cmd = m_path.vertex(i, &vx, &vy); + if(is_vertex(cmd)) + { + if(calc_distance(x, y, vx, vy) <= r) + { + return i; + } + } + } + return -1; + } + + void modify_vertex(unsigned i, double x, double y) + { + m_affine.inverse_transform(&x, &y); + m_path.modify_vertex(i, x, y); + } + + private: + path_storage m_path; + trans_affine m_affine; + conv_curve m_curve; + conv_transform > m_trans; + pod_bvector m_styles; + double m_x1, m_y1, m_x2, m_y2; + int m_min_style; + int m_max_style; + + FILE* m_fd; + }; + +} + + + + + + +class the_application : public agg::platform_support +{ + +public: + agg::compound_shape m_shape; + agg::rgba8 m_colors[100]; + agg::trans_affine m_scale; + agg::gamma_lut<> m_gamma; + int m_point_idx; + + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_point_idx(-1) + { + m_gamma.gamma(2.0); + + for(unsigned i = 0; i < 100; i++) + { + m_colors[i] = agg::rgba8( + (rand() & 0xFF), + (rand() & 0xFF), + (rand() & 0xFF), + 230); + + m_colors[i].apply_gamma_dir(m_gamma); + m_colors[i].premultiply(); + } + } + + + + bool open(const char* fname) + { + return m_shape.open(full_file_name(fname)); + } + + void read_next() + { + m_shape.read_next(); + m_shape.scale(width(), height()); + } + + virtual void on_draw() + { + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_scanline; + typedef agg::scanline_u8 scanline; + + pixfmt pixf(rbuf_window()); + renderer_base ren_base(pixf); + ren_base.clear(agg::rgba(1.0, 1.0, 0.95)); + renderer_scanline ren(ren_base); + + agg::rasterizer_scanline_aa ras; + agg::scanline_u8 sl; + agg::conv_transform shape(m_shape, m_scale); + agg::conv_stroke > stroke(shape); + + m_shape.approximation_scale(m_scale.scale()); + + unsigned i; + agg::path_storage tmp_path; + + ras.clip_box(0, 0, width(), height()); + + // This is an alternative method of Flash rasterization. + // We decompose the compound shape into separate paths + // and select the ones that fit the given style (left or right). + // So that, we form a sub-shape and draw it as a whole. + // + // Here the regular scanline rasterizer is used, but it doesn't + // automatically close the polygons. So that, the rasterizer + // actually works with a set of polylines instead of polygons. + // Of course, the data integrity must be preserved, that is, + // the polylines must eventually form a closed contour + // (or a set of closed contours). So that, first we set + // auto_close(false); + // + // The second important thing is that one path can be rasterized + // twice, if it has both, left and right fill. Sometimes the + // path has equal left and right fill, so that, the same path + // will be added twice even for a single sub-shape. If the + // rasterizer can tolerate these degenerates you can add them, + // but it's also fine just to omit them. + // + // The third thing is that for one side (left or right) + // you should invert the direction of the paths. + // + // The main disadvantage of this method is imperfect stitching + // of the adjacent polygons. The problem can be solved if we use + // compositing operation "plus" instead of alpha-blend. But + // in this case we are forced to use an RGBA buffer, clean it with + // zero, rasterize using "plus" operation, and then alpha-blend + // the result over the final scene. It can be too expensive. + //------------------------------------------------------------ + ras.auto_close(false); + //ras.filling_rule(agg::fill_even_odd); + start_timer(); + for(int s = m_shape.min_style(); s <= m_shape.max_style(); s++) + { + ras.reset(); + for(i = 0; i < m_shape.paths(); i++) + { + const agg::path_style& style = m_shape.style(i); + if(style.left_fill != style.right_fill) + { + if(style.left_fill == s) + { + ras.add_path(shape, style.path_id); + } + if(style.right_fill == s) + { + tmp_path.remove_all(); + tmp_path.concat_path(shape, style.path_id); + tmp_path.invert_polygon(0); + ras.add_path(tmp_path); + } + } + } + agg::render_scanlines_aa_solid(ras, sl, ren_base, m_colors[s]); + } + double tfill = elapsed_time(); + ras.auto_close(true); + + // Draw strokes + //---------------------- + start_timer(); + stroke.width(sqrt(m_scale.scale())); + stroke.line_join(agg::round_join); + stroke.line_cap(agg::round_cap); + for(i = 0; i < m_shape.paths(); i++) + { + ras.reset(); + if(m_shape.style(i).line >= 0) + { + ras.add_path(stroke, m_shape.style(i).path_id); + ren.color(agg::rgba8(0,0,0, 128)); + agg::render_scanlines(ras, sl, ren); + } + } + double tstroke = elapsed_time(); + + + char buf[256]; + agg::gsv_text t; + t.size(8.0); + t.flip(true); + + agg::conv_stroke ts(t); + ts.width(1.6); + ts.line_cap(agg::round_cap); + + sprintf(buf, "Fill=%.2fms (%dFPS) Stroke=%.2fms (%dFPS) Total=%.2fms (%dFPS)\n\n" + "Space: Next Shape\n\n" + "+/- : ZoomIn/ZoomOut (with respect to the mouse pointer)", + tfill, int(1000.0 / tfill), + tstroke, int(1000.0 / tstroke), + tfill+tstroke, int(1000.0 / (tfill+tstroke))); + + t.start_point(10.0, 20.0); + t.text(buf); + + ras.add_path(ts); + ren.color(agg::rgba(0,0,0)); + agg::render_scanlines(ras, sl, ren); + + if(m_gamma.gamma() != 1.0) + { + pixf.apply_gamma_inv(m_gamma); + } + } + + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + if(key == ' ') + { + m_shape.read_next(); + m_shape.scale(width(), height()); + force_redraw(); + } + + if(key == '+' || key == agg::key_kp_plus) + { + m_scale *= agg::trans_affine_translation(-x, -y); + m_scale *= agg::trans_affine_scaling(1.1); + m_scale *= agg::trans_affine_translation(x, y); + force_redraw(); + } + + if(key == '-' || key == agg::key_kp_minus) + { + m_scale *= agg::trans_affine_translation(-x, -y); + m_scale *= agg::trans_affine_scaling(1/1.1); + m_scale *= agg::trans_affine_translation(x, y); + force_redraw(); + } + + if(key == agg::key_left) + { + m_scale *= agg::trans_affine_translation(-x, -y); + m_scale *= agg::trans_affine_rotation(-agg::pi / 20.0); + m_scale *= agg::trans_affine_translation(x, y); + force_redraw(); + } + + if(key == agg::key_right) + { + m_scale *= agg::trans_affine_translation(-x, -y); + m_scale *= agg::trans_affine_rotation(agg::pi / 20.0); + m_scale *= agg::trans_affine_translation(x, y); + force_redraw(); + } + } + + void on_mouse_move(int x, int y, unsigned flags) + { + if((flags & 1) == 0) + { + on_mouse_button_up(x, y, flags); + } + else + { + if(m_point_idx >= 0) + { + double xd = x; + double yd = y; + m_scale.inverse_transform(&xd, &yd); + m_shape.modify_vertex(m_point_idx, xd, yd); + force_redraw(); + } + } + } + + void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & 1) + { + double xd = x; + double yd = y; + double r = 4.0 / m_scale.scale(); + m_scale.inverse_transform(&xd, &yd); + m_point_idx = m_shape.hit_test(xd, yd, r); + force_redraw(); + } + } + + void on_mouse_button_up(int x, int y, unsigned flags) + { + m_point_idx = -1; + } + + +}; + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgra32, flip_y); + app.caption("AGG Example - Flash Rasterizer"); + const char* fname = "shapes.txt"; + if(argc > 1) fname = argv[1]; + if(!app.open(fname)) + { + char buf[256]; + if(strcmp(fname, "shapes.txt") == 0) + { + sprintf(buf, "File not found: %s. Download http://www.antigrain.com/%s\n" + "or copy it from another directory if available.", + fname, fname); + } + else + { + sprintf(buf, "File not found: %s", fname); + } + app.message(buf); + return 1; + } + + if(app.init(655, 520, agg::window_resize)) + { + app.read_next(); + return app.run(); + } + return 1; +} + + + + + diff --git a/jni/desmume/src/android/agg/examples/freetype_test.cpp b/jni/desmume/src/android/agg/examples/freetype_test.cpp new file mode 100755 index 0000000..8ca015c --- /dev/null +++ b/jni/desmume/src/android/agg/examples/freetype_test.cpp @@ -0,0 +1,484 @@ +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_scanline_u.h" +#include "agg_scanline_bin.h" +#include "agg_renderer_scanline.h" +#include "agg_renderer_primitives.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_conv_curve.h" +#include "agg_conv_contour.h" +#include "agg_pixfmt_rgb.h" +#include "agg_font_freetype.h" +#include "platform/agg_platform_support.h" + +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" + + +enum flip_y_e { flip_y = true }; +bool font_flip_y = !flip_y; + + +#define pix_format agg::pix_format_bgr24 +typedef agg::pixfmt_bgr24 pixfmt_type; + + +static char text[] = +"Anti-Grain Geometry is designed as a set of loosely coupled " +"algorithms and class templates united with a common idea, " +"so that all the components can be easily combined. Also, " +"the template based design allows you to replace any part of " +"the library without the necessity to modify a single byte in " +"the existing code. " +"AGG is designed keeping in mind extensibility and flexibility. " +"Basically I just wanted to create a toolkit that would allow me " +"(and anyone else) to add new fancy algorithms very easily. " +"AGG does not dictate you any style of its use, you are free to " +"use any part of it. However, AGG is often associated with a tool " +"for rendering images in memory. That is not quite true, but it can " +"be a good starting point in studying. The tutorials describe the " +"use of AGG starting from the low level functionality that deals with " +"frame buffers and pixels. Then you will gradually understand how to " +"abstract different parts of the library and how to use them separately. " +"Remember, the raster picture is often not the only thing you want to " +"obtain, you will probably want to print your graphics with highest " +"possible quality and in this case you can easily combine the \"vectorial\" " +"part of the library with some API like Windows GDI, having a common " +"external interface. If that API can render multi-polygons with non-zero " +"and even-odd filling rules it's all you need to incorporate AGG into " +"your application. For example, Windows API PolyPolygon perfectly fits " +"these needs, except certain advanced things like gradient filling, " +"Gouraud shading, image transformations, and so on. Or, as an alternative, " +"you can use all AGG algorithms producing high resolution pixel images and " +"then to send the result to the printer as a pixel map." +"Below is a typical brief scheme of the AGG rendering pipeline. " +"Please note that any component between the Vertex Source " +"and Screen Output is not mandatory. It all depends on your " +"particular needs. For example, you can use your own rasterizer, " +"based on Windows API. In this case you won't need the AGG rasterizer " +"and renderers. Or, if you need to draw only lines, you can use the " +"AGG outline rasterizer that has certain restrictions but works faster. " +"The number of possibilities is endless. " +"Vertex Source is some object that produces polygons or polylines as " +"a set of consecutive 2D vertices with commands like MoveTo, LineTo. " +"It can be a container or some other object that generates vertices " +"on demand. " +"Coordinate conversion pipeline consists of a number of coordinate " +"converters. It always works with vectorial data (X,Y) represented " +"as floating point numbers (double). For example, it can contain an " +"affine transformer, outline (stroke) generator, some marker " +"generator (like arrowheads/arrowtails), dashed lines generator, " +"and so on. The pipeline can have branches and you also can have " +"any number of different pipelines. You also can write your own " +"converter and include it into the pipeline. " +"Scanline Rasterizer converts vectorial data into a number of " +"horizontal scanlines. The scanlines usually (but not obligatory) " +"carry information about Anti-Aliasing as coverage values. " +"Renderers render scanlines, sorry for the tautology. The simplest " +"example is solid filling. The renderer just adds a color to the " +"scanline and writes the result into the rendering buffer. " +"More complex renderers can produce multi-color result, " +"like gradients, Gouraud shading, image transformations, " +"patterns, and so on. Rendering Buffer is a buffer in memory " +"that will be displayed afterwards. Usually but not obligatory " +"it contains pixels in format that fits your video system. " +"For example, 24 bits B-G-R, 32 bits B-G-R-A, or 15 " +"bits R-G-B-555 for Windows. But in general, there're no " +"restrictions on pixel formats or color space if you write " +"your own low level class that supports that format. " +"Colors in AGG appear only in renderers, that is, when you " +"actually put some data to the rendering buffer. In general, " +"there's no general purpose structure or class like color, " +"instead, AGG always operates with concrete color space. " +"There are plenty of color spaces in the world, like RGB, " +"HSV, CMYK, etc., and all of them have certain restrictions. " +"For example, the RGB color space is just a poor subset of " +"colors that a human eye can recognize. If you look at the full " +"CIE Chromaticity Diagram, you will see that the RGB triangle " +"is just a little part of it. " +"In other words there are plenty of colors in the real world " +"that cannot be reproduced with RGB, CMYK, HSV, etc. Any color " +"space except the one existing in Nature is restrictive. Thus, " +"it was decided not to introduce such an object like color in " +"order not to restrict the possibilities in advance. Instead, " +"there are objects that operate with concrete color spaces. " +"Currently there are agg::rgba and agg::rgba8 that operate " +"with the most popular RGB color space (strictly speaking there's " +"RGB plus Alpha). The RGB color space is used with different " +"pixel formats, like 24-bit RGB or 32-bit RGBA with different " +"order of color components. But the common property of all of " +"them is that they are essentially RGB. Although, AGG doesn't " +"explicitly support any other color spaces, there is at least " +"a potential possibility of adding them. It means that all " +"class and function templates that depend on the color type " +"are parameterized with the ColorT argument. " +"Basically, AGG operates with coordinates of the output device. " +"On your screen there are pixels. But unlike many other libraries " +"and APIs AGG initially supports Subpixel Accuracy. It means " +"that the coordinates are represented as doubles, where fractional " +"values actually take effect. AGG doesn't have an embedded " +"conversion mechanism from world to screen coordinates in order " +"not to restrict your freedom. It's very important where and when " +"you do that conversion, so, different applications can require " +"different approaches. AGG just provides you a transformer of " +"that kind, namely, that can convert your own view port to the " +"device one. And it's your responsibility to include it into " +"the proper place of the pipeline. You can also write your " +"own very simple class that will allow you to operate with " +"millimeters, inches, or any other physical units. " +"Internally, the rasterizers use integer coordinates of the " +"format 24.8 bits, that is, 24 bits for the integer part and 8 " +"bits for the fractional one. In other words, all the internal " +"coordinates are multiplied by 256. If you intend to use AGG in " +"some embedded system that has inefficient floating point " +"processing, you still can use the rasterizers with their " +"integer interfaces. Although, you won't be able to use the " +"floating point coordinate pipelines in this case. "; + + + + + + + +template void dump_path(VS& path) +{ + FILE* fd = fopen("dump_path", "a"); + fprintf(fd, "-------\n"); + path.rewind(0); + unsigned cmd; + double x, y; + while(!agg::is_stop(cmd = path.vertex(&x, &y))) + { + fprintf(fd, "%02X %8.2f %8.2f\n", cmd, x, y); + } + fclose(fd); +} + + + + +class the_application : public agg::platform_support +{ + typedef agg::renderer_base base_ren_type; + typedef agg::renderer_scanline_aa_solid renderer_solid; + typedef agg::renderer_scanline_bin_solid renderer_bin; + typedef agg::font_engine_freetype_int32 font_engine_type; + typedef agg::font_cache_manager font_manager_type; + + agg::rbox_ctrl m_ren_type; + agg::slider_ctrl m_height; + agg::slider_ctrl m_width; + agg::slider_ctrl m_weight; + agg::slider_ctrl m_gamma; + agg::cbox_ctrl m_hinting; + agg::cbox_ctrl m_kerning; + agg::cbox_ctrl m_performance; + font_engine_type m_feng; + font_manager_type m_fman; + double m_old_height; + + // Pipeline to process the vectors glyph paths (curves + contour) + agg::conv_curve m_curves; + agg::conv_contour > m_contour; + + + + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_ren_type (5.0, 5.0, 5.0+150.0, 110.0, !flip_y), + m_height (160, 10.0, 640-5.0, 18.0, !flip_y), + m_width (160, 30.0, 640-5.0, 38.0, !flip_y), + m_weight (160, 50.0, 640-5.0, 58.0, !flip_y), + m_gamma (260, 70.0, 640-5.0, 78.0, !flip_y), + m_hinting (160, 65.0, "Hinting", !flip_y), + m_kerning (160, 80.0, "Kerning", !flip_y), + m_performance (160, 95.0, "Test Performance", !flip_y), + m_feng(), + m_fman(m_feng), + m_old_height(0.0), + m_curves(m_fman.path_adaptor()), + m_contour(m_curves) + { + m_ren_type.add_item("Native Mono"); + m_ren_type.add_item("Native Gray 8"); + m_ren_type.add_item("Outline"); + m_ren_type.add_item("AGG Mono"); + m_ren_type.add_item("AGG Gray 8"); + m_ren_type.cur_item(1); + add_ctrl(m_ren_type); + m_ren_type.no_transform(); + + m_height.label("Font Height=%.2f"); + m_height.range(8, 32); + m_height.num_steps(32-8); + m_height.value(18); + m_height.text_thickness(1.5); + add_ctrl(m_height); + m_height.no_transform(); + + m_width.label("Font Width=%.2f"); + m_width.range(8, 32); + m_width.num_steps(32-8); + m_width.text_thickness(1.5); + m_width.value(18); + add_ctrl(m_width); + m_width.no_transform(); + + m_weight.label("Font Weight=%.2f"); + m_weight.range(-1, 1); + m_weight.text_thickness(1.5); + add_ctrl(m_weight); + m_weight.no_transform(); + + m_gamma.label("Gamma=%.2f"); + m_gamma.range(0.1, 2.0); + m_gamma.value(1.0); + m_gamma.text_thickness(1.5); + add_ctrl(m_gamma); + m_gamma.no_transform(); + + add_ctrl(m_hinting); + m_hinting.status(true); + m_hinting.no_transform(); + + add_ctrl(m_kerning); + m_kerning.status(true); + m_kerning.no_transform(); + + add_ctrl(m_performance); + m_performance.no_transform(); + + m_curves.approximation_scale(2.0); + m_contour.auto_detect_orientation(false); + } + + + template + unsigned draw_text(Rasterizer& ras, Scanline& sl, + RenSolid& ren_solid, RenBin& ren_bin) + { + agg::glyph_rendering gren = agg::glyph_ren_native_mono; + switch(m_ren_type.cur_item()) + { + case 0: gren = agg::glyph_ren_native_mono; break; + case 1: gren = agg::glyph_ren_native_gray8; break; + case 2: gren = agg::glyph_ren_outline; break; + case 3: gren = agg::glyph_ren_agg_mono; break; + case 4: gren = agg::glyph_ren_agg_gray8; break; + } + + unsigned num_glyphs = 0; + + m_contour.width(-m_weight.value() * m_height.value() * 0.05); + + if(m_feng.load_font(full_file_name("timesi.ttf"), 0, gren)) + { + m_feng.hinting(m_hinting.status()); + m_feng.height(m_height.value()); + m_feng.width(m_width.value()); + m_feng.flip_y(font_flip_y); + + agg::trans_affine mtx; + mtx *= agg::trans_affine_rotation(agg::deg2rad(-4.0)); + //mtx *= agg::trans_affine_skewing(-0.4, 0); + //mtx *= agg::trans_affine_translation(1, 0); + m_feng.transform(mtx); + + double x = 10.0; + double y0 = height() - m_height.value() - 10.0; + double y = y0; + const char* p = text; + + while(*p) + { + const agg::glyph_cache* glyph = m_fman.glyph(*p); + if(glyph) + { + if(m_kerning.status()) + { + m_fman.add_kerning(&x, &y); + } + + if(x >= width() - m_height.value()) + { + x = 10.0; + y0 -= m_height.value(); + if(y0 <= 120) break; + y = y0; + } + + m_fman.init_embedded_adaptors(glyph, x, y); + + switch(glyph->data_type) + { + default: break; + case agg::glyph_data_mono: + ren_bin.color(agg::rgba8(0, 0, 0)); + agg::render_scanlines(m_fman.mono_adaptor(), + m_fman.mono_scanline(), + ren_bin); + break; + + case agg::glyph_data_gray8: + ren_solid.color(agg::rgba8(0, 0, 0)); + agg::render_scanlines(m_fman.gray8_adaptor(), + m_fman.gray8_scanline(), + ren_solid); + break; + + case agg::glyph_data_outline: + ras.reset(); + if(fabs(m_weight.value()) <= 0.01) + { + // For the sake of efficiency skip the + // contour converter if the weight is about zero. + //----------------------- + ras.add_path(m_curves); + } + else + { + ras.add_path(m_contour); + } + ren_solid.color(agg::rgba8(0, 0, 0)); + agg::render_scanlines(ras, sl, ren_solid); +//dump_path(m_fman.path_adaptor()); + break; + } + + // increment pen position + x += glyph->advance_x; + y += glyph->advance_y; + ++num_glyphs; + } + ++p; + } + } + else + { + message("Please copy file timesi.ttf to the current directory\n" + "or download it from http://www.antigrain.com/timesi.zip"); + } + + return num_glyphs; + } + + + virtual void on_draw() + { + pixfmt_type pf(rbuf_window()); + base_ren_type ren_base(pf); + renderer_solid ren_solid(ren_base); + renderer_bin ren_bin(ren_base); + ren_base.clear(agg::rgba(1,1,1)); + + agg::scanline_u8 sl; + agg::rasterizer_scanline_aa<> ras; + + if(m_height.value() != m_old_height) + { + m_width.value(m_old_height = m_height.value()); + } + + if(m_ren_type.cur_item() == 3) + { + // When rendering in mono format, + // Set threshold gamma = 0.5 + //------------------- + m_feng.gamma(agg::gamma_threshold(m_gamma.value() / 2.0)); + } + else + { + m_feng.gamma(agg::gamma_power(m_gamma.value())); + } + + if(m_ren_type.cur_item() == 2) + { + // For outline cache set gamma for the rasterizer + //------------------- + ras.gamma(agg::gamma_power(m_gamma.value())); + } + +//ren_base.copy_hline(0, int(height() - m_height.value()) - 10, 100, agg::rgba(0,0,0)); + draw_text(ras, sl, ren_solid, ren_bin); + + ras.gamma(agg::gamma_power(1.0)); + + + agg::render_ctrl(ras, sl, ren_base, m_ren_type); + agg::render_ctrl(ras, sl, ren_base, m_height); + agg::render_ctrl(ras, sl, ren_base, m_width); + agg::render_ctrl(ras, sl, ren_base, m_weight); + agg::render_ctrl(ras, sl, ren_base, m_gamma); + agg::render_ctrl(ras, sl, ren_base, m_hinting); + agg::render_ctrl(ras, sl, ren_base, m_kerning); + agg::render_ctrl(ras, sl, ren_base, m_performance); + } + + + + virtual void on_ctrl_change() + { + if(m_performance.status()) + { + pixfmt_type pf(rbuf_window()); + base_ren_type ren_base(pf); + renderer_solid ren_solid(ren_base); + renderer_bin ren_bin(ren_base); + ren_base.clear(agg::rgba(1,1,1)); + + agg::scanline_u8 sl; + agg::rasterizer_scanline_aa<> ras; + + unsigned num_glyphs = 0; + start_timer(); + for(int i = 0; i < 50; i++) + { + num_glyphs += draw_text(ras, sl, ren_solid, ren_bin); + } + double t = elapsed_time(); + char buf[100]; + sprintf(buf, + "Glyphs=%u, Time=%.3fms, %.3f glyps/sec, %.3f microsecond/glyph", + num_glyphs, + t, + (num_glyphs / t) * 1000.0, + (t / num_glyphs) * 1000.0); + message(buf); + + m_performance.status(false); + force_redraw(); + } + } + + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + if(key == ' ') + { + font_flip_y = !font_flip_y; + force_redraw(); + } + } + +}; + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Rendering Fonts with FreeType"); + + if(app.init(640, 520, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/gamma_correction.cpp b/jni/desmume/src/android/agg/examples/gamma_correction.cpp new file mode 100755 index 0000000..05e747f --- /dev/null +++ b/jni/desmume/src/android/agg/examples/gamma_correction.cpp @@ -0,0 +1,170 @@ +#include +#include "agg_trans_affine.h" +#include "agg_conv_stroke.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_rendering_buffer.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_gamma_lut.h" +#include "ctrl/agg_slider_ctrl.h" +#include "platform/agg_platform_support.h" + +#define AGG_BGR24 +//#define AGG_RGB24 +//#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + +enum flip_y_e { flip_y = true }; + +class the_application : public agg::platform_support +{ + agg::slider_ctrl m_thickness; + agg::slider_ctrl m_gamma; + agg::slider_ctrl m_contrast; + double m_rx; + double m_ry; + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_thickness(5, 5, 400-5, 11, !flip_y), + m_gamma (5, 5+15, 400-5, 11+15, !flip_y), + m_contrast (5, 5+30, 400-5, 11+30, !flip_y) + { + add_ctrl(m_thickness); + add_ctrl(m_gamma); + add_ctrl(m_contrast); + + m_thickness.label("Thickness=%3.2f"); + m_gamma.label("Gamma=%3.2f"); + m_contrast.label("Contrast"); + + m_thickness.range(0.0, 3.0); + m_gamma.range(0.5, 3.0); + m_contrast.range(0.0, 1.0); + + m_thickness.value(1.0); + m_gamma.value(1.0); + m_contrast.value(1.0); + } + + virtual void on_init() + { + m_rx = width() / 3.0; + m_ry = height() / 3.0; + } + + virtual void on_draw() + { + typedef agg::gamma_lut gamma_type; + typedef pixfmt_gamma pixfmt_type; + typedef agg::renderer_base ren_base; + + double g = m_gamma.value(); + gamma_type gamma(g); + pixfmt_type pixf(rbuf_window(), gamma); + ren_base renb(pixf); + renb.clear(agg::rgba(1, 1, 1)); + + + double dark = 1.0 - m_contrast.value(); + double light = m_contrast.value(); + + renb.copy_bar(0,0,int(width())/2, int(height()), agg::rgba(dark,dark,dark)); + renb.copy_bar(int(width())/2+1,0, int(width()), int(height()), agg::rgba(light,light,light)); + renb.copy_bar(0,int(height())/2+1, int(width()), int(height()), agg::rgba(1.0,dark,dark)); + + agg::rasterizer_scanline_aa<> ras; + agg::scanline_u8 sl; + agg::path_storage path; + + + unsigned i; + double x = (width() - 256.0) / 2.0; + double y = 50.0; + path.remove_all(); + agg::gamma_power gp(g); + for(i = 0; i < 256; i++) + { + double v = double(i) / 255.0; + double gval = gp(v); + double dy = gval * 255.0; + if(i == 0) path.move_to(x + i, y + dy); + else path.line_to(x + i, y + dy); + } + agg::conv_stroke gpoly(path); + gpoly.width(2.0); + ras.reset(); + ras.add_path(gpoly); + agg::render_scanlines_aa_solid(ras, sl, renb, agg::rgba8(80,127,80)); + + agg::ellipse ell(width() / 2, height() / 2, m_rx, m_ry, 150); + agg::conv_stroke poly(ell); + poly.width(m_thickness.value()); + ras.reset(); + ras.add_path(poly); + agg::render_scanlines_aa_solid(ras, sl, renb, agg::rgba8(255,0,0)); + + ell.init(width() / 2, height() / 2, m_rx-5.0, m_ry-5.0, 150); + ras.reset(); + ras.add_path(poly); + agg::render_scanlines_aa_solid(ras, sl, renb, agg::rgba8(0,255,0)); + + ell.init(width() / 2, height() / 2, m_rx-10.0, m_ry-10.0, 150); + ras.reset(); + ras.add_path(poly); + agg::render_scanlines_aa_solid(ras, sl, renb, agg::rgba8(0,0,255)); + + ell.init(width() / 2, height() / 2, m_rx-15.0, m_ry-15.0, 150); + ras.reset(); + ras.add_path(poly); + agg::render_scanlines_aa_solid(ras, sl, renb, agg::rgba8(0,0,0)); + + ell.init(width() / 2, height() / 2, m_rx-20.0, m_ry-20.0, 150); + ras.reset(); + ras.add_path(poly); + agg::render_scanlines_aa_solid(ras, sl, renb, agg::rgba8(255,255,255)); + + agg::render_ctrl(ras, sl, renb, m_thickness); + agg::render_ctrl(ras, sl, renb, m_gamma); + agg::render_ctrl(ras, sl, renb, m_contrast); + } + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + m_rx = fabs(width()/2 - x); + m_ry = fabs(height()/2 - y); + force_redraw(); + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + on_mouse_button_down(x, y, flags); + } + +}; + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Thin red ellipse"); + + if(app.init(400, 320, 0)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/gamma_ctrl.cpp b/jni/desmume/src/android/agg/examples/gamma_ctrl.cpp new file mode 100755 index 0000000..7349d12 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/gamma_ctrl.cpp @@ -0,0 +1,249 @@ +#include +#include +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_gsv_text.h" +#include "agg_conv_stroke.h" +#include "agg_path_storage.h" +#include "ctrl/agg_gamma_ctrl.h" +#include "platform/agg_platform_support.h" + +#define AGG_BGR24 +//#define AGG_RGB24 +//#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + +enum flip_y_e { flip_y = true }; + + +agg::gamma_ctrl g_ctrl(10.0, 10.0, 300.0, 200.0, !flip_y); + +void read_gamma(const char* fname) +{ + FILE* fd = fopen(fname, "rb"); + if(fd) + { + char buf[32]; + double kx1, ky1, kx2, ky2; + fgets(buf, 30, fd); kx1 = atof(buf); + fgets(buf, 30, fd); ky1 = atof(buf); + fgets(buf, 30, fd); kx2 = atof(buf); + fgets(buf, 30, fd); ky2 = atof(buf); + g_ctrl.values(kx1, ky1, kx2, ky2); + fclose(fd); + } +} + + + +void write_gamma_bin(const char* fname) +{ + const unsigned char* gamma = g_ctrl.gamma(); + FILE* fd = fopen(fname, "wb"); + if(fd) + { + fwrite(gamma, 256, 1, fd); + fclose(fd); + } +} + + +void write_gamma_txt(const char* fname) +{ + const unsigned char* gamma = g_ctrl.gamma(); + FILE* fd = fopen(fname, "w"); + if(fd) + { + double kx1, ky1, kx2, ky2; + g_ctrl.values(&kx1, &ky1, &kx2, &ky2); + fprintf(fd, "%5.3f\n", kx1); + fprintf(fd, "%5.3f\n", ky1); + fprintf(fd, "%5.3f\n", kx2); + fprintf(fd, "%5.3f\n", ky2); + for(int i = 0; i < 16; i++) + { + for(int j = 0; j < 16; j++) + { + fprintf(fd, "%3d,", gamma[i*16 + j]); + } + fprintf(fd, "\n"); + } + fclose(fd); + } +} + + + +class the_application : public agg::platform_support +{ +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y) + { + add_ctrl(g_ctrl); + } + + virtual void on_init() + { + read_gamma(full_file_name("gamma.txt")); + } + + virtual ~the_application() + { + write_gamma_txt(full_file_name("gamma.txt")); + write_gamma_bin(full_file_name("gamma.bin")); + } + + virtual void on_draw() + { + double ewidth = initial_width() / 2 - 10; + double ecenter = initial_width() / 2; + + typedef agg::renderer_base ren_base; + + pixfmt pixf(rbuf_window()); + ren_base rb(pixf); + agg::rgba8 color; + rb.clear(agg::rgba(1, 1, 1)); + + g_ctrl.text_size(10.0, 12.0); + + agg::rasterizer_scanline_aa<> ras; + agg::scanline_p8 sl; + + agg::render_ctrl(ras, sl, rb, g_ctrl); + + ras.gamma(g_ctrl); + + agg::ellipse ellipse; + agg::conv_stroke poly(ellipse); + agg::conv_transform > tpoly(poly, trans_affine_resizing()); + color = agg::rgba8(0, 0, 0); + + ellipse.init(ecenter, 220, ewidth, 15, 100); + poly.width(2.0); + ras.add_path(tpoly, 0); + agg::render_scanlines_aa_solid(ras, sl, rb, color); + + ellipse.init(ecenter, 220, 11, 11, 100); + poly.width(2.0); + ras.add_path(tpoly, 0); + agg::render_scanlines_aa_solid(ras, sl, rb, color); + + color = agg::rgba8(127, 127, 127); + + ellipse.init(ecenter, 260, ewidth, 15, 100); + poly.width(2.0); + ras.add_path(tpoly, 0); + agg::render_scanlines_aa_solid(ras, sl, rb, color); + + ellipse.init(ecenter, 260, 11, 11, 100); + poly.width(2.0); + ras.add_path(tpoly, 0); + agg::render_scanlines_aa_solid(ras, sl, rb, color); + + color = agg::rgba8(192, 192, 192); + + ellipse.init(ecenter, 300, ewidth, 15, 100); + poly.width(2.0); + ras.add_path(tpoly, 0); + agg::render_scanlines_aa_solid(ras, sl, rb, color); + + ellipse.init(ecenter, 300, 11, 11, 100); + poly.width(2.0); + ras.add_path(tpoly, 0); + agg::render_scanlines_aa_solid(ras, sl, rb, color); + + color = agg::rgba(0.0, 0.0, 0.4); + + ellipse.init(ecenter, 340, ewidth, 15.5, 100); + poly.width(1.0); + ras.add_path(tpoly, 0); + agg::render_scanlines_aa_solid(ras, sl, rb, color); + + ellipse.init(ecenter, 340, 10.5, 10.5, 100); + poly.width(1.0); + ras.add_path(tpoly, 0); + agg::render_scanlines_aa_solid(ras, sl, rb, color); + + ellipse.init(ecenter, 380, ewidth, 15.5, 100); + poly.width(0.4); + ras.add_path(tpoly, 0); + agg::render_scanlines_aa_solid(ras, sl, rb, color); + + ellipse.init(ecenter, 380, 10.5, 10.5, 100); + poly.width(0.4); + ras.add_path(tpoly, 0); + agg::render_scanlines_aa_solid(ras, sl, rb, color); + + ellipse.init(ecenter, 420, ewidth, 15.5, 100); + poly.width(0.1); + ras.add_path(tpoly, 0); + agg::render_scanlines_aa_solid(ras, sl, rb, color); + + ellipse.init(ecenter, 420, 10.5, 10.5, 100); + poly.width(0.1); + ras.add_path(tpoly, 0); + agg::render_scanlines_aa_solid(ras, sl, rb, color); + + agg::trans_affine mtx; + mtx *= agg::trans_affine_skewing(0.15, 0.0); + mtx *= trans_affine_resizing(); + agg::gsv_text text; + agg::gsv_text_outline text1(text, mtx); + text.text("Text 2345"); + text.size(50, 20); + text1.width(2.0); + text.start_point(320, 10); + + color = agg::rgba(0.0, 0.5, 0.0); + ras.add_path(text1, 0); + agg::render_scanlines_aa_solid(ras, sl, rb, color); + + + color = agg::rgba(0.5, 0.0, 0.0); + agg::path_storage path; + path.move_to(30, -1.0); + path.line_to(60, 0.0); + path.line_to(30, 1.0); + + path.move_to(27, -1.0); + path.line_to(10, 0.0); + path.line_to(27, 1.0); + + agg::conv_transform trans(path, mtx); + + for(int i = 0; i < 35; i++) + { + mtx.reset(); + mtx *= agg::trans_affine_rotation(double(i) / 35.0 * agg::pi * 2.0); + mtx *= agg::trans_affine_translation(400, 130); + mtx *= trans_affine_resizing(); + ras.add_path(trans, 0); + agg::render_scanlines_aa_solid(ras, sl, rb, color); + } + } +}; + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("Anti-Aliasing Gamma Correction"); + + if(app.init(500, 400, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/gamma_tuner.cpp b/jni/desmume/src/android/agg/examples/gamma_tuner.cpp new file mode 100755 index 0000000..34fab55 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/gamma_tuner.cpp @@ -0,0 +1,238 @@ +#include +#include "agg_trans_affine.h" +#include "agg_conv_stroke.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_rendering_buffer.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_gamma_lut.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "platform/agg_platform_support.h" + +#include "agg_pixfmt_rgb.h" +#define pix_format agg::pix_format_bgr24 +typedef agg::pixfmt_bgr24 pixfmt; +typedef agg::pixfmt_bgr24_pre pixfmt_pre; +#define pixfmt_gamma agg::pixfmt_bgr24_gamma +typedef agg::rgba8 color_type; +typedef agg::order_bgr component_order; + +enum flip_y_e { flip_y = true }; + +class the_application : public agg::platform_support +{ + agg::slider_ctrl m_gamma; + agg::slider_ctrl m_r; + agg::slider_ctrl m_g; + agg::slider_ctrl m_b; + agg::rbox_ctrl m_pattern; + + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_gamma (5, 5, 350-5, 11, !flip_y), + m_r (5, 5+15, 350-5, 11+15, !flip_y), + m_g (5, 5+30, 350-5, 11+30, !flip_y), + m_b (5, 5+45, 350-5, 11+45, !flip_y), + m_pattern (355, 1, 495, 60, !flip_y) + { + m_pattern.text_size(8); + m_pattern.add_item("Horizontal"); + m_pattern.add_item("Vertical"); + m_pattern.add_item("Checkered"); + m_pattern.cur_item(2); + + add_ctrl(m_gamma); + add_ctrl(m_r); + add_ctrl(m_g); + add_ctrl(m_b); + add_ctrl(m_pattern); + + m_gamma.range(0.5, 4.0); + m_gamma.value(2.2); + m_gamma.label("Gamma=%.2f"); + + m_r.value(1.0); + m_g.value(1.0); + m_b.value(1.0); + + m_r.label("R=%.2f"); + m_g.label("G=%.2f"); + m_b.label("B=%.2f"); + } + + virtual void on_init() + { + } + + virtual void on_draw() + { + typedef agg::gamma_lut gamma_type; + + typedef pixfmt_gamma pixfmt_type; + typedef agg::renderer_base ren_base; + + double g = m_gamma.value(); + gamma_type gamma(g); + + pixfmt_type pixf(rbuf_window(), gamma); + ren_base renb(pixf); + + agg::rasterizer_scanline_aa<> ras; + agg::scanline_u8 sl; + + + enum + { + square_size = 400, + ver_strips = 5 + }; + + color_type span1[square_size]; + color_type span2[square_size]; + + color_type color(agg::rgba(m_r.value(), m_g.value(), m_b.value())); + + unsigned i, j; + + + // Draw vertical gradient + //----------------------- + unsigned w = (unsigned)width(); + unsigned h = (unsigned)height(); + for(i = 0; i < h; i++) + { + double k = (i - 80) / double(square_size - 1); + if(i < 80) k = 0.0; + if(i >= 80+square_size) k = 1.0; + + k = 1 - pow(k/2, 1/m_gamma.value()); + color_type c = color.gradient(color_type(0,0,0), k); + renb.copy_hline(0, i, w-1, c); + } + + // Calculate spans + //----------------------- + switch(m_pattern.cur_item()) + { + case 0: + for(i = 0; i < square_size; i++) + { + span1[i] = span2[i] = color; + span1[i].a = i * color_type::base_mask / square_size; + span2[i].a = color_type::base_mask - span1[i].a; + } + break; + + case 1: + for(i = 0; i < square_size; i++) + { + span1[i] = span2[i] = color; + if(i & 1) + { + span1[i].a = i * color_type::base_mask / square_size; + span2[i].a = span1[i].a; + } + else + { + span1[i].a = color_type::base_mask - + i * color_type::base_mask / square_size; + span2[i].a = span1[i].a; + } + } + break; + + case 2: + for(i = 0; i < square_size; i++) + { + span1[i] = span2[i] = color; + if(i & 1) + { + span1[i].a = i * color_type::base_mask / square_size; + span2[i].a = color_type::base_mask - span1[i].a; + } + else + { + span2[i].a = i * color_type::base_mask / square_size; + span1[i].a = color_type::base_mask - span2[i].a; + } + } + break; + } + + // Clear the area + //--------------------- + renb.copy_bar(50, 80, 50+square_size-1, 80+square_size-1, agg::rgba(0,0,0)); + + + // Draw the patern + //--------------------- + for(i = 0; i < square_size; i += 2) + { + double k = i / double(square_size - 1); + k = 1 - pow(k, 1/m_gamma.value()); + color_type c = color.gradient(agg::rgba(0,0,0), k); + for(j = 0; j < square_size; j++) + { + span1[j].r = span2[j].r = c.r; + span1[j].g = span2[j].g = c.g; + span1[j].b = span2[j].b = c.b; + } + renb.blend_color_hspan(50, i + 80 + 0, square_size, span1, 0, 255); + renb.blend_color_hspan(50, i + 80 + 1, square_size, span2, 0, 255); + } + + + // Draw vertical strips + //--------------------- + for(i = 0; i < square_size; i++) + { + double k = i / double(square_size - 1); + + k = 1 - pow(k/2, 1/m_gamma.value()); + color_type c = color.gradient(color_type(0,0,0), k); + for(j = 0; j < ver_strips; j++) + { + int xc = square_size * (j + 1) / (ver_strips + 1); + renb.copy_hline(50+xc-10, i+80, 50+xc+10, c); + } + } + + + agg::render_ctrl(ras, sl, renb, m_gamma); + agg::render_ctrl(ras, sl, renb, m_r); + agg::render_ctrl(ras, sl, renb, m_g); + agg::render_ctrl(ras, sl, renb, m_b); + agg::render_ctrl(ras, sl, renb, m_pattern); + + } + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + } + +}; + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Gamma Tuner"); + + if(app.init(500, 500, 0)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/gouraud.cpp b/jni/desmume/src/android/agg/examples/gouraud.cpp new file mode 100755 index 0000000..c6840d2 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/gouraud.cpp @@ -0,0 +1,314 @@ +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_span_allocator.h" +#include "agg_span_gouraud_rgba.h" +#include "agg_span_gouraud_gray.h" +#include "agg_span_solid.h" +#include "platform/agg_platform_support.h" + +#include "ctrl/agg_slider_ctrl.h" + + +//#define AGG_GRAY8 +#define AGG_BGR24 +//#define AGG_RGB24 +//#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + +enum flip_y_e { flip_y = true }; + + +#include "agg_math.h" +#include "agg_dda_line.h" + + +class the_application : public agg::platform_support +{ + double m_x[3]; + double m_y[3]; + double m_dx; + double m_dy; + int m_idx; + + agg::slider_ctrl m_dilation; + agg::slider_ctrl m_gamma; + agg::slider_ctrl m_alpha; + + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_idx(-1), + m_dilation(5, 5, 400-5, 11, !flip_y), + m_gamma (5, 5+15, 400-5, 11+15, !flip_y), + m_alpha (5, 5+30, 400-5, 11+30, !flip_y) + + { + m_x[0] = 57; m_y[0] = 60; + m_x[1] = 369; m_y[1] = 170; + m_x[2] = 143; m_y[2] = 310; + + add_ctrl(m_dilation); + add_ctrl(m_gamma); + add_ctrl(m_alpha); + + m_dilation.label("Dilation=%3.2f"); + m_gamma.label("Linear gamma=%3.2f"); + m_alpha.label("Opacity=%3.2f"); + + m_dilation.value(0.175); + m_gamma.value(0.809); + m_alpha.value(1.0); + } + + + template + void render_gouraud(Scanline& sl, Ras& ras) + { + double alpha = m_alpha.value(); + double brc = 1; + + typedef agg::renderer_base base_ren_type; +#ifdef AGG_GRAY8 + typedef agg::span_gouraud_gray span_gen_type; +#else + typedef agg::span_gouraud_rgba span_gen_type; +#endif + typedef agg::span_allocator span_alloc_type; + + pixfmt pf(rbuf_window()); + base_ren_type ren_base(pf); + + span_alloc_type span_alloc; + span_gen_type span_gen; + + ras.gamma(agg::gamma_linear(0.0, m_gamma.value())); + + double d = m_dilation.value(); + + // Single triangle + //span_gen.colors(agg::rgba(1, 0, 0, alpha), + // agg::rgba(0, 1, 0, alpha), + // agg::rgba(0, 0, 1, alpha)); + //span_gen.triangle(m_x[0], m_y[0], m_x[1], m_y[1], m_x[2], m_y[2], d); + //ras.add_path(span_gen); + //agg::render_scanlines_aa(ras, sl, ren_base, span_alloc, span_gen); + + + // Six triangles + double xc = (m_x[0] + m_x[1] + m_x[2]) / 3.0; + double yc = (m_y[0] + m_y[1] + m_y[2]) / 3.0; + + double x1 = (m_x[1] + m_x[0]) / 2 - (xc - (m_x[1] + m_x[0]) / 2); + double y1 = (m_y[1] + m_y[0]) / 2 - (yc - (m_y[1] + m_y[0]) / 2); + + double x2 = (m_x[2] + m_x[1]) / 2 - (xc - (m_x[2] + m_x[1]) / 2); + double y2 = (m_y[2] + m_y[1]) / 2 - (yc - (m_y[2] + m_y[1]) / 2); + + double x3 = (m_x[0] + m_x[2]) / 2 - (xc - (m_x[0] + m_x[2]) / 2); + double y3 = (m_y[0] + m_y[2]) / 2 - (yc - (m_y[0] + m_y[2]) / 2); + + span_gen.colors(agg::rgba(1, 0, 0, alpha), + agg::rgba(0, 1, 0, alpha), + agg::rgba(brc, brc, brc, alpha)); + span_gen.triangle(m_x[0], m_y[0], m_x[1], m_y[1], xc, yc, d); + ras.add_path(span_gen); + agg::render_scanlines_aa(ras, sl, ren_base, span_alloc, span_gen); + + + span_gen.colors(agg::rgba(0, 1, 0, alpha), + agg::rgba(0, 0, 1, alpha), + agg::rgba(brc, brc, brc, alpha)); + span_gen.triangle(m_x[1], m_y[1], m_x[2], m_y[2], xc, yc, d); + ras.add_path(span_gen); + agg::render_scanlines_aa(ras, sl, ren_base, span_alloc, span_gen); + + + span_gen.colors(agg::rgba(0, 0, 1, alpha), + agg::rgba(1, 0, 0, alpha), + agg::rgba(brc, brc, brc, alpha)); + span_gen.triangle(m_x[2], m_y[2], m_x[0], m_y[0], xc, yc, d); + ras.add_path(span_gen); + agg::render_scanlines_aa(ras, sl, ren_base, span_alloc, span_gen); + + + brc = 1-brc; + span_gen.colors(agg::rgba(1, 0, 0, alpha), + agg::rgba(0, 1, 0, alpha), + agg::rgba(brc, brc, brc, alpha)); + span_gen.triangle(m_x[0], m_y[0], m_x[1], m_y[1], x1, y1, d); + ras.add_path(span_gen); + agg::render_scanlines_aa(ras, sl, ren_base, span_alloc, span_gen); + + + span_gen.colors(agg::rgba(0, 1, 0, alpha), + agg::rgba(0, 0, 1, alpha), + agg::rgba(brc, brc, brc, alpha)); + span_gen.triangle(m_x[1], m_y[1], m_x[2], m_y[2], x2, y2, d); + ras.add_path(span_gen); + agg::render_scanlines_aa(ras, sl, ren_base, span_alloc, span_gen); + + + span_gen.colors(agg::rgba(0, 0, 1, alpha), + agg::rgba(1, 0, 0, alpha), + agg::rgba(brc, brc, brc, alpha)); + span_gen.triangle(m_x[2], m_y[2], m_x[0], m_y[0], x3, y3, d); + ras.add_path(span_gen); + agg::render_scanlines_aa(ras, sl, ren_base, span_alloc, span_gen); + } + + + + + + + + + virtual void on_draw() + { + typedef agg::renderer_base base_ren_type; + + pixfmt pf(rbuf_window()); + base_ren_type ren_base(pf); + ren_base.clear(agg::rgba(1,1,1)); + + agg::scanline_u8 sl; + agg::rasterizer_scanline_aa<> ras; + + render_gouraud(sl, ras); + + ras.gamma(agg::gamma_none()); + agg::render_ctrl(ras, sl, ren_base, m_dilation); + agg::render_ctrl(ras, sl, ren_base, m_gamma); + agg::render_ctrl(ras, sl, ren_base, m_alpha); + } + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + unsigned i; + if(flags & agg::mouse_right) + { + agg::scanline_u8 sl; + agg::rasterizer_scanline_aa<> ras; + start_timer(); + for(i = 0; i < 100; i++) + { + render_gouraud(sl, ras); + } + char buf[100]; + sprintf(buf, "Time=%2.2f ms", elapsed_time()); + message(buf); + } + + if(flags & agg::mouse_left) + { + for (i = 0; i < 3; i++) + { + if(sqrt( (x-m_x[i]) * (x-m_x[i]) + (y-m_y[i]) * (y-m_y[i]) ) < 10.0) + { + m_dx = x - m_x[i]; + m_dy = y - m_y[i]; + m_idx = i; + break; + } + } + if(i == 3) + { + if(agg::point_in_triangle(m_x[0], m_y[0], + m_x[1], m_y[1], + m_x[2], m_y[2], + x, y)) + { + m_dx = x - m_x[0]; + m_dy = y - m_y[0]; + m_idx = 3; + } + + } + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_idx == 3) + { + double dx = x - m_dx; + double dy = y - m_dy; + m_x[1] -= m_x[0] - dx; + m_y[1] -= m_y[0] - dy; + m_x[2] -= m_x[0] - dx; + m_y[2] -= m_y[0] - dy; + m_x[0] = dx; + m_y[0] = dy; + force_redraw(); + return; + } + + if(m_idx >= 0) + { + m_x[m_idx] = x - m_dx; + m_y[m_idx] = y - m_dy; + force_redraw(); + } + } + else + { + on_mouse_button_up(x, y, flags); + } + } + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + m_idx = -1; + } + + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + double dx = 0; + double dy = 0; + switch(key) + { + case agg::key_left: dx = -0.1; break; + case agg::key_right: dx = 0.1; break; + case agg::key_up: dy = 0.1; break; + case agg::key_down: dy = -0.1; break; + } + m_x[0] += dx; + m_y[0] += dy; + m_x[1] += dx; + m_y[1] += dy; + force_redraw(); + } + + +}; + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Gouraud Shading"); + + if(app.init(400, 320, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/gouraud_mesh.cpp b/jni/desmume/src/android/agg/examples/gouraud_mesh.cpp new file mode 100755 index 0000000..16380f6 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/gouraud_mesh.cpp @@ -0,0 +1,498 @@ +#include +#include +#include +#include "agg_rendering_buffer.h" +#include "agg_conv_transform.h" +#include "agg_conv_stroke.h" +#include "agg_conv_clip_polyline.h" +#include "agg_scanline_u.h" +#include "agg_scanline_bin.h" +#include "agg_renderer_scanline.h" +#include "agg_rasterizer_outline_aa.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_span_allocator.h" +#include "agg_span_gouraud_rgba.h" +#include "agg_gamma_lut.h" +#include "agg_arc.h" +#include "agg_bezier_arc.h" +#include "agg_pixfmt_rgb.h" +#include "agg_pixfmt_rgba.h" +#include "agg_bounding_rect.h" +#include "agg_vpgen_clip_polygon.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_bezier_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "platform/agg_platform_support.h" + +#include "agg_rasterizer_compound_aa.h" + + +enum { flip_y = true }; + +typedef agg::pixfmt_bgra32_pre pixfmt; + + +namespace agg +{ + + struct mesh_point + { + double x,y; + double dx,dy; + rgba8 color; + rgba8 dc; + + mesh_point() {} + mesh_point(double x_, double y_, + double dx_, double dy_, + rgba8 c, rgba8 dc_) : + x(x_), y(y_), + dx(dx_), dy(dy_), + color(c), dc(dc_) + {} + }; + + struct mesh_triangle + { + unsigned p1, p2, p3; + + mesh_triangle() {} + mesh_triangle(unsigned i, unsigned j, unsigned k) : + p1(i), p2(j), p3(k) + {} + }; + + struct mesh_edge + { + unsigned p1, p2; + int tl, tr; + + mesh_edge() {} + mesh_edge(unsigned p1_, unsigned p2_, int tl_, int tr_) : + p1(p1_), p2(p2_), tl(tl_), tr(tr_) + {} + }; + + + static double random(double v1, double v2) + { + return (v2 - v1) * (rand() % 1000) / 999.0 + v1; + } + + + class mesh_ctrl + { + public: + mesh_ctrl(); + + void generate(unsigned cols, unsigned rows, + double cell_w, double cell_h, + double start_x, double start_y); + + void randomize_points(double delta); + void rotate_colors(); + + + bool on_mouse_button_down(double x, double y, unsigned flags); + bool on_mouse_move(double x, double y, unsigned flags); + bool on_mouse_button_up(double x, double y, unsigned flags); + + unsigned num_vertices() const { return m_vertices.size(); } + const mesh_point& vertex(unsigned i) const { return m_vertices[i]; } + mesh_point& vertex(unsigned i) { return m_vertices[i]; } + + const mesh_point& vertex(unsigned x, unsigned y) const { return m_vertices[y * m_rows + x]; } + mesh_point& vertex(unsigned x, unsigned y) { return m_vertices[y * m_rows + x]; } + + unsigned num_triangles() const { return m_triangles.size(); } + const mesh_triangle& triangle(unsigned i) const { return m_triangles[i]; } + mesh_triangle& triangle(unsigned i) { return m_triangles[i]; } + + unsigned num_edges() const { return m_edges.size(); } + const mesh_edge& edge(unsigned i) const { return m_edges[i]; } + mesh_edge& edge(unsigned i) { return m_edges[i]; } + + private: + unsigned m_cols; + unsigned m_rows; + int m_drag_idx; + double m_drag_dx; + double m_drag_dy; + double m_cell_w; + double m_cell_h; + double m_start_x; + double m_start_y; + pod_bvector m_vertices; + pod_bvector m_triangles; + pod_bvector m_edges; + }; + + + mesh_ctrl::mesh_ctrl() : + m_cols(0), + m_rows(0), + m_drag_idx(-1), + m_drag_dx(0), + m_drag_dy(0) + {} + + + void mesh_ctrl::generate(unsigned cols, unsigned rows, + double cell_w, double cell_h, + double start_x, double start_y) + { + m_cols = cols; + m_rows = rows; + m_cell_w = cell_w; + m_cell_h = cell_h; + m_start_x = start_x; + m_start_y = start_y; + + m_vertices.remove_all(); + unsigned i, j; + for(i = 0; i < m_rows; i++) + { + double x = start_x; + for(j = 0; j < m_cols; j++) + { + double dx = random(-0.5, 0.5); + double dy = random(-0.5, 0.5); + rgba8 c(rand() & 0xFF, rand() & 0xFF, rand() & 0xFF); + rgba8 dc(rand() & 1, rand() & 1, rand() & 1); + m_vertices.add(mesh_point(x, start_y, dx, dy, c, dc)); + x += cell_w; + } + start_y += cell_h; + } + + + + // 4---3 + // |t2/| + // | / | + // |/t1| + // 1---2 + m_triangles.remove_all(); + m_edges.remove_all(); + for(i = 0; i < m_rows - 1; i++) + { + for(j = 0; j < m_cols - 1; j++) + { + int p1 = i * m_cols + j; + int p2 = p1 + 1; + int p3 = p2 + m_cols; + int p4 = p1 + m_cols; + m_triangles.add(mesh_triangle(p1, p2, p3)); + m_triangles.add(mesh_triangle(p3, p4, p1)); + + int curr_cell = i * (m_cols - 1) + j; + int left_cell = j ? int(curr_cell - 1) : -1; + int bott_cell = i ? int(curr_cell - (m_cols - 1)) : -1; + + int curr_t1 = curr_cell * 2; + int curr_t2 = curr_t1 + 1; + + int left_t1 = (left_cell >= 0) ? left_cell * 2 : -1; + int left_t2 = (left_cell >= 0) ? left_t1 + 1 : -1; + + int bott_t1 = (bott_cell >= 0) ? bott_cell * 2 : -1; + int bott_t2 = (bott_cell >= 0) ? bott_t1 + 1 : -1; + + m_edges.add(mesh_edge(p1, p2, curr_t1, bott_t2)); + m_edges.add(mesh_edge(p1, p3, curr_t2, curr_t1)); + m_edges.add(mesh_edge(p1, p4, left_t1, curr_t2)); + + if(j == m_cols - 2) // Last column + { + m_edges.add(mesh_edge(p2, p3, curr_t1, -1)); + } + + if(i == m_rows - 2) // Last row + { + m_edges.add(mesh_edge(p3, p4, curr_t2, -1)); + } + } + } + } + + void mesh_ctrl::randomize_points(double delta) + { + unsigned i, j; + for(i = 0; i < m_rows; i++) + { + for(j = 0; j < m_cols; j++) + { + double xc = j * m_cell_w + m_start_x; + double yc = i * m_cell_h + m_start_y; + double x1 = xc - m_cell_w / 4; + double y1 = yc - m_cell_h / 4; + double x2 = xc + m_cell_w / 4; + double y2 = yc + m_cell_h / 4; + mesh_point& p = vertex(j, i); + p.x += p.dx; + p.y += p.dy; + if(p.x < x1) { p.x = x1; p.dx = -p.dx; } + if(p.y < y1) { p.y = y1; p.dy = -p.dy; } + if(p.x > x2) { p.x = x2; p.dx = -p.dx; } + if(p.y > y2) { p.y = y2; p.dy = -p.dy; } + } + } + } + + + void mesh_ctrl::rotate_colors() + { + unsigned i; + for(i = 1; i < m_vertices.size(); i++) + { + rgba8& c = m_vertices[i].color; + rgba8& dc = m_vertices[i].dc; + int r = c.r + (dc.r ? 5 : -5); + int g = c.g + (dc.g ? 5 : -5); + int b = c.b + (dc.b ? 5 : -5); + if(r < 0) { r = 0; dc.r ^= 1; } if(r > 255) { r = 255; dc.r ^= 1; } + if(g < 0) { g = 0; dc.g ^= 1; } if(g > 255) { g = 255; dc.g ^= 1; } + if(b < 0) { b = 0; dc.b ^= 1; } if(b > 255) { b = 255; dc.b ^= 1; } + c.r = r; + c.g = g; + c.b = b; + } + } + + + bool mesh_ctrl::on_mouse_button_down(double x, double y, unsigned flags) + { + if(flags & 1) + { + unsigned i; + for(i = 0; i < m_vertices.size(); i++) + { + if(calc_distance(x, y, m_vertices[i].x, m_vertices[i].y) < 5) + { + m_drag_idx = i; + m_drag_dx = x - m_vertices[i].x; + m_drag_dy = y - m_vertices[i].y; + return true; + } + } + } + return false; + } + + bool mesh_ctrl::on_mouse_move(double x, double y, unsigned flags) + { + if(flags & 1) + { + if(m_drag_idx >= 0) + { + m_vertices[m_drag_idx].x = x - m_drag_dx; + m_vertices[m_drag_idx].y = y - m_drag_dy; + return true; + } + } + else + { + return on_mouse_button_up(x, y, flags); + } + return false; + } + + bool mesh_ctrl::on_mouse_button_up(double x, double y, unsigned flags) + { + bool ret = m_drag_idx >= 0; + m_drag_idx = -1; + return ret; + } + + + + class styles_gouraud + { + public: + typedef span_gouraud_rgba gouraud_type; + + template + styles_gouraud(const mesh_ctrl& mesh, const Gamma& gamma) + { + unsigned i; + for(i = 0; i < mesh.num_triangles(); i++) + { + const agg::mesh_triangle& t = mesh.triangle(i); + const agg::mesh_point& p1 = mesh.vertex(t.p1); + const agg::mesh_point& p2 = mesh.vertex(t.p2); + const agg::mesh_point& p3 = mesh.vertex(t.p3); + + agg::rgba8 c1 = p1.color; + agg::rgba8 c2 = p2.color; + agg::rgba8 c3 = p3.color; + c1.apply_gamma_dir(gamma); + c2.apply_gamma_dir(gamma); + c3.apply_gamma_dir(gamma); + gouraud_type gouraud(c1, c2, c3, + p1.x, p1.y, + p2.x, p2.y, + p3.x, p3.y); + gouraud.prepare(); + m_triangles.add(gouraud); + } + } + + bool is_solid(unsigned style) const { return false; } + + rgba8 color(unsigned style) const { return rgba8(0,0,0,0); } + + void generate_span(rgba8* span, int x, int y, unsigned len, unsigned style) + { + m_triangles[style].generate(span, x, y, len); + } + + private: + pod_bvector m_triangles; + }; +} + + + + + +class the_application : public agg::platform_support +{ + +public: + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_scanline; + typedef agg::rasterizer_scanline_aa<> rasterizer_scanline; + typedef agg::scanline_u8 scanline; + + agg::mesh_ctrl m_mesh; + agg::gamma_lut<> m_gamma; + + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y) + { +// m_gamma.gamma(2.0); + } + + virtual void on_init() + { + m_mesh.generate(20, 20, 17, 17, 40, 40); + } + + + virtual void on_draw() + { + pixfmt pf(rbuf_window()); + renderer_base ren_base(pf); + ren_base.clear(agg::rgba(0, 0, 0)); + renderer_scanline ren(ren_base); + + rasterizer_scanline ras; + agg::scanline_u8 sl; + agg::scanline_bin sl_bin; + + agg::rasterizer_compound_aa<> rasc; + agg::span_allocator alloc; + + unsigned i; + agg::styles_gouraud styles(m_mesh, m_gamma); + start_timer(); + rasc.reset(); + //rasc.clip_box(40, 40, width() - 40, height() - 40); + for(i = 0; i < m_mesh.num_edges(); i++) + { + const agg::mesh_edge& e = m_mesh.edge(i); + const agg::mesh_point& p1 = m_mesh.vertex(e.p1); + const agg::mesh_point& p2 = m_mesh.vertex(e.p2); + rasc.styles(e.tl, e.tr); + rasc.move_to_d(p1.x, p1.y); + rasc.line_to_d(p2.x, p2.y); + } + agg::render_scanlines_compound(rasc, sl, sl_bin, ren_base, alloc, styles); + double tm = elapsed_time(); + + char buf[256]; + agg::gsv_text t; + t.size(10.0); + + agg::conv_stroke pt(t); + pt.width(1.5); + pt.line_cap(agg::round_cap); + pt.line_join(agg::round_join); + + sprintf(buf, "%3.2f ms, %d triangles, %.0f tri/sec", + tm, + m_mesh.num_triangles(), + m_mesh.num_triangles() / tm * 1000.0); + t.start_point(10.0, 10.0); + t.text(buf); + + ras.add_path(pt); + agg::render_scanlines_aa_solid(ras, sl, ren_base, agg::rgba(1,1,1)); + + + if(m_gamma.gamma() != 1.0) + { + pf.apply_gamma_inv(m_gamma); + } + } + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(m_mesh.on_mouse_move(x, y, flags)) + { + force_redraw(); + } + } + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(m_mesh.on_mouse_button_down(x, y, flags)) + { + force_redraw(); + } + } + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + if(m_mesh.on_mouse_button_up(x, y, flags)) + { + force_redraw(); + } + } + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + } + + void on_idle() + { + m_mesh.randomize_points(1.0); + m_mesh.rotate_colors(); + force_redraw(); + } + + virtual void on_ctrl_change() + { + } +}; + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgra32, flip_y); + app.caption("AGG Example"); + + if(app.init(400, 400, 0))//agg::window_resize)) + { + app.wait_mode(false); + return app.run(); + } + return 1; +} + + + + + diff --git a/jni/desmume/src/android/agg/examples/gpc_test.cpp b/jni/desmume/src/android/agg/examples/gpc_test.cpp new file mode 100755 index 0000000..459a499 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/gpc_test.cpp @@ -0,0 +1,682 @@ +#include +#include "agg_conv_gpc.h" +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_renderer_primitives.h" +#include "agg_conv_curve.h" +#include "agg_conv_stroke.h" +#include "agg_conv_clip_polygon.h" +#include "agg_gsv_text.h" +#include "agg_pixfmt_rgb.h" +#include "platform/agg_platform_support.h" + +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" + + +enum flip_y_e { flip_y = true }; + + + + +class spiral +{ +public: + spiral(double x, double y, double r1, double r2, double step, double start_angle=0) : + m_x(x), + m_y(y), + m_r1(r1), + m_r2(r2), + m_step(step), + m_start_angle(start_angle), + m_angle(start_angle), + m_da(agg::deg2rad(4.0)), + m_dr(m_step / 90.0) + { + } + + void rewind(unsigned) + { + m_angle = m_start_angle; + m_curr_r = m_r1; + m_start = true; + } + + unsigned vertex(double* x, double* y) + { + if(m_curr_r > m_r2) return agg::path_cmd_stop; + + *x = m_x + cos(m_angle) * m_curr_r; + *y = m_y + sin(m_angle) * m_curr_r; + m_curr_r += m_dr; + m_angle += m_da; + if(m_start) + { + m_start = false; + return agg::path_cmd_move_to; + } + return agg::path_cmd_line_to; + } + +private: + double m_x; + double m_y; + double m_r1; + double m_r2; + double m_step; + double m_start_angle; + + double m_angle; + double m_curr_r; + double m_da; + double m_dr; + bool m_start; +}; + + + +namespace agg +{ + // A simple counter of points and contours + template struct conv_poly_counter + { + unsigned m_contours; + unsigned m_points; + + conv_poly_counter(Src& src) : m_src(&src), m_contours(0), m_points(0) {} + + void rewind(unsigned path_id) + { + m_contours = 0; + m_points = 0; + m_src->rewind(path_id); + } + + unsigned vertex(double* x, double* y) + { + unsigned cmd = m_src->vertex(x, y); + if(is_vertex(cmd)) ++m_points; + if(is_move_to(cmd)) ++m_contours; + return cmd; + } + + private: + Src* m_src; + }; +} + + + + +void make_gb_poly(agg::path_storage& ps); +void make_arrows(agg::path_storage& ps); + + +class the_application : public agg::platform_support +{ + agg::rbox_ctrl m_polygons; + agg::rbox_ctrl m_operation; + double m_x; + double m_y; + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_polygons (5.0, 5.0, 5.0+205.0, 110.0, !flip_y), + m_operation(555.0, 5.0, 555.0+80.0, 130.0, !flip_y) + { + m_operation.add_item("None"); + m_operation.add_item("OR"); + m_operation.add_item("AND"); + m_operation.add_item("XOR"); + m_operation.add_item("A-B"); + m_operation.add_item("B-A"); + m_operation.cur_item(2); + add_ctrl(m_operation); + + m_polygons.add_item("Two Simple Paths"); + m_polygons.add_item("Closed Stroke"); + m_polygons.add_item("Great Britain and Arrows"); + m_polygons.add_item("Great Britain and Spiral"); + m_polygons.add_item("Spiral and Glyph"); + m_polygons.cur_item(3); + add_ctrl(m_polygons); + } + + + template + void perform_rendering(Scanline& sl, Ras& ras, Ren& ren, Gpc& gpc) + { + if(m_operation.cur_item() > 0) + { + ras.reset(); + switch(m_operation.cur_item()) + { + case 1: gpc.operation(agg::gpc_or); break; + case 2: gpc.operation(agg::gpc_and); break; + case 3: gpc.operation(agg::gpc_xor); break; + case 4: gpc.operation(agg::gpc_a_minus_b); break; + case 5: gpc.operation(agg::gpc_b_minus_a); break; + } + agg::conv_poly_counter counter(gpc); + + + start_timer(); + counter.rewind(0); + double t1 = elapsed_time(); + + ras.reset(); + double x; + double y; + unsigned cmd; + start_timer(); + while(!agg::is_stop(cmd = counter.vertex(&x, &y))) + { + ras.add_vertex(x, y, cmd); + } + + ren.color(agg::rgba(0.5, 0.0, 0, 0.5)); + agg::render_scanlines(ras, sl, ren); + double t2 = elapsed_time(); + + char buf[100]; + sprintf(buf, "Contours: %d Points: %d", counter.m_contours, counter.m_points); + agg::gsv_text txt; + agg::conv_stroke txt_stroke(txt); + txt_stroke.width(1.5); + txt_stroke.line_cap(agg::round_cap); + txt.size(10.0); + txt.start_point(250, 5); + txt.text(buf); + ras.add_path(txt_stroke); + ren.color(agg::rgba(0.0, 0.0, 0.0)); + agg::render_scanlines(ras, sl, ren); + + sprintf(buf, "GPC=%.3fms Render=%.3fms", t1, t2); + txt.start_point(250, 20); + txt.text(buf); + ras.add_path(txt_stroke); + ren.color(agg::rgba(0.0, 0.0, 0.0)); + agg::render_scanlines(ras, sl, ren); + } + } + + + template + unsigned render_gpc(Scanline& sl, Ras& ras) + { + agg::pixfmt_bgr24 pf(rbuf_window()); + agg::renderer_base rb(pf); + agg::renderer_scanline_aa_solid > ren(rb); + + + switch(m_polygons.cur_item()) + { + case 0: + { + //------------------------------------ + // Two simple paths + // + agg::path_storage ps1; + agg::path_storage ps2; + + agg::conv_gpc gpc(ps1, ps2); + + double x = m_x - initial_width()/2 + 100; + double y = m_y - initial_height()/2 + 100; + ps1.move_to(x+140, y+145); + ps1.line_to(x+225, y+44); + ps1.line_to(x+296, y+219); + ps1.close_polygon(); + + ps1.line_to(x+226, y+289); + ps1.line_to(x+82, y+292); + + ps1.move_to(x+220, y+222); + ps1.line_to(x+363, y+249); + ps1.line_to(x+265, y+331); + + ps1.move_to(x+242, y+243); + ps1.line_to(x+268, y+309); + ps1.line_to(x+325, y+261); + + ps1.move_to(x+259, y+259); + ps1.line_to(x+273, y+288); + ps1.line_to(x+298, y+266); + + ps2.move_to(100+32, 100+77); + ps2.line_to(100+473, 100+263); + ps2.line_to(100+351, 100+290); + ps2.line_to(100+354, 100+374); + + ras.reset(); + ras.add_path(ps1); + ren.color(agg::rgba(0, 0, 0, 0.1)); + agg::render_scanlines(ras, sl, ren); + + ras.reset(); + ras.add_path(ps2); + ren.color(agg::rgba(0, 0.6, 0, 0.1)); + agg::render_scanlines(ras, sl, ren); + + perform_rendering(sl, ras, ren, gpc); + } + break; + + case 1: + { + //------------------------------------ + // Closed stroke + // + agg::path_storage ps1; + agg::path_storage ps2; + agg::conv_stroke stroke(ps2); + stroke.width(10.0); + + agg::conv_gpc > gpc(ps1, stroke); + + + double x = m_x - initial_width()/2 + 100; + double y = m_y - initial_height()/2 + 100; + ps1.move_to(x+140, y+145); + ps1.line_to(x+225, y+44); + ps1.line_to(x+296, y+219); + ps1.close_polygon(); + + ps1.line_to(x+226, y+289); + ps1.line_to(x+82, y+292); + + ps1.move_to(x+220-50, y+222); + ps1.line_to(x+265-50, y+331); + ps1.line_to(x+363-50, y+249); + ps1.close_polygon(agg::path_flags_ccw); + + ps2.move_to(100+32, 100+77); + ps2.line_to(100+473, 100+263); + ps2.line_to(100+351, 100+290); + ps2.line_to(100+354, 100+374); + ps2.close_polygon(); + + ras.reset(); + ras.add_path(ps1); + ren.color(agg::rgba(0, 0, 0, 0.1)); + agg::render_scanlines(ras, sl, ren); + + ras.reset(); + ras.add_path(stroke); + ren.color(agg::rgba(0, 0.6, 0, 0.1)); + agg::render_scanlines(ras, sl, ren); + + perform_rendering(sl, ras, ren, gpc); + } + break; + + + case 2: + { + //------------------------------------ + // Great Britain and Arrows + // + agg::path_storage gb_poly; + agg::path_storage arrows; + make_gb_poly(gb_poly); + make_arrows(arrows); + + agg::trans_affine mtx1; + agg::trans_affine mtx2; + mtx1 *= agg::trans_affine_translation(-1150, -1150); + mtx1 *= agg::trans_affine_scaling(2.0); + + mtx2 = mtx1; + mtx2 *= agg::trans_affine_translation(m_x - initial_width()/2, + m_y - initial_height()/2); + + agg::conv_transform trans_gb_poly(gb_poly, mtx1); + agg::conv_transform trans_arrows(arrows, mtx2); + + agg::conv_gpc, + agg::conv_transform > gpc(trans_gb_poly, trans_arrows); + + ras.add_path(trans_gb_poly); + ren.color(agg::rgba(0.5, 0.5, 0, 0.1)); + agg::render_scanlines(ras, sl, ren); + + agg::conv_stroke > stroke_gb_poly(trans_gb_poly); + stroke_gb_poly.width(0.1); + ras.add_path(stroke_gb_poly); + ren.color(agg::rgba(0, 0, 0)); + agg::render_scanlines(ras, sl, ren); + + ras.add_path(trans_arrows); + ren.color(agg::rgba(0.0, 0.5, 0.5, 0.1)); + agg::render_scanlines(ras, sl, ren); + + perform_rendering(sl, ras, ren, gpc); + } + break; + + + case 3: + { + //------------------------------------ + // Great Britain and a Spiral + // + spiral sp(m_x, m_y, 10, 150, 30, 0.0); + agg::conv_stroke stroke(sp); + stroke.width(15.0); + + agg::path_storage gb_poly; + make_gb_poly(gb_poly); + + agg::trans_affine mtx; + mtx *= agg::trans_affine_translation(-1150, -1150); + mtx *= agg::trans_affine_scaling(2.0); + + agg::conv_transform trans_gb_poly(gb_poly, mtx); + + agg::conv_gpc, + agg::conv_stroke > gpc(trans_gb_poly, stroke); + + +/* +FILE* fd = fopen("contours.txt", "w"); +if(fd) +{ + unsigned cmd; + double x, y; + trans_gb_poly.rewind(0); + while(!agg::is_stop(cmd = trans_gb_poly.vertex(&x, &y))) + { + if(agg::is_move_to(cmd)) + { + fprintf(fd, "\npoly[] = {\n"); + } + fprintf(fd, " %.3f, %.3f,\n", x, y); + } + + stroke.rewind(0); + while(!agg::is_stop(cmd = stroke.vertex(&x, &y))) + { + if(agg::is_move_to(cmd)) + { + fprintf(fd, "\nspiral[] = {\n"); + } + fprintf(fd, " %.3f, %.3f,\n", x, y); + } + + fclose(fd); +} +*/ + + ras.add_path(trans_gb_poly); + ren.color(agg::rgba(0.5, 0.5, 0, 0.1)); + agg::render_scanlines(ras, sl, ren); + + agg::conv_stroke > stroke_gb_poly(trans_gb_poly); + stroke_gb_poly.width(0.1); + ras.add_path(stroke_gb_poly); + ren.color(agg::rgba(0, 0, 0)); + agg::render_scanlines(ras, sl, ren); + + ras.add_path(stroke); + ren.color(agg::rgba(0.0, 0.5, 0.5, 0.1)); + agg::render_scanlines(ras, sl, ren); + + perform_rendering(sl, ras, ren, gpc); + } + break; + + + case 4: + { + //------------------------------------ + // Spiral and glyph + // + spiral sp(m_x, m_y, 10, 150, 30, 0.0); + agg::conv_stroke stroke(sp); + stroke.width(15.0); + + agg::path_storage glyph; + glyph.move_to(28.47, 6.45); + glyph.curve3(21.58, 1.12, 19.82, 0.29); + glyph.curve3(17.19, -0.93, 14.21, -0.93); + glyph.curve3(9.57, -0.93, 6.57, 2.25); + glyph.curve3(3.56, 5.42, 3.56, 10.60); + glyph.curve3(3.56, 13.87, 5.03, 16.26); + glyph.curve3(7.03, 19.58, 11.99, 22.51); + glyph.curve3(16.94, 25.44, 28.47, 29.64); + glyph.line_to(28.47, 31.40); + glyph.curve3(28.47, 38.09, 26.34, 40.58); + glyph.curve3(24.22, 43.07, 20.17, 43.07); + glyph.curve3(17.09, 43.07, 15.28, 41.41); + glyph.curve3(13.43, 39.75, 13.43, 37.60); + glyph.line_to(13.53, 34.77); + glyph.curve3(13.53, 32.52, 12.38, 31.30); + glyph.curve3(11.23, 30.08, 9.38, 30.08); + glyph.curve3(7.57, 30.08, 6.42, 31.35); + glyph.curve3(5.27, 32.62, 5.27, 34.81); + glyph.curve3(5.27, 39.01, 9.57, 42.53); + glyph.curve3(13.87, 46.04, 21.63, 46.04); + glyph.curve3(27.59, 46.04, 31.40, 44.04); + glyph.curve3(34.28, 42.53, 35.64, 39.31); + glyph.curve3(36.52, 37.21, 36.52, 30.71); + glyph.line_to(36.52, 15.53); + glyph.curve3(36.52, 9.13, 36.77, 7.69); + glyph.curve3(37.01, 6.25, 37.57, 5.76); + glyph.curve3(38.13, 5.27, 38.87, 5.27); + glyph.curve3(39.65, 5.27, 40.23, 5.62); + glyph.curve3(41.26, 6.25, 44.19, 9.18); + glyph.line_to(44.19, 6.45); + glyph.curve3(38.72, -0.88, 33.74, -0.88); + glyph.curve3(31.35, -0.88, 29.93, 0.78); + glyph.curve3(28.52, 2.44, 28.47, 6.45); + glyph.close_polygon(); + + glyph.move_to(28.47, 9.62); + glyph.line_to(28.47, 26.66); + glyph.curve3(21.09, 23.73, 18.95, 22.51); + glyph.curve3(15.09, 20.36, 13.43, 18.02); + glyph.curve3(11.77, 15.67, 11.77, 12.89); + glyph.curve3(11.77, 9.38, 13.87, 7.06); + glyph.curve3(15.97, 4.74, 18.70, 4.74); + glyph.curve3(22.41, 4.74, 28.47, 9.62); + glyph.close_polygon(); + + agg::trans_affine mtx; + mtx *= agg::trans_affine_scaling(4.0); + mtx *= agg::trans_affine_translation(220, 200); + agg::conv_transform trans(glyph, mtx); + agg::conv_curve > curve(trans); + + agg::conv_gpc, + agg::conv_curve< + agg::conv_transform< + agg::path_storage> > > gpc(stroke, curve); + + ras.reset(); + ras.add_path(stroke); + ren.color(agg::rgba(0, 0, 0, 0.1)); + agg::render_scanlines(ras, sl, ren); + + ras.reset(); + ras.add_path(curve); + ren.color(agg::rgba(0, 0.6, 0, 0.1)); + agg::render_scanlines(ras, sl, ren); + + perform_rendering(sl, ras, ren, gpc); + } + break; + } + + return 0; + } + + + virtual void on_init() + { + m_x = width() / 2.0; + m_y = height() / 2.0; + } + + virtual void on_draw() + { + typedef agg::renderer_base base_ren_type; + + agg::pixfmt_bgr24 pf(rbuf_window()); + base_ren_type ren_base(pf); + ren_base.clear(agg::rgba(1,1,1)); + + agg::scanline_u8 sl; + agg::rasterizer_scanline_aa<> ras; + + render_gpc(sl, ras); + + agg::render_ctrl(ras, sl, ren_base, m_polygons); + agg::render_ctrl(ras, sl, ren_base, m_operation); + } + + +/* +// Stress-test. +// Works quite well on random polygons, no crashes, no memory leaks! +// Sometimes takes long to produce the result + + double random(double min, double max) + { + int r = (rand() << 15) | rand(); + return ((r & 0xFFFFFFF) / double(0xFFFFFFF + 1)) * (max - min) + min; + } + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + agg::scanline_u8 sl; + agg::rasterizer_scanline_aa<> ras; + + typedef agg::renderer_base base_ren_type; + typedef agg::renderer_scanline_aa_solid renderer_solid; + + agg::pixfmt_bgr24 pf(rbuf_window()); + base_ren_type ren_base(pf); + renderer_solid ren_solid(ren_base); + + agg::path_storage ps1; + agg::path_storage ps2; + + agg::conv_gpc gpc(ps1, ps2); + + unsigned i; + for(i = 0; i < 1000; i++) + { + ren_base.clear(agg::rgba(1,1,1)); + + unsigned num_poly1 = rand() % 10 + 1; + unsigned num_poly2 = rand() % 10 + 1; + unsigned j; + + ps1.remove_all(); + ps2.remove_all(); + + for(j = 0; j < num_poly1; j++) + { + ps1.move_to(random(0, width()), random(0, height())); + unsigned k; + unsigned np = rand() % 20 + 2; + for(k = 0; k < np; k++) + { + ps1.line_to(random(0, width()), random(0, height())); + } + } + + for(j = 0; j < num_poly2; j++) + { + ps2.move_to(random(0, width()), random(0, height())); + unsigned k; + unsigned np = rand() % 20 + 2; + for(k = 0; k < np; k++) + { + ps2.line_to(random(0, width()), random(0, height())); + } + } + + unsigned op = rand() % 5; + switch(op) + { + case 0: gpc.operation(agg::gpc_or); break; + case 1: gpc.operation(agg::gpc_and); break; + case 2: gpc.operation(agg::gpc_xor); break; + case 3: gpc.operation(agg::gpc_a_minus_b); break; + case 4: gpc.operation(agg::gpc_b_minus_a); break; + } + + + ras.add_path(gpc); + ren_solid.color(agg::rgba(0.5, 0.0, 0, 0.5)); + agg::render_scanlines(ras, sl, ren_solid); + update_window(); + + } + + message("Done"); + } +*/ + + + + + + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + m_x = x; + m_y = y; + force_redraw(); + } + + if(flags & agg::mouse_right) + { + char buf[100]; + sprintf(buf, "%d %d", x, y); + message(buf); + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + m_x = x; + m_y = y; + force_redraw(); + } + } + + + +}; + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("AGG Example. General Polygon Clipping (GPC)"); + + if(app.init(640, 520, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/gradient_focal.cpp b/jni/desmume/src/android/agg/examples/gradient_focal.cpp new file mode 100755 index 0000000..c4b433c --- /dev/null +++ b/jni/desmume/src/android/agg/examples/gradient_focal.cpp @@ -0,0 +1,257 @@ +#include +#include +#include +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_span_allocator.h" +#include "agg_span_gradient.h" +#include "agg_gradient_lut.h" +#include "agg_gamma_lut.h" +#include "agg_span_interpolator_linear.h" +#include "ctrl/agg_slider_ctrl.h" +#include "platform/agg_platform_support.h" + + +#include "agg_pixfmt_rgb.h" +#define pix_format agg::pix_format_bgr24 +typedef agg::pixfmt_bgr24 pixfmt; +typedef agg::rgba8 color_type; +typedef agg::order_bgr component_order; + + +enum { flip_y = true }; + + +class the_application : public agg::platform_support +{ + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_solid; + typedef agg::gamma_lut gamma_lut_type; + typedef agg::gradient_radial_focus gradient_func_type; + typedef agg::gradient_reflect_adaptor gradient_adaptor_type; + typedef agg::gradient_lut, 1024> color_func_type; + typedef agg::span_interpolator_linear<> interpolator_type; + typedef agg::span_allocator span_allocator_type; + typedef agg::span_gradient span_gradient_type; + + agg::slider_ctrl m_gamma; + + agg::scanline_u8 m_scanline; + agg::rasterizer_scanline_aa<> m_rasterizer; + span_allocator_type m_alloc; + color_func_type m_gradient_lut; + gamma_lut_type m_gamma_lut; + + double m_mouse_x, m_mouse_y; + double m_old_gamma; + + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_gamma(5.0, 5.0, 340.0, 12.0, !flip_y), + m_mouse_x(200), m_mouse_y(200) + { + m_gamma.range(0.5, 2.5); + m_gamma.value(1.8); + m_gamma.label("Gamma = %.3f"); + add_ctrl(m_gamma); + m_gamma.no_transform(); + + m_gamma_lut.gamma(m_gamma.value()); + m_old_gamma = m_gamma.value(); + + build_gradient_lut(); + } + + virtual void on_init() + { + m_mouse_y = initial_height() / 2; + m_mouse_x = initial_width() / 2; + } + + void build_gradient_lut() + { + m_gradient_lut.remove_all(); + + m_gradient_lut.add_color(0.0, agg::rgba8_gamma_dir(agg::rgba8(0, 255, 0), m_gamma_lut)); + m_gradient_lut.add_color(0.2, agg::rgba8_gamma_dir(agg::rgba8(120, 0, 0), m_gamma_lut)); + m_gradient_lut.add_color(0.7, agg::rgba8_gamma_dir(agg::rgba8(120, 120, 0), m_gamma_lut)); + m_gradient_lut.add_color(1.0, agg::rgba8_gamma_dir(agg::rgba8(0, 0, 255), m_gamma_lut)); + + //m_gradient_lut.add_color(0.0, agg::rgba8::from_wavelength(380, m_gamma.value())); + //m_gradient_lut.add_color(0.1, agg::rgba8::from_wavelength(420, m_gamma.value())); + //m_gradient_lut.add_color(0.2, agg::rgba8::from_wavelength(460, m_gamma.value())); + //m_gradient_lut.add_color(0.3, agg::rgba8::from_wavelength(500, m_gamma.value())); + //m_gradient_lut.add_color(0.4, agg::rgba8::from_wavelength(540, m_gamma.value())); + //m_gradient_lut.add_color(0.5, agg::rgba8::from_wavelength(580, m_gamma.value())); + //m_gradient_lut.add_color(0.6, agg::rgba8::from_wavelength(620, m_gamma.value())); + //m_gradient_lut.add_color(0.7, agg::rgba8::from_wavelength(660, m_gamma.value())); + //m_gradient_lut.add_color(0.8, agg::rgba8::from_wavelength(700, m_gamma.value())); + //m_gradient_lut.add_color(0.9, agg::rgba8::from_wavelength(740, m_gamma.value())); + //m_gradient_lut.add_color(1.0, agg::rgba8::from_wavelength(780, m_gamma.value())); + + m_gradient_lut.build_lut(); + } + + virtual void on_draw() + { + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + renderer_solid rs(rb); + rb.clear(agg::rgba(1, 1, 1)); + + // When Gamma changes rebuild the gamma and gradient LUTs + //------------------ + if(m_old_gamma != m_gamma.value()) + { + m_gamma_lut.gamma(m_gamma.value()); + build_gradient_lut(); + m_old_gamma = m_gamma.value(); + } + + + // Gradient center. All gradient functions assume the + // center being in the origin (0,0) and you can't + // change it. But you can apply arbitrary transformations + // to the gradient (see below). + //------------------ + double cx = initial_width() / 2; + double cy = initial_height() / 2; + double r = 100; + + // Focal center. Defined in the gradient coordinates, + // that is, with respect to the origin (0,0) + //------------------ + double fx = m_mouse_x - cx; + double fy = m_mouse_y - cy; + + gradient_func_type gradient_func(r, fx, fy); + gradient_adaptor_type gradient_adaptor(gradient_func); + agg::trans_affine gradient_mtx; + + // Making the affine matrix. Move to (cx,cy), + // apply the resizing transformations and invert + // the matrix. Gradients and images always assume the + // inverse transformations. + //------------------ + gradient_mtx.translate(cx, cy); + gradient_mtx *= trans_affine_resizing(); + gradient_mtx.invert(); + + interpolator_type span_interpolator(gradient_mtx); + span_gradient_type span_gradient(span_interpolator, + gradient_adaptor, + m_gradient_lut, + 0, r); + + // Form the simple rectangle + //------------------ + m_rasterizer.reset(); + m_rasterizer.move_to_d(0,0); + m_rasterizer.line_to_d(width(), 0); + m_rasterizer.line_to_d(width(), height()); + m_rasterizer.line_to_d(0, height()); + + // Render the gradient to the whole screen and measure the time + //------------------ + start_timer(); + agg::render_scanlines_aa(m_rasterizer, m_scanline, rb, m_alloc, span_gradient); + double tm = elapsed_time(); + + // Draw the transformed circle that shows the gradient boundary + //------------------ + agg::ellipse e(cx, cy, r, r); + agg::conv_stroke estr(e); + agg::conv_transform< + agg::conv_stroke< + agg::ellipse> > etrans(estr, trans_affine_resizing()); + + m_rasterizer.add_path(etrans); + agg::render_scanlines_aa_solid(m_rasterizer, m_scanline, rb, agg::rgba(1,1,1)); + + // Show the gradient time + //------------------ + char buf[64]; + agg::gsv_text t; + t.size(10.0); + agg::conv_stroke pt(t); + pt.width(1.5); + sprintf(buf, "%3.2f ms", tm); + t.start_point(10.0, 35.0); + t.text(buf); + m_rasterizer.add_path(pt); + agg::render_scanlines_aa_solid(m_rasterizer, m_scanline, rb, agg::rgba(0,0,0)); + + // Show the controls + //------------------ + agg::render_ctrl(m_rasterizer, m_scanline, rb, m_gamma); + + // Apply the inverse gamma to the whole buffer + // (transform the colors to the perceptually uniform space) + //------------------ + pixf.apply_gamma_inv(m_gamma_lut); + } + + + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + m_mouse_x = x; + m_mouse_y = y; + trans_affine_resizing().inverse_transform(&m_mouse_x, &m_mouse_y); + force_redraw(); + } + } + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + m_mouse_x = x; + m_mouse_y = y; + trans_affine_resizing().inverse_transform(&m_mouse_x, &m_mouse_y); + force_redraw(); + } + } + + + + + + + +}; + + + + + + + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. PDF linear and radial gradients"); + + if(app.init(600, 400, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/gradients.cpp b/jni/desmume/src/android/agg/examples/gradients.cpp new file mode 100755 index 0000000..b67d6ea --- /dev/null +++ b/jni/desmume/src/android/agg/examples/gradients.cpp @@ -0,0 +1,528 @@ +#include +#include +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_scanline_p.h" +#include "agg_conv_transform.h" +#include "agg_color_rgba.h" +#include "agg_color_gray.h" +#include "agg_span_allocator.h" +#include "agg_span_gradient.h" +#include "agg_span_interpolator_linear.h" +#include "agg_renderer_scanline.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "ctrl/agg_spline_ctrl.h" +#include "ctrl/agg_gamma_ctrl.h" +#include "platform/agg_platform_support.h" + + +//#define AGG_GRAY16 +#define AGG_BGR24 +//#define AGG_RGB24 +//#define AGG_RGB_AAA +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + +enum flip_y_e { flip_y = true }; + +const double center_x = 350; +const double center_y = 280; + + + + +class gradient_polymorphic_wrapper_base +{ +public: + virtual int calculate(int x, int y, int) const = 0; +}; + +template +class gradient_polymorphic_wrapper : public gradient_polymorphic_wrapper_base +{ +public: + gradient_polymorphic_wrapper() : m_adaptor(m_gradient) {} + + virtual int calculate(int x, int y, int d) const + { + return m_adaptor.calculate(x, y, d); + } + GradientF m_gradient; + agg::gradient_reflect_adaptor m_adaptor; +}; + + + +struct color_function_profile +{ + color_function_profile() {} + color_function_profile(const color_type* colors, const agg::int8u* profile) : + m_colors(colors), m_profile(profile) {} + + static unsigned size() { return 256; } + const color_type& operator [] (unsigned v) const + { + return m_colors[m_profile[v]]; + } + + const color_type* m_colors; + const agg::int8u* m_profile; +}; + + +class the_application : public agg::platform_support +{ + agg::gamma_ctrl m_profile; + agg::spline_ctrl m_spline_r; + agg::spline_ctrl m_spline_g; + agg::spline_ctrl m_spline_b; + agg::spline_ctrl m_spline_a; + agg::rbox_ctrl m_rbox; + + double m_pdx; + double m_pdy; + double m_center_x; + double m_center_y; + double m_scale; + double m_prev_scale; + double m_angle; + double m_prev_angle; + double m_scale_x; + double m_prev_scale_x; + double m_scale_y; + double m_prev_scale_y; + bool m_mouse_move; + +public: + virtual ~the_application() + { + FILE* fd = fopen(full_file_name("settings.dat"), "w"); + fprintf(fd, "%f\n", m_center_x); + fprintf(fd, "%f\n", m_center_y); + fprintf(fd, "%f\n", m_scale); + fprintf(fd, "%f\n", m_angle); + fprintf(fd, "%f\n", m_spline_r.x(0)); + fprintf(fd, "%f\n", m_spline_r.y(0)); + fprintf(fd, "%f\n", m_spline_r.x(1)); + fprintf(fd, "%f\n", m_spline_r.y(1)); + fprintf(fd, "%f\n", m_spline_r.x(2)); + fprintf(fd, "%f\n", m_spline_r.y(2)); + fprintf(fd, "%f\n", m_spline_r.x(3)); + fprintf(fd, "%f\n", m_spline_r.y(3)); + fprintf(fd, "%f\n", m_spline_r.x(4)); + fprintf(fd, "%f\n", m_spline_r.y(4)); + fprintf(fd, "%f\n", m_spline_r.x(5)); + fprintf(fd, "%f\n", m_spline_r.y(5)); + fprintf(fd, "%f\n", m_spline_g.x(0)); + fprintf(fd, "%f\n", m_spline_g.y(0)); + fprintf(fd, "%f\n", m_spline_g.x(1)); + fprintf(fd, "%f\n", m_spline_g.y(1)); + fprintf(fd, "%f\n", m_spline_g.x(2)); + fprintf(fd, "%f\n", m_spline_g.y(2)); + fprintf(fd, "%f\n", m_spline_g.x(3)); + fprintf(fd, "%f\n", m_spline_g.y(3)); + fprintf(fd, "%f\n", m_spline_g.x(4)); + fprintf(fd, "%f\n", m_spline_g.y(4)); + fprintf(fd, "%f\n", m_spline_g.x(5)); + fprintf(fd, "%f\n", m_spline_g.y(5)); + fprintf(fd, "%f\n", m_spline_b.x(0)); + fprintf(fd, "%f\n", m_spline_b.y(0)); + fprintf(fd, "%f\n", m_spline_b.x(1)); + fprintf(fd, "%f\n", m_spline_b.y(1)); + fprintf(fd, "%f\n", m_spline_b.x(2)); + fprintf(fd, "%f\n", m_spline_b.y(2)); + fprintf(fd, "%f\n", m_spline_b.x(3)); + fprintf(fd, "%f\n", m_spline_b.y(3)); + fprintf(fd, "%f\n", m_spline_b.x(4)); + fprintf(fd, "%f\n", m_spline_b.y(4)); + fprintf(fd, "%f\n", m_spline_b.x(5)); + fprintf(fd, "%f\n", m_spline_b.y(5)); + fprintf(fd, "%f\n", m_spline_a.x(0)); + fprintf(fd, "%f\n", m_spline_a.y(0)); + fprintf(fd, "%f\n", m_spline_a.x(1)); + fprintf(fd, "%f\n", m_spline_a.y(1)); + fprintf(fd, "%f\n", m_spline_a.x(2)); + fprintf(fd, "%f\n", m_spline_a.y(2)); + fprintf(fd, "%f\n", m_spline_a.x(3)); + fprintf(fd, "%f\n", m_spline_a.y(3)); + fprintf(fd, "%f\n", m_spline_a.x(4)); + fprintf(fd, "%f\n", m_spline_a.y(4)); + fprintf(fd, "%f\n", m_spline_a.x(5)); + fprintf(fd, "%f\n", m_spline_a.y(5)); + double x1,y1,x2,y2; + m_profile.values(&x1, &y1, &x2, &y2); + fprintf(fd, "%f\n", x1); + fprintf(fd, "%f\n", y1); + fprintf(fd, "%f\n", x2); + fprintf(fd, "%f\n", y2); + fclose(fd); + } + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_profile(10.0, 10.0, 200.0, 170.0-5.0, !flip_y), + m_spline_r(210, 10, 210+250, 5+40, 6, !flip_y), + m_spline_g(210, 10+40, 210+250, 5+80, 6, !flip_y), + m_spline_b(210, 10+80, 210+250, 5+120, 6, !flip_y), + m_spline_a(210, 10+120, 210+250, 5+160, 6, !flip_y), + m_rbox(10.0, 180.0, 200.0, 300.0, !flip_y), + + m_pdx(0.0), + m_pdy(0.0), + m_center_x(center_x), + m_center_y(center_y), + m_scale(1.0), + m_prev_scale(1.0), + m_angle(0.0), + m_prev_angle(0.0), + m_scale_x(1.0), + m_prev_scale_x(1.0), + m_scale_y(1.0), + m_prev_scale_y(1.0), + m_mouse_move(false) + { + add_ctrl(m_profile); + add_ctrl(m_spline_r); + add_ctrl(m_spline_g); + add_ctrl(m_spline_b); + add_ctrl(m_spline_a); + add_ctrl(m_rbox); + + m_profile.border_width(2.0, 2.0); + + m_spline_r.background_color(agg::rgba(1.0, 0.8, 0.8)); + m_spline_g.background_color(agg::rgba(0.8, 1.0, 0.8)); + m_spline_b.background_color(agg::rgba(0.8, 0.8, 1.0)); + m_spline_a.background_color(agg::rgba(1.0, 1.0, 1.0)); + + m_spline_r.border_width(1.0, 2.0); + m_spline_g.border_width(1.0, 2.0); + m_spline_b.border_width(1.0, 2.0); + m_spline_a.border_width(1.0, 2.0); + m_rbox.border_width(2.0, 2.0); + + m_spline_r.point(0, 0.0, 1.0); + m_spline_r.point(1, 1.0/5.0, 1.0 - 1.0/5.0); + m_spline_r.point(2, 2.0/5.0, 1.0 - 2.0/5.0); + m_spline_r.point(3, 3.0/5.0, 1.0 - 3.0/5.0); + m_spline_r.point(4, 4.0/5.0, 1.0 - 4.0/5.0); + m_spline_r.point(5, 1.0, 0.0); + m_spline_r.update_spline(); + + m_spline_g.point(0, 0.0, 1.0); + m_spline_g.point(1, 1.0/5.0, 1.0 - 1.0/5.0); + m_spline_g.point(2, 2.0/5.0, 1.0 - 2.0/5.0); + m_spline_g.point(3, 3.0/5.0, 1.0 - 3.0/5.0); + m_spline_g.point(4, 4.0/5.0, 1.0 - 4.0/5.0); + m_spline_g.point(5, 1.0, 0.0); + m_spline_g.update_spline(); + + m_spline_b.point(0, 0.0, 1.0); + m_spline_b.point(1, 1.0/5.0, 1.0 - 1.0/5.0); + m_spline_b.point(2, 2.0/5.0, 1.0 - 2.0/5.0); + m_spline_b.point(3, 3.0/5.0, 1.0 - 3.0/5.0); + m_spline_b.point(4, 4.0/5.0, 1.0 - 4.0/5.0); + m_spline_b.point(5, 1.0, 0.0); + m_spline_b.update_spline(); + + m_spline_a.point(0, 0.0, 1.0); + m_spline_a.point(1, 1.0/5.0, 1.0); + m_spline_a.point(2, 2.0/5.0, 1.0); + m_spline_a.point(3, 3.0/5.0, 1.0); + m_spline_a.point(4, 4.0/5.0, 1.0); + m_spline_a.point(5, 1.0, 1.0); + m_spline_a.update_spline(); + + m_rbox.add_item("Circular"); + m_rbox.add_item("Diamond"); + m_rbox.add_item("Linear"); + m_rbox.add_item("XY"); + m_rbox.add_item("sqrt(XY)"); + m_rbox.add_item("Conic"); + m_rbox.cur_item(0); + + FILE* fd = fopen(full_file_name("settings.dat"), "r"); + if(fd) + { + float x; + float y; + float x2; + float y2; + float t; + + fscanf(fd, "%f\n", &t); m_center_x = t; + fscanf(fd, "%f\n", &t); m_center_y = t; + fscanf(fd, "%f\n", &t); m_scale = t; + fscanf(fd, "%f\n", &t); m_angle = t; + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_r.point(0, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_r.point(1, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_r.point(2, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_r.point(3, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_r.point(4, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_r.point(5, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_g.point(0, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_g.point(1, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_g.point(2, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_g.point(3, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_g.point(4, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_g.point(5, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_b.point(0, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_b.point(1, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_b.point(2, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_b.point(3, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_b.point(4, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_b.point(5, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_a.point(0, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_a.point(1, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_a.point(2, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_a.point(3, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_a.point(4, x, y); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); m_spline_a.point(5, x, y); + m_spline_r.update_spline(); + m_spline_g.update_spline(); + m_spline_b.update_spline(); + m_spline_a.update_spline(); + fscanf(fd, "%f\n", &x); + fscanf(fd, "%f\n", &y); + fscanf(fd, "%f\n", &x2); + fscanf(fd, "%f\n", &y2); + m_profile.values(x, y, x2, y2); + fclose(fd); + } + + } + + + virtual void on_draw() + { + agg::rasterizer_scanline_aa<> ras; + + typedef agg::renderer_base renderer_base; + agg::scanline_u8 sl; + + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + rb.clear(agg::rgba(0, 0, 0)); + + m_profile.text_size(8.0); + + agg::render_ctrl(ras, sl, rb, m_profile); + agg::render_ctrl(ras, sl, rb, m_spline_r); + agg::render_ctrl(ras, sl, rb, m_spline_g); + agg::render_ctrl(ras, sl, rb, m_spline_b); + agg::render_ctrl(ras, sl, rb, m_spline_a); + agg::render_ctrl(ras, sl, rb, m_rbox); + + double ini_scale = 1.0; + + agg::trans_affine mtx1; + mtx1 *= agg::trans_affine_scaling(ini_scale, ini_scale); + mtx1 *= agg::trans_affine_rotation(agg::deg2rad(0.0)); + mtx1 *= agg::trans_affine_translation(center_x, center_y); + mtx1 *= trans_affine_resizing(); + + agg::ellipse e1; + e1.init(0.0, 0.0, 110.0, 110.0, 64); + + agg::trans_affine mtx_g1; + mtx_g1 *= agg::trans_affine_scaling(ini_scale, ini_scale); + mtx_g1 *= agg::trans_affine_scaling(m_scale, m_scale); + mtx_g1 *= agg::trans_affine_scaling(m_scale_x, m_scale_y); + mtx_g1 *= agg::trans_affine_rotation(m_angle); + mtx_g1 *= agg::trans_affine_translation(m_center_x, m_center_y); + mtx_g1 *= trans_affine_resizing(); + mtx_g1.invert(); + + + color_type color_profile[256]; // color_type is defined in pixel_formats.h + int i; + for(i = 0; i < 256; i++) + { + color_profile[i] = color_type(agg::rgba(m_spline_r.spline()[i], + m_spline_g.spline()[i], + m_spline_b.spline()[i], + m_spline_a.spline()[i])); + } + + agg::conv_transform t1(e1, mtx1); + + gradient_polymorphic_wrapper gr_circle; + gradient_polymorphic_wrapper gr_diamond; + gradient_polymorphic_wrapper gr_x; + gradient_polymorphic_wrapper gr_xy; + gradient_polymorphic_wrapper gr_sqrt_xy; + gradient_polymorphic_wrapper gr_conic; + + gradient_polymorphic_wrapper_base* gr_ptr = &gr_circle; + +// gr_circle.m_gradient.init(150, 80, 80); + + switch(m_rbox.cur_item()) + { + case 1: gr_ptr = &gr_diamond; break; + case 2: gr_ptr = &gr_x; break; + case 3: gr_ptr = &gr_xy; break; + case 4: gr_ptr = &gr_sqrt_xy; break; + case 5: gr_ptr = &gr_conic; break; + } + + typedef agg::span_interpolator_linear<> interpolator_type; + typedef agg::span_gradient gradient_span_gen; + typedef agg::span_allocator gradient_span_alloc; + + gradient_span_alloc span_alloc; + color_function_profile colors(color_profile, m_profile.gamma()); + interpolator_type inter(mtx_g1); + gradient_span_gen span_gen(inter, *gr_ptr, colors, 0, 150); + + ras.add_path(t1); + agg::render_scanlines_aa(ras, sl, rb, span_alloc, span_gen); + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(m_mouse_move) + { + double x2 = x; + double y2 = y; + trans_affine_resizing().inverse_transform(&x2, &y2); + + if(flags & agg::kbd_ctrl) + { + double dx = x2 - m_center_x; + double dy = y2 - m_center_y; + m_scale_x = m_prev_scale_x * dx / m_pdx; + m_scale_y = m_prev_scale_y * dy / m_pdy; + force_redraw(); + } + else + { + if(flags & agg::mouse_left) + { + m_center_x = x2 + m_pdx; + m_center_y = y2 + m_pdy; + force_redraw(); + } + + if(flags & agg::mouse_right) + { + double dx = x2 - m_center_x; + double dy = y2 - m_center_y; + m_scale = m_prev_scale * + sqrt(dx * dx + dy * dy) / + sqrt(m_pdx * m_pdx + m_pdy * m_pdy); + + m_angle = m_prev_angle + atan2(dy, dx) - atan2(m_pdy, m_pdx); + force_redraw(); + } + } + } + } + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + m_mouse_move = true; + double x2 = x; + double y2 = y; + trans_affine_resizing().inverse_transform(&x2, &y2); + + m_pdx = m_center_x - x2; + m_pdy = m_center_y - y2; + m_prev_scale = m_scale; + m_prev_angle = m_angle + agg::pi; + m_prev_scale_x = m_scale_x; + m_prev_scale_y = m_scale_y; + force_redraw(); + } + + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + m_mouse_move = false; + } + + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + if(key == agg::key_f1) + { + FILE* fd = fopen(full_file_name("colors.dat"), "w"); + int i; + for(i = 0; i < 256; i++) + { + color_type c = agg::rgba(m_spline_r.spline()[i], + m_spline_g.spline()[i], + m_spline_b.spline()[i], + m_spline_a.spline()[i]); + fprintf(fd, " %3d, %3d, %3d, %3d,\n", c.r, c.g, c.b, c.a); + } + fclose(fd); + + fd = fopen(full_file_name("profile.dat"), "w"); + for(i = 0; i < 256; i++) + { + fprintf(fd, "%3d, ", unsigned(m_profile.gamma()[i])); + if((i & 0xF) == 0xF) fprintf(fd, "\n"); + } + fclose(fd); + } + + + } + +}; + + + +int agg_main(int argc, char* argv[]) +{ + //#ifdef _WIN32 + // FILE* fd = fopen("stdout.txt", "w"); fclose(fd); + //#endif + //AGG_WATCHDOGGY(wd1, false); + + the_application app(pix_format, flip_y); + app.caption("AGG gradients with Mach bands compensation"); + + if(app.init(512, 400, agg::window_resize | agg::window_hw_buffer)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/graph_test.cpp b/jni/desmume/src/android/agg/examples/graph_test.cpp new file mode 100755 index 0000000..8d2e36b --- /dev/null +++ b/jni/desmume/src/android/agg/examples/graph_test.cpp @@ -0,0 +1,923 @@ +#include +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_rasterizer_outline.h" +#include "agg_conv_stroke.h" +#include "agg_conv_dash.h" +#include "agg_conv_curve.h" +#include "agg_conv_contour.h" +#include "agg_conv_marker.h" +#include "agg_conv_shorten_path.h" +#include "agg_conv_marker_adaptor.h" +#include "agg_conv_concat.h" +#include "agg_arrowhead.h" +#include "agg_vcgen_markers_term.h" +#include "agg_scanline_p.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_renderer_primitives.h" +#include "agg_span_allocator.h" +#include "agg_span_gradient.h" +#include "agg_span_interpolator_linear.h" +#include "agg_pixfmt_rgb.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "platform/agg_platform_support.h" + +enum flip_y_e { flip_y = true }; + + +typedef agg::pixfmt_bgr24 pixfmt; +typedef pixfmt::color_type color_type; +typedef agg::renderer_base base_renderer; +typedef agg::renderer_primitives primitives_renderer; + +typedef agg::renderer_scanline_aa_solid solid_renderer; +typedef agg::renderer_scanline_bin_solid draft_renderer; + +typedef agg::gradient_radial_d gradient_function; +typedef agg::span_interpolator_linear<> interpolator; +typedef agg::pod_auto_array color_array_type; +typedef agg::span_gradient gradient_span_gen; +typedef agg::span_allocator gradient_span_alloc; + +typedef agg::renderer_scanline_aa gradient_renderer; + +typedef agg::rasterizer_scanline_aa<> scanline_rasterizer; +typedef agg::rasterizer_outline outline_rasterizer; + + + +//============================================================================ +class graph +{ +public: + struct node + { + double x, y; + node() {} + node(double x_, double y_) : x(x_), y(y_) {} + }; + + struct edge + { + int node1; + int node2; + edge() {} + edge(int n1, int n2) : node1(n1), node2(n2) {} + }; + + ~graph() + { + delete [] m_edges; + delete [] m_nodes; + } + + graph(int num_nodes, int num_edges) : + m_num_nodes(num_nodes), + m_num_edges(num_edges), + m_nodes(new node[num_nodes]), + m_edges(new edge[num_edges]) + { + int i; + + srand(100); + + for(i = 0; i < m_num_nodes; i++) + { + m_nodes[i].x = (double(rand()) / RAND_MAX) * 0.75 + 0.2; + m_nodes[i].y = (double(rand()) / RAND_MAX) * 0.85 + 0.1; + } + + for(i = 0; i < m_num_edges; i++) + { + m_edges[i].node1 = rand() % m_num_nodes; + m_edges[i].node2 = rand() % m_num_nodes; + if(m_edges[i].node1 == m_edges[i].node2) i--; + } + } + + int get_num_nodes() const { return m_num_nodes; } + int get_num_edges() const { return m_num_edges; } + + node get_node(int idx, double w, double h) const + { + node p(0.0, 0.0); + if(idx < m_num_nodes) + { + p = m_nodes[idx]; + p.x = p.x * w; + p.y = p.y * h; + } + return p; + } + + edge get_edge(int idx) const + { + edge b(0,0); + if(idx < m_num_edges) + { + b = m_edges[idx]; + } + return b; + } + +private: + graph(const graph&); + const graph& operator = (const graph&); + + int m_num_nodes; + int m_num_edges; + node* m_nodes; + edge* m_edges; +}; + + + + + + + + + +//============================================================================ +struct line +{ + double x1, y1, x2, y2; + int f; + + line(double x1_, double y1_, double x2_, double y2_) : + x1(x1_), y1(y1_), x2(x2_), y2(y2_), f(0) {} + + void rewind(unsigned) { f = 0; } + unsigned vertex(double* x, double* y) + { + if(f == 0) { ++f; *x = x1; *y = y1; return agg::path_cmd_move_to; } + if(f == 1) { ++f; *x = x2; *y = y2; return agg::path_cmd_line_to; } + return agg::path_cmd_stop; + } +}; + + + + +//============================================================================ +struct curve +{ + agg::curve4 c; + + curve(double x1, double y1, double x2, double y2, double k=0.5) + { + c.init(x1, y1, + x1 - (y2 - y1) * k, + y1 + (x2 - x1) * k, + x2 + (y2 - y1) * k, + y2 - (x2 - x1) * k, + x2, y2); + } + + void rewind(unsigned path_id) { c.rewind(path_id); } + unsigned vertex(double* x, double* y) { return c.vertex(x, y); } +}; + + + +//============================================================================ +template struct stroke_draft_simple +{ + Source& s; + stroke_draft_simple(Source& src, double w) : + s(src) + { + } + + void rewind(unsigned path_id) { s.rewind(path_id); } + unsigned vertex(double* x, double* y) { return s.vertex(x, y); } +}; + + +//============================================================================ +template struct stroke_draft_arrow +{ + typedef agg::conv_marker_adaptor stroke_type; + typedef agg::conv_marker marker_type; + typedef agg::conv_concat concat_type; + + stroke_type s; + agg::arrowhead ah; + marker_type m; + concat_type c; + + stroke_draft_arrow(Source& src, double w) : + s(src), + ah(), + m(s.markers(), ah), + c(s, m) + { + ah.head(0, 10, 5, 0); + s.shorten(10.0); + } + + void rewind(unsigned path_id) { c.rewind(path_id); } + unsigned vertex(double* x, double* y) { return c.vertex(x, y); } +}; + + + +//============================================================================ +template struct stroke_fine_simple +{ + typedef agg::conv_stroke stroke_type; + + stroke_type s; + + stroke_fine_simple(Source& src, double w) : + s(src) + { + s.width(w); + } + void rewind(unsigned path_id) { s.rewind(path_id); } + unsigned vertex(double* x, double* y) { return s.vertex(x, y); } +}; + + + +//============================================================================ +template struct stroke_fine_arrow +{ + typedef agg::conv_stroke stroke_type; + typedef agg::conv_marker marker_type; + typedef agg::conv_concat concat_type; + + stroke_type s; + agg::arrowhead ah; + marker_type m; + concat_type c; + + stroke_fine_arrow(Source& src, double w) : + s(src), + ah(), + m(s.markers(), ah), + c(s, m) + { + s.width(w); + ah.head(0, 10, 5, 0); + s.shorten(w * 2.0); + } + + void rewind(unsigned path_id) { c.rewind(path_id); } + unsigned vertex(double* x, double* y) { return c.vertex(x, y); } +}; + + + +//============================================================================ +template struct dash_stroke_draft_simple +{ + typedef agg::conv_dash dash_type; + + dash_type d; + + dash_stroke_draft_simple(Source& src, + double dash_len, + double gap_len, + double w) : + d(src) + { + d.add_dash(dash_len, gap_len); + } + + void rewind(unsigned path_id) { d.rewind(path_id); } + unsigned vertex(double* x, double* y) { return d.vertex(x, y); } +}; + + +//============================================================================ +template struct dash_stroke_draft_arrow +{ + typedef agg::conv_dash dash_type; + typedef agg::conv_marker marker_type; + typedef agg::conv_concat concat_type; + + dash_type d; + agg::arrowhead ah; + marker_type m; + concat_type c; + + dash_stroke_draft_arrow(Source& src, + double dash_len, double gap_len, double w) : + d(src), + ah(), + m(d.markers(), ah), + c(d, m) + { + d.add_dash(dash_len, gap_len); + ah.head(0, 10, 5, 0); + d.shorten(10.0); + } + + void rewind(unsigned path_id) { c.rewind(path_id); } + unsigned vertex(double* x, double* y) { return c.vertex(x, y); } +}; + + + + +//============================================================================ +template struct dash_stroke_fine_simple +{ + typedef agg::conv_dash dash_type; + typedef agg::conv_stroke stroke_type; + + dash_type d; + stroke_type s; + + dash_stroke_fine_simple(Source& src, + double dash_len, double gap_len, double w) : + d(src), + s(d) + { + d.add_dash(dash_len, gap_len); + s.width(w); + } + + void rewind(unsigned path_id) { s.rewind(path_id); } + unsigned vertex(double* x, double* y) { return s.vertex(x, y); } +}; + + + + + + +//============================================================================ +template struct dash_stroke_fine_arrow +{ + typedef agg::conv_dash dash_type; + typedef agg::conv_stroke stroke_type; + typedef agg::conv_marker marker_type; + typedef agg::conv_concat concat_type; + + dash_type d; + stroke_type s; + agg::arrowhead ah; + marker_type m; + concat_type c; + + dash_stroke_fine_arrow(Source& src, + double dash_len, double gap_len, double w) : + d(src), + s(d), + ah(), + m(d.markers(), ah), + c(s, m) + { + d.add_dash(dash_len, gap_len); + s.width(w); + ah.head(0, 10, 5, 0); + d.shorten(w * 2.0); + } + + void rewind(unsigned path_id) { c.rewind(path_id); } + unsigned vertex(double* x, double* y) { return c.vertex(x, y); } +}; + + + +//#define stroke_draft stroke_draft_simple +//#define dash_stroke_draft dash_stroke_draft_simple +//#define stroke_fine stroke_fine_simple +//#define dash_stroke_fine dash_stroke_fine_simple + +#define stroke_draft stroke_draft_arrow +#define dash_stroke_draft dash_stroke_draft_arrow +#define stroke_fine stroke_fine_arrow +#define dash_stroke_fine dash_stroke_fine_arrow + + + + + +class the_application : public agg::platform_support +{ + agg::rbox_ctrl m_type; + agg::slider_ctrl m_width; + agg::cbox_ctrl m_benchmark; + agg::cbox_ctrl m_draw_nodes; + agg::cbox_ctrl m_draw_edges; + agg::cbox_ctrl m_draft; + agg::cbox_ctrl m_translucent; + graph m_graph; + color_array_type m_gradient_colors; + int m_draw; + agg::scanline_u8 m_sl; + + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_type(-1, -1, -1, -1, !flip_y), + m_width(110+80, 8.0, 110+200.0+80, 8.0 + 7.0, !flip_y), + m_benchmark(110+200+80+8, 8.0-2.0, "Benchmark", !flip_y), + m_draw_nodes(110+200+80+8, 8.0-2.0+15.0, "Draw Nodes", !flip_y), + m_draw_edges(200+200+80+8, 8.0-2.0+15.0, "Draw Edges", !flip_y), + m_draft(200+200+80+8, 8.0-2.0, "Draft Mode", !flip_y), + m_translucent(110+80, 8.0-2.0+15.0, "Translucent Mode", !flip_y), + m_graph(200, 100), + m_gradient_colors(), + m_draw(3) + { + add_ctrl(m_type); + m_type.text_size(8.0); + m_type.add_item("Solid lines"); + m_type.add_item("Bezier curves"); + m_type.add_item("Dashed curves"); + m_type.add_item("Poygons AA"); + m_type.add_item("Poygons Bin"); + m_type.cur_item(0); + + add_ctrl(m_width); + m_width.num_steps(20); + m_width.range(0.0, 5.0); + m_width.value(2.0); + m_width.label("Width=%1.2f"); + + m_benchmark.text_size(8.0); + m_draw_nodes.text_size(8.0); + m_draft.text_size(8.0); + m_draw_nodes.status(true); + m_draw_edges.status(true); + add_ctrl(m_benchmark); + add_ctrl(m_draw_nodes); + add_ctrl(m_draw_edges); + add_ctrl(m_draft); + add_ctrl(m_translucent); + + agg::rgba c1(1, 1, 0, 0.25); + agg::rgba c2(0, 0, 1); + + int i; + for(i = 0; i < 256; i++) + { + m_gradient_colors[i] = c1.gradient(c2, double(i) / 255.0); + } + } + + + + + + + //------------------------------------------------------------------------ + void draw_nodes_draft() + { + pixfmt pixf(rbuf_window()); + base_renderer rb(pixf); + primitives_renderer prim(rb); + int i; + for(i = 0; i < m_graph.get_num_nodes(); i++) + { + graph::node n = m_graph.get_node(i, width(), height()); + prim.fill_color(m_gradient_colors[147]); + prim.line_color(m_gradient_colors[255]); + prim.outlined_ellipse(int(n.x), int(n.y), 10, 10); + prim.fill_color(m_gradient_colors[50]); + prim.solid_ellipse(int(n.x), int(n.y), 4, 4); + } + } + + + + //------------------------------------------------------------------------ + void draw_nodes_fine(scanline_rasterizer& ras) + { + gradient_span_alloc sa; + pixfmt pixf(rbuf_window()); + base_renderer rb(pixf); + int i; + for(i = 0; i < m_graph.get_num_nodes(); i++) + { + graph::node n = m_graph.get_node(i, width(), height()); + agg::ellipse ell(n.x, n.y, 5.0 * m_width.value(), 5.0 * m_width.value()); + + double x, y; + switch(m_draw) + { + case 0: + ell.rewind(0); + while(!agg::is_stop(ell.vertex(&x, &y))); + break; + + case 1: + ras.reset(); + ras.add_path(ell); + break; + + case 2: + ras.reset(); + ras.add_path(ell); + ras.sort(); + break; + + case 3: + { + gradient_function gf; + agg::trans_affine mtx; + mtx *= agg::trans_affine_scaling(m_width.value() / 2.0); + mtx *= agg::trans_affine_translation(n.x, n.y); + mtx.invert(); + interpolator inter(mtx); + gradient_span_gen sg(inter, gf, m_gradient_colors, 0.0, 10.0); + gradient_renderer ren(rb, sa, sg); + ras.add_path(ell); + agg::render_scanlines(ras, m_sl, ren); + } + break; + } + } + } + + + + + + //------------------------------------------------------------------------ + template + void render_edge_fine(scanline_rasterizer& ras, + solid_renderer& ren_fine, + draft_renderer& ren_draft, + Source& src) + { + double x, y; + switch(m_draw) + { + case 0: + src.rewind(0); + while(!agg::is_stop(src.vertex(&x, &y))); + break; + + case 1: + ras.reset(); + ras.add_path(src); + break; + + case 2: + ras.reset(); + ras.add_path(src); + ras.sort(); + break; + + case 3: + { + int r = rand() & 0x7F; + int g = rand() & 0x7F; + int b = rand() & 0x7F; + int a = 255; + if(m_translucent.status()) a = 80; + ras.add_path(src); + + if(m_type.cur_item() < 4) + { + ren_fine.color(agg::rgba8(r, g, b, a)); + agg::render_scanlines(ras, m_sl, ren_fine); + } + else + { + ren_draft.color(agg::rgba8(r, g, b, a)); + agg::render_scanlines(ras, m_sl, ren_draft); + } + } + break; + } + } + + + + //------------------------------------------------------------------------ + void draw_lines_draft() + { + pixfmt pixf(rbuf_window()); + base_renderer rb(pixf); + primitives_renderer prim(rb); + outline_rasterizer ras(prim); + + int i; + for(i = 0; i < m_graph.get_num_edges(); i++) + { + graph::edge e = m_graph.get_edge(i); + graph::node n1 = m_graph.get_node(e.node1, width(), height()); + graph::node n2 = m_graph.get_node(e.node2, width(), height()); + line l(n1.x, n1.y, n2.x, n2.y); + stroke_draft s(l, m_width.value()); + + int r = rand() & 0x7F; + int g = rand() & 0x7F; + int b = rand() & 0x7F; + int a = 255; + if(m_translucent.status()) a = 80; + prim.line_color(agg::rgba8(r, g, b, a)); + ras.add_path(s); + } + } + + + //------------------------------------------------------------------------ + void draw_curves_draft() + { + pixfmt pixf(rbuf_window()); + base_renderer rb(pixf); + primitives_renderer prim(rb); + outline_rasterizer ras(prim); + + int i; + for(i = 0; i < m_graph.get_num_edges(); i++) + { + graph::edge e = m_graph.get_edge(i); + graph::node n1 = m_graph.get_node(e.node1, width(), height()); + graph::node n2 = m_graph.get_node(e.node2, width(), height()); + curve c(n1.x, n1.y, n2.x, n2.y); + stroke_draft s(c, m_width.value()); + + int r = rand() & 0x7F; + int g = rand() & 0x7F; + int b = rand() & 0x7F; + int a = 255; + if(m_translucent.status()) a = 80; + prim.line_color(agg::rgba8(r, g, b, a)); + ras.add_path(s); + } + } + + + //------------------------------------------------------------------------ + void draw_dashes_draft() + { + pixfmt pixf(rbuf_window()); + base_renderer rb(pixf); + primitives_renderer prim(rb); + outline_rasterizer ras(prim); + + int i; + for(i = 0; i < m_graph.get_num_edges(); i++) + { + graph::edge e = m_graph.get_edge(i); + graph::node n1 = m_graph.get_node(e.node1, width(), height()); + graph::node n2 = m_graph.get_node(e.node2, width(), height()); + curve c(n1.x, n1.y, n2.x, n2.y); + dash_stroke_draft s(c, 6.0, 3.0, m_width.value()); + + int r = rand() & 0x7F; + int g = rand() & 0x7F; + int b = rand() & 0x7F; + int a = 255; + if(m_translucent.status()) a = 80; + prim.line_color(agg::rgba8(r, g, b, a)); + ras.add_path(s); + } + } + + + //------------------------------------------------------------------------ + void draw_lines_fine(scanline_rasterizer& ras, + solid_renderer& solid, + draft_renderer& draft) + { + int i; + for(i = 0; i < m_graph.get_num_edges(); i++) + { + graph::edge b = m_graph.get_edge(i); + graph::node n1 = m_graph.get_node(b.node1, width(), height()); + graph::node n2 = m_graph.get_node(b.node2, width(), height()); + line l(n1.x, n1.y, n2.x, n2.y); + stroke_fine s(l, m_width.value()); + render_edge_fine(ras, solid, draft, s); + } + } + + + //------------------------------------------------------------------------ + void draw_curves_fine(scanline_rasterizer& ras, + solid_renderer& solid, + draft_renderer& draft) + + { + int i; + for(i = 0; i < m_graph.get_num_edges(); i++) + { + graph::edge b = m_graph.get_edge(i); + graph::node n1 = m_graph.get_node(b.node1, width(), height()); + graph::node n2 = m_graph.get_node(b.node2, width(), height()); + curve c(n1.x, n1.y, n2.x, n2.y); + stroke_fine s(c, m_width.value()); + render_edge_fine(ras, solid, draft, s); + } + } + + + //------------------------------------------------------------------------ + void draw_dashes_fine(scanline_rasterizer& ras, + solid_renderer& solid, + draft_renderer& draft) + { + int i; + for(i = 0; i < m_graph.get_num_edges(); i++) + { + graph::edge b = m_graph.get_edge(i); + graph::node n1 = m_graph.get_node(b.node1, width(), height()); + graph::node n2 = m_graph.get_node(b.node2, width(), height()); + curve c(n1.x, n1.y, n2.x, n2.y); + dash_stroke_fine s(c, 6.0, 3.0, m_width.value()); + render_edge_fine(ras, solid, draft, s); + } + } + + + //------------------------------------------------------------------------ + void draw_polygons(scanline_rasterizer& ras, + solid_renderer& solid, + draft_renderer& draft) + { + int i; + if(m_type.cur_item() == 4) + { + ras.gamma(agg::gamma_threshold(0.5)); + } + for(i = 0; i < m_graph.get_num_edges(); i++) + { + graph::edge b = m_graph.get_edge(i); + graph::node n1 = m_graph.get_node(b.node1, width(), height()); + graph::node n2 = m_graph.get_node(b.node2, width(), height()); + curve c(n1.x, n1.y, n2.x, n2.y); + render_edge_fine(ras, solid, draft, c); + } + ras.gamma(agg::gamma_none()); + } + + + + //------------------------------------------------------------------------ + void draw_scene(scanline_rasterizer& ras, + solid_renderer& solid, + draft_renderer& draft) + { + ras.gamma(agg::gamma_none()); + srand(100); + if(m_draw_nodes.status()) + { + if(m_draft.status()) + { + draw_nodes_draft(); + } + else + { + draw_nodes_fine(ras); + } + } + + if(m_draw_edges.status()) + { + if(m_draft.status()) + { + switch(m_type.cur_item()) + { + case 0: draw_lines_draft(); break; + case 1: draw_curves_draft(); break; + case 2: draw_dashes_draft(); break; + } + } + else + { + switch(m_type.cur_item()) + { + case 0: draw_lines_fine(ras, solid, draft); break; + case 1: draw_curves_fine(ras, solid, draft); break; + case 2: draw_dashes_fine(ras, solid, draft); break; + case 3: + case 4: draw_polygons(ras, solid, draft); break; + } + } + } + } + + + + + + + + + + + + + //------------------------------------------------------------------------ + virtual void on_draw() + { + scanline_rasterizer ras; + + pixfmt pixf(rbuf_window()); + base_renderer rb(pixf); + solid_renderer solid(rb); + draft_renderer draft(rb); + + rb.clear(agg::rgba(1, 1, 1)); + draw_scene(ras, solid, draft); + + ras.filling_rule(agg::fill_non_zero); + agg::render_ctrl(ras, m_sl, rb, m_type); + agg::render_ctrl(ras, m_sl, rb, m_width); + agg::render_ctrl(ras, m_sl, rb, m_benchmark); + agg::render_ctrl(ras, m_sl, rb, m_draw_nodes); + agg::render_ctrl(ras, m_sl, rb, m_draw_edges); + agg::render_ctrl(ras, m_sl, rb, m_draft); + agg::render_ctrl(ras, m_sl, rb, m_translucent); + } + + + + + virtual void on_ctrl_change() + { + if(m_benchmark.status()) + { + int i; + on_draw(); + update_window(); + + scanline_rasterizer ras; + + pixfmt pixf(rbuf_window()); + base_renderer rb(pixf); + solid_renderer solid(rb); + draft_renderer draft(rb); + + char buf[256]; + if(m_draft.status()) + { + start_timer(); + for(i = 0; i < 10; i++) + { + draw_scene(ras, solid, draft); + } + sprintf(buf, "%3.3f milliseconds", elapsed_time()); + } + else + { + double times[5]; + for(m_draw = 0; m_draw < 4; m_draw++) + { + start_timer(); + for(i = 0; i < 10; i++) + { + draw_scene(ras, solid, draft); + } + times[m_draw] = elapsed_time(); + } + m_draw = 3; + + times[4] = times[3]; + times[3] -= times[2]; + times[2] -= times[1]; + times[1] -= times[0]; + + FILE* fd = fopen(full_file_name("benchmark"), "a"); + fprintf(fd, "%10.3f %10.3f %10.3f %10.3f %10.3f\n", + times[0], times[1], times[2], times[3], times[4]); + fclose(fd); + + + sprintf(buf, " pipeline add_path sort render total\n" + "%10.3f %10.3f %10.3f %10.3f %10.3f", + times[0], times[1], times[2], times[3], times[4]); + } + message(buf); + + m_benchmark.status(false); + force_redraw(); + } + } +}; + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("AGG Example. Line Join"); + + if(app.init(600+100, 500+30, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/idea.cpp b/jni/desmume/src/android/agg/examples/idea.cpp new file mode 100755 index 0000000..73cb5d3 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/idea.cpp @@ -0,0 +1,362 @@ +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_trans_affine.h" +#include "agg_conv_stroke.h" +#include "agg_conv_transform.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "ctrl/agg_slider_ctrl.h" +#include "platform/agg_platform_support.h" + +#define AGG_BGR24 +//#define AGG_RGB24 +//#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + +enum flip_y_e { flip_y = false }; + + +struct path_attributes +{ + unsigned index; + agg::rgba8 fill_color; + agg::rgba8 stroke_color; + double stroke_width; + + path_attributes() {} + path_attributes(unsigned idx, + const agg::rgba8& fill, + const agg::rgba8& stroke, + double width) : + index(idx), + fill_color(fill), + stroke_color(stroke), + stroke_width(width) + { + } +}; + + + +static double g_poly_bulb[] = +{ + -6,-67, -6,-71, -7,-74, -8,-76, -10,-79, + -10,-82, -9,-84, -6,-86, -4,-87, -2,-86, + -1,-86, 1,-84, 2,-82, 2,-79, 0,-77, + -2,-73, -2,-71, -2,-69, -3,-67, -4,-65 +}; + +static double g_poly_beam1[] = +{ + -14,-84,-22,-85,-23,-87,-22,-88,-21,-88 +}; + +static double g_poly_beam2[] = +{ + -10,-92, -14,-96, -14,-98, -12,-99, -11,-97 +}; + +static double g_poly_beam3[] = +{ + -1,-92, -2,-98, 0,-100, 2,-100, 1,-98 +}; + +static double g_poly_beam4[] = +{ + 5,-89, 11,-94, 13,-93, 13,-92, 12,-91 +}; + + +static double g_poly_fig1[] = +{ + 1,-48,-3,-54,-7,-58,-12,-58,-17,-55,-20,-52,-21,-47, + -20,-40,-17,-33,-11,-28,-6,-26,-2,-25,2,-26,4,-28,5, + -33,5,-39,3,-44,12,-48,12,-50,12,-51,3,-46 +}; + + +static double g_poly_fig2[] = +{ + 11,-27,6,-23,4,-22,3,-19,5, + -16,6,-15,11,-17,19,-23,25,-30,32,-38,32,-41,32,-50,30,-64,32,-72, + 32,-75,31,-77,28,-78,26,-80,28,-87,27,-89,25,-88,24,-79,24,-76,23, + -75,20,-76,17,-76,17,-74,19,-73,22,-73,24,-71,26,-69,27,-64,28,-55, + 28,-47,28,-40,26,-38,20,-33,14,-30 +}; + + +static double g_poly_fig3[] = +{ + -6,-20,-9,-21,-15,-21,-20,-17, + -28,-8,-32,-1,-32,1,-30,6,-26,8,-20,10,-16,12,-14,14,-15,16,-18,20, + -22,20,-25,19,-27,20,-26,22,-23,23,-18,23,-14,22,-11,20,-10,17,-9,14, + -11,11,-16,9,-22,8,-26,5,-28,2,-27,-2,-23,-8,-19,-11,-12,-14,-6,-15, + -6,-18 +}; + + +static double g_poly_fig4[] = +{ + 11,-6,8,-16,5,-21,-1,-23,-7, + -22,-10,-17,-9,-10,-8,0,-8,10,-10,18,-11,22,-10,26,-7,28,-3,30,0,31, + 5,31,10,27,14,18,14,11,11,2 +}; + + +static double g_poly_fig5[] = +{ + 0,22,-5,21,-8,22,-9,26,-8,49, + -8,54,-10,64,-10,75,-9,81,-10,84,-16,89,-18,95,-18,97,-13,100,-12,99, + -12,95,-10,90,-8,87,-6,86,-4,83,-3,82,-5,80,-6,79,-7,74,-6,63,-3,52, + 0,42,1,31 +}; + + +static double g_poly_fig6[] = +{ + 12,31,12,24,8,21,3,21,2,24,3, + 30,5,40,8,47,10,56,11,64,11,71,10,76,8,77,8,79,10,81,13,82,17,82,26, + 84,28,87,32,86,33,81,32,80,25,79,17,79,14,79,13,76,14,72,14,64,13,55, + 12,44,12,34 +}; + + + +static path_attributes g_attr[3]; +static agg::path_storage g_path; +static unsigned g_npaths = 0; +static agg::filling_rule_e g_pflag = agg::fill_non_zero; +static agg::rasterizer_scanline_aa<> g_rasterizer; +static agg::scanline_p8 g_scanline; +static double g_angle = 0.0; + +#define AGG_POLY_SIZE(p) (sizeof(p) / (sizeof(*p) * 2)) + + + +struct trans_roundoff +{ + static void transform(double* x, double* y) + { + *x = floor(*x + 0.5); + *y = floor(*y + 0.5); + } +}; + + +class the_application : public agg::platform_support +{ + double m_dx; + double m_dy; + agg::cbox_ctrl m_rotate; + agg::cbox_ctrl m_even_odd; + agg::cbox_ctrl m_draft; + agg::cbox_ctrl m_roundoff; + agg::slider_ctrl m_angle_delta; + bool m_redraw_flag; + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_rotate(10, 3, "Rotate", !flip_y), + m_even_odd(60, 3, "Even-Odd", !flip_y), + m_draft(130, 3, "Draft", !flip_y), + m_roundoff(175, 3, "Roundoff", !flip_y), + m_angle_delta(10, 21, 250-10, 27, !flip_y), + m_redraw_flag(true) + { + m_angle_delta.label("Step=%4.3f degree"); + + g_attr[g_npaths++] = path_attributes(g_path.start_new_path(), + agg::rgba8(255, 255, 0), + agg::rgba8(0, 0, 0), + 1.0); + + g_path.concat_poly(g_poly_bulb, AGG_POLY_SIZE(g_poly_bulb), true); + + g_attr[g_npaths++] = path_attributes(g_path.start_new_path(), + agg::rgba8(255, 255, 200), + agg::rgba8(90, 0, 0), + 0.7); + + g_path.concat_poly(g_poly_beam1, AGG_POLY_SIZE(g_poly_beam1), true); + g_path.concat_poly(g_poly_beam2, AGG_POLY_SIZE(g_poly_beam2), true); + g_path.concat_poly(g_poly_beam3, AGG_POLY_SIZE(g_poly_beam3), true); + g_path.concat_poly(g_poly_beam4, AGG_POLY_SIZE(g_poly_beam4), true); + + g_attr[g_npaths++] = path_attributes(g_path.start_new_path(), + agg::rgba8(0, 0, 0), + agg::rgba8(0, 0, 0), + 0.0); + + g_path.concat_poly(g_poly_fig1, AGG_POLY_SIZE(g_poly_fig1), true); + g_path.concat_poly(g_poly_fig2, AGG_POLY_SIZE(g_poly_fig2), true); + g_path.concat_poly(g_poly_fig3, AGG_POLY_SIZE(g_poly_fig3), true); + g_path.concat_poly(g_poly_fig4, AGG_POLY_SIZE(g_poly_fig4), true); + g_path.concat_poly(g_poly_fig5, AGG_POLY_SIZE(g_poly_fig5), true); + g_path.concat_poly(g_poly_fig6, AGG_POLY_SIZE(g_poly_fig6), true); + + m_rotate.text_size(7); + m_even_odd.text_size(7); + m_draft.text_size(7); + m_roundoff.text_size(7); + add_ctrl(m_rotate); + add_ctrl(m_even_odd); + add_ctrl(m_draft); + add_ctrl(m_roundoff); + add_ctrl(m_angle_delta); + m_angle_delta.value(0.01); + } + + + virtual void on_init() + { + m_dx = rbuf_window().width(); + m_dy = rbuf_window().height(); + } + + virtual void on_resize(int, int) + { + m_redraw_flag = true; + } + + virtual void on_draw() + { + typedef agg::renderer_base ren_base; + + pixfmt pixf(rbuf_window()); + ren_base rbase(pixf); + trans_roundoff roundoff; + + if(m_redraw_flag) + { + g_rasterizer.gamma(agg::gamma_none()); + rbase.clear(agg::rgba8(255,255,255)); + g_rasterizer.filling_rule(agg::fill_non_zero); + agg::render_ctrl(g_rasterizer, g_scanline, rbase, m_rotate); + agg::render_ctrl(g_rasterizer, g_scanline, rbase, m_even_odd); + agg::render_ctrl(g_rasterizer, g_scanline, rbase, m_draft); + agg::render_ctrl(g_rasterizer, g_scanline, rbase, m_roundoff); + agg::render_ctrl(g_rasterizer, g_scanline, rbase, m_angle_delta); + m_redraw_flag = false; + } + else + { + rbase.copy_bar(0, + int(32.0 * rbuf_window().height() / m_dy), + rbuf_window().width(), + rbuf_window().height(), + agg::rgba8(255,255,255)); + } + + + if(m_draft.status()) + { + g_rasterizer.gamma(agg::gamma_threshold(0.4)); + } + + agg::trans_affine mtx; + mtx.reset(); + mtx *= agg::trans_affine_rotation(g_angle * agg::pi / 180.0); + mtx *= agg::trans_affine_translation(m_dx / 2, m_dy / 2 + 10); + mtx *= agg::trans_affine_scaling(rbuf_window().width() / m_dx, + rbuf_window().height() / m_dy); + + agg::conv_transform fill(g_path, mtx); + agg::conv_transform + < + agg::conv_transform, + trans_roundoff + > + fill_roundoff(fill, roundoff); + + agg::conv_stroke + < + agg::conv_transform + > + stroke(fill); + + agg::conv_stroke + < + agg::conv_transform + < + agg::conv_transform, + trans_roundoff + > + > + stroke_roundoff(fill_roundoff); + + g_pflag = m_even_odd.status() ? agg::fill_even_odd : agg::fill_non_zero; + + unsigned i; + for(i = 0; i < g_npaths; i++) + { + g_rasterizer.filling_rule(g_pflag); + if(m_roundoff.status()) g_rasterizer.add_path(fill_roundoff, g_attr[i].index); + else g_rasterizer.add_path(fill, g_attr[i].index); + + if(m_draft.status()) + { + agg::render_scanlines_bin_solid(g_rasterizer, g_scanline, rbase, g_attr[i].fill_color); + } + else + { + agg::render_scanlines_aa_solid(g_rasterizer, g_scanline, rbase, g_attr[i].fill_color); + } + + if(g_attr[i].stroke_width > 0.001) + { + stroke.width(g_attr[i].stroke_width * mtx.scale()); + stroke_roundoff.width(g_attr[i].stroke_width * mtx.scale()); + if(m_roundoff.status()) g_rasterizer.add_path(stroke_roundoff, g_attr[i].index); + else g_rasterizer.add_path(stroke, g_attr[i].index); + if(m_draft.status()) + { + agg::render_scanlines_bin_solid(g_rasterizer, g_scanline, rbase, g_attr[i].stroke_color); + } + else + { + agg::render_scanlines_aa_solid(g_rasterizer, g_scanline, rbase, g_attr[i].stroke_color); + } + } + } + } + + virtual void on_idle() + { + g_angle += m_angle_delta.value(); + if(g_angle > 360.0) g_angle -= 360.0; + force_redraw(); + } + + virtual void on_ctrl_change() + { + wait_mode(!m_rotate.status()); + m_redraw_flag = true; + } + +}; + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Idea"); + + if(app.init(250, 280, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/image1.cpp b/jni/desmume/src/android/agg/examples/image1.cpp new file mode 100755 index 0000000..37aef1e --- /dev/null +++ b/jni/desmume/src/android/agg/examples/image1.cpp @@ -0,0 +1,213 @@ +#include +#include +#include +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_ellipse.h" +#include "agg_trans_affine.h" +#include "agg_conv_transform.h" +#include "agg_span_image_filter_rgb.h" +#include "agg_span_image_filter_rgba.h" +#include "agg_span_image_filter_gray.h" +#include "agg_pixfmt_rgba.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_span_allocator.h" +#include "agg_span_interpolator_linear.h" +#include "agg_image_accessors.h" +#include "ctrl/agg_slider_ctrl.h" +#include "platform/agg_platform_support.h" + +enum flip_y_e { flip_y = true }; + +#define AGG_BGR24 +#include "pixel_formats.h" + + +class the_application : public agg::platform_support +{ + agg::slider_ctrl m_angle; + agg::slider_ctrl m_scale; + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_angle(5, 5, 300, 12, !flip_y), + m_scale(5, 5+15, 300, 12+15, !flip_y) + { + add_ctrl(m_angle); + add_ctrl(m_scale); + m_angle.label("Angle=%3.2f"); + m_scale.label("Scale=%3.2f"); + m_angle.range(-180.0, 180.0); + m_angle.value(0.0); + m_scale.range(0.1, 5.0); + m_scale.value(1.0); + } + + virtual ~the_application() + { + } + + virtual void on_draw() + { + typedef agg::renderer_base renderer_base; + typedef agg::renderer_base renderer_base_pre; + + pixfmt pixf(rbuf_window()); + pixfmt_pre pixf_pre(rbuf_window()); + renderer_base rb(pixf); + renderer_base_pre rb_pre(pixf_pre); + + rb.clear(agg::rgba(1.0, 1.0, 1.0)); + + agg::trans_affine src_mtx; + src_mtx *= agg::trans_affine_translation(-initial_width()/2 - 10, -initial_height()/2 - 20 - 10); + src_mtx *= agg::trans_affine_rotation(m_angle.value() * agg::pi / 180.0); + src_mtx *= agg::trans_affine_scaling(m_scale.value()); + src_mtx *= agg::trans_affine_translation(initial_width()/2, initial_height()/2 + 20); + src_mtx *= trans_affine_resizing(); + + agg::trans_affine img_mtx; + img_mtx *= agg::trans_affine_translation(-initial_width()/2 + 10, -initial_height()/2 + 20 + 10); + img_mtx *= agg::trans_affine_rotation(m_angle.value() * agg::pi / 180.0); + img_mtx *= agg::trans_affine_scaling(m_scale.value()); + img_mtx *= agg::trans_affine_translation(initial_width()/2, initial_height()/2 + 20); + img_mtx *= trans_affine_resizing(); + img_mtx.invert(); + + agg::span_allocator sa; + + typedef agg::span_interpolator_linear<> interpolator_type; + interpolator_type interpolator(img_mtx); + + typedef agg::image_accessor_clip img_source_type; + + pixfmt img_pixf(rbuf_img(0)); + img_source_type img_src(img_pixf, agg::rgba_pre(0, 0.4, 0, 0.5)); + +/* + // Version without filtering (nearest neighbor) + //------------------------------------------ + typedef agg::span_image_filter_rgb_nn span_gen_type; + span_gen_type sg(img_src, interpolator); + //------------------------------------------ +*/ + + // Version with "hardcoded" bilinear filter and without + // image_accessor (direct filter, the old variant) + //------------------------------------------ + typedef agg::span_image_filter_rgb_bilinear_clip span_gen_type; + span_gen_type sg(img_pixf, agg::rgba_pre(0, 0.4, 0, 0.5), interpolator); + //------------------------------------------ + +/* + // Version with arbitrary 2x2 filter + //------------------------------------------ + typedef agg::span_image_filter_rgb_2x2 span_gen_type; + agg::image_filter filter; + span_gen_type sg(img_src, interpolator, filter); + //------------------------------------------ +*/ +/* + // Version with arbitrary filter + //------------------------------------------ + typedef agg::span_image_filter_rgb span_gen_type; + agg::image_filter filter; + span_gen_type sg(img_src, interpolator, filter); + //------------------------------------------ +*/ + + agg::rasterizer_scanline_aa<> ras; + ras.clip_box(0, 0, width(), height()); + agg::scanline_u8 sl; + double r = initial_width(); + if(initial_height() - 60 < r) r = initial_height() - 60; + agg::ellipse ell(initial_width() / 2.0 + 10, + initial_height() / 2.0 + 20 + 10, + r / 2.0 + 16.0, + r / 2.0 + 16.0, 200); + + + agg::conv_transform tr(ell, src_mtx); + + ras.add_path(tr); + agg::render_scanlines_aa(ras, sl, rb_pre, sa, sg); + + agg::render_ctrl(ras, sl, rb, m_angle); + agg::render_ctrl(ras, sl, rb, m_scale); + } + +}; + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("Image Affine Transformations with filtering"); + + const char* img_name = "spheres"; + if(argc >= 2) img_name = argv[1]; + if(!app.load_img(0, img_name)) + { + char buf[256]; + if(strcmp(img_name, "spheres") == 0) + { + sprintf(buf, "File not found: %s%s. Download http://www.antigrain.com/%s%s\n" + "or copy it from another directory if available.", + img_name, app.img_ext(), img_name, app.img_ext()); + } + else + { + sprintf(buf, "File not found: %s%s", img_name, app.img_ext()); + } + app.message(buf); + return 1; + } + + if(app.init(app.rbuf_img(0).width() + 20, app.rbuf_img(0).height() + 40 + 20, agg::window_resize)) + { + +// Test the plain/premultiplied issue +//------------------- +//typedef agg::pixfmt_bgra32 pixfmt; +//typedef agg::renderer_base renderer_base; +//pixfmt pixf(app.rbuf_img(0)); +//renderer_base rb(pixf); +//for(unsigned i = 0; i < app.rbuf_img(0).height(); i += 2) +//{ +// // Fully transparent +// rb.copy_hline(0, i, app.rbuf_img(0).width(), agg::rgba(0, 0, 0, 0)); +// if(i + 1 < app.rbuf_img(0).height()) +// { +// // Fully opaque white +// rb.copy_hline(0, i + 1, app.rbuf_img(0).width(), agg::rgba(1, 1, 1, 1)); +// } +//} + + return app.run(); + } + return 0; +} + + + +/* +E:\agg23\examples\image1.cpp(111) : error C2664: + + '__thiscall agg::span_image_filter_gray_bilinear >::agg::span_image_filter_gray_bilinear >(class agg::span_interpolator_linear &,const class agg::row_ptr_cache &,const struct agg::gray8 &,struct agg::order_bgra &)' : + +cannot convert parameter 1 from + +'class agg::span_allocator' to +'class agg::span_interpolator_linear &' +*/ diff --git a/jni/desmume/src/android/agg/examples/image_alpha.cpp b/jni/desmume/src/android/agg/examples/image_alpha.cpp new file mode 100755 index 0000000..de16531 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/image_alpha.cpp @@ -0,0 +1,247 @@ +#include +#include +#include +#include "agg_ellipse.h" +#include "agg_trans_affine.h" +#include "agg_conv_transform.h" + +#include "agg_rendering_buffer.h" +#include "agg_pixfmt_rgb.h" +#include "agg_span_allocator.h" +#include "agg_span_image_filter_rgb.h" +#include "agg_image_accessors.h" +#include "agg_span_interpolator_linear.h" +#include "agg_span_converter.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_rasterizer_scanline_aa.h" + +#include "ctrl/agg_spline_ctrl.h" +#include "platform/agg_platform_support.h" + +enum flip_y_e { flip_y = true }; + + +namespace agg +{ + + //-------------------------------------------------------------------- + class span_conv_brightness_alpha_rgb8 + { + public: + typedef rgba8 color_type; + typedef int8u alpha_type; + + enum array_size_e + { + array_size = 256 * 3 + }; + + span_conv_brightness_alpha_rgb8(const alpha_type* alpha_array) : + m_alpha_array(alpha_array) + { + } + + void prepare() {} + void generate(color_type* span, int x, int y, unsigned len) const + { + do + { + span->a = m_alpha_array[span->r + span->g + span->b]; + ++span; + } + while(--len); + } + + private: + const alpha_type* m_alpha_array; + }; + +} + + + + +class the_application : public agg::platform_support +{ + agg::spline_ctrl m_alpha; + double m_x[50]; + double m_y[50]; + double m_rx[50]; + double m_ry[50]; + agg::rgba8 m_colors[50]; + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_alpha(2, 2, 200, 30, 6, !flip_y) + { + m_alpha.value(0, 1.0); + m_alpha.value(1, 1.0); + m_alpha.value(2, 1.0); + m_alpha.value(3, 0.5); + m_alpha.value(4, 0.5); + m_alpha.value(5, 1.0); + m_alpha.update_spline(); + add_ctrl(m_alpha); + } + + virtual ~the_application() + { + } + + + virtual void on_init() + { + unsigned i; + for(i = 0; i < 50; i++) + { + m_x[i] = rand() % int(width()); + m_y[i] = rand() % int(height()); + m_rx[i] = rand() % 60 + 10; + m_ry[i] = rand() % 60 + 10; + m_colors[i] = agg::rgba8(rand() & 0xFF, + rand() & 0xFF, + rand() & 0xFF, + rand() & 0xFF); + } + } + + + + virtual void on_draw() + { + typedef agg::pixfmt_bgr24 pixfmt; + typedef agg::renderer_base renderer_base; + + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + + rb.clear(agg::rgba(1.0, 1.0, 1.0)); + + agg::trans_affine src_mtx; + src_mtx *= agg::trans_affine_translation(-initial_width()/2, -initial_height()/2); + src_mtx *= agg::trans_affine_rotation(10.0 * agg::pi / 180.0); + src_mtx *= agg::trans_affine_translation(initial_width()/2, initial_height()/2); + src_mtx *= trans_affine_resizing(); + + agg::trans_affine img_mtx = src_mtx; + img_mtx.invert(); + + typedef agg::span_allocator span_alloc; + + unsigned i; + + unsigned char brightness_alpha_array[agg::span_conv_brightness_alpha_rgb8::array_size]; + for(i = 0; i < agg::span_conv_brightness_alpha_rgb8::array_size; i++) + { + brightness_alpha_array[i] = + agg::int8u(m_alpha.value(double(i) / + double(agg::span_conv_brightness_alpha_rgb8::array_size)) * 255.0); + } + agg::span_conv_brightness_alpha_rgb8 color_alpha(brightness_alpha_array); + + + + typedef agg::image_accessor_clip img_source_type; + typedef agg::span_interpolator_linear<> interpolator_type; + typedef agg::span_image_filter_rgb_bilinear span_gen; + typedef agg::span_converter span_conv; + + + span_alloc sa; + interpolator_type interpolator(img_mtx); + pixfmt img_pixf(rbuf_img(0)); + img_source_type img_src(img_pixf, agg::rgba(0,0,0,0)); + span_gen sg(img_src, interpolator); + span_conv sc(sg, color_alpha); + agg::ellipse ell; + agg::rasterizer_scanline_aa<> ras; + agg::scanline_u8 sl; + + for(i = 0; i < 50; i++) + { + ell.init(m_x[i], m_y[i], m_rx[i], m_ry[i], 50); + ras.add_path(ell); + agg::render_scanlines_aa_solid(ras, sl, rb, m_colors[i]); + } + + + ell.init(initial_width() / 2.0, + initial_height() / 2.0, + initial_width() / 1.9, + initial_height() / 1.9, 200); + + + agg::conv_transform tr(ell, src_mtx); + + + ras.add_path(tr); + agg::render_scanlines_aa(ras, sl, rb, sa, sc); + + agg::render_ctrl(ras, sl, rb, m_alpha); + } + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + if(key == ' ') + { + FILE* fd = fopen(full_file_name("alpha"), "w"); + + int i; + for(i = 0; i < agg::span_conv_brightness_alpha_rgb8::array_size; i++) + { + int alpha = + agg::int8u(m_alpha.value(double(i) / + double(agg::span_conv_brightness_alpha_rgb8::array_size)) * 255.0); + if(i % 32 == 0) fprintf(fd, "\n"); + fprintf(fd, "%3d, ", alpha); + } + + fclose(fd); + } + } + + + + +}; + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("Image Affine Transformations with Alpha-function"); + + const char* img_name = "spheres"; + if(argc >= 2) img_name = argv[1]; + if(!app.load_img(0, img_name)) + { + char buf[256]; + if(strcmp(img_name, "spheres") == 0) + { + sprintf(buf, "File not found: %s%s. Download http://www.antigrain.com/%s%s\n" + "or copy it from another directory if available.", + img_name, app.img_ext(), img_name, app.img_ext()); + } + else + { + sprintf(buf, "File not found: %s%s", img_name, app.img_ext()); + } + app.message(buf); + return 1; + } + + if(app.init(app.rbuf_img(0).width(), app.rbuf_img(0).height(), agg::window_resize)) + { + return app.run(); + } + return 0; +} + + diff --git a/jni/desmume/src/android/agg/examples/image_filters.cpp b/jni/desmume/src/android/agg/examples/image_filters.cpp new file mode 100755 index 0000000..deb6d51 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/image_filters.cpp @@ -0,0 +1,430 @@ +#include +#include +#include +#include +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_ellipse.h" +#include "agg_trans_affine.h" +#include "agg_conv_transform.h" +#include "agg_scanline_u.h" +#include "agg_scanline_p.h" +#include "agg_image_accessors.h" +#include "agg_renderer_scanline.h" +#include "agg_span_allocator.h" +#include "agg_span_interpolator_linear.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "platform/agg_platform_support.h" + + +#include "agg_pixfmt_rgb.h" +#include "agg_span_image_filter_rgb.h" +#define span_image_filter span_image_filter_rgb +#define span_image_filter_nn span_image_filter_rgb_nn +#define span_image_filter_bilinear span_image_filter_rgb_bilinear_clip +#define span_image_filter_2x2 span_image_filter_rgb_2x2 +#define pix_format agg::pix_format_bgr24 +typedef agg::pixfmt_bgr24 pixfmt; +typedef agg::pixfmt_bgr24_pre pixfmt_pre; +typedef pixfmt::color_type color_type; + +enum flip_y_e { flip_y = true }; + +// Uncomment this for more accurate timings. +// Well, it currently works well only on Windows, where there's +// high accuracy QueryPerformanceCounter is available. On Unix +// it uses regular clock() anyway, so, it won't work for short +// time periods and will give you totally wrong result (probably #INF). +#define AGG_ACCURATE_TIME + + +class the_application : public agg::platform_support +{ + typedef agg::renderer_base renderer_base; + typedef agg::renderer_base renderer_base_pre; + + agg::slider_ctrl m_radius; + agg::slider_ctrl m_step; + agg::rbox_ctrl m_filters; + agg::cbox_ctrl m_normalize; + agg::cbox_ctrl m_run; + agg::cbox_ctrl m_single_step; + agg::cbox_ctrl m_refresh; + + double m_cur_angle; + int m_cur_filter; + int m_num_steps; + double m_num_pix; + double m_time1; + double m_time2; + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_step (115, 5, 400, 11, !flip_y), + m_radius(115, 5+15, 400, 11+15, !flip_y), + m_filters(0.0, 0.0, 110.0, 210.0, !flip_y), + m_normalize (8.0, 215.0, "Normalize Filter", !flip_y), + m_run (8.0, 245.0, "RUN Test!", !flip_y), + m_single_step(8.0, 230.0, "Single Step", !flip_y), + m_refresh (8.0, 265.0, "Refresh", !flip_y), + m_cur_angle(0.0), + m_cur_filter(1), + m_num_steps(0), + m_num_pix(0.0), + m_time1(0), + m_time2(0) + { + add_ctrl(m_radius); + add_ctrl(m_step); + add_ctrl(m_filters); + add_ctrl(m_run); + add_ctrl(m_single_step); + add_ctrl(m_normalize); + add_ctrl(m_refresh); + m_run.text_size(7.5); + m_single_step.text_size(7.5); + m_normalize.text_size(7.5); + m_refresh.text_size(7.5); + m_normalize.status(true); + + m_radius.label("Filter Radius=%.3f"); + m_step.label("Step=%3.2f"); + m_radius.range(2.0, 8.0); + m_radius.value(4.0); + m_step.range(1.0, 10.0); + m_step.value(5.0); + + m_filters.add_item("simple (NN)"); + m_filters.add_item("bilinear"); + m_filters.add_item("bicubic"); + m_filters.add_item("spline16"); + m_filters.add_item("spline36"); + m_filters.add_item("hanning"); + m_filters.add_item("hamming"); + m_filters.add_item("hermite"); + m_filters.add_item("kaiser"); + m_filters.add_item("quadric"); + m_filters.add_item("catrom"); + m_filters.add_item("gaussian"); + m_filters.add_item("bessel"); + m_filters.add_item("mitchell"); + m_filters.add_item("sinc"); + m_filters.add_item("lanczos"); + m_filters.add_item("blackman"); + m_filters.cur_item(1); + + m_filters.border_width(0, 0); + m_filters.background_color(agg::rgba(0.0, 0.0, 0.0, 0.1)); + m_filters.text_size(6.0); + m_filters.text_thickness(0.85); + } + + virtual ~the_application() + { + } + + virtual void on_draw() + { + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + + rb.clear(agg::rgba(1.0, 1.0, 1.0)); + rb.copy_from(rbuf_img(0), 0, 110, 35); + + agg::rasterizer_scanline_aa<> ras; + agg::scanline_p8 sl; + + char buf[64]; + sprintf(buf, "NSteps=%d", m_num_steps); + agg::gsv_text t; + t.start_point(10.0, 295.0); + t.size(10.0); + t.text(buf); + + agg::conv_stroke pt(t); + pt.width(1.5); + + ras.add_path(pt); + agg::render_scanlines_aa_solid(ras, sl, rb, agg::rgba(0,0,0)); + + if(m_time1 != m_time2 && m_num_pix > 0.0) + { +#ifdef AGG_ACCURATE_TIME + sprintf(buf, "%3.2f Kpix/sec", m_num_pix / (m_time2 - m_time1)); +#else + sprintf(buf, "%3.2f Kpix/sec", m_num_pix / + 1000.0 / + (double(m_time2 - m_time1) / CLOCKS_PER_SEC)); +#endif + t.start_point(10.0, 310.0); + t.text(buf); + ras.add_path(pt); + agg::render_scanlines_aa_solid(ras, sl, rb, agg::rgba(0,0,0)); + } + + if(m_filters.cur_item() >= 14) + { + agg::render_ctrl(ras, sl, rb, m_radius); + } + agg::render_ctrl(ras, sl, rb, m_step); + agg::render_ctrl(ras, sl, rb, m_filters); + agg::render_ctrl(ras, sl, rb, m_run); + agg::render_ctrl(ras, sl, rb, m_normalize); + agg::render_ctrl(ras, sl, rb, m_single_step); + agg::render_ctrl(ras, sl, rb, m_refresh); + } + + + + void transform_image(double angle) + { + double width = rbuf_img(0).width(); + double height = rbuf_img(0).height(); + + pixfmt pixf(rbuf_img(0)); + pixfmt_pre pixf_pre(rbuf_img(0)); + renderer_base rb(pixf); + renderer_base_pre rb_pre(pixf_pre); + + rb.clear(agg::rgba(1.0, 1.0, 1.0)); + + agg::rasterizer_scanline_aa<> ras; + agg::scanline_u8 sl; + agg::span_allocator sa; + + agg::trans_affine src_mtx; + src_mtx *= agg::trans_affine_translation(-width/2.0, -height/2.0); + src_mtx *= agg::trans_affine_rotation(angle * agg::pi / 180.0); + src_mtx *= agg::trans_affine_translation(width/2.0, height/2.0); + + agg::trans_affine img_mtx = src_mtx; + img_mtx.invert(); + + double r = width; + if(height < r) r = height; + + r *= 0.5; + r -= 4.0; + agg::ellipse ell(width / 2.0, + height / 2.0, + r, r, 200); + agg::conv_transform tr(ell, src_mtx); + + m_num_pix += r * r * agg::pi; + + typedef agg::span_interpolator_linear<> interpolator_type; + interpolator_type interpolator(img_mtx); + + agg::image_filter_lut filter; + bool norm = m_normalize.status(); + + typedef agg::image_accessor_clip source_type; + pixfmt pixf_img(rbuf_img(1)); + source_type source(pixf_img, agg::rgba_pre(0,0,0,0)); + + switch(m_filters.cur_item()) + { + case 0: + { + typedef agg::span_image_filter_nn span_gen_type; + span_gen_type sg(source, interpolator); + ras.add_path(tr); + agg::render_scanlines_aa(ras, sl, rb_pre, sa, sg); + } + break; + + case 1: + { + typedef agg::span_image_filter_bilinear span_gen_type; + span_gen_type sg(pixf_img, agg::rgba_pre(0,0,0,0), interpolator); + ras.add_path(tr); + agg::render_scanlines_aa(ras, sl, rb_pre, sa, sg); + } + break; + + case 5: + case 6: + case 7: + { + switch(m_filters.cur_item()) + { + case 5: filter.calculate(agg::image_filter_hanning(), norm); break; + case 6: filter.calculate(agg::image_filter_hamming(), norm); break; + case 7: filter.calculate(agg::image_filter_hermite(), norm); break; + } + + typedef agg::span_image_filter_2x2 span_gen_type; + span_gen_type sg(source, interpolator, filter); + ras.add_path(tr); + agg::render_scanlines_aa(ras, sl, rb_pre, sa, sg); + } + break; + + case 2: + case 3: + case 4: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + { + switch(m_filters.cur_item()) + { + case 2: filter.calculate(agg::image_filter_bicubic(), norm); break; + case 3: filter.calculate(agg::image_filter_spline16(), norm); break; + case 4: filter.calculate(agg::image_filter_spline36(), norm); break; + case 8: filter.calculate(agg::image_filter_kaiser(), norm); break; + case 9: filter.calculate(agg::image_filter_quadric(), norm); break; + case 10: filter.calculate(agg::image_filter_catrom(), norm); break; + case 11: filter.calculate(agg::image_filter_gaussian(), norm); break; + case 12: filter.calculate(agg::image_filter_bessel(), norm); break; + case 13: filter.calculate(agg::image_filter_mitchell(), norm); break; + case 14: filter.calculate(agg::image_filter_sinc(m_radius.value()), norm); break; + case 15: filter.calculate(agg::image_filter_lanczos(m_radius.value()), norm); break; + case 16: filter.calculate(agg::image_filter_blackman(m_radius.value()), norm); break; + } + + typedef agg::span_image_filter span_gen_type; + span_gen_type sg(source, interpolator, filter); + ras.add_path(tr); + agg::render_scanlines_aa(ras, sl, rb_pre, sa, sg); + } + break; + } + + } + + + void on_ctrl_change() + { + if(m_single_step.status()) + { + m_cur_angle += m_step.value(); + copy_img_to_img(1, 0); + transform_image(m_step.value()); + m_num_steps++; + force_redraw(); + m_single_step.status(false); + } + + if(m_run.status()) + { +#ifdef AGG_ACCURATE_TIME + start_timer(); + m_time1 = m_time2 = elapsed_time(); +#else + m_time1 = m_time2 = clock(); +#endif + m_num_pix = 0.0; + wait_mode(false); + } + if(m_refresh.status() || m_filters.cur_item() != m_cur_filter) + { +#ifdef AGG_ACCURATE_TIME + start_timer(); + m_time1 = m_time2 = 0; +#else + m_time1 = m_time2 = clock(); +#endif + m_num_pix = 0.0; + m_cur_angle = 0.0; + copy_img_to_img(1, 2); + transform_image(0.0); + m_refresh.status(false); + m_cur_filter = m_filters.cur_item(); + m_num_steps = 0; + force_redraw(); + } + } + + void on_idle() + { + if(m_run.status()) + { + if(m_cur_angle < 360.0) + { + m_cur_angle += m_step.value(); + copy_img_to_img(1, 0); +#ifdef AGG_ACCURATE_TIME + start_timer(); +#endif + transform_image(m_step.value()); +#ifdef AGG_ACCURATE_TIME + m_time2 += elapsed_time(); +#endif + m_num_steps++; + } + else + { + m_cur_angle = 0.0; +#ifndef AGG_ACCURATE_TIME + m_time2 = clock(); +#endif + wait_mode(true); + m_run.status(false); + } + force_redraw(); + } + else + { + wait_mode(true); + } + } + + +}; + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("Image transformation filters comparison"); + + const char* img_name = "spheres"; + if(argc >= 2) img_name = argv[1]; + if(!app.load_img(0, img_name)) + { + char buf[256]; + if(strcmp(img_name, "spheres") == 0) + { + sprintf(buf, "File not found: %s%s. Download http://www.antigrain.com/%s%s\n" + "or copy it from another directory if available.", + img_name, app.img_ext(), img_name, app.img_ext()); + } + else + { + sprintf(buf, "File not found: %s%s", img_name, app.img_ext()); + } + app.message(buf); + return 1; + } + + app.copy_img_to_img(1, 0); + app.copy_img_to_img(2, 0); + app.transform_image(0.0); + + unsigned w = app.rbuf_img(0).width() + 110; + unsigned h = app.rbuf_img(0).height() + 40; + + if(w < 305) w = 305; + if(h < 325) h = 325; + + if(app.init(w, h, 0)) + { + return app.run(); + } + return 0; +} + + diff --git a/jni/desmume/src/android/agg/examples/image_filters2.cpp b/jni/desmume/src/android/agg/examples/image_filters2.cpp new file mode 100755 index 0000000..2d07100 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/image_filters2.cpp @@ -0,0 +1,279 @@ +#include +#include +#include +#include +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_ellipse.h" +#include "agg_trans_affine.h" +#include "agg_conv_transform.h" +#include "agg_scanline_u.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_pixfmt_rgba.h" +#include "agg_gamma_lut.h" +#include "agg_span_allocator.h" +#include "agg_span_image_filter_rgba.h" +#include "agg_span_interpolator_linear.h" +#include "agg_image_accessors.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "platform/agg_platform_support.h" + +enum flip_y_e { flip_y = true }; + +enum { l = 255 }; +static agg::int8u g_image[] = +{ + 0,l,0,l, 0,0,l,l, l,l,l,l, l,0,0,l, + l,0,0,l, 0,0,0,l, l,l,l,l, l,l,l,l, + l,l,l,l, l,l,l,l, 0,0,l,l, l,0,0,l, + 0,0,l,l, l,l,l,l, 0,0,0,l, 0,l,0,l +}; + +class the_application : public agg::platform_support +{ + typedef agg::pixfmt_bgra32 pixfmt; + typedef agg::pixfmt_bgra32_pre pixfmt_pre; + typedef agg::renderer_base renderer_base; + typedef agg::renderer_base renderer_base_pre; + + agg::slider_ctrl m_gamma; + agg::slider_ctrl m_radius; + agg::rbox_ctrl m_filters; + agg::cbox_ctrl m_normalize; + + double m_cur_angle; + int m_cur_filter; + int m_num_steps; + double m_num_pix; + clock_t m_time1; + clock_t m_time2; + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_gamma (115, 5, 500-5, 11, !flip_y), + m_radius(115, 5+15, 500-5, 11+15, !flip_y), + m_filters(0.0, 0.0, 110.0, 210.0, !flip_y), + m_normalize (8.0, 215.0, "Normalize Filter", !flip_y), + m_cur_angle(0.0), + m_cur_filter(1), + m_num_steps(0), + m_num_pix(0.0), + m_time1(0), + m_time2(0) + { + add_ctrl(m_gamma); + add_ctrl(m_radius); + add_ctrl(m_filters); + add_ctrl(m_normalize); + m_normalize.text_size(7.5); + m_normalize.status(true); + + m_radius.label("Filter Radius=%.3f"); + m_radius.range(2.0, 8.0); + m_radius.value(4.0); + + m_gamma.label("Gamma=%.3f"); + m_gamma.range(0.5, 3.0); + m_gamma.value(1.0); + + m_filters.add_item("simple (NN)"); + m_filters.add_item("bilinear"); + m_filters.add_item("bicubic"); + m_filters.add_item("spline16"); + m_filters.add_item("spline36"); + m_filters.add_item("hanning"); + m_filters.add_item("hamming"); + m_filters.add_item("hermite"); + m_filters.add_item("kaiser"); + m_filters.add_item("quadric"); + m_filters.add_item("catrom"); + m_filters.add_item("gaussian"); + m_filters.add_item("bessel"); + m_filters.add_item("mitchell"); + m_filters.add_item("sinc"); + m_filters.add_item("lanczos"); + m_filters.add_item("blackman"); + m_filters.cur_item(1); + + m_filters.border_width(0, 0); + m_filters.background_color(agg::rgba(0.0, 0.0, 0.0, 0.1)); + m_filters.text_size(6.0); + m_filters.text_thickness(0.85); + } + + virtual ~the_application() + { + } + + virtual void on_draw() + { + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + + rb.clear(agg::rgba(1.0, 1.0, 1.0)); + rb.copy_from(rbuf_img(0), 0, 110, 35); + + agg::rasterizer_scanline_aa<> ras; + agg::scanline_u8 sl; + + agg::rendering_buffer img_rbuf(g_image, 4, 4, 4*4); + + double para[] = { 200, 40, 200+300, 40, 200+300, 40+300, 200, 40+300 }; + agg::trans_affine img_mtx(para, 0,0,4,4); + + typedef agg::span_interpolator_linear<> interpolator_type; + interpolator_type interpolator(img_mtx); + agg::span_allocator sa; + + pixfmt img_pixf(img_rbuf); + typedef agg::image_accessor_clone img_source_type; + img_source_type source(img_pixf); + + ras.reset(); + ras.move_to_d(para[0], para[1]); + ras.line_to_d(para[2], para[3]); + ras.line_to_d(para[4], para[5]); + ras.line_to_d(para[6], para[7]); + + switch(m_filters.cur_item()) + { + case 0: + { + typedef agg::span_image_filter_rgba_nn span_gen_type; + + span_gen_type sg(source, interpolator); + agg::render_scanlines_aa(ras, sl, rb, sa, sg); + } + break; + + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + { + agg::image_filter_lut filter; + bool norm = m_normalize.status(); + switch(m_filters.cur_item()) + { + case 1: filter.calculate(agg::image_filter_bilinear(), norm); break; + case 2: filter.calculate(agg::image_filter_bicubic(), norm); break; + case 3: filter.calculate(agg::image_filter_spline16(), norm); break; + case 4: filter.calculate(agg::image_filter_spline36(), norm); break; + case 5: filter.calculate(agg::image_filter_hanning(), norm); break; + case 6: filter.calculate(agg::image_filter_hamming(), norm); break; + case 7: filter.calculate(agg::image_filter_hermite(), norm); break; + case 8: filter.calculate(agg::image_filter_kaiser(), norm); break; + case 9: filter.calculate(agg::image_filter_quadric(), norm); break; + case 10: filter.calculate(agg::image_filter_catrom(), norm); break; + case 11: filter.calculate(agg::image_filter_gaussian(), norm); break; + case 12: filter.calculate(agg::image_filter_bessel(), norm); break; + case 13: filter.calculate(agg::image_filter_mitchell(), norm); break; + case 14: filter.calculate(agg::image_filter_sinc(m_radius.value()), norm); break; + case 15: filter.calculate(agg::image_filter_lanczos(m_radius.value()), norm); break; + case 16: filter.calculate(agg::image_filter_blackman(m_radius.value()), norm); break; + } + + typedef agg::span_image_filter_rgba span_gen_type; + + span_gen_type sg(source, interpolator, filter); + agg::render_scanlines_aa(ras, sl, rb, sa, sg); + + agg::gamma_lut gamma(m_gamma.value()); + pixf.apply_gamma_inv(gamma); + + double x_start = 5.0; + double x_end = 195.0; + double y_start = 235.0; + double y_end = initial_height() - 5.0; + double x_center = (x_start + x_end) / 2; + + agg::path_storage p; + agg::conv_stroke stroke(p); + stroke.width(0.8); + + unsigned i; + for(i = 0; i <= 16; i++) + { + double x = x_start + (x_end - x_start) * i / 16.0; + p.remove_all(); + p.move_to(x+0.5, y_start); + p.line_to(x+0.5, y_end); + ras.add_path(stroke); + agg::render_scanlines_aa_solid(ras, sl, rb, + agg::rgba8(0, 0, 0, i == 8 ? 255 : 100)); + } + + double ys = y_start + (y_end - y_start) / 6.0; + p.remove_all(); + p.move_to(x_start, ys); + p.line_to(x_end, ys); + ras.add_path(stroke); + agg::render_scanlines_aa_solid(ras, sl, rb, agg::rgba8(0, 0, 0)); + + double radius = filter.radius(); + unsigned n = unsigned(radius * 256 * 2); + double dx = (x_end - x_start) * radius / 8.0; + double dy = y_end - ys; + + const agg::int16* weights = filter.weight_array(); + double xs = (x_end + x_start)/2.0 - (filter.diameter() * (x_end - x_start) / 32.0); + unsigned nn = filter.diameter() * 256; + p.remove_all(); + p.move_to(xs+0.5, ys + dy * weights[0] / agg::image_filter_scale); + for(i = 1; i < nn; i++) + { + p.line_to(xs + dx * i / n + 0.5, + ys + dy * weights[i] / agg::image_filter_scale); + } + ras.add_path(stroke); + agg::render_scanlines_aa_solid(ras, sl, rb, agg::rgba8(100, 0, 0)); + } + break; + } + + agg::render_ctrl(ras, sl, rb, m_gamma); + if(m_filters.cur_item() >= 14) + { + agg::render_ctrl(ras, sl, rb, m_radius); + } + agg::render_ctrl(ras, sl, rb, m_filters); + agg::render_ctrl(ras, sl, rb, m_normalize); + } + +}; + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgra32, flip_y); + app.caption("Image transformation filters comparison"); + + if(app.init(500, 340, 0)) + { + return app.run(); + } + return 0; +} + + diff --git a/jni/desmume/src/android/agg/examples/image_fltr_graph.cpp b/jni/desmume/src/android/agg/examples/image_fltr_graph.cpp new file mode 100755 index 0000000..96bdeb4 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/image_fltr_graph.cpp @@ -0,0 +1,314 @@ +#include +#include +#include +#include +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_ellipse.h" +#include "agg_trans_affine.h" +#include "agg_conv_transform.h" +#include "agg_conv_stroke.h" +#include "agg_pixfmt_rgb.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_image_filters.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "platform/agg_platform_support.h" + + +enum flip_y_e { flip_y = true }; + + +struct filter_base +{ + virtual double radius() const = 0; + virtual void set_radius(double r) = 0; + virtual double calc_weight(double x) const = 0; +}; + + +template struct image_filter_const_radius_adaptor : filter_base +{ + virtual double radius() const { return m_filter.radius(); } + virtual void set_radius(double r) {} + virtual double calc_weight(double x) const { return m_filter.calc_weight(fabs(x)); } + Filter m_filter; +}; + + +template struct image_filter_variable_radius_adaptor : filter_base +{ + virtual double radius() const { return m_filter.radius(); } + virtual double calc_weight(double x) const { return m_filter.calc_weight(fabs(x)); } + virtual void set_radius(double r) { m_filter = Filter(r); } + image_filter_variable_radius_adaptor() : m_filter(2.0) {} + Filter m_filter; +}; + + + +class the_application : public agg::platform_support +{ + agg::slider_ctrl m_radius; + agg::cbox_ctrl m_bilinear; + agg::cbox_ctrl m_bicubic; + agg::cbox_ctrl m_spline16; + agg::cbox_ctrl m_spline36; + agg::cbox_ctrl m_hanning; + agg::cbox_ctrl m_hamming; + agg::cbox_ctrl m_hermite; + agg::cbox_ctrl m_kaiser; + agg::cbox_ctrl m_quadric; + agg::cbox_ctrl m_catrom; + agg::cbox_ctrl m_gaussian; + agg::cbox_ctrl m_bessel; + agg::cbox_ctrl m_mitchell; + agg::cbox_ctrl m_sinc; + agg::cbox_ctrl m_lanczos; + agg::cbox_ctrl m_blackman; + agg::cbox_ctrl* m_filters[32]; + + image_filter_const_radius_adaptor m_filter_bilinear; + image_filter_const_radius_adaptor m_filter_bicubic; + image_filter_const_radius_adaptor m_filter_spline16; + image_filter_const_radius_adaptor m_filter_spline36; + image_filter_const_radius_adaptor m_filter_hanning; + image_filter_const_radius_adaptor m_filter_hamming; + image_filter_const_radius_adaptor m_filter_hermite; + image_filter_const_radius_adaptor m_filter_kaiser; + image_filter_const_radius_adaptor m_filter_quadric; + image_filter_const_radius_adaptor m_filter_catrom; + image_filter_const_radius_adaptor m_filter_gaussian; + image_filter_const_radius_adaptor m_filter_bessel; + image_filter_const_radius_adaptor m_filter_mitchell; + image_filter_variable_radius_adaptor m_filter_sinc; + image_filter_variable_radius_adaptor m_filter_lanczos; + image_filter_variable_radius_adaptor m_filter_blackman; + + filter_base* m_filter_func[32]; + unsigned m_num_filters; + + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_radius (5.0, 5.0, 780-5, 10.0, !flip_y), + m_bilinear (8.0, 30.0+15*0, "bilinear", !flip_y), + m_bicubic (8.0, 30.0+15*1, "bicubic ", !flip_y), + m_spline16 (8.0, 30.0+15*2, "spline16", !flip_y), + m_spline36 (8.0, 30.0+15*3, "spline36", !flip_y), + m_hanning (8.0, 30.0+15*4, "hanning ", !flip_y), + m_hamming (8.0, 30.0+15*5, "hamming ", !flip_y), + m_hermite (8.0, 30.0+15*6, "hermite ", !flip_y), + m_kaiser (8.0, 30.0+15*7, "kaiser ", !flip_y), + m_quadric (8.0, 30.0+15*8, "quadric ", !flip_y), + m_catrom (8.0, 30.0+15*9, "catrom ", !flip_y), + m_gaussian (8.0, 30.0+15*10, "gaussian", !flip_y), + m_bessel (8.0, 30.0+15*11, "bessel ", !flip_y), + m_mitchell (8.0, 30.0+15*12, "mitchell", !flip_y), + m_sinc (8.0, 30.0+15*13, "sinc ", !flip_y), + m_lanczos (8.0, 30.0+15*14, "lanczos ", !flip_y), + m_blackman (8.0, 30.0+15*15, "blackman", !flip_y), + m_num_filters(0) + { + m_filters[m_num_filters++] = &m_bilinear; + m_filters[m_num_filters++] = &m_bicubic; + m_filters[m_num_filters++] = &m_spline16; + m_filters[m_num_filters++] = &m_spline36; + m_filters[m_num_filters++] = &m_hanning; + m_filters[m_num_filters++] = &m_hamming; + m_filters[m_num_filters++] = &m_hermite; + m_filters[m_num_filters++] = &m_kaiser; + m_filters[m_num_filters++] = &m_quadric; + m_filters[m_num_filters++] = &m_catrom; + m_filters[m_num_filters++] = &m_gaussian; + m_filters[m_num_filters++] = &m_bessel; + m_filters[m_num_filters++] = &m_mitchell; + m_filters[m_num_filters++] = &m_sinc; + m_filters[m_num_filters++] = &m_lanczos; + m_filters[m_num_filters++] = &m_blackman; + + unsigned i = 0; + + m_filter_func[i++] = &m_filter_bilinear; + m_filter_func[i++] = &m_filter_bicubic; + m_filter_func[i++] = &m_filter_spline16; + m_filter_func[i++] = &m_filter_spline36; + m_filter_func[i++] = &m_filter_hanning; + m_filter_func[i++] = &m_filter_hamming; + m_filter_func[i++] = &m_filter_hermite; + m_filter_func[i++] = &m_filter_kaiser; + m_filter_func[i++] = &m_filter_quadric; + m_filter_func[i++] = &m_filter_catrom; + m_filter_func[i++] = &m_filter_gaussian; + m_filter_func[i++] = &m_filter_bessel; + m_filter_func[i++] = &m_filter_mitchell; + m_filter_func[i++] = &m_filter_sinc; + m_filter_func[i++] = &m_filter_lanczos; + m_filter_func[i++] = &m_filter_blackman; + for(i = 0; i < m_num_filters; i++) + { + add_ctrl(*m_filters[i]); + } + + m_radius.range(2.0, 8.0); + m_radius.value(4.0); + m_radius.label("Radius=%.3f"); + add_ctrl(m_radius); + } + + virtual ~the_application() + { + } + + virtual void on_draw() + { + typedef agg::pixfmt_bgr24 pixfmt; + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_solid; + + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + renderer_solid rs(rb); + + rb.clear(agg::rgba(1.0, 1.0, 1.0)); + agg::rasterizer_scanline_aa<> ras; + agg::scanline_p8 sl; + + double x_start = 125.0; + double x_end = initial_width() - 15.0; + double y_start = 10.0; + double y_end = initial_height() - 10.0; + double x_center = (x_start + x_end) / 2; + + unsigned i; + + agg::path_storage p; + agg::conv_stroke pl(p); + agg::conv_transform > tr(pl, trans_affine_resizing()); + + for(i = 0; i <= 16; i++) + { + double x = x_start + (x_end - x_start) * i / 16.0; + p.remove_all(); + p.move_to(x+0.5, y_start); + p.line_to(x+0.5, y_end); + ras.add_path(tr); + rs.color(agg::rgba8(0, 0, 0, i == 8 ? 255 : 100)); + agg::render_scanlines(ras, sl, rs); + } + + double ys = y_start + (y_end - y_start) / 6.0; + + p.remove_all(); + p.move_to(x_start, ys); + p.line_to(x_end, ys); + ras.add_path(tr); + rs.color(agg::rgba8(0, 0, 0)); + agg::render_scanlines(ras, sl, rs); + + + pl.width(1.0); + + for(i = 0; i < m_num_filters; i++) + { + if(m_filters[i]->status()) + { + m_filter_func[i]->set_radius(m_radius.value()); + unsigned j; + + double radius = m_filter_func[i]->radius(); + unsigned n = unsigned(radius * 256 * 2); + double dy = y_end - ys; + + double xs = (x_end + x_start)/2.0 - (radius * (x_end - x_start) / 16.0); + double dx = (x_end - x_start) * radius / 8.0; + + p.remove_all(); + p.move_to(xs+0.5, ys + dy * m_filter_func[i]->calc_weight(-radius)); + for(j = 1; j < n; j++) + { + p.line_to(xs + dx * j / n + 0.5, + ys + dy * m_filter_func[i]->calc_weight(j / 256.0 - radius)); + } + ras.add_path(tr); + rs.color(agg::rgba8(100, 0, 0)); + agg::render_scanlines(ras, sl, rs); + + p.remove_all(); + unsigned xint; + int ir = int(ceil(radius) + 0.1); + + for(xint = 0; xint < 256; xint++) + { + int xfract; + double sum = 0; + for(xfract = -ir; xfract < ir; xfract++) + { + double xf = xint/256.0 + xfract; + if(xf >= -radius || xf <= radius) + { + sum += m_filter_func[i]->calc_weight(xf); + } + } + + double x = x_center + ((-128.0 + xint) / 128.0) * radius * (x_end - x_start) / 16.0; + double y = ys + sum * 256 - 256; + + if(xint == 0) p.move_to(x, y); + else p.line_to(x, y); + } + ras.add_path(tr); + rs.color(agg::rgba8(0, 100, 0)); + agg::render_scanlines(ras, sl, rs); + + agg::image_filter_lut normalized(*m_filter_func[i]); + const agg::int16* weights = normalized.weight_array(); + + xs = (x_end + x_start)/2.0 - (normalized.diameter() * (x_end - x_start) / 32.0); + unsigned nn = normalized.diameter() * 256; + p.remove_all(); + p.move_to(xs+0.5, ys + dy * weights[0] / agg::image_filter_scale); + for(j = 1; j < nn; j++) + { + p.line_to(xs + dx * j / n + 0.5, + ys + dy * weights[j] / agg::image_filter_scale); + } + ras.add_path(tr); + rs.color(agg::rgba8(0, 0, 100, 255)); + agg::render_scanlines(ras, sl, rs); + } + } + + for(i = 0; i < m_num_filters; i++) + { + agg::render_ctrl(ras, sl, rb, *m_filters[i]); + } + if(m_sinc.status() || m_lanczos.status() || m_blackman.status()) + { + agg::render_ctrl(ras, sl, rb, m_radius); + } + } +}; + + + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("Image filters' shape comparison"); + + if(app.init(780, 300, agg::window_resize)) + { + return app.run(); + } + return 0; +} + + diff --git a/jni/desmume/src/android/agg/examples/image_perspective.cpp b/jni/desmume/src/android/agg/examples/image_perspective.cpp new file mode 100755 index 0000000..24fa7eb --- /dev/null +++ b/jni/desmume/src/android/agg/examples/image_perspective.cpp @@ -0,0 +1,330 @@ +#include +#include +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_path_storage.h" +#include "agg_conv_transform.h" +#include "agg_trans_affine.h" +#include "agg_trans_bilinear.h" +#include "agg_trans_perspective.h" +#include "agg_span_allocator.h" +#include "agg_span_interpolator_linear.h" +#include "agg_span_interpolator_trans.h" +#include "agg_span_subdiv_adaptor.h" +#include "agg_pixfmt_rgba.h" +#include "agg_image_accessors.h" +#include "agg_span_image_filter_rgba.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "platform/agg_platform_support.h" +#include "interactive_polygon.h" + + +enum flip_y_e { flip_y = true }; + +agg::rasterizer_scanline_aa<> g_rasterizer; +agg::scanline_u8 g_scanline; +double g_x1 = 0; +double g_y1 = 0; +double g_x2 = 0; +double g_y2 = 0; + + + +class the_application : public agg::platform_support +{ +public: + typedef agg::pixfmt_bgra32 pixfmt; + typedef pixfmt::color_type color_type; + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_solid; + + typedef agg::pixfmt_bgra32_pre pixfmt_pre; + typedef agg::renderer_base renderer_base_pre; + + agg::interactive_polygon m_quad; + agg::rbox_ctrl m_trans_type; + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_quad(4, 5.0), + m_trans_type(420, 5.0, 420+170.0, 70.0, !flip_y) + { + m_trans_type.add_item("Affine Parallelogram"); + m_trans_type.add_item("Bilinear"); + m_trans_type.add_item("Perspective"); + m_trans_type.cur_item(2); + add_ctrl(m_trans_type); + } + + + virtual void on_init() + { + double d = 0.0; + g_x1 = d; + g_y1 = d; + g_x2 = rbuf_img(0).width() - d; + g_y2 = rbuf_img(0).height() - d; + + m_quad.xn(0) = 100; + m_quad.yn(0) = 100; + m_quad.xn(1) = width() - 100; + m_quad.yn(1) = 100; + m_quad.xn(2) = width() - 100; + m_quad.yn(2) = height() - 100; + m_quad.xn(3) = 100; + m_quad.yn(3) = height() - 100; + } + + virtual void on_draw() + { + pixfmt pixf(rbuf_window()); + pixfmt_pre pixf_pre(rbuf_window()); + renderer_base rb(pixf); + renderer_base_pre rb_pre(pixf_pre); + + renderer_solid r(rb); + + + rb.clear(agg::rgba(1, 1, 1)); + + if(m_trans_type.cur_item() == 0) + { + // For the affine parallelogram transformations we + // calculate the 4-th (implicit) point of the parallelogram + m_quad.xn(3) = m_quad.xn(0) + (m_quad.xn(2) - m_quad.xn(1)); + m_quad.yn(3) = m_quad.yn(0) + (m_quad.yn(2) - m_quad.yn(1)); + } + + //-------------------------- + // Render the "quad" tool and controls + g_rasterizer.add_path(m_quad); + agg::render_scanlines_aa_solid(g_rasterizer, g_scanline, rb, + agg::rgba(0, 0.3, 0.5, 0.6)); + + // Prepare the polygon to rasterize. Here we need to fill + // the destination (transformed) polygon. + g_rasterizer.clip_box(0, 0, width(), height()); + g_rasterizer.reset(); + g_rasterizer.move_to_d(m_quad.xn(0), m_quad.yn(0)); + g_rasterizer.line_to_d(m_quad.xn(1), m_quad.yn(1)); + g_rasterizer.line_to_d(m_quad.xn(2), m_quad.yn(2)); + g_rasterizer.line_to_d(m_quad.xn(3), m_quad.yn(3)); + + agg::span_allocator sa; + agg::image_filter_bilinear filter_kernel; + agg::image_filter_lut filter(filter_kernel, false); + + pixfmt pixf_img(rbuf_img(0)); + + //typedef agg::image_accessor_wrap img_accessor_type; + //img_accessor_type ia(pixf_img); + + //typedef agg::image_accessor_clip img_accessor_type; + //img_accessor_type ia(pixf_img, agg::rgba(1,1,1)); + + typedef agg::image_accessor_clone img_accessor_type; + img_accessor_type ia(pixf_img); + + start_timer(); + switch(m_trans_type.cur_item()) + { + case 0: + { + // Note that we consruct an affine matrix that transforms + // a parallelogram to a rectangle, i.e., it's inverted. + // It's actually the same as: + // tr(g_x1, g_y1, g_x2, g_y2, m_triangle.polygon()); + // tr.invert(); + agg::trans_affine tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); + + // Also note that we can use the linear interpolator instead of + // arbitrary span_interpolator_trans. It works much faster, + // but the transformations must be linear and parellel. + typedef agg::span_interpolator_linear interpolator_type; + interpolator_type interpolator(tr); + + typedef agg::span_image_filter_rgba_nn span_gen_type; + span_gen_type sg(ia, interpolator); + agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); + break; + } + + case 1: + { + agg::trans_bilinear tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); + if(tr.is_valid()) + { + typedef agg::span_interpolator_linear interpolator_type; + interpolator_type interpolator(tr); + + typedef agg::span_image_filter_rgba_2x2 span_gen_type; + span_gen_type sg(ia, interpolator, filter); + agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); + } + break; + } + + case 2: + { + agg::trans_perspective tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); + if(tr.is_valid()) + { + // Subdivision and linear interpolation (faster, but less accurate) + //----------------------- + //typedef agg::span_interpolator_linear interpolator_type; + //typedef agg::span_subdiv_adaptor subdiv_adaptor_type; + //interpolator_type interpolator(tr); + //subdiv_adaptor_type subdiv_adaptor(interpolator); + // + //typedef agg::span_image_filter_rgba_2x2 span_gen_type; + //span_gen_type sg(ia, subdiv_adaptor, filter); + //----------------------- + + // Direct calculations of the coordinates + //----------------------- + typedef agg::span_interpolator_trans interpolator_type; + interpolator_type interpolator(tr); + typedef agg::span_image_filter_rgba_2x2 span_gen_type; + span_gen_type sg(ia, interpolator, filter); + //----------------------- + + agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); + } + break; + } + } + double tm = elapsed_time(); + + char buf[128]; + agg::gsv_text t; + t.size(10.0); + + agg::conv_stroke pt(t); + pt.width(1.5); + + sprintf(buf, "%3.2f ms", tm); + t.start_point(10.0, 10.0); + t.text(buf); + + g_rasterizer.add_path(pt); + agg::render_scanlines_aa_solid(g_rasterizer, g_scanline, rb, + agg::rgba(0,0,0)); + + //-------------------------- + agg::render_ctrl(g_rasterizer, g_scanline, rb, m_trans_type); + } + + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_quad.on_mouse_button_down(x, y)) + { + force_redraw(); + } + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_quad.on_mouse_move(x, y)) + { + force_redraw(); + } + } + if((flags & agg::mouse_left) == 0) + { + on_mouse_button_up(x, y, flags); + } + } + + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + if(m_quad.on_mouse_button_up(x, y)) + { + force_redraw(); + } + } + +}; + + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgra32, flip_y); + app.caption("AGG Example. Image Perspective Transformations"); + + const char* img_name = "spheres"; + if(argc >= 2) img_name = argv[1]; + if(!app.load_img(0, img_name)) + { + char buf[256]; + if(strcmp(img_name, "spheres") == 0) + { + sprintf(buf, "File not found: %s%s. Download http://www.antigrain.com/%s%s\n" + "or copy it from another directory if available.", + img_name, app.img_ext(), img_name, app.img_ext()); + } + else + { + sprintf(buf, "File not found: %s%s", img_name, app.img_ext()); + } + app.message(buf); + return 1; + } + +/* + // Testing the "black border" issue with alpha channel + //---------------------------------------- + the_application::pixfmt pixf(app.rbuf_img(0)); + the_application::renderer_base rbase(pixf); + rbase.clear(agg::rgba8(0,0,0,0)); + unsigned i; + for(i = 0; i < 50; i++) + { + agg::ellipse ell(rand() % rbase.width(), + rand() % rbase.height(), + rand() % 20 + 5, + rand() % 20 + 5, + 100); + g_rasterizer.add_path(ell); + agg::render_scanlines_aa_solid(g_rasterizer, g_scanline, rbase, + agg::rgba8((rand() & 0x7F) + 127, + (rand() & 0x7F) + 127, + (rand() & 0x7F) + 127, + 255)); + } +*/ + + if(app.init(600, 600, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + + + + + diff --git a/jni/desmume/src/android/agg/examples/image_resample.cpp b/jni/desmume/src/android/agg/examples/image_resample.cpp new file mode 100755 index 0000000..9543c4f --- /dev/null +++ b/jni/desmume/src/android/agg/examples/image_resample.cpp @@ -0,0 +1,396 @@ +#include +#include +#include +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_path_storage.h" +#include "agg_conv_transform.h" +#include "agg_trans_affine.h" +#include "agg_span_allocator.h" +#include "agg_span_interpolator_linear.h" +#include "agg_span_interpolator_trans.h" +#include "agg_span_interpolator_persp.h" +#include "agg_span_subdiv_adaptor.h" +#include "agg_image_accessors.h" +#include "agg_gamma_lut.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "ctrl/agg_slider_ctrl.h" +#include "platform/agg_platform_support.h" +#include "interactive_polygon.h" + + +int global_offset = 0; + + +enum flip_y_e { flip_y = true }; + +agg::rasterizer_scanline_aa<> g_rasterizer; +agg::scanline_u8 g_scanline; +double g_x1 = 0; +double g_y1 = 0; +double g_x2 = 0; +double g_y2 = 0; + +#include "agg_pixfmt_rgba.h" +#include "agg_span_image_filter_rgba.h" +#define pix_format agg::pix_format_bgra32 +typedef agg::pixfmt_bgra32 pixfmt; +typedef agg::pixfmt_bgra32_pre pixfmt_pre; +#define image_filter_2x2_type agg::span_image_filter_rgba_2x2 +#define image_resample_affine_type agg::span_image_resample_rgba_affine +#define image_resample_type agg::span_image_resample_rgba + +typedef pixfmt::color_type color_type; +typedef color_type::value_type value_type; +typedef agg::renderer_base renderer_base; +typedef agg::renderer_base renderer_base_pre; +typedef agg::renderer_scanline_aa_solid renderer_solid; +enum base_scale_e { base_shift = color_type::base_shift }; + +class the_application : public agg::platform_support +{ +public: + agg::gamma_lut m_gamma_lut; + agg::interactive_polygon m_quad; + agg::rbox_ctrl m_trans_type; + agg::slider_ctrl m_gamma; + agg::slider_ctrl m_blur; + double m_old_gamma; + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_gamma_lut(2.0), + m_quad(4, 5.0), + m_trans_type(400, 5.0, 430+170.0, 100.0, !flip_y), + m_gamma(5.0, 5.0+15*0, 400-5, 10.0+15*0, !flip_y), + m_blur (5.0, 5.0+15*1, 400-5, 10.0+15*1, !flip_y), + m_old_gamma(2.0) + { + m_trans_type.text_size(7); + m_trans_type.add_item("Affine No Resample"); + m_trans_type.add_item("Affine Resample"); + m_trans_type.add_item("Perspective No Resample LERP"); + m_trans_type.add_item("Perspective No Resample Exact"); + m_trans_type.add_item("Perspective Resample LERP"); + m_trans_type.add_item("Perspective Resample Exact"); + m_trans_type.cur_item(4); + add_ctrl(m_trans_type); + + m_gamma.range(0.5, 3.0); + m_gamma.value(2.0); + m_gamma.label("Gamma=%.3f"); + add_ctrl(m_gamma); + + m_blur.range(0.5, 5.0); + m_blur.value(1.0); + m_blur.label("Blur=%.3f"); + add_ctrl(m_blur); + } + + + virtual void on_init() + { + g_x1 = 0.0; + g_y1 = 0.0; + g_x2 = rbuf_img(0).width(); + g_y2 = rbuf_img(0).height(); + + double x1 = g_x1;// * 100.0; + double y1 = g_y1;// * 100.0; + double x2 = g_x2;// * 100.0; + double y2 = g_y2;// * 100.0; + + double dx = width() / 2.0 - (x2 - x1) / 2.0; + double dy = height() / 2.0 - (y2 - y1) / 2.0; + m_quad.xn(0) = floor(x1 + dx); + m_quad.yn(0) = floor(y1 + dy);// - 150; + m_quad.xn(1) = floor(x2 + dx); + m_quad.yn(1) = floor(y1 + dy);// - 110; + m_quad.xn(2) = floor(x2 + dx); + m_quad.yn(2) = floor(y2 + dy);// - 300; + m_quad.xn(3) = floor(x1 + dx); + m_quad.yn(3) = floor(y2 + dy);// - 200; + + pixfmt pixf(rbuf_img(0)); + pixf.apply_gamma_dir(m_gamma_lut); + } + + virtual void on_draw() + { + if(m_gamma.value() != m_old_gamma) + { + m_gamma_lut.gamma(m_gamma.value()); + load_img(0, "spheres"); + pixfmt pixf(rbuf_img(0)); + pixf.apply_gamma_dir(m_gamma_lut); + m_old_gamma = m_gamma.value(); + } + + pixfmt pixf(rbuf_window()); + pixfmt_pre pixf_pre(rbuf_window()); + renderer_base rb(pixf); + renderer_base_pre rb_pre(pixf_pre); + + renderer_solid r(rb); + + rb.clear(agg::rgba(1, 1, 1)); + + if(m_trans_type.cur_item() < 2) + { + // For the affine parallelogram transformations we + // calculate the 4-th (implicit) point of the parallelogram + m_quad.xn(3) = m_quad.xn(0) + (m_quad.xn(2) - m_quad.xn(1)); + m_quad.yn(3) = m_quad.yn(0) + (m_quad.yn(2) - m_quad.yn(1)); + } + + //-------------------------- + // Render the "quad" tool and controls + g_rasterizer.add_path(m_quad); + r.color(agg::rgba(0, 0.3, 0.5, 0.1)); + agg::render_scanlines(g_rasterizer, g_scanline, r); + + // Prepare the polygon to rasterize. Here we need to fill + // the destination (transformed) polygon. + g_rasterizer.clip_box(0, 0, width(), height()); + g_rasterizer.reset(); + int b = 0; + g_rasterizer.move_to_d(m_quad.xn(0)-b, m_quad.yn(0)-b); + g_rasterizer.line_to_d(m_quad.xn(1)+b, m_quad.yn(1)-b); + g_rasterizer.line_to_d(m_quad.xn(2)+b, m_quad.yn(2)+b); + g_rasterizer.line_to_d(m_quad.xn(3)-b, m_quad.yn(3)+b); + + typedef agg::span_allocator span_alloc_type; + span_alloc_type sa; + agg::image_filter_bilinear filter_kernel; + agg::image_filter_lut filter(filter_kernel, true); + + pixfmt pixf_img(rbuf_img(0)); + typedef agg::image_accessor_clone source_type; + source_type source(pixf_img); + + start_timer(); + switch(m_trans_type.cur_item()) + { + case 0: + { + agg::trans_affine tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); + + typedef agg::span_interpolator_linear interpolator_type; + interpolator_type interpolator(tr); + + typedef image_filter_2x2_type span_gen_type; + span_gen_type sg(source, interpolator, filter); + agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); + break; + } + + case 1: + { + agg::trans_affine tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); + + typedef agg::span_interpolator_linear interpolator_type; + typedef image_resample_affine_type span_gen_type; + + interpolator_type interpolator(tr); + span_gen_type sg(source, interpolator, filter); + sg.blur(m_blur.value()); + agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); + break; + } + + case 2: + { + agg::trans_perspective tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); + if(tr.is_valid()) + { + typedef agg::span_interpolator_linear_subdiv interpolator_type; + interpolator_type interpolator(tr); + + typedef image_filter_2x2_type span_gen_type; + span_gen_type sg(source, interpolator, filter); + agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); + } + break; + } + + case 3: + { + agg::trans_perspective tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); + if(tr.is_valid()) + { + typedef agg::span_interpolator_trans interpolator_type; + interpolator_type interpolator(tr); + + typedef image_filter_2x2_type span_gen_type; + span_gen_type sg(source, interpolator, filter); + agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); + } + break; + } + + case 4: + { + typedef agg::span_interpolator_persp_lerp<> interpolator_type; + typedef agg::span_subdiv_adaptor subdiv_adaptor_type; + + interpolator_type interpolator(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); + subdiv_adaptor_type subdiv_adaptor(interpolator); + + if(interpolator.is_valid()) + { + typedef image_resample_type span_gen_type; + span_gen_type sg(source, subdiv_adaptor, filter); + sg.blur(m_blur.value()); + agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); + } + break; + } + + case 5: + { + typedef agg::span_interpolator_persp_exact<> interpolator_type; + typedef agg::span_subdiv_adaptor subdiv_adaptor_type; + + interpolator_type interpolator(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); + subdiv_adaptor_type subdiv_adaptor(interpolator); + + if(interpolator.is_valid()) + { + typedef image_resample_type span_gen_type; + span_gen_type sg(source, subdiv_adaptor, filter); + sg.blur(m_blur.value()); + agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); + } + break; + } + } + double tm = elapsed_time(); + pixf.apply_gamma_inv(m_gamma_lut); + + char buf[64]; + agg::gsv_text t; + t.size(10.0); + + agg::conv_stroke pt(t); + pt.width(1.5); + + sprintf(buf, "%3.2f ms", tm); + t.start_point(10.0, 70.0); + t.text(buf); + + g_rasterizer.add_path(pt); + r.color(agg::rgba(0,0,0)); + agg::render_scanlines(g_rasterizer, g_scanline, r); + + //-------------------------- + agg::render_ctrl(g_rasterizer, g_scanline, rb, m_trans_type); + agg::render_ctrl(g_rasterizer, g_scanline, rb, m_gamma); + agg::render_ctrl(g_rasterizer, g_scanline, rb, m_blur); + } + + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_quad.on_mouse_button_down(x, y)) + { + force_redraw(); + } + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_quad.on_mouse_move(x, y)) + { + force_redraw(); + } + } + if((flags & agg::mouse_left) == 0) + { + on_mouse_button_up(x, y, flags); + } + } + + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + if(m_quad.on_mouse_button_up(x, y)) + { + force_redraw(); + } + } + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + if(key == ' ') + { + double cx = (m_quad.xn(0) + m_quad.xn(1) + m_quad.xn(2) + m_quad.xn(3)) / 4; + double cy = (m_quad.yn(0) + m_quad.yn(1) + m_quad.yn(2) + m_quad.yn(3)) / 4; + agg::trans_affine tr = agg::trans_affine_translation(-cx, -cy); + tr *= agg::trans_affine_rotation(agg::pi / 2.0); + tr *= agg::trans_affine_translation(cx, cy); + tr.transform(&m_quad.xn(0), &m_quad.yn(0)); + tr.transform(&m_quad.xn(1), &m_quad.yn(1)); + tr.transform(&m_quad.xn(2), &m_quad.yn(2)); + tr.transform(&m_quad.xn(3), &m_quad.yn(3)); + force_redraw(); + } + } + +}; + + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Image Transformations with Resampling"); + + const char* img_name = "spheres"; + if(argc >= 2) img_name = argv[1]; + if(!app.load_img(0, img_name)) + { + char buf[256]; + if(strcmp(img_name, "spheres") == 0) + { + sprintf(buf, "File not found: %s%s. Download http://www.antigrain.com/%s%s\n" + "or copy it from another directory if available.", + img_name, app.img_ext(), img_name, app.img_ext()); + } + else + { + sprintf(buf, "File not found: %s%s", img_name, app.img_ext()); + } + app.message(buf); + return 1; + } + + + if(app.init(600, 600, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + + + + + diff --git a/jni/desmume/src/android/agg/examples/image_transforms.cpp b/jni/desmume/src/android/agg/examples/image_transforms.cpp new file mode 100755 index 0000000..c7066b2 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/image_transforms.cpp @@ -0,0 +1,452 @@ +#include +#include +#include +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_path_storage.h" +#include "agg_trans_affine.h" +#include "agg_conv_transform.h" +#include "agg_pixfmt_rgba.h" +#include "agg_span_image_filter_rgba.h" +#include "agg_span_interpolator_linear.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_span_allocator.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "platform/agg_platform_support.h" + +enum flip_y_e { flip_y = true }; + + + + +class the_application : public agg::platform_support +{ + agg::slider_ctrl m_polygon_angle; + agg::slider_ctrl m_polygon_scale; + + agg::slider_ctrl m_image_angle; + agg::slider_ctrl m_image_scale; + + agg::cbox_ctrl m_rotate_polygon; + agg::cbox_ctrl m_rotate_image; + + agg::rbox_ctrl m_example; + + double m_image_center_x; + double m_image_center_y; + + double m_polygon_cx; + double m_polygon_cy; + + double m_image_cx; + double m_image_cy; + + double m_dx; + double m_dy; + + int m_flag; + + +public: + //------------------------------------------------------------------------ + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_polygon_angle(5, 5, 145, 11, !flip_y), + m_polygon_scale(5, 5+14, 145, 12+14, !flip_y), + m_image_angle (155, 5, 300, 12, !flip_y), + m_image_scale (155, 5+14, 300, 12+14, !flip_y), + m_rotate_polygon(5, 5+14+14, "Rotate Polygon", !flip_y), + m_rotate_image (5, 5+14+14+14, "Rotate Image", !flip_y), + m_example(-3.0, 14+14+14+14, -3.0, 14+14+14+14, !flip_y), + m_flag(0) + { + add_ctrl(m_polygon_angle); + add_ctrl(m_polygon_scale); + add_ctrl(m_image_angle); + add_ctrl(m_image_scale); + add_ctrl(m_rotate_polygon); + add_ctrl(m_rotate_image); + add_ctrl(m_example); + + m_polygon_angle.label("Polygon Angle=%3.2f"); + m_polygon_scale.label("Polygon Scale=%3.2f"); + m_polygon_angle.range(-180.0, 180.0); + m_polygon_scale.range(0.1, 5.0); + m_polygon_scale.value(1.0); + + m_image_angle.label("Image Angle=%3.2f"); + m_image_scale.label("Image Scale=%3.2f"); + m_image_angle.range(-180.0, 180.0); + m_image_scale.range(0.1, 5.0); + m_image_scale.value(1.0); + + m_example.add_item("0"); + m_example.add_item("1"); + m_example.add_item("2"); + m_example.add_item("3"); + m_example.add_item("4"); + m_example.add_item("5"); + m_example.add_item("6"); + m_example.cur_item(0); + } + + + //------------------------------------------------------------------------ + virtual ~the_application() + { + } + + + //------------------------------------------------------------------------ + virtual void on_init() + { + m_image_center_x = initial_width() / 2.0; + m_image_center_y = initial_height() / 2.0; + m_polygon_cx = m_image_cx = initial_width() / 2.0; + m_polygon_cy = m_image_cy = initial_height() / 2.0; + } + + + //------------------------------------------------------------------------ + void create_star(agg::path_storage& ps) + { + double r = initial_width(); + if(initial_height() < r) r = initial_height(); + + double r1 = r / 3 - 8.0; + double r2 = r1 / 1.45; + unsigned nr = 14; + + unsigned i; + for(i = 0; i < nr; i++) + { + double a = agg::pi * 2.0 * i / nr - agg::pi / 2.0; + double dx = cos(a); + double dy = sin(a); + + if(i & 1) + { + ps.line_to(m_polygon_cx + dx * r1, m_polygon_cy + dy * r1); + } + else + { + if(i) ps.line_to(m_polygon_cx + dx * r2, m_polygon_cy + dy * r2); + else ps.move_to(m_polygon_cx + dx * r2, m_polygon_cy + dy * r2); + } + } + } + + + + + + //------------------------------------------------------------------------ + virtual void on_draw() + { + typedef agg::pixfmt_bgra32 pixfmt; + typedef pixfmt::color_type color_type; + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_solid; + + pixfmt pixf(rbuf_window()); + pixfmt pixf_img(rbuf_img(0)); + renderer_base rb(pixf); + renderer_solid rs(rb); + + rb.clear(agg::rgba(1.0, 1.0, 1.0)); + + agg::trans_affine image_mtx; + agg::trans_affine polygon_mtx; + + polygon_mtx *= agg::trans_affine_translation(-m_polygon_cx, -m_polygon_cy); + polygon_mtx *= agg::trans_affine_rotation(m_polygon_angle.value() * agg::pi / 180.0); + polygon_mtx *= agg::trans_affine_scaling(m_polygon_scale.value()); + polygon_mtx *= agg::trans_affine_translation(m_polygon_cx, m_polygon_cy); + + + + switch(m_example.cur_item()) + { + default: + case 0: +// --------------(Example 0, Identity matrix) + break; + + + case 1: +// --------------(Example 1) + image_mtx *= agg::trans_affine_translation(-m_image_center_x, -m_image_center_y); + image_mtx *= agg::trans_affine_rotation(m_polygon_angle.value() * agg::pi / 180.0); + image_mtx *= agg::trans_affine_scaling(m_polygon_scale.value()); + image_mtx *= agg::trans_affine_translation(m_polygon_cx, m_polygon_cy); + image_mtx.invert(); + break; + + + + case 2: +// --------------(Example 2) + image_mtx *= agg::trans_affine_translation(-m_image_center_x, -m_image_center_y); + image_mtx *= agg::trans_affine_rotation(m_image_angle.value() * agg::pi / 180.0); + image_mtx *= agg::trans_affine_scaling(m_image_scale.value()); + image_mtx *= agg::trans_affine_translation(m_image_cx, m_image_cy); + image_mtx.invert(); + break; + + + + case 3: +// --------------(Example 3) + image_mtx *= agg::trans_affine_translation(-m_image_center_x, -m_image_center_y); + image_mtx *= agg::trans_affine_rotation(m_image_angle.value() * agg::pi / 180.0); + image_mtx *= agg::trans_affine_scaling(m_image_scale.value()); + image_mtx *= agg::trans_affine_translation(m_polygon_cx, m_polygon_cy); + image_mtx.invert(); + break; + + + + case 4: +// --------------(Example 4) + image_mtx *= agg::trans_affine_translation(-m_image_cx, -m_image_cy); + image_mtx *= agg::trans_affine_rotation(m_polygon_angle.value() * agg::pi / 180.0); + image_mtx *= agg::trans_affine_scaling(m_polygon_scale.value()); + image_mtx *= agg::trans_affine_translation(m_polygon_cx, m_polygon_cy); + image_mtx.invert(); + break; + + + + case 5: +// --------------(Example 5) + image_mtx *= agg::trans_affine_translation(-m_image_center_x, -m_image_center_y); + image_mtx *= agg::trans_affine_rotation(m_image_angle.value() * agg::pi / 180.0); + image_mtx *= agg::trans_affine_rotation(m_polygon_angle.value() * agg::pi / 180.0); + image_mtx *= agg::trans_affine_scaling(m_image_scale.value()); + image_mtx *= agg::trans_affine_scaling(m_polygon_scale.value()); + image_mtx *= agg::trans_affine_translation(m_image_cx, m_image_cy); + image_mtx.invert(); + break; + + + + case 6: +// --------------(Example 6) + image_mtx *= agg::trans_affine_translation(-m_image_cx, -m_image_cy); + image_mtx *= agg::trans_affine_rotation(m_image_angle.value() * agg::pi / 180.0); + image_mtx *= agg::trans_affine_scaling(m_image_scale.value()); + image_mtx *= agg::trans_affine_translation(m_image_cx, m_image_cy); + image_mtx.invert(); + break; + + } + + typedef agg::span_interpolator_linear<> interpolator_type; + interpolator_type interpolator(image_mtx); + agg::span_allocator sa; + + // "hardcoded" bilinear filter + //------------------------------------------ + typedef agg::span_image_filter_rgba_bilinear_clip span_gen_type; + span_gen_type sg(pixf_img, agg::rgba(1,1,1), interpolator); + //------------------------------------------ + + agg::rasterizer_scanline_aa<> ras; + agg::scanline_u8 sl; + agg::path_storage ps; + create_star(ps); + + agg::conv_transform tr(ps, polygon_mtx); + + ras.add_path(tr); + agg::render_scanlines_aa(ras, sl, rb, sa, sg); + + agg::ellipse e1(m_image_cx, m_image_cy, 5, 5, 20); + agg::ellipse e2(m_image_cx, m_image_cy, 2, 2, 20); + agg::conv_stroke c1(e1); + + rs.color(agg::rgba(0.7,0.8,0)); + ras.add_path(e1); + agg::render_scanlines(ras, sl, rs); + + rs.color(agg::rgba(0,0,0)); + ras.add_path(c1); + agg::render_scanlines(ras, sl, rs); + + ras.add_path(e2); + agg::render_scanlines(ras, sl, rs); + + agg::render_ctrl(ras, sl, rb, m_polygon_angle); + agg::render_ctrl(ras, sl, rb, m_polygon_scale); + agg::render_ctrl(ras, sl, rb, m_image_angle); + agg::render_ctrl(ras, sl, rb, m_image_scale); + agg::render_ctrl(ras, sl, rb, m_rotate_polygon); + agg::render_ctrl(ras, sl, rb, m_rotate_image); + agg::render_ctrl(ras, sl, rb, m_example); + } + + + + //------------------------------------------------------------------------ + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(sqrt((x - m_image_cx) * (x - m_image_cx) + + (y - m_image_cy) * (y - m_image_cy) ) < 5.0) + { + m_dx = x - m_image_cx; + m_dy = y - m_image_cy; + m_flag = 1; + } + else + { + agg::rasterizer_scanline_aa<> ras; + agg::trans_affine polygon_mtx; + + polygon_mtx *= agg::trans_affine_translation(-m_polygon_cx, -m_polygon_cy); + polygon_mtx *= agg::trans_affine_rotation(m_polygon_angle.value() * agg::pi / 180.0); + polygon_mtx *= agg::trans_affine_scaling(m_polygon_scale.value(), m_polygon_scale.value()); + polygon_mtx *= agg::trans_affine_translation(m_polygon_cx, m_polygon_cy); + + agg::path_storage ps; + create_star(ps); + + agg::conv_transform tr(ps, polygon_mtx); + ras.add_path(tr); + if(ras.hit_test(x, y)) + { + m_dx = x - m_polygon_cx; + m_dy = y - m_polygon_cy; + m_flag = 2; + } + } + } + } + + + //------------------------------------------------------------------------ + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_flag == 1) + { + m_image_cx = x - m_dx; + m_image_cy = y - m_dy; + force_redraw(); + } + + if(m_flag == 2) + { + m_polygon_cx = x - m_dx; + m_polygon_cy = y - m_dy; + force_redraw(); + } + } + else + { + on_mouse_button_up(x, y, flags); + } + } + + + + + + + //------------------------------------------------------------------------ + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + m_flag = 0; + } + + + + //------------------------------------------------------------------------ + virtual void on_ctrl_change() + { + if(m_rotate_polygon.status() || m_rotate_image.status()) + { + wait_mode(false); + } + else + { + wait_mode(true); + } + force_redraw(); + } + + //------------------------------------------------------------------------ + virtual void on_idle() + { + bool redraw = false; + if(m_rotate_polygon.status()) + { + m_polygon_angle.value(m_polygon_angle.value() + 0.5); + if(m_polygon_angle.value() >= 180.0) + { + m_polygon_angle.value(m_polygon_angle.value() - 360.0); + } + redraw = true; + } + + if(m_rotate_image.status()) + { + m_image_angle.value(m_image_angle.value() + 0.5); + if(m_image_angle.value() >= 180.0) + { + m_image_angle.value(m_image_angle.value() - 360.0); + } + redraw = true; + } + + if(redraw) force_redraw(); + + } + + +}; + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgra32, flip_y); + app.caption("Image Affine Transformations with filtering"); + + const char* img_name = "spheres"; + if(argc >= 2) img_name = argv[1]; + if(!app.load_img(0, img_name)) + { + char buf[256]; + if(strcmp(img_name, "spheres") == 0) + { + sprintf(buf, "File not found: %s%s. Download http://www.antigrain.com/%s%s\n" + "or copy it from another directory if available.", + img_name, app.img_ext(), img_name, app.img_ext()); + } + else + { + sprintf(buf, "File not found: %s%s", img_name, app.img_ext()); + } + app.message(buf); + return 1; + } + + if(app.init(app.rbuf_img(0).width(), + app.rbuf_img(0).height(), + 0)) + { + return app.run(); + } + return 0; +} + + diff --git a/jni/desmume/src/android/agg/examples/interactive_polygon.cpp b/jni/desmume/src/android/agg/examples/interactive_polygon.cpp new file mode 100755 index 0000000..ae2f695 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/interactive_polygon.cpp @@ -0,0 +1,284 @@ +#include "agg_basics.h" +#include "interactive_polygon.h" + +namespace agg +{ + interactive_polygon::interactive_polygon(unsigned np, double point_radius) : + m_polygon(np * 2), + m_num_points(np), + m_node(-1), + m_edge(-1), + m_vs(&m_polygon[0], m_num_points, false), + m_stroke(m_vs), + m_point_radius(point_radius), + m_status(0), + m_dx(0.0), + m_dy(0.0) + { + m_stroke.width(1.0); + } + + + void interactive_polygon::rewind(unsigned) + { + m_status = 0; + m_stroke.rewind(0); + } + + unsigned interactive_polygon::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + double r = m_point_radius; + if(m_status == 0) + { + cmd = m_stroke.vertex(x, y); + if(!is_stop(cmd)) return cmd; + if(m_node >= 0 && m_node == int(m_status)) r *= 1.2; + m_ellipse.init(xn(m_status), yn(m_status), r, r, 32); + ++m_status; + } + cmd = m_ellipse.vertex(x, y); + if(!is_stop(cmd)) return cmd; + if(m_status >= m_num_points) return path_cmd_stop; + if(m_node >= 0 && m_node == int(m_status)) r *= 1.2; + m_ellipse.init(xn(m_status), yn(m_status), r, r, 32); + ++m_status; + return m_ellipse.vertex(x, y); + } + + + bool interactive_polygon::check_edge(unsigned i, double x, double y) const + { + bool ret = false; + + unsigned n1 = i; + unsigned n2 = (i + m_num_points - 1) % m_num_points; + double x1 = xn(n1); + double y1 = yn(n1); + double x2 = xn(n2); + double y2 = yn(n2); + + double dx = x2 - x1; + double dy = y2 - y1; + + if(sqrt(dx*dx + dy*dy) > 0.0000001) + { + double x3 = x; + double y3 = y; + double x4 = x3 - dy; + double y4 = y3 + dx; + + double den = (y4-y3) * (x2-x1) - (x4-x3) * (y2-y1); + double u1 = ((x4-x3) * (y1-y3) - (y4-y3) * (x1-x3)) / den; + + double xi = x1 + u1 * (x2 - x1); + double yi = y1 + u1 * (y2 - y1); + + dx = xi - x; + dy = yi - y; + + if (u1 > 0.0 && u1 < 1.0 && sqrt(dx*dx + dy*dy) <= m_point_radius) + { + ret = true; + } + } + return ret; + } + + + + bool interactive_polygon::on_mouse_button_down(double x, double y) + { + unsigned i; + bool ret = false; + m_node = -1; + m_edge = -1; + for (i = 0; i < m_num_points; i++) + { + if(sqrt( (x-xn(i)) * (x-xn(i)) + (y-yn(i)) * (y-yn(i)) ) < m_point_radius) + { + m_dx = x - xn(i); + m_dy = y - yn(i); + m_node = int(i); + ret = true; + break; + } + } + + if(!ret) + { + for (i = 0; i < m_num_points; i++) + { + if(check_edge(i, x, y)) + { + m_dx = x; + m_dy = y; + m_edge = int(i); + ret = true; + break; + } + } + } + + if(!ret) + { + if(point_in_polygon(x, y)) + { + m_dx = x; + m_dy = y; + m_node = int(m_num_points); + ret = true; + } + } + return ret; + } + + + bool interactive_polygon::on_mouse_move(double x, double y) + { + bool ret = false; + double dx; + double dy; + if(m_node == int(m_num_points)) + { + dx = x - m_dx; + dy = y - m_dy; + unsigned i; + for(i = 0; i < m_num_points; i++) + { + xn(i) += dx; + yn(i) += dy; + } + m_dx = x; + m_dy = y; + ret = true; + } + else + { + if(m_edge >= 0) + { + unsigned n1 = m_edge; + unsigned n2 = (n1 + m_num_points - 1) % m_num_points; + dx = x - m_dx; + dy = y - m_dy; + xn(n1) += dx; + yn(n1) += dy; + xn(n2) += dx; + yn(n2) += dy; + m_dx = x; + m_dy = y; + ret = true; + } + else + { + if(m_node >= 0) + { + xn(m_node) = x - m_dx; + yn(m_node) = y - m_dy; + ret = true; + } + } + } + return ret; + } + + bool interactive_polygon::on_mouse_button_up(double x, double y) + { + bool ret = (m_node >= 0) || (m_edge >= 0); + m_node = -1; + m_edge = -1; + return ret; + } + + + + //======= Crossings Multiply algorithm of InsideTest ======================== + // + // By Eric Haines, 3D/Eye Inc, erich@eye.com + // + // This version is usually somewhat faster than the original published in + // Graphics Gems IV; by turning the division for testing the X axis crossing + // into a tricky multiplication test this part of the test became faster, + // which had the additional effect of making the test for "both to left or + // both to right" a bit slower for triangles than simply computing the + // intersection each time. The main increase is in triangle testing speed, + // which was about 15% faster; all other polygon complexities were pretty much + // the same as before. On machines where division is very expensive (not the + // case on the HP 9000 series on which I tested) this test should be much + // faster overall than the old code. Your mileage may (in fact, will) vary, + // depending on the machine and the test data, but in general I believe this + // code is both shorter and faster. This test was inspired by unpublished + // Graphics Gems submitted by Joseph Samosky and Mark Haigh-Hutchinson. + // Related work by Samosky is in: + // + // Samosky, Joseph, "SectionView: A system for interactively specifying and + // visualizing sections through three-dimensional medical image data", + // M.S. Thesis, Department of Electrical Engineering and Computer Science, + // Massachusetts Institute of Technology, 1993. + // + // Shoot a test ray along +X axis. The strategy is to compare vertex Y values + // to the testing point's Y and quickly discard edges which are entirely to one + // side of the test ray. Note that CONVEX and WINDING code can be added as + // for the CrossingsTest() code; it is left out here for clarity. + // + // Input 2D polygon _pgon_ with _numverts_ number of vertices and test point + // _point_, returns 1 if inside, 0 if outside. + bool interactive_polygon::point_in_polygon(double tx, double ty) const + { + if(m_num_points < 3) return false; + + unsigned j; + int yflag0, yflag1, inside_flag; + double vtx0, vty0, vtx1, vty1; + + vtx0 = xn(m_num_points - 1); + vty0 = yn(m_num_points - 1); + + // get test bit for above/below X axis + yflag0 = (vty0 >= ty); + + vtx1 = xn(0); + vty1 = yn(0); + + inside_flag = 0; + for (j = 1; j <= m_num_points; ++j) + { + yflag1 = (vty1 >= ty); + // Check if endpoints straddle (are on opposite sides) of X axis + // (i.e. the Y's differ); if so, +X ray could intersect this edge. + // The old test also checked whether the endpoints are both to the + // right or to the left of the test point. However, given the faster + // intersection point computation used below, this test was found to + // be a break-even proposition for most polygons and a loser for + // triangles (where 50% or more of the edges which survive this test + // will cross quadrants and so have to have the X intersection computed + // anyway). I credit Joseph Samosky with inspiring me to try dropping + // the "both left or both right" part of my code. + if (yflag0 != yflag1) + { + // Check intersection of pgon segment with +X ray. + // Note if >= point's X; if so, the ray hits it. + // The division operation is avoided for the ">=" test by checking + // the sign of the first vertex wrto the test point; idea inspired + // by Joseph Samosky's and Mark Haigh-Hutchinson's different + // polygon inclusion tests. + if ( ((vty1-ty) * (vtx0-vtx1) >= + (vtx1-tx) * (vty0-vty1)) == yflag1 ) + { + inside_flag ^= 1; + } + } + + // Move to the next pair of vertices, retaining info as possible. + yflag0 = yflag1; + vtx0 = vtx1; + vty0 = vty1; + + unsigned k = (j >= m_num_points) ? j - m_num_points : j; + vtx1 = xn(k); + vty1 = yn(k); + } + return inside_flag != 0; + } +} + diff --git a/jni/desmume/src/android/agg/examples/interactive_polygon.h b/jni/desmume/src/android/agg/examples/interactive_polygon.h new file mode 100755 index 0000000..8e4befe --- /dev/null +++ b/jni/desmume/src/android/agg/examples/interactive_polygon.h @@ -0,0 +1,111 @@ +#ifndef INTERACTIVE_POLYGON_INCLUDED +#define INTERACTIVE_POLYGON_INCLUDED + +#include "agg_array.h" +#include "agg_conv_stroke.h" +#include "agg_ellipse.h" + +namespace agg +{ + class simple_polygon_vertex_source + { + public: + simple_polygon_vertex_source(const double* polygon, unsigned np, + bool roundoff = false, + bool close = true) : + m_polygon(polygon), + m_num_points(np), + m_vertex(0), + m_roundoff(roundoff), + m_close(close) + { + } + + void close(bool f) { m_close = f; } + bool close() const { return m_close; } + + void rewind(unsigned) + { + m_vertex = 0; + } + + unsigned vertex(double* x, double* y) + { + if(m_vertex > m_num_points) return path_cmd_stop; + if(m_vertex == m_num_points) + { + ++m_vertex; + return path_cmd_end_poly | (m_close ? path_flags_close : 0); + } + *x = m_polygon[m_vertex * 2]; + *y = m_polygon[m_vertex * 2 + 1]; + if(m_roundoff) + { + *x = floor(*x) + 0.5; + *y = floor(*y) + 0.5; + } + ++m_vertex; + return (m_vertex == 1) ? path_cmd_move_to : path_cmd_line_to; + } + + private: + const double* m_polygon; + unsigned m_num_points; + unsigned m_vertex; + bool m_roundoff; + bool m_close; + }; + + + + + class interactive_polygon + { + public: + interactive_polygon(unsigned np, double point_radius); + + unsigned num_points() const { return m_num_points; } + double xn(unsigned n) const { return m_polygon[n * 2]; } + double yn(unsigned n) const { return m_polygon[n * 2 + 1]; } + double& xn(unsigned n) { return m_polygon[n * 2]; } + double& yn(unsigned n) { return m_polygon[n * 2 + 1]; } + + const double* polygon() const { return &m_polygon[0]; } + + int node() const { return m_node; } + void node(int n) { m_node = n; } + + void close(bool f) { m_vs.close(f); } + bool close() const { return m_vs.close(); } + + void rewind(unsigned); + unsigned vertex(double* x, double* y); + + bool on_mouse_button_down(double x, double y); + bool on_mouse_move(double x, double y); + bool on_mouse_button_up(double x, double y); + + + private: + bool check_edge(unsigned i, double x, double y) const; + bool point_in_polygon(double x, double y) const; + + + pod_array m_polygon; + unsigned m_num_points; + int m_node; + int m_edge; + simple_polygon_vertex_source m_vs; + conv_stroke m_stroke; + ellipse m_ellipse; + double m_point_radius; + unsigned m_status; + double m_dx; + double m_dy; + }; + + +} + +#endif + diff --git a/jni/desmume/src/android/agg/examples/line_patterns.cpp b/jni/desmume/src/android/agg/examples/line_patterns.cpp new file mode 100755 index 0000000..c907c50 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/line_patterns.cpp @@ -0,0 +1,329 @@ +#include +#include +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_conv_transform.h" +#include "agg_conv_stroke.h" +#include "agg_conv_clip_polyline.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_rasterizer_outline_aa.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_pattern_filters_rgba.h" +#include "agg_renderer_outline_aa.h" +#include "agg_renderer_outline_image.h" +#include "agg_pixfmt_rgb.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_bezier_ctrl.h" +#include "platform/agg_platform_support.h" + + +enum flip_y_e { flip_y = true }; + +typedef agg::pixfmt_bgr24 pixfmt; + + +static agg::int8u brightness_to_alpha[256 * 3] = +{ + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, + 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, + 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 251, 251, 251, 251, 251, + 251, 251, 251, 251, 250, 250, 250, 250, 250, 250, 250, 250, 249, 249, 249, 249, + 249, 249, 249, 248, 248, 248, 248, 248, 248, 248, 247, 247, 247, 247, 247, 246, + 246, 246, 246, 246, 246, 245, 245, 245, 245, 245, 244, 244, 244, 244, 243, 243, + 243, 243, 243, 242, 242, 242, 242, 241, 241, 241, 241, 240, 240, 240, 239, 239, + 239, 239, 238, 238, 238, 238, 237, 237, 237, 236, 236, 236, 235, 235, 235, 234, + 234, 234, 233, 233, 233, 232, 232, 232, 231, 231, 230, 230, 230, 229, 229, 229, + 228, 228, 227, 227, 227, 226, 226, 225, 225, 224, 224, 224, 223, 223, 222, 222, + 221, 221, 220, 220, 219, 219, 219, 218, 218, 217, 217, 216, 216, 215, 214, 214, + 213, 213, 212, 212, 211, 211, 210, 210, 209, 209, 208, 207, 207, 206, 206, 205, + 204, 204, 203, 203, 202, 201, 201, 200, 200, 199, 198, 198, 197, 196, 196, 195, + 194, 194, 193, 192, 192, 191, 190, 190, 189, 188, 188, 187, 186, 186, 185, 184, + 183, 183, 182, 181, 180, 180, 179, 178, 177, 177, 176, 175, 174, 174, 173, 172, + 171, 171, 170, 169, 168, 167, 166, 166, 165, 164, 163, 162, 162, 161, 160, 159, + 158, 157, 156, 156, 155, 154, 153, 152, 151, 150, 149, 148, 148, 147, 146, 145, + 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, + 128, 128, 127, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, + 112, 111, 110, 109, 108, 107, 106, 105, 104, 102, 101, 100, 99, 98, 97, 96, + 95, 94, 93, 91, 90, 89, 88, 87, 86, 85, 84, 82, 81, 80, 79, 78, + 77, 75, 74, 73, 72, 71, 70, 69, 67, 66, 65, 64, 63, 61, 60, 59, + 58, 57, 56, 54, 53, 52, 51, 50, 48, 47, 46, 45, 44, 42, 41, 40, + 39, 37, 36, 35, 34, 33, 31, 30, 29, 28, 27, 25, 24, 23, 22, 20, + 19, 18, 17, 15, 14, 13, 12, 11, 9, 8, 7, 6, 4, 3, 2, 1 +}; + + +class pattern_src_brightness_to_alpha_rgba8 +{ +public: + pattern_src_brightness_to_alpha_rgba8(agg::rendering_buffer& rb) : + m_rb(&rb), m_pf(*m_rb) {} + + unsigned width() const { return m_pf.width(); } + unsigned height() const { return m_pf.height(); } + agg::rgba8 pixel(int x, int y) const + { + agg::rgba8 c = m_pf.pixel(x, y); + c.a = brightness_to_alpha[c.r + c.g + c.b]; + return c; + } + +private: + agg::rendering_buffer* m_rb; + pixfmt m_pf; +}; + + +class the_application : public agg::platform_support +{ + agg::rgba8 m_ctrl_color; + agg::bezier_ctrl m_curve1; + agg::bezier_ctrl m_curve2; + agg::bezier_ctrl m_curve3; + agg::bezier_ctrl m_curve4; + agg::bezier_ctrl m_curve5; + agg::bezier_ctrl m_curve6; + agg::bezier_ctrl m_curve7; + agg::bezier_ctrl m_curve8; + agg::bezier_ctrl m_curve9; + agg::slider_ctrl m_scale_x; + agg::slider_ctrl m_start_x; + +public: + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_scanline; + typedef agg::rasterizer_scanline_aa<> rasterizer_scanline; + typedef agg::scanline_p8 scanline; + + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_ctrl_color(agg::rgba(0, 0.3, 0.5, 0.3)), + m_scale_x(5.0, 5.0, 240.0, 12.0, !flip_y), + m_start_x(250.0, 5.0, 495.0, 12.0, !flip_y) + { + m_curve1.line_color(m_ctrl_color); + m_curve2.line_color(m_ctrl_color); + m_curve3.line_color(m_ctrl_color); + m_curve4.line_color(m_ctrl_color); + m_curve5.line_color(m_ctrl_color); + m_curve6.line_color(m_ctrl_color); + m_curve7.line_color(m_ctrl_color); + m_curve8.line_color(m_ctrl_color); + m_curve9.line_color(m_ctrl_color); + + m_curve1.curve(64, 19, 14, 126, 118, 266, 19, 265); + m_curve2.curve(112, 113, 178, 32, 200, 132, 125, 438); + m_curve3.curve(401, 24, 326, 149, 285, 11, 177, 77); + m_curve4.curve(188, 427, 129, 295, 19, 283, 25, 410); + m_curve5.curve(451, 346, 302, 218, 265, 441, 459, 400); + m_curve6.curve(454, 198, 14, 13, 220, 291, 483, 283); + m_curve7.curve(301, 398, 355, 231, 209, 211, 170, 353); + m_curve8.curve(484, 101, 222, 33, 486, 435, 487, 138); + m_curve9.curve(143, 147, 11, 45, 83, 427, 132, 197); + + add_ctrl(m_curve1); + add_ctrl(m_curve2); + add_ctrl(m_curve3); + add_ctrl(m_curve4); + add_ctrl(m_curve5); + add_ctrl(m_curve6); + add_ctrl(m_curve7); + add_ctrl(m_curve8); + add_ctrl(m_curve9); + + m_curve1.no_transform(); + m_curve2.no_transform(); + m_curve3.no_transform(); + m_curve4.no_transform(); + m_curve5.no_transform(); + m_curve6.no_transform(); + m_curve7.no_transform(); + m_curve8.no_transform(); + m_curve9.no_transform(); + + m_scale_x.label("Scale X=%.2f"); + m_scale_x.range(0.2, 3.0); + m_scale_x.value(1.0); + m_scale_x.no_transform(); + add_ctrl(m_scale_x); + + m_start_x.label("Start X=%.2f"); + m_start_x.range(0.0, 10.0); + m_start_x.value(0.0); + m_start_x.no_transform(); + add_ctrl(m_start_x); + } + + + template + void draw_curve(Pattern& patt, + Rasterizer& ras, + Renderer& ren, + PatternSource& src, + VertexSource& vs) + { + patt.create(src); + ren.scale_x(m_scale_x.value()); + ren.start_x(m_start_x.value()); + ras.add_path(vs); + } + + + virtual void on_draw() + { + pixfmt pf(rbuf_window()); + renderer_base ren_base(pf); + ren_base.clear(agg::rgba(1.0, 1.0, 0.95)); + renderer_scanline ren(ren_base); + + rasterizer_scanline ras; + scanline sl; + + // Pattern source. Must have an interface: + // width() const + // height() const + // pixel(int x, int y) const + // Any agg::renderer_base<> or derived + // is good for the use as a source. + //----------------------------------- + pattern_src_brightness_to_alpha_rgba8 p1(rbuf_img(0)); + pattern_src_brightness_to_alpha_rgba8 p2(rbuf_img(1)); + pattern_src_brightness_to_alpha_rgba8 p3(rbuf_img(2)); + pattern_src_brightness_to_alpha_rgba8 p4(rbuf_img(3)); + pattern_src_brightness_to_alpha_rgba8 p5(rbuf_img(4)); + pattern_src_brightness_to_alpha_rgba8 p6(rbuf_img(5)); + pattern_src_brightness_to_alpha_rgba8 p7(rbuf_img(6)); + pattern_src_brightness_to_alpha_rgba8 p8(rbuf_img(7)); + pattern_src_brightness_to_alpha_rgba8 p9(rbuf_img(8)); + + agg::pattern_filter_bilinear_rgba8 fltr; // Filtering functor + + // agg::line_image_pattern is the main container for the patterns. It creates + // a copy of the patterns extended according to the needs of the filter. + // agg::line_image_pattern can operate with arbitrary image width, but if the + // width of the pattern is power of 2, it's better to use the modified + // version agg::line_image_pattern_pow2 because it works about 15-25 percent + // faster than agg::line_image_pattern (because of using simple masking instead + // of expensive '%' operation). + typedef agg::line_image_pattern pattern_type; + typedef agg::renderer_base base_ren_type; + typedef agg::renderer_outline_image renderer_type; + typedef agg::rasterizer_outline_aa rasterizer_type; + + //-- Create with specifying the source + //pattern_type patt(fltr, src); + + //-- Create uninitialized and set the source + pattern_type patt(fltr); + renderer_type ren_img(ren_base, patt); + rasterizer_type ras_img(ren_img); + + draw_curve(patt, ras_img, ren_img, p1, m_curve1.curve()); + draw_curve(patt, ras_img, ren_img, p2, m_curve2.curve()); + draw_curve(patt, ras_img, ren_img, p3, m_curve3.curve()); + draw_curve(patt, ras_img, ren_img, p4, m_curve4.curve()); + draw_curve(patt, ras_img, ren_img, p5, m_curve5.curve()); + draw_curve(patt, ras_img, ren_img, p6, m_curve6.curve()); + draw_curve(patt, ras_img, ren_img, p7, m_curve7.curve()); + draw_curve(patt, ras_img, ren_img, p8, m_curve8.curve()); + draw_curve(patt, ras_img, ren_img, p9, m_curve9.curve()); + + agg::render_ctrl(ras, sl, ren_base, m_curve1); + agg::render_ctrl(ras, sl, ren_base, m_curve2); + agg::render_ctrl(ras, sl, ren_base, m_curve3); + agg::render_ctrl(ras, sl, ren_base, m_curve4); + agg::render_ctrl(ras, sl, ren_base, m_curve5); + agg::render_ctrl(ras, sl, ren_base, m_curve6); + agg::render_ctrl(ras, sl, ren_base, m_curve7); + agg::render_ctrl(ras, sl, ren_base, m_curve8); + agg::render_ctrl(ras, sl, ren_base, m_curve9); + + agg::render_ctrl(ras, sl, ren_base, m_scale_x); + agg::render_ctrl(ras, sl, ren_base, m_start_x); + } + + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + if(key == ' ') + { + FILE* fd = fopen(full_file_name("coord"), "w"); + fprintf(fd, "%.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f, %.0f", + m_curve1.x1(), m_curve1.y1(), + m_curve1.x2(), m_curve1.y2(), + m_curve1.x3(), m_curve1.y3(), + m_curve1.x4(), m_curve1.y4()); + fclose(fd); + } + } + + virtual void on_ctrl_change() + { + } +}; + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("AGG Example. Drawing Lines with Image Patterns"); + + if(!app.load_img(0, "1") || + !app.load_img(1, "2") || + !app.load_img(2, "3") || + !app.load_img(3, "4") || + !app.load_img(4, "5") || + !app.load_img(5, "6") || + !app.load_img(6, "7") || + !app.load_img(7, "8") || + !app.load_img(8, "9")) + { + char buf[256]; + sprintf(buf, "There must be files 1%s...9%s\n" + "Download and unzip:\n" + "http://www.antigrain.com/line_patterns.bmp.zip\n" + "or\n" + "http://www.antigrain.com/line_patterns.ppm.tar.gz\n", + app.img_ext(), app.img_ext()); + app.message(buf); + return 1; + } + + if(app.init(500, 450, agg::window_resize)) + { + return app.run(); + } + + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/line_patterns_clip.cpp b/jni/desmume/src/android/agg/examples/line_patterns_clip.cpp new file mode 100755 index 0000000..dfbd3d7 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/line_patterns_clip.cpp @@ -0,0 +1,348 @@ +#include +#include +#include +#include "agg_math.h" +#include "agg_rendering_buffer.h" +#include "agg_conv_transform.h" +#include "agg_conv_stroke.h" +#include "agg_conv_clip_polyline.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_rasterizer_outline_aa.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_pattern_filters_rgba.h" +#include "agg_renderer_outline_aa.h" +#include "agg_renderer_outline_image.h" +#include "agg_path_storage.h" +#include "agg_pixfmt_rgb.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_bezier_ctrl.h" +#include "platform/agg_platform_support.h" + + +enum flip_y_e { flip_y = true }; + +typedef agg::pixfmt_bgr24 pixfmt; + + +static agg::int8u brightness_to_alpha[256 * 3] = +{ + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, + 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252, + 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 251, 251, 251, 251, 251, + 251, 251, 251, 251, 250, 250, 250, 250, 250, 250, 250, 250, 249, 249, 249, 249, + 249, 249, 249, 248, 248, 248, 248, 248, 248, 248, 247, 247, 247, 247, 247, 246, + 246, 246, 246, 246, 246, 245, 245, 245, 245, 245, 244, 244, 244, 244, 243, 243, + 243, 243, 243, 242, 242, 242, 242, 241, 241, 241, 241, 240, 240, 240, 239, 239, + 239, 239, 238, 238, 238, 238, 237, 237, 237, 236, 236, 236, 235, 235, 235, 234, + 234, 234, 233, 233, 233, 232, 232, 232, 231, 231, 230, 230, 230, 229, 229, 229, + 228, 228, 227, 227, 227, 226, 226, 225, 225, 224, 224, 224, 223, 223, 222, 222, + 221, 221, 220, 220, 219, 219, 219, 218, 218, 217, 217, 216, 216, 215, 214, 214, + 213, 213, 212, 212, 211, 211, 210, 210, 209, 209, 208, 207, 207, 206, 206, 205, + 204, 204, 203, 203, 202, 201, 201, 200, 200, 199, 198, 198, 197, 196, 196, 195, + 194, 194, 193, 192, 192, 191, 190, 190, 189, 188, 188, 187, 186, 186, 185, 184, + 183, 183, 182, 181, 180, 180, 179, 178, 177, 177, 176, 175, 174, 174, 173, 172, + 171, 171, 170, 169, 168, 167, 166, 166, 165, 164, 163, 162, 162, 161, 160, 159, + 158, 157, 156, 156, 155, 154, 153, 152, 151, 150, 149, 148, 148, 147, 146, 145, + 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, + 128, 128, 127, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, + 112, 111, 110, 109, 108, 107, 106, 105, 104, 102, 101, 100, 99, 98, 97, 96, + 95, 94, 93, 91, 90, 89, 88, 87, 86, 85, 84, 82, 81, 80, 79, 78, + 77, 75, 74, 73, 72, 71, 70, 69, 67, 66, 65, 64, 63, 61, 60, 59, + 58, 57, 56, 54, 53, 52, 51, 50, 48, 47, 46, 45, 44, 42, 41, 40, + 39, 37, 36, 35, 34, 33, 31, 30, 29, 28, 27, 25, 24, 23, 22, 20, + 19, 18, 17, 15, 14, 13, 12, 11, 9, 8, 7, 6, 4, 3, 2, 1 +}; + + +class pattern_src_brightness_to_alpha_rgba8 +{ +public: + pattern_src_brightness_to_alpha_rgba8(agg::rendering_buffer& rb) : + m_rb(&rb), m_pf(*m_rb) {} + + unsigned width() const { return m_pf.width(); } + unsigned height() const { return m_pf.height(); } + agg::rgba8 pixel(int x, int y) const + { + agg::rgba8 c = m_pf.pixel(x, y); + c.a = brightness_to_alpha[c.r + c.g + c.b]; + return c; + } + +private: + agg::rendering_buffer* m_rb; + pixfmt m_pf; +}; + + +class the_application : public agg::platform_support +{ + agg::rgba8 m_ctrl_color; + agg::polygon_ctrl m_line1; + agg::slider_ctrl m_scale_x; + agg::slider_ctrl m_start_x; + agg::trans_affine m_scale; + +public: + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_scanline; + typedef agg::rasterizer_scanline_aa rasterizer_scanline; + typedef agg::scanline_p8 scanline; + + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_ctrl_color(agg::rgba(0, 0.3, 0.5, 0.3)), + m_line1(5), + m_scale_x(5.0, 5.0, 240.0, 12.0, !flip_y), + m_start_x(250.0, 5.0, 495.0, 12.0, !flip_y) + { + m_line1.line_color(m_ctrl_color); + m_line1.xn(0) = 20; + m_line1.yn(0) = 20; + m_line1.xn(1) = 500-20; + m_line1.yn(1) = 500-20; + m_line1.xn(2) = 500-60; + m_line1.yn(2) = 20; + m_line1.xn(3) = 40; + m_line1.yn(3) = 500-40; + m_line1.xn(4) = 100; + m_line1.yn(4) = 300; + m_line1.close(false); + + add_ctrl(m_line1); + m_line1.transform(m_scale); + + m_scale_x.label("Scale X=%.2f"); + m_scale_x.range(0.2, 3.0); + m_scale_x.value(1.0); + add_ctrl(m_scale_x); + m_scale_x.no_transform(); + + m_start_x.label("Start X=%.2f"); + m_start_x.range(0.0, 10.0); + m_start_x.value(0.0); + add_ctrl(m_start_x); + m_start_x.no_transform(); + } + + + template + void draw_polyline(Rasterizer& ras, + Renderer& ren, + const double* polyline, + int num_points) + { + agg::poly_plain_adaptor vs(polyline, num_points, m_line1.close()); + agg::conv_transform > trans(vs, m_scale); + ras.add_path(trans); + } + + + virtual void on_draw() + { + pixfmt pf(rbuf_window()); + renderer_base ren_base(pf); + ren_base.clear(agg::rgba(0.5, 0.75, 0.85)); + renderer_scanline ren(ren_base); + + rasterizer_scanline ras; + scanline sl; + + ras.clip_box(0, 0, width(), height()); + + // Pattern source. Must have an interface: + // width() const + // height() const + // pixel(int x, int y) const + // Any agg::renderer_base<> or derived + // is good for the use as a source. + //----------------------------------- + pattern_src_brightness_to_alpha_rgba8 p1(rbuf_img(0)); + + agg::pattern_filter_bilinear_rgba8 fltr; // Filtering functor + + // agg::line_image_pattern is the main container for the patterns. It creates + // a copy of the patterns extended according to the needs of the filter. + // agg::line_image_pattern can operate with arbitrary image width, but if the + // width of the pattern is power of 2, it's better to use the modified + // version agg::line_image_pattern_pow2 because it works about 15-25 percent + // faster than agg::line_image_pattern (because of using simple masking instead + // of expensive '%' operation). + typedef agg::line_image_pattern pattern_type; + typedef agg::renderer_base base_ren_type; + typedef agg::renderer_outline_image renderer_img_type; + typedef agg::rasterizer_outline_aa rasterizer_img_type; + + typedef agg::renderer_outline_aa renderer_line_type; + typedef agg::rasterizer_outline_aa rasterizer_line_type; + + + //-- Create with specifying the source + //pattern_type patt(fltr, src); + + //-- Create uninitialized and set the source + pattern_type patt(fltr); + patt.create(p1); + renderer_img_type ren_img(ren_base, patt); + rasterizer_img_type ras_img(ren_img); + + + //-- create uninitialized and set parameters + agg::line_profile_aa profile; + profile.smoother_width(10.0); //optional + profile.width(8.0); //mandatory! + renderer_line_type ren_line(ren_base, profile); + ren_line.color(agg::rgba8(0,0,127)); //mandatory! + rasterizer_line_type ras_line(ren_line); + ras_line.round_cap(true); //optional + //ras_line.line_join(agg::outline_no_join); //optional + + // Calculate the dilation value so that, the line caps were + // drawn correctly. + //--------------- + double w2 = 9.0;//p1.height() / 2 + 2; + + + // Set the clip box a bit bigger than you expect. You need it + // to draw the clipped line caps correctly. The correct result + // is achieved with raster clipping. + //------------------------ + ren_img.scale_x(m_scale_x.value()); + ren_img.start_x(m_start_x.value()); + ren_img.clip_box (50-w2, 50-w2, width()-50+w2, height()-50+w2); + ren_line.clip_box(50-w2, 50-w2, width()-50+w2, height()-50+w2); + + // First, draw polyline without raster clipping just to show the idea + //------------------------ + draw_polyline(ras_line, ren_line, m_line1.polygon(), m_line1.num_points()); + draw_polyline(ras_img, ren_img, m_line1.polygon(), m_line1.num_points()); + + // Clear the area, almost opaque, but not completely + //------------------------ + ren_base.blend_bar(0, 0, (int)width(), (int)height(), agg::rgba(1,1,1), 200); + + + // Set the raster clip box and then, draw again. + // In reality there shouldn't be two calls above. + // It's done only for demonstration + //------------------------ + ren_base.clip_box((int)50, (int)50, (int)width()-50, (int)height()-50); + + // This "copy_bar" is also for demonstration only + //------------------------ + ren_base.copy_bar(0, 0, (int)width(), (int)height(), agg::rgba(1,1,1)); + + // Finally draw polyline correctly clipped: We use double clipping, + // first is vector clipping, with extended clip box, second is raster + // clipping with normal clip box. + //------------------------ + ren_img.scale_x(m_scale_x.value()); + ren_img.start_x(m_start_x.value()); + draw_polyline(ras_line, ren_line, m_line1.polygon(), m_line1.num_points()); + draw_polyline(ras_img, ren_img, m_line1.polygon(), m_line1.num_points()); + + + // Reset clipping and draw the controls and stuff + ren_base.reset_clipping(true); + + m_line1.line_width(1/m_scale.scale()); + m_line1.point_radius(5/m_scale.scale()); + + agg::render_ctrl(ras, sl, ren_base, m_line1); + agg::render_ctrl(ras, sl, ren_base, m_scale_x); + agg::render_ctrl(ras, sl, ren_base, m_start_x); + + + char buf[256]; + agg::gsv_text t; + t.size(10.0); + + agg::conv_stroke pt(t); + pt.width(1.5); + pt.line_cap(agg::round_cap); + + const double* p = m_line1.polygon(); + sprintf(buf, "Len=%.2f", agg::calc_distance(p[0], p[1], p[2], p[3]) * m_scale.scale()); + + t.start_point(10.0, 30.0); + t.text(buf); + + ras.add_path(pt); + ren.color(agg::rgba(0,0,0)); + agg::render_scanlines(ras, sl, ren); + + } + + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + if(key == '+' || key == agg::key_kp_plus) + { + m_scale *= agg::trans_affine_translation(-x, -y); + m_scale *= agg::trans_affine_scaling(1.1); + m_scale *= agg::trans_affine_translation(x, y); + force_redraw(); + } + + if(key == '-' || key == agg::key_kp_minus) + { + m_scale *= agg::trans_affine_translation(-x, -y); + m_scale *= agg::trans_affine_scaling(1/1.1); + m_scale *= agg::trans_affine_translation(x, y); + force_redraw(); + } + } + + virtual void on_ctrl_change() + { + } +}; + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("AGG Example. Clipping Lines with Image Patterns"); + + if(!app.load_img(0, "1")) + { + char buf[256]; + sprintf(buf, "There must be file 1%s\n", app.img_ext(), app.img_ext()); + app.message(buf); + return 1; + } + + if(app.init(500, 500, agg::window_resize)) + { + return app.run(); + } + + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/lion.cpp b/jni/desmume/src/android/agg/examples/lion.cpp new file mode 100755 index 0000000..9db3e33 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/lion.cpp @@ -0,0 +1,172 @@ +#include +#include +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_path_storage.h" +#include "agg_conv_transform.h" +#include "agg_bounding_rect.h" +#include "ctrl/agg_slider_ctrl.h" +#include "platform/agg_platform_support.h" + +//#define AGG_GRAY16 +//#define AGG_BGR24 +//#define AGG_BGR48 +//#define AGG_RGB_AAA +#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + +enum flip_y_e { flip_y = true }; + +agg::rasterizer_scanline_aa<> g_rasterizer; +agg::scanline_p8 g_scanline; +agg::path_storage g_path; +agg::rgba8 g_colors[100]; +unsigned g_path_idx[100]; +unsigned g_npaths = 0; +double g_x1 = 0; +double g_y1 = 0; +double g_x2 = 0; +double g_y2 = 0; +double g_base_dx = 0; +double g_base_dy = 0; +double g_angle = 0; +double g_scale = 1.0; +double g_skew_x = 0; +double g_skew_y = 0; +int g_nclick = 0; + +unsigned parse_lion(agg::path_storage& ps, agg::rgba8* colors, unsigned* path_idx); +void parse_lion() +{ + g_npaths = parse_lion(g_path, g_colors, g_path_idx); + agg::pod_array_adaptor path_idx(g_path_idx, 100); + agg::bounding_rect(g_path, path_idx, 0, g_npaths, &g_x1, &g_y1, &g_x2, &g_y2); + g_base_dx = (g_x2 - g_x1) / 2.0; + g_base_dy = (g_y2 - g_y1) / 2.0; +} + + + +class the_application : public agg::platform_support +{ + agg::slider_ctrl m_alpha_slider; + +public: + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_solid; + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_alpha_slider(5, 5, 512-5, 12, !flip_y) + { + parse_lion(); + add_ctrl(m_alpha_slider); + m_alpha_slider.no_transform(); + m_alpha_slider.label("Alpha%3.3f"); + m_alpha_slider.value(0.1); + } + + virtual void on_resize(int cx, int cy) + { + pixfmt pf(rbuf_window()); + renderer_base r(pf); + r.clear(agg::rgba(1, 1, 1)); + } + + virtual void on_draw() + { + int width = rbuf_window().width(); + int height = rbuf_window().height(); + + unsigned i; + for(i = 0; i < g_npaths; i++) + { + g_colors[i].a = agg::int8u(m_alpha_slider.value() * 255); + } + + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + renderer_solid r(rb); + + agg::trans_affine mtx; + mtx *= agg::trans_affine_translation(-g_base_dx, -g_base_dy); + mtx *= agg::trans_affine_scaling(g_scale, g_scale); + mtx *= agg::trans_affine_rotation(g_angle + agg::pi); + mtx *= agg::trans_affine_skewing(g_skew_x/1000.0, g_skew_y/1000.0); + mtx *= agg::trans_affine_translation(width/2, height/2); + + // This code renders the lion: + agg::conv_transform trans(g_path, mtx); + agg::render_all_paths(g_rasterizer, g_scanline, r, trans, g_colors, g_path_idx, g_npaths); + + // Render the control + agg::render_ctrl(g_rasterizer, g_scanline, rb, m_alpha_slider); + } + + + void transform(double width, double height, double x, double y) + { + x -= width / 2; + y -= height / 2; + g_angle = atan2(y, x); + g_scale = sqrt(y * y + x * x) / 100.0; + } + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + int width = rbuf_window().width(); + int height = rbuf_window().height(); + transform(width, height, x, y); + force_redraw(); + } + + if(flags & agg::mouse_right) + { + g_skew_x = x; + g_skew_y = y; + force_redraw(); + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + on_mouse_button_down(x, y, flags); + } + +}; + + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Lion"); + + if(app.init(512, 400, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + + + + + diff --git a/jni/desmume/src/android/agg/examples/lion_lens.cpp b/jni/desmume/src/android/agg/examples/lion_lens.cpp new file mode 100755 index 0000000..e0c1ea8 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/lion_lens.cpp @@ -0,0 +1,202 @@ +#include +#include +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_path_storage.h" +#include "agg_conv_transform.h" +#include "agg_trans_warp_magnifier.h" +#include "agg_conv_segmentator.h" +#include "agg_bounding_rect.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "platform/agg_platform_support.h" + +#define AGG_BGR24 +//#define AGG_RGB24 +//#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +//#define AGG_RGB_AAA +#include "pixel_formats.h" + +enum flip_y_e { flip_y = true }; + +agg::rasterizer_scanline_aa<> g_rasterizer; +agg::scanline_p8 g_scanline; +agg::path_storage g_path; +agg::rgba8 g_colors[100]; +unsigned g_path_idx[100]; +unsigned g_npaths = 0; +double g_x1 = 0; +double g_y1 = 0; +double g_x2 = 0; +double g_y2 = 0; +double g_base_dx = 0; +double g_base_dy = 0; +double g_angle = 0; +double g_scale = 1.0; +double g_skew_x = 0; +double g_skew_y = 0; +int g_nclick = 0; + +unsigned parse_lion(agg::path_storage& ps, agg::rgba8* colors, unsigned* path_idx); +void parse_lion() +{ + g_npaths = parse_lion(g_path, g_colors, g_path_idx); + agg::pod_array_adaptor path_idx(g_path_idx, 100); + agg::bounding_rect(g_path, path_idx, 0, g_npaths, &g_x1, &g_y1, &g_x2, &g_y2); + g_base_dx = (g_x2 - g_x1) / 2.0; + g_base_dy = (g_y2 - g_y1) / 2.0; +} + + +class the_application : public agg::platform_support +{ + agg::slider_ctrl m_magn_slider; + agg::slider_ctrl m_radius_slider; + +public: + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_solid; + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_magn_slider (5, 5, 495, 12, !flip_y), + m_radius_slider(5, 20, 495, 27, !flip_y) + { + parse_lion(); + add_ctrl(m_magn_slider); + + m_magn_slider.no_transform(); + m_magn_slider.range(0.01, 4.0); + m_magn_slider.value(3.0); + m_magn_slider.label("Scale=%3.2f"); + + add_ctrl(m_radius_slider); + m_radius_slider.no_transform(); + m_radius_slider.range(0.0, 100.0); + m_radius_slider.value(70.0); + m_radius_slider.label("Radius=%3.2f"); + + } + + + virtual void on_init() + { + g_x1 = 200; + g_y1 = 150; + } + + virtual void on_resize(int cx, int cy) + { + } + + virtual void on_draw() + { + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + renderer_solid r(rb); + + rb.clear(agg::rgba(1, 1, 1)); + + agg::trans_warp_magnifier lens; + lens.center(g_x1, g_y1); + lens.magnification(m_magn_slider.value()); + lens.radius(m_radius_slider.value() / m_magn_slider.value()); + + agg::conv_segmentator segm(g_path); + + agg::trans_affine mtx; + mtx *= agg::trans_affine_translation(-g_base_dx, -g_base_dy); + mtx *= agg::trans_affine_rotation(g_angle + agg::pi); + mtx *= agg::trans_affine_translation(width()/2, height()/2); + + agg::conv_transform< + agg::conv_segmentator< + agg::path_storage> > trans_mtx(segm, mtx); + + agg::conv_transform< + agg::conv_transform< + agg::conv_segmentator< + agg::path_storage> >, agg::trans_warp_magnifier> trans_lens(trans_mtx, lens); + + agg::render_all_paths(g_rasterizer, g_scanline, r, trans_lens, g_colors, g_path_idx, g_npaths); + + agg::render_ctrl(g_rasterizer, g_scanline, rb, m_magn_slider); + agg::render_ctrl(g_rasterizer, g_scanline, rb, m_radius_slider); + + + // Testing inverse_transform() + //-------------------- + //double x, y; + //for(y = 0; y < height(); y += 10) + //{ + // for(x = 0; x < height(); x += 10) + // { + // double x2 = x+0.5; + // double y2 = y+0.5; + // lens.transform(&x2, &y2); + // lens.inverse_transform(&x2, &y2); + // agg::ellipse e(x2, y2, 1, 1); + // g_rasterizer.add_path(e); + // r.color(agg::rgba8(0,0,0)); + // agg::render_scanlines(g_rasterizer, g_scanline, r); + // } + //} + } + + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + g_x1 = x; + g_y1 = y; + force_redraw(); + } + if(flags & agg::mouse_right) + { + g_x2 = x; + g_y2 = y; + force_redraw(); + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + on_mouse_button_down(x, y, flags); + } + +}; + + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Lion"); + + if(app.init(500, 600, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + + + + + diff --git a/jni/desmume/src/android/agg/examples/lion_outline.cpp b/jni/desmume/src/android/agg/examples/lion_outline.cpp new file mode 100755 index 0000000..d11499c --- /dev/null +++ b/jni/desmume/src/android/agg/examples/lion_outline.cpp @@ -0,0 +1,190 @@ +#include +#include +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_renderer_outline_aa.h" +#include "agg_rasterizer_outline_aa.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_path_storage.h" +#include "agg_conv_transform.h" +#include "agg_bounding_rect.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "platform/agg_platform_support.h" + +#define AGG_BGR24 +//#define AGG_RGB24 +//#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + +enum flip_y_e { flip_y = true }; + + +agg::rasterizer_scanline_aa<> g_rasterizer; +agg::scanline_p8 g_scanline; +agg::path_storage g_path; +agg::rgba8 g_colors[100]; +unsigned g_path_idx[100]; +unsigned g_npaths = 0; +double g_x1 = 0; +double g_y1 = 0; +double g_x2 = 0; +double g_y2 = 0; +double g_base_dx = 0; +double g_base_dy = 0; +double g_angle = 0; +double g_scale = 1.0; +double g_skew_x = 0; +double g_skew_y = 0; +int g_nclick = 0; + + +unsigned parse_lion(agg::path_storage& ps, agg::rgba8* colors, unsigned* path_idx); +void parse_lion() +{ + g_npaths = parse_lion(g_path, g_colors, g_path_idx); + agg::pod_array_adaptor path_idx(g_path_idx, 100); + agg::bounding_rect(g_path, path_idx, 0, g_npaths, &g_x1, &g_y1, &g_x2, &g_y2); + g_base_dx = (g_x2 - g_x1) / 2.0; + g_base_dy = (g_y2 - g_y1) / 2.0; +} + + +class the_application : public agg::platform_support +{ + agg::slider_ctrl m_width_slider; + agg::cbox_ctrl m_scanline; + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_width_slider(5, 5, 150, 12, !flip_y), + m_scanline(160, 5, "Use Scanline Rasterizer", !flip_y) + { + parse_lion(); + add_ctrl(m_width_slider); + m_width_slider.no_transform(); + m_width_slider.range(0.0, 4.0); + m_width_slider.value(1.0); + m_width_slider.label("Width %3.2f"); + + add_ctrl(m_scanline); + m_scanline.no_transform(); + } + + + virtual void on_draw() + { + int width = rbuf_window().width(); + int height = rbuf_window().height(); + + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_solid; + + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + renderer_solid r(rb); + rb.clear(agg::rgba(1,1,1)); + + agg::trans_affine mtx; + mtx *= agg::trans_affine_translation(-g_base_dx, -g_base_dy); + mtx *= agg::trans_affine_scaling(g_scale, g_scale); + mtx *= agg::trans_affine_rotation(g_angle + agg::pi); + mtx *= agg::trans_affine_skewing(g_skew_x/1000.0, g_skew_y/1000.0); + mtx *= agg::trans_affine_translation(width/2, height/2); + + if(m_scanline.status()) + { + agg::conv_stroke stroke(g_path); + stroke.width(m_width_slider.value()); + stroke.line_join(agg::round_join); + agg::conv_transform > trans(stroke, mtx); + agg::render_all_paths(g_rasterizer, g_scanline, r, trans, g_colors, g_path_idx, g_npaths); + } + else + { + typedef agg::renderer_outline_aa renderer_type; + typedef agg::rasterizer_outline_aa rasterizer_type; + + double w = m_width_slider.value() * mtx.scale(); + + agg::line_profile_aa profile(w, agg::gamma_none()); + renderer_type ren(rb, profile); + rasterizer_type ras(ren); + + agg::conv_transform trans(g_path, mtx); + + ras.render_all_paths(trans, g_colors, g_path_idx, g_npaths); + } + + + agg::render_ctrl(g_rasterizer, g_scanline, rb, m_width_slider); + agg::render_ctrl(g_rasterizer, g_scanline, rb, m_scanline); + } + + + void transform(double width, double height, double x, double y) + { + x -= width / 2; + y -= height / 2; + g_angle = atan2(y, x); + g_scale = sqrt(y * y + x * x) / 100.0; + } + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + int width = rbuf_window().width(); + int height = rbuf_window().height(); + transform(width, height, x, y); + force_redraw(); + } + + if(flags & agg::mouse_right) + { + g_skew_x = x; + g_skew_y = y; + force_redraw(); + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + on_mouse_button_down(x, y, flags); + } + +}; + + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Lion"); + + if(app.init(512, 512, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + + + + + diff --git a/jni/desmume/src/android/agg/examples/macosx_carbon/Makefile b/jni/desmume/src/android/agg/examples/macosx_carbon/Makefile new file mode 100755 index 0000000..e1fa5d2 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/macosx_carbon/Makefile @@ -0,0 +1,295 @@ +AGGLIBS= -lagg -framework Carbon -framework QuickTime +AGGCXXFLAGS = -bind_at_load -O3 -I/Developer/Headers/FlatCarbon +CXX = g++ +C = gcc +#CXX = icc +LIB = ar cr -s + +PLATFORM=mac + +PLATFORMSOURCES=../../src/platform/$(PLATFORM)/agg_platform_support.o ../../src/platform/$(PLATFORM)/agg_mac_pmap.o + +CXXFLAGS= $(AGGCXXFLAGS) -I../../include \ +-L../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm + +all: + cd ../../src/; make + make aa_demo + make aa_test + make alpha_gradient + make alpha_mask + make alpha_mask2 + make alpha_mask3 + make bezier_div + make blur + make blend_color + make bspline + make circles + make component_rendering + make conv_contour + make conv_dash_marker + make conv_stroke + make gamma_correction + make gamma_ctrl + make gouraud + make gradient_focal + make gradients + make graph_test + make idea + make lion + make lion_lens + make lion_outline + make multi_clip + make pattern_fill + make perspective + make polymorphic_renderer + make raster_text + make rasterizers + make rasterizers2 + make rasterizer_compound + make rounded_rect + make scanline_boolean + make scanline_boolean2 + make simple_blur + make trans_polar + make image_alpha + make image_filters + make image_filters2 + make image_fltr_graph + make image_perspective + make image_resample + make image_transforms + make image1 + make distortions + make pattern_perspective + make compositing + make line_patterns + make mol_view + +aa_demo: ../aa_demo.o $(PLATFORMSOURCES) aa_demo.app + $(CXX) $(CXXFLAGS) ../aa_demo.o $(PLATFORMSOURCES) -o aa_demo.app/Contents/MacOS/aa_demo $(LIBS) + +aa_test: ../aa_test.o $(PLATFORMSOURCES) aa_test.app + $(CXX) $(CXXFLAGS) ../aa_test.o $(PLATFORMSOURCES) -o aa_test.app/Contents/MacOS/aa_test $(LIBS) + +alpha_gradient: ../alpha_gradient.o $(PLATFORMSOURCES) alpha_gradient.app + $(CXX) $(CXXFLAGS) ../alpha_gradient.o $(PLATFORMSOURCES) -o alpha_gradient.app/Contents/MacOS/alpha_gradient $(LIBS) + +alpha_mask: ../alpha_mask.o ../parse_lion.o $(PLATFORMSOURCES) alpha_mask.app + $(CXX) $(CXXFLAGS) ../alpha_mask.o ../parse_lion.o $(PLATFORMSOURCES) -o alpha_mask.app/Contents/MacOS/alpha_mask $(LIBS) + +alpha_mask2: ../alpha_mask2.o ../parse_lion.o $(PLATFORMSOURCES) alpha_mask2.app + $(CXX) $(CXXFLAGS) ../alpha_mask2.o ../parse_lion.o $(PLATFORMSOURCES) -o alpha_mask2.app/Contents/MacOS/alpha_mask2 $(LIBS) + +alpha_mask3: ../alpha_mask3.o ../make_arrows.o ../make_gb_poly.o $(PLATFORMSOURCES) alpha_mask3.app + $(CXX) $(CXXFLAGS) ../alpha_mask3.o ../make_arrows.o ../make_gb_poly.o $(PLATFORMSOURCES) -o alpha_mask3.app/Contents/MacOS/alpha_mask3 $(LIBS) + +bezier_div: ../bezier_div.o ../interactive_polygon.o $(PLATFORMSOURCES) bezier_div.app + $(CXX) $(CXXFLAGS) ../bezier_div.o ../interactive_polygon.o $(PLATFORMSOURCES) -o bezier_div.app/Contents/MacOS/bezier_div $(LIBS) + +blur: ../blur.o $(PLATFORMSOURCES) blur.app + $(CXX) $(CXXFLAGS) ../blur.o $(PLATFORMSOURCES) -o blur.app/Contents/MacOS/blur $(LIBS) + +blend_color: ../blend_color.o $(PLATFORMSOURCES) blend_color.app + $(CXX) $(CXXFLAGS) ../blend_color.o $(PLATFORMSOURCES) -o blend_color.app/Contents/MacOS/blend_color $(LIBS) + +bspline: ../bspline.o ../interactive_polygon.o $(PLATFORMSOURCES) bspline.app + $(CXX) $(CXXFLAGS) ../bspline.o ../interactive_polygon.o $(PLATFORMSOURCES) -o bspline.app/Contents/MacOS/bspline $(LIBS) + +circles: ../circles.o $(PLATFORMSOURCES) circles.app + $(CXX) $(CXXFLAGS) ../circles.o $(PLATFORMSOURCES) -o circles.app/Contents/MacOS/circles $(LIBS) + +component_rendering: ../component_rendering.o $(PLATFORMSOURCES) component_rendering.app + $(CXX) $(CXXFLAGS) ../component_rendering.o $(PLATFORMSOURCES) -o component_rendering.app/Contents/MacOS/component_rendering $(LIBS) + +compositing: ../compositing.o $(PLATFORMSOURCES) compositing.bmp compositing.app + cp compositing.bmp compositing.app/Contents/MacOS/compositing.bmp + $(CXX) $(CXXFLAGS) ../compositing.o $(PLATFORMSOURCES) -o compositing.app/Contents/MacOS/compositing $(LIBS) + +conv_contour: ../conv_contour.o $(PLATFORMSOURCES) conv_contour.app + $(CXX) $(CXXFLAGS) ../conv_contour.o $(PLATFORMSOURCES) -o conv_contour.app/Contents/MacOS/conv_contour $(LIBS) + +conv_dash_marker: ../conv_dash_marker.o $(PLATFORMSOURCES) conv_dash_marker.app + $(CXX) $(CXXFLAGS) ../conv_dash_marker.o $(PLATFORMSOURCES) -o conv_dash_marker.app/Contents/MacOS/conv_dash_marker $(LIBS) + +conv_stroke: ../conv_stroke.o $(PLATFORMSOURCES) conv_stroke.app + $(CXX) $(CXXFLAGS) ../conv_stroke.o $(PLATFORMSOURCES) -o conv_stroke.app/Contents/MacOS/conv_stroke $(LIBS) + +distortions: ../distortions.o $(PLATFORMSOURCES) spheres.bmp distortions.app + cp spheres.bmp distortions.app/Contents/MacOS/spheres.bmp + $(CXX) $(CXXFLAGS) ../distortions.o $(PLATFORMSOURCES) -o distortions.app/Contents/MacOS/distortions $(LIBS) + +gamma_correction: ../gamma_correction.o $(PLATFORMSOURCES) gamma_correction.app + $(CXX) $(CXXFLAGS) ../gamma_correction.o $(PLATFORMSOURCES) -o gamma_correction.app/Contents/MacOS/gamma_correction $(LIBS) + +gamma_ctrl: ../gamma_ctrl.o $(PLATFORMSOURCES) gamma_ctrl.app + $(CXX) $(CXXFLAGS) ../gamma_ctrl.o $(PLATFORMSOURCES) -o gamma_ctrl.app/Contents/MacOS/gamma_ctrl $(LIBS) + +gouraud: ../gouraud.o $(PLATFORMSOURCES) gouraud.app + $(CXX) $(CXXFLAGS) ../gouraud.o $(PLATFORMSOURCES) -o gouraud.app/Contents/MacOS/gouraud $(LIBS) + +gradient_focal: ../gradient_focal.o $(PLATFORMSOURCES) gradient_focal.app + $(CXX) $(CXXFLAGS) ../gradient_focal.o $(PLATFORMSOURCES) -o gradient_focal.app/Contents/MacOS/gradient_focal $(LIBS) + +gradients: ../gradients.o $(PLATFORMSOURCES) gradients.app + $(CXX) $(CXXFLAGS) ../gradients.o $(PLATFORMSOURCES) -o gradients.app/Contents/MacOS/gradients $(LIBS) + +graph_test: ../graph_test.o $(PLATFORMSOURCES) graph_test.app + $(CXX) $(CXXFLAGS) ../graph_test.o $(PLATFORMSOURCES) -o graph_test.app/Contents/MacOS/graph_test $(LIBS) + +idea: ../idea.o $(PLATFORMSOURCES) idea.app + $(CXX) $(CXXFLAGS) ../idea.o $(PLATFORMSOURCES) -o idea.app/Contents/MacOS/idea $(LIBS) + +image_alpha: ../image_alpha.o $(PLATFORMSOURCES) spheres.bmp image_alpha.app + cp spheres.bmp image_alpha.app/Contents/MacOS/spheres.bmp + $(CXX) $(CXXFLAGS) ../image_alpha.o $(PLATFORMSOURCES) -o image_alpha.app/Contents/MacOS/image_alpha $(LIBS) + +image_filters: ../image_filters.o $(PLATFORMSOURCES) spheres.bmp image_filters.app + cp spheres.bmp image_filters.app/Contents/MacOS/spheres.bmp + $(CXX) $(CXXFLAGS) ../image_filters.o $(PLATFORMSOURCES) -o image_filters.app/Contents/MacOS/image_filters $(LIBS) + +image_filters2: ../image_filters2.o $(PLATFORMSOURCES) spheres.bmp image_filters2.app + cp spheres.bmp image_filters2.app/Contents/MacOS/spheres.bmp + $(CXX) $(CXXFLAGS) ../image_filters2.o $(PLATFORMSOURCES) -o image_filters2.app/Contents/MacOS/image_filters2 $(LIBS) + +image_fltr_graph: ../image_fltr_graph.o $(PLATFORMSOURCES) spheres.bmp image_fltr_graph.app + cp spheres.bmp image_fltr_graph.app/Contents/MacOS/spheres.bmp + $(CXX) $(CXXFLAGS) ../image_fltr_graph.o $(PLATFORMSOURCES) -o image_fltr_graph.app/Contents/MacOS/image_fltr_graph $(LIBS) + +image_perspective: ../image_perspective.o ../interactive_polygon.o $(PLATFORMSOURCES) spheres.bmp image_perspective.app + cp spheres.bmp image_perspective.app/Contents/MacOS/spheres.bmp + $(CXX) $(CXXFLAGS) ../image_perspective.o ../interactive_polygon.o $(PLATFORMSOURCES) -o image_perspective.app/Contents/MacOS/image_perspective $(LIBS) + +image_resample: ../image_resample.o ../interactive_polygon.o $(PLATFORMSOURCES) spheres.bmp image_resample.app + cp spheres.bmp image_resample.app/Contents/MacOS/spheres.bmp + $(CXX) $(CXXFLAGS) ../image_resample.o ../interactive_polygon.o $(PLATFORMSOURCES) -o image_resample.app/Contents/MacOS/image_resample $(LIBS) + +image_transforms: ../image_transforms.o $(PLATFORMSOURCES) spheres.bmp image_transforms.app + cp spheres.bmp image_transforms.app/Contents/MacOS/spheres.bmp + $(CXX) $(CXXFLAGS) ../image_transforms.o $(PLATFORMSOURCES) -o image_transforms.app/Contents/MacOS/image_transforms $(LIBS) + +image1: ../image1.o $(PLATFORMSOURCES) spheres.bmp image1.app + cp spheres.bmp image1.app/Contents/MacOS/spheres.bmp + $(CXX) $(CXXFLAGS) ../image1.o $(PLATFORMSOURCES) -o image1.app/Contents/MacOS/image1 $(LIBS) + +line_patterns: ../line_patterns.o $(PLATFORMSOURCES) 1.bmp 2.bmp 3.bmp 4.bmp 5.bmp 6.bmp 7.bmp 8.bmp 9.bmp line_patterns.app + cp 1.bmp line_patterns.app/Contents/MacOS/1.bmp + cp 2.bmp line_patterns.app/Contents/MacOS/2.bmp + cp 3.bmp line_patterns.app/Contents/MacOS/3.bmp + cp 4.bmp line_patterns.app/Contents/MacOS/4.bmp + cp 5.bmp line_patterns.app/Contents/MacOS/5.bmp + cp 6.bmp line_patterns.app/Contents/MacOS/6.bmp + cp 7.bmp line_patterns.app/Contents/MacOS/7.bmp + cp 8.bmp line_patterns.app/Contents/MacOS/8.bmp + cp 9.bmp line_patterns.app/Contents/MacOS/9.bmp + $(CXX) $(CXXFLAGS) ../line_patterns.o $(PLATFORMSOURCES) -o line_patterns.app/Contents/MacOS/line_patterns $(LIBS) + +lion: ../lion.o ../parse_lion.o $(PLATFORMSOURCES) lion.app + $(CXX) $(CXXFLAGS) ../lion.o ../parse_lion.o $(PLATFORMSOURCES) -o lion.app/Contents/MacOS/lion $(LIBS) + +lion_lens: ../lion_lens.o ../parse_lion.o $(PLATFORMSOURCES) lion_lens.app + $(CXX) $(CXXFLAGS) ../lion_lens.o ../parse_lion.o $(PLATFORMSOURCES) -o lion_lens.app/Contents/MacOS/lion_lens $(LIBS) + +lion_outline: ../lion_outline.o ../parse_lion.o $(PLATFORMSOURCES) lion_outline.app + $(CXX) $(CXXFLAGS) ../lion_outline.o ../parse_lion.o $(PLATFORMSOURCES) -o lion_outline.app/Contents/MacOS/lion_outline $(LIBS) + +mol_view: ../mol_view.o $(PLATFORMSOURCES) 1.sdf mol_view.app + cp 1.sdf mol_view.app/Contents/MacOS/1.sdf + $(CXX) $(CXXFLAGS) ../mol_view.o $(PLATFORMSOURCES) -o mol_view.app/Contents/MacOS/mol_view $(LIBS) + +multi_clip: ../multi_clip.o ../parse_lion.o $(PLATFORMSOURCES) multi_clip.app + $(CXX) $(CXXFLAGS) ../multi_clip.o ../parse_lion.o $(PLATFORMSOURCES) -o multi_clip.app/Contents/MacOS/multi_clip $(LIBS) + +pattern_fill: ../pattern_fill.o $(PLATFORMSOURCES) pattern_fill.app + $(CXX) $(CXXFLAGS) ../pattern_fill.o $(PLATFORMSOURCES) -o pattern_fill.app/Contents/MacOS/pattern_fill $(LIBS) + +pattern_perspective: ../pattern_perspective.o ../interactive_polygon.o $(PLATFORMSOURCES) agg.bmp pattern_perspective.app + cp agg.bmp pattern_perspective.app/Contents/MacOS/agg.bmp + $(CXX) $(CXXFLAGS) ../pattern_perspective.o ../interactive_polygon.o $(PLATFORMSOURCES) -o pattern_perspective.app/Contents/MacOS/pattern_perspective $(LIBS) + +perspective: ../perspective.o ../interactive_polygon.o ../parse_lion.o $(PLATFORMSOURCES) perspective.app + $(CXX) $(CXXFLAGS) ../perspective.o ../interactive_polygon.o ../parse_lion.o $(PLATFORMSOURCES) -o perspective.app/Contents/MacOS/perspective $(LIBS) + +polymorphic_renderer: ../polymorphic_renderer.o $(PLATFORMSOURCES) polymorphic_renderer.app + $(CXX) $(CXXFLAGS) ../polymorphic_renderer.o $(PLATFORMSOURCES) -o polymorphic_renderer.app/Contents/MacOS/polymorphic_renderer $(LIBS) + +raster_text: ../raster_text.o $(PLATFORMSOURCES) raster_text.app + $(CXX) $(CXXFLAGS) ../raster_text.o $(PLATFORMSOURCES) -o raster_text.app/Contents/MacOS/raster_text $(LIBS) + +rasterizers: ../rasterizers.o $(PLATFORMSOURCES) rasterizers.app + $(CXX) $(CXXFLAGS) ../rasterizers.o $(PLATFORMSOURCES) -o rasterizers.app/Contents/MacOS/rasterizers $(LIBS) + +rasterizers2: ../rasterizers2.o $(PLATFORMSOURCES) rasterizers2.app + $(CXX) $(CXXFLAGS) ../rasterizers2.o $(PLATFORMSOURCES) -o rasterizers2.app/Contents/MacOS/rasterizers2 $(LIBS) + +rasterizer_compound: ../rasterizer_compound.o $(PLATFORMSOURCES) rasterizer_compound.app + $(CXX) $(CXXFLAGS) ../rasterizer_compound.o $(PLATFORMSOURCES) -o rasterizer_compound.app/Contents/MacOS/rasterizer_compound $(LIBS) + +rounded_rect: ../rounded_rect.o $(PLATFORMSOURCES) rounded_rect.app + $(CXX) $(CXXFLAGS) ../rounded_rect.o $(PLATFORMSOURCES) -o rounded_rect.app/Contents/MacOS/rounded_rect $(LIBS) + +scanline_boolean: ../scanline_boolean.o ../interactive_polygon.o $(PLATFORMSOURCES) scanline_boolean.app + $(CXX) $(CXXFLAGS) ../scanline_boolean.o ../interactive_polygon.o $(PLATFORMSOURCES) -o scanline_boolean.app/Contents/MacOS/scanline_boolean $(LIBS) + +scanline_boolean2: ../scanline_boolean2.o ../make_arrows.o ../make_gb_poly.o $(PLATFORMSOURCES) scanline_boolean2.app + $(CXX) $(CXXFLAGS) ../scanline_boolean2.o ../make_arrows.o ../make_gb_poly.o $(PLATFORMSOURCES) -o scanline_boolean2.app/Contents/MacOS/scanline_boolean2 $(LIBS) + +simple_blur: ../simple_blur.o ../parse_lion.o $(PLATFORMSOURCES) simple_blur.app + $(CXX) $(CXXFLAGS) ../simple_blur.o ../parse_lion.o $(PLATFORMSOURCES) -o simple_blur.app/Contents/MacOS/simple_blur $(LIBS) + +trans_polar: ../trans_polar.o $(PLATFORMSOURCES) trans_polar.app + $(CXX) $(CXXFLAGS) ../trans_polar.o $(PLATFORMSOURCES) -o trans_polar.app/Contents/MacOS/trans_polar $(LIBS) + + +clean: + rm -rf *.app + rm -f ../*.o + rm -f ../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f ../../src/platform/$(PLATFORM)/agg_mac_pmap.o + +agg.bmp: + @echo "Required file missing!!" + @echo "Please download http://www.antigrain.com/agg.bmp to /examples/macosx_carbon/" + @echo "Attempting to retrieve via curl: (will fail if curl is not installed)" + curl -O http://www.antigrain.com/agg.bmp + +compositing.bmp: + @echo "Required file missing!!" + @echo "Please download http://www.antigrain.com/compositing.bmp to /examples/macosx_carbon/" + @echo "Attempting to retrieve via curl: (will fail if curl is not installed)" + curl -O http://www.antigrain.com/compositing.bmp + +spheres.bmp: + @echo "Required file missing!!" + @echo "Please download http://www.antigrain.com/spheres.bmp to /examples/macosx_carbon/" + @echo "Attempting to retrieve file: (will fail if curl is not installed)" + curl -O http://www.antigrain.com/spheres.bmp + +1.sdf: + @echo "Required file missing!!" + @echo "Please download http://www.antigrain.com/1.sdf to /examples/macosx_carbon/" + @echo "Attempting to retrieve file: (will fail if curl is not installed)" + curl -O http://www.antigrain.com/1.sdf + +1.bmp: + @echo "Required file missing!!" + @echo "Please download http://www.antigrain.com/line_patterns.bmp.zip to /examples/macosx_carbon/ and decoompress it" + @echo "Attempting to retrieve file: (will fail if curl is not installed)" + curl -O http://www.antigrain.com/line_patterns.bmp.zip + unzip -o line_patterns.bmp.zip + +%.app: + mkdir $*.app + mkdir $*.app/Contents + mkdir $*.app/Contents/MacOS + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + +.PHONY : clean + + diff --git a/jni/desmume/src/android/agg/examples/macosx_carbon/readme.txt b/jni/desmume/src/android/agg/examples/macosx_carbon/readme.txt new file mode 100755 index 0000000..7aad9ab --- /dev/null +++ b/jni/desmume/src/android/agg/examples/macosx_carbon/readme.txt @@ -0,0 +1,24 @@ +The Anti-Grain Geometry Project +A high quality rendering engine for C++ +http://antigrain.com + +Anti-Grain Geometry +Copyright (C) 2002-2005 Maxim Shemanarev (McSeem) + +Permission to copy, use, modify, sell and distribute this software +is granted provided this copyright notice appears in all copies. +This software is provided "as is" without express or implied +warranty, and with no claim as to its suitability for any purpose. + +By default only the examples that do not require extra dependancies are built. +with the following commands: + +cd (AGGDIRECTORY)/examples/macosx_carbon +make clean +make + +Alternatively you can also build the examples one by one, using the example name directly: + +make aa_demo +make aa_test +... \ No newline at end of file diff --git a/jni/desmume/src/android/agg/examples/macosx_sdl/Makefile b/jni/desmume/src/android/agg/examples/macosx_sdl/Makefile new file mode 100755 index 0000000..0dd1b6d --- /dev/null +++ b/jni/desmume/src/android/agg/examples/macosx_sdl/Makefile @@ -0,0 +1,376 @@ +include ../../Makefile.in.$(shell uname).SDL + +PLATFORM=sdl + +PLATFORMSOURCES=../../src/platform/$(PLATFORM)/agg_platform_support.o + +CXXFLAGS= $(AGGCXXFLAGS) -I../../include \ +-L../../src \ +$(PIXFMT) + +CXXFREETYPEFLAGS= $(AGGCXXFLAGS) -Wall \ +-I../../include \ +-I../../font_freetype \ +-I/usr/local/include/freetype2 \ +-L../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm + +base: + cd ../../src/; make + make aa_demo + make aa_test + make alpha_gradient + make alpha_mask + make alpha_mask2 + make alpha_mask3 + make bspline + make blur + make blend_color + make bezier_div + make circles + make component_rendering + make conv_contour + make conv_dash_marker + make conv_stroke + make gamma_correction + make gamma_ctrl + make gouraud + make gradient_focal + make gradients + make graph_test + make idea + make lion + make lion_lens + make lion_outline + make multi_clip + make pattern_fill + make perspective + make polymorphic_renderer + make raster_text + make rasterizers + make rasterizers2 + make rasterizer_compound + make rounded_rect + make scanline_boolean + make scanline_boolean2 + make simple_blur + make trans_polar + make image_alpha + make image_filters + make image_filters2 + make image_fltr_graph + make image_perspective + make image_resample + make image_transforms + make image1 + make distortions + make pattern_perspective + make compositing + make line_patterns + make mol_view + +freetype: + make freetype_test + make trans_curve1_ft + make trans_curve2_ft + +gpc: + make gpc_test + +all: + make base + make freetype + make gpc + +aa_demo: ../aa_demo.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o aa_demo $(LIBS) + +aa_test: ../aa_test.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o aa_test $(LIBS) + +alpha_gradient: ../alpha_gradient.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o alpha_gradient $(LIBS) + +alpha_mask: ../alpha_mask.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o alpha_mask $(LIBS) + +alpha_mask2: ../alpha_mask2.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o alpha_mask2 $(LIBS) + +alpha_mask3: ../alpha_mask3.o ../make_arrows.o ../make_gb_poly.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o alpha_mask3 $(LIBS) + +bezier_div: ../bezier_div.o ../interactive_polygon.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o bezier_div $(LIBS) + +blur: ../blur.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o blur $(LIBS) + +blend_color: ../blend_color.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o blend_color $(LIBS) + +bspline: ../bspline.o ../interactive_polygon.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o bspline $(LIBS) + +circles: ../circles.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o circles $(LIBS) + +component_rendering: ../component_rendering.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o component_rendering $(LIBS) + +compositing: ../compositing.o $(PLATFORMSOURCES) compositing.bmp + $(CXX) $(CXXFLAGS) ../compositing.o $(PLATFORMSOURCES) -o compositing $(LIBS) + +conv_contour: ../conv_contour.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o conv_contour $(LIBS) + +conv_dash_marker: ../conv_dash_marker.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o conv_dash_marker $(LIBS) + +conv_stroke: ../conv_stroke.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o conv_stroke $(LIBS) + +distortions: ../distortions.o $(PLATFORMSOURCES) spheres.bmp + $(CXX) $(CXXFLAGS) ../distortions.o $(PLATFORMSOURCES) -o distortions $(LIBS) + +gamma_correction: ../gamma_correction.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gamma_correction $(LIBS) + +gamma_ctrl: ../gamma_ctrl.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gamma_ctrl $(LIBS) + +gouraud: ../gouraud.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gouraud $(LIBS) + +gradient_focal: ../gradient_focal.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gradient_focal $(LIBS) + +gradients: ../gradients.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gradients $(LIBS) + +graph_test: ../graph_test.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o graph_test $(LIBS) + +idea: ../idea.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o idea $(LIBS) + +image_alpha: ../image_alpha.o $(PLATFORMSOURCES) spheres.bmp + $(CXX) $(CXXFLAGS) ../image_alpha.o $(PLATFORMSOURCES) -o image_alpha $(LIBS) + +image_filters: ../image_filters.o $(PLATFORMSOURCES) spheres.bmp + $(CXX) $(CXXFLAGS) ../image_filters.o $(PLATFORMSOURCES) -o image_filters $(LIBS) + +image_filters2: ../image_filters2.o $(PLATFORMSOURCES) spheres.bmp + $(CXX) $(CXXFLAGS) ../image_filters2.o $(PLATFORMSOURCES) -o image_filters2 $(LIBS) + +image_fltr_graph: ../image_fltr_graph.o $(PLATFORMSOURCES) spheres.bmp + $(CXX) $(CXXFLAGS) ../image_fltr_graph.o $(PLATFORMSOURCES) -o image_fltr_graph $(LIBS) + +image_perspective: ../image_perspective.o ../interactive_polygon.o $(PLATFORMSOURCES) spheres.bmp + $(CXX) $(CXXFLAGS) ../image_perspective.o ../interactive_polygon.o $(PLATFORMSOURCES) -o image_perspective $(LIBS) + +image_resample: ../image_resample.o ../interactive_polygon.o $(PLATFORMSOURCES) spheres.bmp + $(CXX) $(CXXFLAGS) ../image_resample.o ../interactive_polygon.o $(PLATFORMSOURCES) -o image_resample $(LIBS) + +image_transforms: ../image_transforms.o $(PLATFORMSOURCES) spheres.bmp + $(CXX) $(CXXFLAGS) ../image_transforms.o $(PLATFORMSOURCES) -o image_transforms $(LIBS) + +image1: ../image1.o $(PLATFORMSOURCES) spheres.bmp + $(CXX) $(CXXFLAGS) ../image1.o $(PLATFORMSOURCES) -o image1 $(LIBS) + +line_patterns: ../line_patterns.o $(PLATFORMSOURCES) 1.bmp 2.bmp 3.bmp 4.bmp 5.bmp 6.bmp 7.bmp 8.bmp 9.bmp + $(CXX) $(CXXFLAGS) ../line_patterns.o $(PLATFORMSOURCES) -o line_patterns $(LIBS) + +lion: ../lion.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o lion $(LIBS) + +lion_lens: ../lion_lens.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o lion_lens $(LIBS) + +lion_outline: ../lion_outline.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o lion_outline $(LIBS) + +mol_view: ../mol_view.o $(PLATFORMSOURCES) 1.sdf + $(CXX) $(CXXFLAGS) ../mol_view.o $(PLATFORMSOURCES) -o mol_view $(LIBS) + +multi_clip: ../multi_clip.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o multi_clip $(LIBS) + +pattern_fill: ../pattern_fill.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o pattern_fill $(LIBS) + +pattern_perspective: ../pattern_perspective.o ../interactive_polygon.o $(PLATFORMSOURCES) agg.bmp + $(CXX) $(CXXFLAGS) ../pattern_perspective.o ../interactive_polygon.o $(PLATFORMSOURCES) -o pattern_perspective $(LIBS) + +perspective: ../perspective.o ../interactive_polygon.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o perspective $(LIBS) + +polymorphic_renderer: ../polymorphic_renderer.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o polymorphic_renderer $(LIBS) + +raster_text: ../raster_text.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o raster_text $(LIBS) + +rasterizers: ../rasterizers.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o rasterizers $(LIBS) + +rasterizers2: ../rasterizers2.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o rasterizers2 $(LIBS) + +rasterizer_compound: ../rasterizer_compound.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o rasterizer_compound $(LIBS) + +rounded_rect: ../rounded_rect.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o rounded_rect $(LIBS) + +scanline_boolean: ../scanline_boolean.o ../interactive_polygon.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o scanline_boolean $(LIBS) + +scanline_boolean2: ../scanline_boolean2.o ../make_arrows.o ../make_gb_poly.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o scanline_boolean2 $(LIBS) + +simple_blur: ../simple_blur.o ../parse_lion.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o simple_blur $(LIBS) + +trans_polar: ../trans_polar.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o trans_polar $(LIBS) + + +freetype_test: ../freetype_test.o ../../font_freetype/agg_font_freetype.o $(PLATFORMSOURCES) timesi.ttf + $(CXX) $(CXXFREETYPEFLAGS) ../freetype_test.o ../../font_freetype/agg_font_freetype.o $(PLATFORMSOURCES) -o freetype_test $(LIBS) -lfreetype + +trans_curve1_ft: ../trans_curve1_ft.o ../../font_freetype/agg_font_freetype.o ../interactive_polygon.o $(PLATFORMSOURCES) timesi.ttf + $(CXX) $(CXXFLAGS) ../trans_curve1_ft.o ../../font_freetype/agg_font_freetype.o ../interactive_polygon.o $(PLATFORMSOURCES) -o trans_curve1_ft $(LIBS) -lfreetype + +trans_curve2_ft: ../trans_curve2_ft.o ../../font_freetype/agg_font_freetype.o ../interactive_polygon.o $(PLATFORMSOURCES) timesi.ttf + $(CXX) $(CXXFLAGS) ../trans_curve2_ft.o ../../font_freetype/agg_font_freetype.o ../interactive_polygon.o $(PLATFORMSOURCES) -o trans_curve2_ft $(LIBS) -lfreetype + +gpc_test: ../gpc_test.o ../make_arrows.o ../make_gb_poly.o $(PLATFORMSOURCES) + $(CXX) $(CXXFLAGS) $^ -o gpc_test $(LIBS) + + +clean: + rm -f ../*.o + rm -f ../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f aa_demo + rm -f aa_test + rm -f alpha_gradient + rm -f alpha_mask + rm -f alpha_mask2 + rm -f alpha_mask3 + rm -f blur + rm -f blend_color + rm -f bezier_div + rm -f bspline + rm -f circles + rm -f component_rendering + rm -f conv_contour + rm -f conv_dash_marker + rm -f conv_stroke + rm -f gamma_correction + rm -f gamma_ctrl + rm -f gouraud + rm -f gradients + rm -f gradient_focal + rm -f graph_test + rm -f idea + rm -f lion + rm -f lion_lens + rm -f lion_outline + rm -f multi_clip + rm -f pattern_fill + rm -f perspective + rm -f polymorphic_renderer + rm -f raster_text + rm -f rasterizers + rm -f rasterizers2 + rm -f rounded_rect + rm -f scanline_boolean + rm -f scanline_boolean2 + rm -f simple_blur + rm -f trans_polar + rm -f image_alpha + rm -f image_filters + rm -f image_filters2 + rm -f image_fltr_graph + rm -f image_perspective + rm -f image_resample + rm -f image_transforms + rm -f image1 + rm -f distortions + rm -f pattern_perspective + rm -f compositing + rm -f line_patterns + rm -f mol_view + rm -f freetype_test + rm -f trans_curve1_ft + rm -f trans_curve2_ft + rm -f gpc_test + +agg.bmp: + @echo "Required file missing!!" + @echo "Please download http://www.antigrain.com/agg.bmp to /examples/sdl/" + @echo "Attempting to retrieve via curl -O : (will fail if curl -O is not installed)" + curl -O http://www.antigrain.com/agg.bmp + +compositing.bmp: + @echo "Required file missing!!" + @echo "Please download http://www.antigrain.com/compositing.bmp to /examples/sdl/" + @echo "Attempting to retrieve via curl -O : (will fail if curl -O is not installed)" + curl -O http://www.antigrain.com/compositing.bmp + +spheres.bmp: + @echo "Required file missing!!" + @echo "Please download http://www.antigrain.com/spheres.bmp to /examples/sdl/" + @echo "Attempting to retrieve file: (will fail if curl -O is not installed)" + curl -O http://www.antigrain.com/spheres.bmp + +1.sdf: + @echo "Required file missing!!" + @echo "Please download http://www.antigrain.com/1.sdf to /examples/sdl/" + @echo "Attempting to retrieve file: (will fail if curl -O is not installed)" + curl -O http://www.antigrain.com/1.sdf + +1.bmp: + @echo "Required file missing!!" + @echo "Please download http://www.antigrain.com/line_patterns.bmp.zip to /examples/sdl/ and decompress it" + @echo "Attempting to retrieve file: (will fail if curl -O is not installed)" + curl -O http://www.antigrain.com/line_patterns.bmp.zip + unzip -o line_patterns.bmp.zip + +timesi.ttf: + @echo "Required file missing!!" + @echo "Please download http://www.antigrain.com/timesi.zip to /examples/sdl/ and decompress it" + @echo "Attempting to retrieve file: (will fail if curl -O is not installed)" + curl -O http://www.antigrain.com/timesi.zip + unzip -o timesi.zip + +../freetype_test.o: ../freetype_test.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFREETYPEFLAGS) $*.cpp -o $@ + +../trans_curve1_ft.o: ../trans_curve1_ft.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFREETYPEFLAGS) $*.cpp -o $@ + +../trans_curve2_ft.o: ../trans_curve2_ft.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFREETYPEFLAGS) $*.cpp -o $@ + +../../font_freetype/agg_font_freetype.o: ../../font_freetype/agg_font_freetype.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFREETYPEFLAGS) $*.cpp -o $@ + +../gpc_test.o: ../gpc_test.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) -I../../gpc $*.cpp -o $@ + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + +.PHONY : clean + + diff --git a/jni/desmume/src/android/agg/examples/macosx_sdl/readme.txt b/jni/desmume/src/android/agg/examples/macosx_sdl/readme.txt new file mode 100755 index 0000000..015b506 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/macosx_sdl/readme.txt @@ -0,0 +1,36 @@ +The Anti-Grain Geometry Project +A high quality rendering engine for C++ +http://antigrain.com + +Anti-Grain Geometry +Copyright (C) 2002-2005 Maxim Shemanarev (McSeem) + +Permission to copy, use, modify, sell and distribute this software +is granted provided this copyright notice appears in all copies. +This software is provided "as is" without express or implied +warranty, and with no claim as to its suitability for any purpose. + +By default only the examples that do not require extra dependancies are built. +with the following commands: + +cd (AGGDIRECTORY)/examples/sdl +make clean +make + +Some examples (freetype_test, trans_curve1_ft and trans_curve2_ft) require the Freetype Library, and can be built with: + +make freetype + +There is also an example (gpc_test) that requires the GPC library, build it with: + +make gpc + +Of course, to build ALL examples run: + +make all + +Alternatively you can also build the examples one by one, using the example name directly: + +make aa_demo +make aa_test +... \ No newline at end of file diff --git a/jni/desmume/src/android/agg/examples/make_arrows.cpp b/jni/desmume/src/android/agg/examples/make_arrows.cpp new file mode 100755 index 0000000..77b2879 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/make_arrows.cpp @@ -0,0 +1,43 @@ +#include "agg_path_storage.h" + +void make_arrows(agg::path_storage& ps) +{ + ps.remove_all(); + + ps.move_to(1330.599999999999909,1282.399999999999864); + ps.line_to(1377.400000000000091,1282.399999999999864); + ps.line_to(1361.799999999999955,1298.000000000000000); + ps.line_to(1393.000000000000000,1313.599999999999909); + ps.line_to(1361.799999999999955,1344.799999999999955); + ps.line_to(1346.200000000000045,1313.599999999999909); + ps.line_to(1330.599999999999909,1329.200000000000045); + ps.close_polygon(); + + ps.move_to(1330.599999999999909,1266.799999999999955); + ps.line_to(1377.400000000000091,1266.799999999999955); + ps.line_to(1361.799999999999955,1251.200000000000045); + ps.line_to(1393.000000000000000,1235.599999999999909); + ps.line_to(1361.799999999999955,1204.399999999999864); + ps.line_to(1346.200000000000045,1235.599999999999909); + ps.line_to(1330.599999999999909,1220.000000000000000); + ps.close_polygon(); + + ps.move_to(1315.000000000000000,1282.399999999999864); + ps.line_to(1315.000000000000000,1329.200000000000045); + ps.line_to(1299.400000000000091,1313.599999999999909); + ps.line_to(1283.799999999999955,1344.799999999999955); + ps.line_to(1252.599999999999909,1313.599999999999909); + ps.line_to(1283.799999999999955,1298.000000000000000); + ps.line_to(1268.200000000000045,1282.399999999999864); + ps.close_polygon(); + + ps.move_to(1268.200000000000045,1266.799999999999955); + ps.line_to(1315.000000000000000,1266.799999999999955); + ps.line_to(1315.000000000000000,1220.000000000000000); + ps.line_to(1299.400000000000091,1235.599999999999909); + ps.line_to(1283.799999999999955,1204.399999999999864); + ps.line_to(1252.599999999999909,1235.599999999999909); + ps.line_to(1283.799999999999955,1251.200000000000045); + ps.close_polygon(); + +} diff --git a/jni/desmume/src/android/agg/examples/make_gb_poly.cpp b/jni/desmume/src/android/agg/examples/make_gb_poly.cpp new file mode 100755 index 0000000..15f76a9 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/make_gb_poly.cpp @@ -0,0 +1,1894 @@ +#include "agg_path_storage.h" + +static double poly1[] = +{ + 1250.8,1312.4, + 1252.8,1311.6, + 1254,1312, + 1254.8,1313.6, + 1254.8,1314.8, + 1256,1314, + 1257.6,1313.6, + 1258.4,1314.4, + 1260.4,1315.6, + 1261.6,1315.6, + 1262.4,1315.6, + 1263.2,1315.6, + 1264.8,1314.8, + 1266,1315.2, + 1266.8,1315.2, + 1267.2,1312.8, + 1266.8,1311.2, + 1267.6,1310.8, + 1268,1310.4, + 1268,1308.8, + 1268.8,1308.4, + 1270,1307.2, + 1270,1306.8, + 1270,1305.6, + 1270.8,1305.6, + 1271.2,1304, + 1271.2,1304, + 1270.4,1305.6, + 1270.8,1306.4, + 1271.2,1306, + 1271.6,1305.6, + 1272,1304.8, + 1271.6,1303.2, + 1271.2,1302.8, + 1269.2,1302, + 1268.4,1300.4, + 1268.4,1300, + 1269.2,1300.4, + 1270.8,1302.4, + 1272.4,1302, + 1273.2,1302, + 1273.6,1300.4, + 1274.8,1299.2, + 1274.4,1298, + 1275.2,1297.2, + 1274.4,1295.6, + 1274.4,1294.8, + 1274.4,1294.4, + 1274.4,1293.6, + 1273.6,1293.6, + 1273.6,1293.6, + 1273.2,1295.2, + 1273.6,1296.4, + 1273.6,1297.6, + 1273.2,1298, + 1272,1299.2, + 1271.6,1299.2, + 1271.2,1298, + 1272,1298, + 1271.6,1297.6, + 1272,1297.2, + 1272.4,1295.6, + 1270.8,1294, + 1272.8,1294.8, + 1273.2,1293.6, + 1273.6,1293.2, + 1272.8,1292.4, + 1271.6,1291.2, + 1271.2,1291.6, + 1270.4,1292, + 1268.8,1290.8, + 1268.8,1289.2, + 1268.4,1287.6, + 1266,1286.4, + 1265.2,1286.4, + 1265.6,1287.2, + 1264.4,1287.6, + 1264,1287.6, + 1263.2,1288, + 1264,1287.6, + 1264.4,1286.4, + 1264.8,1286.4, + 1265.2,1286, + 1264,1285.2, + 1262,1286.4, + 1261.6,1286.4, + 1261.6,1286.4, + 1261.6,1285.6, + 1261.2,1284, + 1261.6,1283.2, + 1262.8,1283.2, + 1262.8,1281.6, + 1263.2,1280.8, + 1263.2,1280, + 1263.2,1278.4, + 1263.2,1277.6, + 1265.2,1275.6, + 1264.8,1274.4, + 1264,1272.4, + 1264.4,1271.2, + 1265.2,1271.2, + 1265.6,1270.4, + 1264,1271.2, + 1263.6,1270.4, + 1263.2,1270.4, + 1263.6,1269.2, + 1264.4,1268.4, + 1264.4,1266.8, + 1265.2,1264.4, + 1264.8,1261.6, + 1266,1261.2, + 1264.8,1258.4, + 1264,1257.6, + 1263.2,1256, + 1262,1254, + 1262.4,1251.6, + 1260,1247.6, + 1259.6,1246.8, + 1258.8,1247.2, + 1258.8,1246.8, + 1258.8,1246, + 1259.2,1245.6, + 1259.2,1246, + 1259.2,1244.4, + 1260,1243.6, + 1259.2,1242.4, + 1258.8,1242.4, + 1259.2,1242.8, + 1258,1242.4, + 1258,1242.8, + 1257.6,1242.8, + 1256,1242.4, + 1254.4,1244, + 1253.2,1243.2, + 1253.6,1244, + 1253.2,1244, + 1252.8,1244, + 1252.4,1243.6, + 1252.8,1242.8, + 1252.4,1242.8, + 1251.6,1242, + 1250.8,1241.2, + 1250.8,1241.6, + 1251.6,1242, + 1251.6,1242.8, + 1251.2,1243.6, + 1250.8,1244, + 1250.4,1245.2, + 1250.8,1243.6, + 1250.4,1242.8, + 1250.8,1242.8, + 1250,1241.6, + 1248.4,1242, + 1249.2,1243.2, + 1248.4,1243.2, + 1248.4,1243.2, + 1248.4,1242.4, + 1247.6,1242.4, + 1247.2,1242, + 1243.6,1242, + 1242,1241.6, + 1242,1241.2, + 1241.2,1241.6, + 1240.8,1241.2, + 1241.2,1240.4, + 1242,1240, + 1241.6,1240, + 1241.6,1239.2, + 1239.6,1239.2, + 1239.2,1238, + 1238.4,1238, + 1237.6,1238, + 1237.2,1238.8, + 1236.8,1238, + 1236.4,1238, + 1236.8,1236.8, + 1235.2,1236.4, + 1234.4,1235.6, + 1234.8,1235.2, + 1232.4,1234.8, + 1231.2,1235.2, + 1231.2,1235.6, + 1232.4,1236, + 1232.8,1236.8, + 1230.8,1236.4, + 1229.6,1237.2, + 1229.2,1236.4, + 1230,1236.4, + 1230.8,1235.6, + 1230.4,1234.8, + 1230.4,1234.4, + 1229.6,1233.2, + 1228.4,1233.2, + 1228,1232.8, + 1226.8,1233.2, + 1227.2,1232.8, + 1226.4,1232, + 1226.4,1230.8, + 1226,1231.2, + 1224.4,1231.2, + 1224,1229.6, + 1223.2,1229.6, + 1223.2,1230.4, + 1221.6,1230.8, + 1221.2,1229.2, + 1220.4,1229.2, + 1220.4,1229.2, + 1219.6,1230.4, + 1218.4,1229.6, + 1217.6,1230.8, + 1218,1229.6, + 1216.8,1229.6, + 1216.8,1230, + 1216.8,1228.8, + 1216.4,1228.8, + 1216,1228.8, + 1216.4,1228.8, + 1215.6,1229.2, + 1215.6,1228.8, + 1214.8,1228.8, + 1214.4,1228.8, + 1214,1229.2, + 1214.4,1230.4, + 1213.6,1231.6, + 1213.6,1230.8, + 1212.8,1230.4, + 1212,1230.8, + 1212,1229.6, + 1211.6,1229.6, + 1211.2,1229.2, + 1210.8,1229.6, + 1210.8,1230.8, + 1209.6,1229.6, + 1210,1229.6, + 1208.8,1229.2, + 1208.8,1230, + 1208,1229.2, + 1208,1230, + 1208,1230, + 1209.6,1231.2, + 1210.8,1231.2, + 1212.4,1232.8, + 1212,1232.8, + 1208.4,1231.2, + 1208,1231.2, + 1208.8,1232, + 1209.6,1232.8, + 1214,1234, + 1214,1234, + 1214,1234.4, + 1213.6,1234.8, + 1213.2,1235.6, + 1212.8,1236, + 1212.8,1235.6, + 1212,1234, + 1207.2,1233.6, + 1206.8,1233.2, + 1205.2,1233.2, + 1204.8,1233.2, + 1204,1233.2, + 1203.6,1233.2, + 1203.6,1233.2, + 1203.6,1233.6, + 1204.8,1233.2, + 1204.8,1234, + 1204.4,1234.4, + 1204.8,1234.4, + 1206.4,1234.8, + 1206.8,1235.6, + 1206,1235.6, + 1206.4,1236.4, + 1207.6,1236.8, + 1208,1236.4, + 1208,1236.8, + 1209.6,1236.8, + 1208.8,1237.2, + 1210,1238.4, + 1211.2,1238.8, + 1212.4,1238.4, + 1210.4,1238.8, + 1209.2,1238, + 1208.4,1238, + 1208,1237.6, + 1207.6,1238, + 1204,1236.4, + 1204,1236.8, + 1202.8,1237.2, + 1203.2,1237.6, + 1203.6,1238.4, + 1203.2,1239.2, + 1202.4,1238.8, + 1201.2,1238, + 1201.6,1239.6, + 1200.8,1239.6, + 1200.4,1240.4, + 1202.4,1240.8, + 1202.8,1240.4, + 1202.4,1241.2, + 1202,1241.6, + 1202.8,1242, + 1202.8,1242.4, + 1206.8,1243.6, + 1207.6,1244.8, + 1207.6,1244, + 1208,1243.6, + 1208.8,1245.6, + 1209.2,1245.2, + 1210.4,1245.2, + 1208.8,1246, + 1207.6,1246, + 1207.6,1245.2, + 1207.2,1246, + 1204.4,1245.2, + 1203.6,1246, + 1202.8,1246, + 1202.4,1246, + 1203.2,1245.6, + 1202.8,1245.2, + 1201.2,1246, + 1202,1245.6, + 1200.8,1245.6, + 1200,1246, + 1200,1246.4, + 1200,1246.8, + 1200.4,1247.2, + 1200,1247.6, + 1200.8,1247.6, + 1200.8,1247.2, + 1201.6,1247.2, + 1201.6,1248.8, + 1202.4,1248.4, + 1203.2,1249.2, + 1204.8,1249.6, + 1204.8,1248.4, + 1206,1248, + 1206.8,1249.6, + 1206.4,1250, + 1207.2,1250.4, + 1206.8,1249.2, + 1208,1248, + 1209.2,1248, + 1209.6,1248, + 1209.6,1248, + 1210.8,1248, + 1210.8,1248.4, + 1208.8,1248.8, + 1208.8,1250, + 1209.6,1249.6, + 1209.6,1250, + 1210,1251.2, + 1208.4,1252, + 1208.4,1252.4, + 1211.2,1252.8, + 1212.4,1254, + 1213.2,1253.2, + 1212.8,1254, + 1212.4,1254, + 1212.4,1254, + 1212.8,1255.2, + 1213.6,1255.6, + 1215.6,1254.8, + 1215.6,1255.2, + 1217.6,1254.8, + 1221.2,1256, + 1221.2,1255.2, + 1222,1255.2, + 1222.8,1256.4, + 1224.4,1256, + 1224.8,1256.4, + 1226,1256.4, + 1224,1257.2, + 1222.8,1257.2, + 1222.8,1257.6, + 1222.4,1258.8, + 1221.2,1258.4, + 1221.2,1257.6, + 1219.6,1255.6, + 1218.4,1256, + 1217.6,1254.8, + 1217.2,1255.6, + 1218,1256.4, + 1216,1256, + 1214.8,1256.4, + 1214.4,1257.2, + 1214,1257.6, + 1214.4,1256.4, + 1212.4,1256.4, + 1212.4,1255.6, + 1209.6,1256, + 1208.8,1256, + 1210.4,1256.4, + 1212.8,1258.4, + 1214,1259.6, + 1215.2,1259.6, + 1215.2,1260.8, + 1216,1261.2, + 1216,1262.8, + 1217.6,1263.6, + 1217.2,1263.6, + 1215.6,1264, + 1215.6,1264, + 1216.4,1264.4, + 1218.8,1268, + 1220.4,1267.6, + 1221.6,1268, + 1221.2,1268, + 1222.8,1268, + 1221.6,1268, + 1223.2,1268, + 1223.2,1268, + 1223.6,1267.6, + 1223.6,1267.6, + 1223.6,1268.4, + 1224.4,1269.6, + 1223.6,1269.2, + 1222.8,1269.6, + 1223.2,1270, + 1223.6,1270.4, + 1224,1270.4, + 1224,1271.2, + 1222.4,1271.2, + 1220.4,1270.4, + 1216,1270.4, + 1215.2,1270.8, + 1215.2,1272.4, + 1215.2,1272, + 1214.8,1270.8, + 1214.8,1270.8, + 1214.8,1271.6, + 1214.8,1272.4, + 1214.8,1273.2, + 1214.8,1273.2, + 1215.2,1273.2, + 1214.8,1273.6, + 1214.8,1273.2, + 1214.8,1273.6, + 1214.4,1273.6, + 1214.8,1274, + 1214.4,1274, + 1213.6,1273.2, + 1213.2,1272.8, + 1212,1273.6, + 1211.2,1273.6, + 1211.6,1274.4, + 1211.2,1274.4, + 1213.2,1275.2, + 1213.2,1275.2, + 1212.8,1275.2, + 1212.8,1275.6, + 1211.6,1275.6, + 1211.6,1275.6, + 1211.6,1275.6, + 1211.2,1275.6, + 1210.8,1275.6, + 1210.4,1274.8, + 1209.2,1275.6, + 1208.8,1276, + 1208,1275.6, + 1207.6,1276.4, + 1207.2,1276, + 1208,1277.6, + 1209.2,1277.2, + 1208.4,1278, + 1208.4,1278.8, + 1208,1279.2, + 1207.2,1279.6, + 1208.8,1279.2, + 1208.8,1280, + 1210.4,1279.6, + 1209.6,1281.2, + 1212,1281.2, + 1212,1282.4, + 1212.4,1283.6, + 1214,1284.4, + 1215.6,1284, + 1216.4,1284.8, + 1215.6,1284.8, + 1216,1285.2, + 1215.6,1285.2, + 1216,1286.4, + 1216,1286.4, + 1216.4,1286.8, + 1214,1286.8, + 1213.2,1286.8, + 1212,1286.8, + 1212,1286.8, + 1212.4,1288.8, + 1213.6,1288, + 1214,1287.6, + 1214,1287.6, + 1214,1289.2, + 1213.6,1289.2, + 1213.6,1288.4, + 1213.6,1289.2, + 1213.6,1289.6, + 1212.8,1290.4, + 1212.8,1291.2, + 1213.6,1291.6, + 1213.2,1291.6, + 1214,1292.4, + 1213.2,1292.4, + 1213.2,1291.6, + 1212.4,1292, + 1212,1292, + 1212,1292, + 1212.8,1292.8, + 1212.4,1293.2, + 1212.8,1293.6, + 1212.4,1294, + 1212.8,1294.4, + 1212.8,1294.4, + 1211.6,1295.2, + 1211.6,1294.4, + 1211.2,1294.4, + 1211.6,1294, + 1210.8,1294, + 1210.8,1293.6, + 1210.4,1293.2, + 1210.8,1292, + 1210,1292.4, + 1210.4,1295.2, + 1210.8,1295.2, + 1210,1296, + 1210.8,1296, + 1210.8,1296.4, + 1212,1297.6, + 1212.4,1296.4, + 1213.2,1295.6, + 1212.8,1294.8, + 1212,1295.6, + 1212,1295.2, + 1213.6,1294.8, + 1213.6,1296, + 1214,1295.6, + 1214,1296.4, + 1214,1296.4, + 1213.6,1297.2, + 1214,1297.6, + 1215.6,1297.2, + 1218.4,1296.8, + 1219.6,1295.2, + 1220.4,1296.4, + 1221.2,1296, + 1221.6,1295.2, + 1222.4,1294.8, + 1222,1294.4, + 1222.4,1294, + 1222,1293.6, + 1222.8,1293.2, + 1223.2,1292.8, + 1224.4,1295.2, + 1226,1295.2, + 1227.6,1294, + 1228.4,1294.4, + 1228.8,1294.4, + 1229.6,1294, + 1230.8,1292.8, + 1231.6,1292.8, + 1230.8,1294, + 1230.4,1294, + 1231.2,1294.4, + 1232.4,1294.4, + 1231.2,1295.6, + 1231.2,1295.6, + 1232.4,1295.2, + 1232.4,1295.6, + 1231.6,1296, + 1230.4,1295.6, + 1230,1296, + 1231.2,1296.8, + 1231.2,1297.6, + 1231.6,1297.6, + 1232.8,1298, + 1232.4,1298.8, + 1232.8,1299.2, + 1233.2,1298.8, + 1235.2,1298.8, + 1236,1300, + 1236.4,1300.4, + 1237.6,1302.4, + 1238,1302.4, + 1238.4,1302, + 1238,1302.4, + 1236,1302.4, + 1235.6,1302.4, + 1235.6,1302.4, + 1235.6,1302.4, + 1234.8,1302.4, + 1233.2,1300.8, + 1233.2,1302, + 1234.4,1302.4, + 1234.4,1302.4, + 1233.2,1302.4, + 1232.8,1302.4, + 1231.6,1302.4, + 1230.4,1302.4, + 1228.8,1304, + 1229.2,1304.4, + 1228.8,1304.4, + 1229.6,1304.4, + 1229.2,1305.6, + 1230.4,1306.4, + 1234,1305.6, + 1233.2,1306.4, + 1232.4,1306.4, + 1233.2,1306.4, + 1234.4,1305.6, + 1232.4,1307.6, + 1233.2,1307.6, + 1235.6,1307.6, + 1234.8,1308.4, + 1234.8,1308.8, + 1235.6,1308.4, + 1236,1308.4, + 1235.6,1308.8, + 1234.8,1309.2, + 1234.8,1308.8, + 1234,1309.2, + 1234,1310.4, + 1235.2,1310.4, + 1234.8,1310.4, + 1234,1312, + 1234.8,1312, + 1234.8,1312.8, + 1235.6,1312.4, + 1235.6,1313.2, + 1236,1313.2, + 1236,1313.2, + 1236.4,1313.2, + 1236.4,1313.6, + 1236.8,1314.8, + 1238.4,1314.4, + 1238.8,1314.4, + 1238.8,1314.4, + 1238.4,1314, + 1239.6,1314.4, + 1240.4,1314.8, + 1240.4,1316.4, + 1240.8,1316.8, + 1241.6,1316.4, + 1241.6,1315.6, + 1242,1315.6, + 1242.4,1314.8, + 1242,1314.4, + 1242.8,1314.4, + 1242,1314.4, + 1242.8,1314.4, + 1242.8,1314.4, + 1243.2,1315.6, + 1242.4,1315.6, + 1242,1316.8, + 1242.8,1316.8, + 1243.2,1316.8, + 1243.2,1314.8, + 1244,1314.4, + 1244.8,1314, + 1244.8,1313.2, + 1245.2,1314, + 1244.8,1316.4, + 1244.4,1314.4, + 1244.4,1315.2, + 1244.4,1316, + 1243.6,1316.4, + 1244,1316.8, + 1244.4,1316.8, + 1245.2,1317.6, + 1246,1316.8, + 1246,1315.2, + 1246.8,1314, + 1246.8,1314, + 1246.8,1312.8, + 1245.2,1311.6, + 1246,1311.6, + 1246.4,1311.6, + 1245.2,1311.2, + 1244.8,1310, + 1246.4,1311.6, + 1247.6,1312, + 1247.6,1312.4, + 1247.6,1314, + 1246.8,1316, + 1247.6,1316.4, + 1246.8,1317.2, + 1247.6,1317.2, + 1247.6,1317.2, + 1248,1317.2, + 1249.2,1317.6, + 1249.6,1317.6, + 1249.6,1317.2, + 1250.8,1317.2, + 1249.6,1317.6, + 1249.2,1318.4, + 1249.6,1318.4, + 1249.2,1319.2, + 1248.8,1319.6, + 1248.8,1319.6, + 1250.8,1319.2, + 1251.6,1318.4, + 1252.4,1317.6, + 1255.2,1316, + 1255.2,1315.6, + 1252,1314 +}; + + +static double poly2[] = +{ + 1284,1396.4, + 1284.4,1395.6, + 1285.2,1395.6, + 1286,1395.2, + 1286,1394.8, + 1286.8,1395.2, + 1286.4,1395.2, + 1286.4,1395.2, + 1286.8,1394.8, + 1288,1394, + 1288,1393.6, + 1286.8,1391.6, + 1288,1392.8, + 1288,1393.6, + 1288.8,1393.6, + 1288.8,1394.8, + 1290,1394.4, + 1290.8,1393.6, + 1291.2,1393.2, + 1290.4,1391.2, + 1291.6,1393.6, + 1292.8,1393.6, + 1293.6,1392.8, + 1293.6,1393.2, + 1293.6,1394, + 1294.4,1393.6, + 1294.8,1394.4, + 1295.6,1394, + 1296,1394.8, + 1296,1394.4, + 1297.6,1394.4, + 1298.8,1394.4, + 1300.4,1394.8, + 1302,1394.8, + 1302,1394.4, + 1302.4,1394.4, + 1303.2,1395.2, + 1304.4,1394.8, + 1304.4,1395.2, + 1303.6,1396.4, + 1304.4,1396.8, + 1304.4,1396.4, + 1306.8,1396, + 1306.8,1395.6, + 1308.4,1396, + 1308.8,1395.6, + 1307.6,1392.8, + 1307.6,1392, + 1308.8,1392, + 1307.6,1389.6, + 1307.2,1389.2, + 1306.4,1387.6, + 1304.4,1387.2, + 1302.8,1384, + 1299.6,1382, + 1298.8,1381.6, + 1298,1380.8, + 1296.4,1379.2, + 1296,1377.6, + 1295.2,1377.6, + 1294.4,1377.2, + 1293.6,1376.8, + 1293.6,1376.4, + 1295.2,1376.4, + 1296.4,1376.8, + 1296.8,1376.8, + 1296.8,1376.4, + 1298,1376.4, + 1298.8,1377.6, + 1299.2,1377.2, + 1298,1375.2, + 1296.4,1373.6, + 1296,1373.6, + 1296,1374, + 1295.2,1374, + 1294,1373.2, + 1292.4,1373.6, + 1292.4,1372.4, + 1290.8,1371.2, + 1290.4,1370.4, + 1293.2,1372.8, + 1295.2,1372.8, + 1295.6,1373.6, + 1296.4,1372.8, + 1294.8,1371.2, + 1294.8,1371.2, + 1294.8,1370.4, + 1294,1370, + 1293.6,1369.6, + 1292.8,1370, + 1293.2,1369.6, + 1292.8,1368.8, + 1293.6,1368.4, + 1294,1368.4, + 1294,1368.4, + 1295.6,1370, + 1295.6,1370.4, + 1295.2,1371.2, + 1298,1371.2, + 1300.4,1372, + 1302,1372.4, + 1302.8,1373.6, + 1304.8,1374.4, + 1308.8,1372.4, + 1310.8,1373.6, + 1311.2,1373.2, + 1312.4,1373.2, + 1316.8,1372.4, + 1317.6,1372.4, + 1318.4,1373.2, + 1319.6,1372.4, + 1320.4,1373.2, + 1322,1373.2, + 1322,1372.4, + 1322.8,1372.8, + 1323.6,1372.4, + 1324,1371.6, + 1324,1370.4, + 1324.8,1368.8, + 1324.4,1368.8, + 1324.8,1368, + 1325.2,1368, + 1321.6,1363.2, + 1320.8,1360.4, + 1321.2,1359.6, + 1319.6,1356, + 1319.6,1354.4, + 1318.4,1352.4, + 1317.2,1351.2, + 1316.8,1351.2, + 1316.8,1349.2, + 1316.8,1349.2, + 1315.6,1348.4, + 1316,1347.6, + 1315.2,1346, + 1312.8,1344.4, + 1312.4,1344, + 1311.6,1344, + 1310.8,1343.6, + 1310,1344, + 1309.2,1343.6, + 1308.4,1343.6, + 1305.6,1342, + 1304.8,1341.6, + 1305.2,1341.2, + 1306.4,1342, + 1310.4,1343.6, + 1311.6,1343.2, + 1311.2,1342, + 1311.2,1341.6, + 1311.2,1341.6, + 1312,1340.4, + 1313.6,1340.4, + 1314.8,1338.8, + 1313.2,1338, + 1311.6,1337.6, + 1310,1337.6, + 1309.6,1337.6, + 1307.2,1335.2, + 1306.8,1334.4, + 1305.2,1334, + 1303.6,1332.8, + 1301.2,1334, + 1299.6,1334, + 1299.6,1332.8, + 1300,1332.8, + 1302,1332.8, + 1304,1332.4, + 1304.4,1332.8, + 1305.2,1332.4, + 1307.2,1332.4, + 1307.6,1331.6, + 1308.8,1331.6, + 1309.6,1332.4, + 1310,1332.4, + 1310.8,1332.8, + 1310.8,1333.6, + 1311.6,1334.4, + 1313.6,1334.4, + 1314.8,1332.8, + 1314.8,1332.8, + 1316,1332.8, + 1318.4,1330.8, + 1320.8,1330.4, + 1320.8,1330.4, + 1321.6,1329.6, + 1322.8,1326.8, + 1324.8,1324.4, + 1325.2,1324.4, + 1325.6,1324, + 1325.6,1323.6, + 1325.6,1323.2, + 1326.8,1323.2, + 1327.2,1323.2, + 1327.6,1321.6, + 1328.4,1320.4, + 1328.4,1319.2, + 1328,1318, + 1328.8,1316.8, + 1328.4,1315.6, + 1329.6,1313.2, + 1329.6,1312.4, + 1330.8,1309.2, + 1331.6,1308, + 1331.6,1307.2, + 1332.8,1303.6, + 1333.2,1302, + 1334.4,1301.6, + 1334,1301.6, + 1334.4,1300.8, + 1334.4,1299.6, + 1334.4,1299.6, + 1334.8,1299.6, + 1334.8,1300, + 1337.2,1299.2, + 1339.6,1298.4, + 1341.6,1297.2, + 1342.8,1296.8, + 1343.6,1296.4, + 1343.6,1295.6, + 1344.8,1294, + 1346,1292, + 1347.2,1291.2, + 1347.6,1289.6, + 1350,1288.8, + 1348.8,1287.6, + 1348,1286.4, + 1349.6,1282.8, + 1351.2,1280, + 1352.8,1277.2, + 1353.2,1275.6, + 1353.2,1275.6, + 1353.2,1276.4, + 1352.8,1276.8, + 1351.6,1277.2, + 1351.2,1276.8, + 1350.4,1276.8, + 1349.6,1277.2, + 1348,1279.2, + 1347.2,1279.6, + 1345.6,1278.4, + 1343.6,1278, + 1342.4,1278.8, + 1341.2,1278, + 1341.6,1277.6, + 1342.8,1278, + 1344,1277.6, + 1344.8,1277.6, + 1347.2,1278.4, + 1348,1278, + 1348.4,1277.2, + 1350.4,1275.6, + 1351.2,1275.6, + 1351.6,1274.4, + 1352.4,1273.2, + 1353.6,1273.2, + 1354,1272.4, + 1354.8,1271.2, + 1356,1267.6, + 1356.8,1266, + 1356.4,1264.4, + 1354,1262, + 1352.8,1259.6, + 1352.4,1259.6, + 1352,1259.2, + 1352.8,1259.2, + 1353.6,1259.2, + 1354,1258.8, + 1355.6,1257.2, + 1357.2,1257.6, + 1357.6,1256.4, + 1357.6,1256.8, + 1358,1258, + 1358.8,1260.8, + 1359.6,1261.6, + 1360.4,1261.2, + 1361.2,1261.6, + 1364,1261.2, + 1364.4,1261.6, + 1364.8,1261.6, + 1365.6,1261.6, + 1366.4,1261.6, + 1365.6,1262, + 1366,1262, + 1366.8,1262, + 1367.6,1261.6, + 1370.4,1261.2, + 1372.4,1259.6, + 1376,1257.2, + 1376.4,1257.2, + 1377.6,1254.4, + 1377.6,1252.8, + 1378,1251.6, + 1377.6,1250, + 1378,1248.8, + 1376.4,1245.6, + 1376.4,1243.6, + 1376,1241.2, + 1374,1240, + 1372.8,1237.2, + 1371.6,1238.8, + 1371.6,1237.6, + 1370,1238, + 1369.6,1237.6, + 1372,1237.6, + 1370.8,1235.2, + 1371.6,1235.2, + 1371.6,1236, + 1372,1235.2, + 1372,1235.2, + 1370.8,1234, + 1369.6,1233.2, + 1368.4,1233.6, + 1367.6,1234, + 1366.8,1234, + 1366,1233.2, + 1365.6,1232.4, + 1363.6,1232, + 1364.4,1231.6, + 1364.8,1231.6, + 1366.4,1232.8, + 1367.2,1232.4, + 1367.2,1231.2, + 1366.8,1229.6, + 1366.4,1229.6, + 1365.2,1229.2, + 1366,1229.6, + 1366.4,1229.2, + 1366.4,1229.6, + 1367.2,1229.6, + 1367.6,1229.2, + 1365.2,1227.2, + 1363.2,1227.2, + 1362,1226, + 1360.4,1226, + 1360,1226, + 1359.2,1225.2, + 1360,1225.2, + 1360.4,1226, + 1361.6,1226, + 1364,1226, + 1364.4,1225.2, + 1364,1224.8, + 1363.2,1224.8, + 1362.4,1224.4, + 1361.6,1224.4, + 1362.4,1223.6, + 1363.2,1223.6, + 1363.6,1223.6, + 1364,1223.6, + 1364,1224.4, + 1364.4,1224, + 1364.4,1224.4, + 1364.4,1225.2, + 1366.8,1224.8, + 1367.6,1223.2, + 1366.8,1223.2, + 1365.2,1222.8, + 1367.2,1222.8, + 1371.6,1224, + 1375.2,1224.4, + 1374.8,1223.2, + 1374,1222, + 1374.8,1220.4, + 1374.4,1218.4, + 1374,1218, + 1372,1217.2, + 1371.6,1217.2, + 1370.4,1216.4, + 1369.2,1215.6, + 1368.4,1214.4, + 1368.8,1212.8, + 1366,1212.8, + 1364.8,1212.4, + 1364,1211.6, + 1359.2,1210, + 1358.4,1208.4, + 1357.6,1207.6, + 1354.4,1208.8, + 1351.2,1210, + 1344,1208.4, + 1343.6,1207.6, + 1343.2,1208.4, + 1343.2,1207.2, + 1342.4,1207.2, + 1340.8,1208.4, + 1341.2,1208.4, + 1340.8,1209.6, + 1340.4,1209.2, + 1340,1209.6, + 1339.6,1209.6, + 1340,1209.2, + 1340.4,1208.4, + 1338.8,1208.4, + 1339.2,1208.4, + 1339.2,1209.6, + 1338.4,1209.2, + 1338.4,1208, + 1338,1208, + 1337.6,1208, + 1338,1209.2, + 1338,1210, + 1336.4,1209.2, + 1337.2,1208.8, + 1336.8,1208, + 1334.4,1209.2, + 1333.6,1210.4, + 1332,1211.2, + 1332,1210.8, + 1333.2,1210.4, + 1334.4,1208.8, + 1333.6,1208, + 1332.4,1208, + 1331.2,1206.8, + 1329.2,1206.8, + 1328,1206.8, + 1328.4,1206.8, + 1328.4,1206.8, + 1327.2,1206.8, + 1326.4,1206.8, + 1325.2,1205.6, + 1325.2,1206.8, + 1323.6,1206.8, + 1323.2,1205.6, + 1323.6,1206, + 1323.6,1205.2, + 1325.2,1205.2, + 1325.2,1204.4, + 1325.6,1204.4, + 1325.2,1204, + 1324.8,1203.2, + 1323.6,1203.2, + 1323.2,1203.2, + 1321.2,1204, + 1318,1204, + 1317.6,1203.6, + 1317.2,1202.8, + 1318,1202, + 1317.2,1201.2, + 1317.2,1202.4, + 1314.8,1204.4, + 1312.4,1206, + 1310.8,1206.4, + 1309.6,1205.6, + 1307.6,1205.6, + 1306,1205.6, + 1303.6,1203.2, + 1302.8,1203.6, + 1302,1205.2, + 1302.4,1203.2, + 1301.2,1201.2, + 1301.6,1200, + 1300.4,1199.2, + 1300.8,1198.8, + 1301.6,1198, + 1301.2,1198, + 1300.8,1197.6, + 1300,1197.2, + 1300,1196.8, + 1299.2,1196.4, + 1299.2,1195.6, + 1299.2,1194.4, + 1298,1194, + 1297.2,1194.4, + 1297.2,1194.4, + 1296.4,1194.4, + 1295.6,1196, + 1294.4,1196.8, + 1292.8,1196.8, + 1291.6,1196.8, + 1291.6,1197.6, + 1290.4,1198, + 1290.4,1198, + 1291.2,1197.6, + 1290.8,1196.8, + 1290,1196.8, + 1289.6,1198, + 1288.8,1198, + 1287.2,1198, + 1286.4,1197.2, + 1283.6,1197.2, + 1283.2,1197.2, + 1283.2,1197.6, + 1282,1197.2, + 1281.2,1194.8, + 1280,1195.2, + 1279.6,1194.4, + 1278.8,1194.4, + 1278.8,1192.8, + 1278,1192.8, + 1278.4,1192.8, + 1278,1192.8, + 1278,1195.2, + 1277.6,1195.2, + 1277.2,1194.4, + 1277.6,1193.6, + 1277.2,1192.8, + 1277.6,1192.8, + 1277.2,1192.8, + 1277.2,1192, + 1276.4,1192, + 1277.2,1191.6, + 1277.2,1190.8, + 1276.8,1190, + 1275.6,1190, + 1275.2,1188.8, + 1274.4,1190, + 1274,1191.2, + 1273.2,1191.6, + 1270.8,1193.2, + 1270,1192.8, + 1270,1192, + 1269.6,1191.2, + 1268,1190.8, + 1267.2,1191.6, + 1267.6,1192, + 1267.2,1193.6, + 1268,1193.2, + 1270,1195.2, + 1271.6,1194.4, + 1272.4,1195.2, + 1273.2,1195.2, + 1274,1196.4, + 1274.8,1197.6, + 1276,1198.4, + 1276,1199.2, + 1277.6,1199.6, + 1278.4,1200.8, + 1278,1201.6, + 1278.4,1202.4, + 1278.8,1202.4, + 1279.6,1203.2, + 1279.6,1202.8, + 1280,1203.6, + 1282,1203.6, + 1282,1205.2, + 1283.2,1206.4, + 1283.6,1207.2, + 1285.6,1208, + 1285.6,1210.8, + 1286.4,1213.2, + 1286.8,1213.2, + 1288.8,1212.8, + 1289.2,1212.8, + 1290.4,1213.6, + 1291.2,1214.4, + 1290,1216.4, + 1290.4,1216.4, + 1290.4,1216.8, + 1290.8,1216.8, + 1297.2,1218.8, + 1300,1218.4, + 1300.4,1218.4, + 1302.4,1217.6, + 1302.8,1217.2, + 1304.4,1217.2, + 1306,1217.6, + 1308,1217.6, + 1308.8,1218.4, + 1308.8,1218.8, + 1308.8,1220, + 1309.2,1220, + 1309.6,1222, + 1310.4,1222.8, + 1312.4,1224.4, + 1313.2,1224.8, + 1316.8,1230, + 1318,1230.8, + 1318,1231.6, + 1318,1230.8, + 1316.8,1230.8, + 1313.2,1227.2, + 1310.8,1226, + 1309.6,1225.6, + 1309.6,1225.6, + 1309.6,1225.6, + 1308.8,1225.6, + 1307.2,1224.4, + 1307.2,1223.6, + 1306.4,1223.6, + 1306.4,1222.8, + 1305.2,1222.4, + 1302.8,1222.4, + 1300.8,1222.8, + 1299.2,1224.4, + 1298.4,1224.4, + 1297.2,1225.6, + 1296.4,1228, + 1294,1228, + 1294,1227.6, + 1294,1226, + 1291.6,1226, + 1291.6,1226, + 1290.8,1225.6, + 1289.6,1226, + 1289.6,1227.2, + 1290,1227.6, + 1290.4,1227.6, + 1290.8,1227.6, + 1292.4,1228, + 1292.8,1228.8, + 1293.2,1229.2, + 1292,1228.8, + 1291.2,1229.6, + 1289.6,1229.2, + 1289.6,1229.2, + 1288.4,1230, + 1288.4,1230.8, + 1289.6,1230, + 1288.8,1231.2, + 1288.8,1232, + 1288.4,1231.2, + 1287.6,1231.6, + 1287.6,1230.8, + 1284.4,1230.4, + 1283.6,1229.2, + 1282.8,1229.2, + 1282.4,1228.4, + 1281.2,1228, + 1280,1227.6, + 1278.4,1228.4, + 1278.4,1229.2, + 1277.6,1229.2, + 1277.6,1229.6, + 1278.4,1229.2, + 1278.8,1229.6, + 1278.8,1229.6, + 1279.6,1229.6, + 1281.2,1230, + 1279.6,1230.4, + 1276.8,1230.4, + 1276.8,1229.6, + 1276,1230.4, + 1275.6,1231.2, + 1276.4,1231.2, + 1276.8,1232, + 1278,1232, + 1277.6,1234, + 1276.4,1234, + 1274.4,1234.4, + 1274.8,1236, + 1276,1235.6, + 1276.4,1236, + 1278,1236.8, + 1278,1237.6, + 1279.6,1237.2, + 1280,1237.2, + 1280.8,1237.2, + 1280.8,1238, + 1281.2,1237.2, + 1282,1237.6, + 1282,1238.4, + 1282.8,1238.8, + 1283.6,1240, + 1284,1240, + 1284,1240.8, + 1286.8,1240.4, + 1288.8,1242.4, + 1289.6,1242.4, + 1290.8,1242.8, + 1292,1244.8, + 1292.8,1246.4, + 1293.6,1249.6, + 1294.4,1250, + 1295.2,1250.4, + 1293.6,1250.4, + 1292.4,1251.6, + 1293.6,1254, + 1294.4,1255.2, + 1293.6,1254.4, + 1293.2,1255.2, + 1292.4,1255.6, + 1292,1256.4, + 1292.8,1257.6, + 1292,1258.4, + 1288.8,1258.4, + 1288,1257.6, + 1287.6,1256.8, + 1287.6,1256.4, + 1286.8,1255.2, + 1285.6,1256.8, + 1285.2,1256.4, + 1284,1256.8, + 1283.6,1256, + 1283.6,1256.8, + 1284,1257.6, + 1285.6,1258.8, + 1286.8,1259.6, + 1289.2,1261.6, + 1289.2,1263.6, + 1290,1263.6, + 1290,1263.6, + 1292,1266.4, + 1292.8,1266.8, + 1293.6,1266.8, + 1296.4,1267.6, + 1296.8,1267.6, + 1296.4,1268.8, + 1297.6,1268.4, + 1298.4,1267.6, + 1300,1268, + 1303.6,1269.2, + 1304.8,1269.2, + 1304.8,1268.8, + 1307.6,1266.4, + 1308,1267.6, + 1306,1270, + 1306.4,1270, + 1308.4,1271.2, + 1308.8,1270.4, + 1310,1268.4, + 1311.2,1268, + 1312.4,1268, + 1312.8,1268.8, + 1312,1268.8, + 1310.4,1268.8, + 1309.6,1270.4, + 1307.6,1273.2, + 1309.2,1277.2, + 1311.2,1278.8, + 1308.4,1278.8, + 1308,1280.4, + 1308.4,1282.8, + 1310.4,1283.6, + 1310.8,1283.2, + 1311.2,1284.4, + 1310.8,1284.4, + 1310.8,1284.8, + 1310.4,1284.8, + 1310,1285.6, + 1310.8,1286.8, + 1311.6,1286.8, + 1311.6,1287.6, + 1311.2,1289.2, + 1311.6,1290, + 1310.8,1290, + 1310,1288.4, + 1309.6,1288.4, + 1308.4,1290, + 1307.6,1287.6, + 1306.8,1286.4, + 1307.2,1286.4, + 1305.6,1287.6, + 1305.6,1288.4, + 1305.6,1288.8, + 1306,1288.8, + 1306.4,1291.2, + 1305.6,1289.6, + 1304.4,1289.6, + 1303.2,1291.6, + 1303.2,1292.8, + 1300,1297.2, + 1300.8,1299.2, + 1301.2,1300.4, + 1302,1302, + 1302.8,1303.2, + 1302.8,1304, + 1303.6,1305.6, + 1304.4,1306, + 1304.4,1305.6, + 1305.2,1305.6, + 1305.6,1306, + 1305.2,1306, + 1305.2,1306.8, + 1306,1307.6, + 1307.6,1306.8, + 1308.4,1307.2, + 1308.4,1307.6, + 1308,1307.6, + 1308,1308, + 1308.8,1308, + 1308.8,1308.4, + 1307.2,1308.4, + 1305.6,1308, + 1303.2,1308, + 1302.8,1308, + 1302,1308, + 1301.6,1308, + 1301.2,1308, + 1301.2,1308, + 1301.2,1305.6, + 1300.8,1305.6, + 1299.2,1306, + 1298.4,1305.6, + 1298,1306, + 1297.6,1305.6, + 1297.6,1306, + 1298,1306, + 1297.2,1305.2, + 1297.6,1304.8, + 1295.6,1303.2, + 1294.4,1303.2, + 1294.4,1304.8, + 1294,1303.6, + 1293.2,1303.6, + 1292,1304.8, + 1292.4,1306, + 1291.6,1304.8, + 1290.4,1306, + 1290,1306.4, + 1289.6,1307.2, + 1289.6,1306, + 1289.2,1306.4, + 1289.2,1304.8, + 1290.4,1304.4, + 1290,1303.6, + 1290.4,1301.6, + 1290,1301.6, + 1288,1301.6, + 1286.8,1303.6, + 1284.4,1304.8, + 1284,1306, + 1283.6,1306.4, + 1282.4,1305.2, + 1281.6,1304.4, + 1282.4,1301.6, + 1282.8,1301.6, + 1283.2,1301.2, + 1283.6,1300.4, + 1283.2,1300.4, + 1282,1301.2, + 1282,1302.4, + 1279.6,1306, + 1278.8,1308, + 1279.2,1309.6, + 1280,1309.6, + 1280.4,1309.6, + 1280.8,1307.6, + 1281.6,1306.4, + 1281.6,1307.2, + 1280.8,1309.6, + 1280.8,1310, + 1281.2,1312.4, + 1283.6,1314.8, + 1284,1317.2, + 1284.8,1317.6, + 1285.2,1319.2, + 1286.8,1319.6, + 1286.8,1320.4, + 1286.4,1321.6, + 1286,1321.6, + 1286.4,1322, + 1286,1323.2, + 1284.4,1324, + 1284.4,1324.4, + 1283.2,1326, + 1284,1326.8, + 1283.6,1328.4, + 1283.2,1330.8, + 1283.6,1331.2, + 1284.8,1332.4, + 1285.6,1330.8, + 1288.8,1330.8, + 1286.8,1332, + 1285.2,1333.2, + 1284.4,1334.4, + 1284.8,1333.2, + 1285.2,1332.8, + 1284.8,1332.8, + 1284,1332.8, + 1283.6,1334.4, + 1284.8,1335.6, + 1284,1335.2, + 1284,1336, + 1283.6,1336.4, + 1283.2,1335.6, + 1284,1334.8, + 1283.6,1333.2, + 1282.8,1333.2, + 1283.2,1332.8, + 1282,1330, + 1281.2,1330, + 1281.2,1331.2, + 1280.8,1332.8, + 1280.8,1330.8, + 1279.6,1331.2, + 1279.6,1332.8, + 1279.6,1332.8, + 1279.2,1330.8, + 1278.8,1330.8, + 1279.2,1329.2, + 1277.6,1330, + 1277.2,1330.8, + 1277.6,1333.2, + 1278.4,1334.8, + 1279.6,1335.6, + 1279.6,1336, + 1281.2,1336.8, + 1281.6,1338, + 1283.2,1339.6, + 1282,1338.8, + 1281.2,1338.8, + 1280.8,1337.2, + 1278.8,1336, + 1277.2,1333.2, + 1276.4,1333.2, + 1276,1333.2, + 1276,1332, + 1276.4,1331.2, + 1276.4,1330, + 1278,1328.4, + 1277.6,1327.6, + 1276.8,1327.2, + 1276,1326, + 1275.6,1324.8, + 1275.2,1323.6, + 1275.6,1323.2, + 1275.2,1322.8, + 1275.2,1322, + 1274,1319.6, + 1273.6,1319.6, + 1274,1319.6, + 1274.8,1318.4, + 1274,1317.2, + 1272,1316.4, + 1270.8,1316.8, + 1270.8,1319.2, + 1272,1319.6, + 1272.4,1322, + 1272,1323.2, + 1272.8,1324.4, + 1272.8,1325.2, + 1275.6,1329.2, + 1274,1328, + 1272.8,1328.4, + 1272.8,1329.6, + 1274.4,1331.6, + 1272.8,1330.8, + 1272.8,1331.6, + 1274.8,1334.4, + 1274,1333.6, + 1272.8,1331.6, + 1272.4,1331.6, + 1272.8,1333.2, + 1273.6,1333.6, + 1273.6,1334.8, + 1274.4,1335.2, + 1275.2,1335.2, + 1274.8,1336, + 1275.2,1338, + 1274.4,1336, + 1274,1336.4, + 1274.8,1338, + 1274.4,1339.2, + 1274.4,1341.2, + 1275.2,1341.2, + 1276.4,1344, + 1279.2,1343.6, + 1278,1344.8, + 1277.2,1344.4, + 1276.8,1344.8, + 1276.8,1344.4, + 1276.4,1344.8, + 1276.8,1345.6, + 1277.6,1345.2, + 1278.4,1346, + 1279.2,1346.4, + 1277.6,1346, + 1277.2,1346.4, + 1278,1348.4, + 1278.4,1348.8, + 1278.4,1348.8, + 1279.6,1349.2, + 1280.8,1349.2, + 1281.6,1349.6, + 1280.8,1349.2, + 1279.2,1349.6, + 1281.2,1352.8, + 1280,1351.6, + 1279.6,1351.6, + 1278.8,1350, + 1278,1349.6, + 1277.6,1349.6, + 1276,1348, + 1275.2,1346, + 1273.2,1345.2, + 1273.2,1345.2, + 1272.4,1346, + 1272.4,1346, + 1270.4,1346.8, + 1269.6,1347.6, + 1269.2,1348.8, + 1270,1349.2, + 1270.8,1349.2, + 1272.8,1350, + 1274,1349.6, + 1275.2,1349.2, + 1273.6,1349.6, + 1272.4,1350, + 1271.6,1349.6, + 1270.8,1350, + 1266.8,1350, + 1266.4,1350.4, + 1267.6,1351.6, + 1269.2,1351.6, + 1270,1352, + 1270.8,1351.6, + 1271.2,1351.2, + 1271.2,1352, + 1271.2,1351.6, + 1272.4,1352, + 1272.4,1352, + 1271.6,1353.2, + 1271.6,1353.6, + 1272.8,1353.6, + 1273.2,1353.6, + 1274,1354, + 1273.6,1354, + 1273.2,1353.6, + 1272.8,1354, + 1273.2,1354.8, + 1270.8,1355.2, + 1271.2,1354.8, + 1272,1354.8, + 1271.6,1355.2, + 1272,1357.2, + 1273.2,1357.6, + 1273.2,1357.2, + 1274,1356.4, + 1276,1356.8, + 1274.8,1356.8, + 1274,1357.2, + 1274,1357.6, + 1274,1358.4, + 1272.8,1358.8, + 1272.8,1359.2, + 1273.6,1360, + 1274.4,1360, + 1276,1358.8, + 1277.2,1359.6, + 1275.6,1359.2, + 1275.6,1360, + 1274.4,1361.2, + 1274,1361.6, + 1274.8,1361.6, + 1274.8,1362.4, + 1274.8,1362.8, + 1274.8,1363.6, + 1276,1363.6, + 1276.4,1363.6, + 1277.6,1362.4, + 1278,1362.8, + 1277.2,1362.8, + 1276.4,1364, + 1274,1364, + 1273.6,1364, + 1274.4,1365.2, + 1276.4,1366.4, + 1277.2,1367.6, + 1276,1366.4, + 1275.2,1365.2, + 1274.8,1366.4, + 1275.2,1366.4, + 1275.2,1366.8, + 1273.2,1365.6, + 1272.4,1365.6, + 1272.4,1366.8, + 1272.8,1367.2, + 1272.4,1367.2, + 1272.8,1367.6, + 1272,1368, + 1272,1369.2, + 1272.8,1370.8, + 1273.2,1370.8, + 1273.6,1370, + 1274,1370.4, + 1274.8,1369.2, + 1274.8,1369.6, + 1275.2,1369.2, + 1276.4,1370, + 1275.6,1370, + 1274.8,1370.4, + 1274.4,1370.8, + 1274.4,1370.8, + 1274,1371.6, + 1274,1372.4, + 1272.8,1372.4, + 1273.2,1374.4, + 1274.4,1374.4, + 1274.4,1374.4, + 1273.6,1374.4, + 1272.8,1375.2, + 1273.2,1376, + 1272.8,1377.6, + 1274.4,1378, + 1274.8,1377.6, + 1274.8,1376, + 1275.2,1375.2, + 1275.6,1376, + 1276,1376, + 1276,1377.6, + 1275.2,1378, + 1275.6,1379.6, + 1276,1379.2, + 1276.4,1379.6, + 1276.4,1378, + 1277.6,1378, + 1278,1379.2, + 1280.8,1377.6, + 1280.4,1378, + 1278.8,1379.6, + 1278.4,1380, + 1278.8,1380, + 1279.6,1378.8, + 1280.4,1379.2, + 1281.6,1378, + 1282.4,1377.2, + 1282.4,1377.6, + 1280.8,1379.2, + 1281.2,1379.6, + 1281.2,1379.6, + 1280,1380.4, + 1279.2,1381.2, + 1278.4,1382.4, + 1278.4,1382.4, + 1278,1382.8, + 1278,1383.6, + 1279.2,1382.8, + 1279.2,1382.8, + 1280.4,1382.8, + 1280.8,1382.8, + 1280,1384, + 1280.4,1384, + 1280,1384.4, + 1280.4,1384.4, + 1280,1384.8, + 1280,1384.8, + 1279.2,1385.6, + 1279.6,1385.6, + 1278.8,1386.8, + 1278.8,1387.6, + 1280,1386, + 1281.2,1387.2, + 1281.6,1386.4, + 1282.4,1387.2, + 1284.4,1386.4, + 1284,1386.8, + 1284.4,1387.2, + 1283.2,1387.2, + 1282,1388, + 1282.4,1388.4, + 1282,1388.4, + 1281.6,1388.8, + 1282.4,1390.4, + 1283.6,1390, + 1283.2,1390.4, + 1282.8,1390.8, + 1283.2,1390.8, + 1282.8,1391.2, + 1283.6,1391.6, + 1284.4,1391.2, + 1284,1392, + 1282.4,1392.8, + 1282.4,1393.2, + 1283.6,1393.6 +}; + + + +void make_gb_poly(agg::path_storage& ps) +{ + ps.remove_all(); + unsigned i; + const double* p = poly1; + ps.move_to(p[0], p[1]); + p += 2; + for(i = 1; i < sizeof(poly1) / sizeof(double) / 2; i++) + { + ps.line_to(p[0], p[1]); + p += 2; + } + ps.close_polygon(); + + p = poly2; + ps.move_to(p[0], p[1]); + p += 2; + for(i = 1; i < sizeof(poly2) / sizeof(double) / 2; i++) + { + ps.line_to(p[0], p[1]); + p += 2; + } + ps.close_polygon(); +} diff --git a/jni/desmume/src/android/agg/examples/mol_view.cpp b/jni/desmume/src/android/agg/examples/mol_view.cpp new file mode 100755 index 0000000..70ad343 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/mol_view.cpp @@ -0,0 +1,1072 @@ +#include +#include +#include +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_conv_transform.h" +#include "agg_conv_stroke.h" +#include "agg_bspline.h" +#include "agg_ellipse.h" +#include "agg_gsv_text.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_scale_ctrl.h" +#include "platform/agg_platform_support.h" + +#define AGG_BGR24 +//#define AGG_RGB24 +//#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + +enum flip_y_e { flip_y = true }; +enum default_num_points_e { default_num_points = 20000 }; + +enum start_size_e +{ + start_width = 400, + start_height = 400 +}; + + +enum atom_color_e +{ + atom_color_general = 0, + atom_color_N = 1, + atom_color_O = 2, + atom_color_S = 3, + atom_color_P = 4, + atom_color_halogen = 5, + end_of_atom_colors +}; + + + +struct atom_type +{ + double x; + double y; + char label[4]; + int charge; + unsigned color_idx; +}; + +struct bond_type +{ + unsigned idx1; + unsigned idx2; + double x1; + double y1; + double x2; + double y2; + unsigned order; + int stereo; + int topology; +}; + + +class molecule +{ +public: + ~molecule(); + molecule(); + + bool read(FILE* fd); + + unsigned num_atoms() const { return m_num_atoms; } + unsigned num_bonds() const { return m_num_bonds; } + + const atom_type& atom(unsigned idx) const { return m_atoms[idx]; } + const bond_type& bond(unsigned idx) const { return m_bonds[idx]; } + + double average_bond_len() const { return m_avr_len; } + + const char* name() const { return m_name; } + + static int get_int(const char* buf, int pos, int len); + static double get_dbl(const char* buf, int pos, int len); + static char* get_str(char* dst, const char* buf, int pos, int len); + +private: + atom_type* m_atoms; + unsigned m_num_atoms; + bond_type* m_bonds; + unsigned m_num_bonds; + char m_name[128]; + double m_avr_len; +}; + + + + +molecule::~molecule() +{ + delete [] m_bonds; + delete [] m_atoms; +} + + + + +molecule::molecule() : + m_atoms(0), + m_num_atoms(0), + m_bonds(0), + m_num_bonds(0), + m_avr_len(0) +{ + m_name[0] = 0; +} + + +int molecule::get_int(const char* buf, int pos, int len) +{ + char tmp[32]; + return atoi(get_str(tmp, buf, pos, len)); +} + +double molecule::get_dbl(const char* buf, int pos, int len) +{ + char tmp[32]; + return atof(get_str(tmp, buf, pos, len)); +} + +char* molecule::get_str(char* dst, const char* buf, int pos, int len) +{ + --pos; + int buf_len = strlen(buf); + buf += pos; + while(pos + len < buf_len && isspace(*buf)) + { + ++buf; + --len; + } + if(len >= 0) + { + if(len > 0) memcpy(dst, buf, len); + dst[len] = 0; + } + + char* ts = dst; + while(*ts && !isspace(*ts)) ts++; + *ts = 0; + return dst; +} + + +unsigned trim_cr_lf(char* buf) +{ + unsigned len = strlen(buf); + + // Trim "\n\r" at the beginning + unsigned pos = 0; + while(len && (buf[0] == '\n' || buf[0] == '\r')) + { + --len; + ++pos; + } + if(pos) strcpy(buf, buf + pos); + + // Trim "\n\r" at the end + while(len && (buf[len-1] == '\n' || buf[len-1] == '\r')) --len; + buf[len] = 0; + return len; +} + + +/* +MFCD00191150 + Mt7.00 09020210442D + + 23 23 0 0 1 0 0 0 0 0999 V2000 + -2.6793 -0.2552 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + . . . + 1 2 1 0 0 0 0 + . . . +M END +> +MFCD00191150 + +$$$$ +*/ +bool molecule::read(FILE* fd) +{ + char buf[512]; + unsigned len; + if(!fgets(buf, 510, fd)) return false; + len = trim_cr_lf(buf); + if(len > 128) len = 128; + + if(len) memcpy(m_name, buf, len); + m_name[len] = 0; + + if(!fgets(buf, 510, fd)) return false; + if(!fgets(buf, 510, fd)) return false; + if(!fgets(buf, 510, fd)) return false; + trim_cr_lf(buf); + m_num_atoms = get_int(buf, 1, 3); + m_num_bonds = get_int(buf, 4, 3); + if(m_num_atoms == 0 || m_num_bonds == 0) return false; + m_atoms = new atom_type[m_num_atoms]; + m_bonds = new bond_type[m_num_bonds]; + memset(m_atoms, 0, sizeof(atom_type) * m_num_atoms); + memset(m_bonds, 0, sizeof(bond_type) * m_num_bonds); + + unsigned i; + for(i = 0; i < m_num_atoms; i++) + { + if(!fgets(buf, 510, fd)) return false; + trim_cr_lf(buf); +/* + -2.6793 -0.2552 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 +*/ + m_atoms[i].x = get_dbl(buf, 1, 10); + m_atoms[i].y = get_dbl(buf, 11, 10); + get_str(m_atoms[i].label, buf, 32, 3); + m_atoms[i].charge = get_int(buf, 39, 1); + if(m_atoms[i].charge) m_atoms[i].charge = 4 - m_atoms[i].charge; + + if(strcmp(m_atoms[i].label, "N") == 0) m_atoms[i].color_idx = atom_color_N; + if(strcmp(m_atoms[i].label, "O") == 0) m_atoms[i].color_idx = atom_color_O; + if(strcmp(m_atoms[i].label, "S") == 0) m_atoms[i].color_idx = atom_color_S; + if(strcmp(m_atoms[i].label, "P") == 0) m_atoms[i].color_idx = atom_color_P; + if(strcmp(m_atoms[i].label, "F") == 0 || + strcmp(m_atoms[i].label, "Cl") == 0 || + strcmp(m_atoms[i].label, "Br") == 0 || + strcmp(m_atoms[i].label, "I") == 0) m_atoms[i].color_idx = atom_color_halogen; + } + + m_avr_len = 0.0; + for(i = 0; i < m_num_bonds; i++) + { + if(!fgets(buf, 510, fd)) return false; + trim_cr_lf(buf); +/* + 1 2 1 0 0 0 0 +*/ + m_bonds[i].idx1 = get_int(buf, 1, 3) - 1; + m_bonds[i].idx2 = get_int(buf, 4, 3) - 1; + + if(m_bonds[i].idx1 >= m_num_atoms || m_bonds[i].idx2 >= m_num_atoms) return false; + + m_bonds[i].x1 = m_atoms[m_bonds[i].idx1].x; + m_bonds[i].y1 = m_atoms[m_bonds[i].idx1].y; + m_bonds[i].x2 = m_atoms[m_bonds[i].idx2].x; + m_bonds[i].y2 = m_atoms[m_bonds[i].idx2].y; + m_bonds[i].order = get_int(buf, 7, 3); + m_bonds[i].stereo = get_int(buf, 10, 3); + m_bonds[i].topology = get_int(buf, 13, 3); + + m_avr_len += sqrt((m_bonds[i].x1 - m_bonds[i].x2) * (m_bonds[i].x1 - m_bonds[i].x2) + + (m_bonds[i].y1 - m_bonds[i].y2) * (m_bonds[i].y1 - m_bonds[i].y2)); + } + m_avr_len /= double(m_num_bonds); + + while(fgets(buf, 510, fd)) + { + trim_cr_lf(buf); + if(buf[0] == '$') return true; + } + + return false; +} + + + +namespace agg +{ + class line + { + public: + line() : + m_x1(0.0), m_y1(0.0), m_x2(1.0), m_y2(0.0), m_thickness(0.1) + { + } + + line(double x1, double y1, double x2, double y2, double thickness) : + m_x1(x1), m_y1(y1), m_x2(x2), m_y2(y2), m_thickness(thickness) + { + } + + void init(double x1, double y1, double x2, double y2) + { + m_x1 = x1; + m_y1 = y1; + m_x2 = x2; + m_y2 = y2; + } + + void thickness(double th) + { + m_thickness = th; + } + + void rewind(unsigned start); + unsigned vertex(double* x, double* y); + + private: + double m_x1; + double m_y1; + double m_x2; + double m_y2; + double m_dx; + double m_dy; + double m_thickness; + unsigned m_vertex; + }; + + + + inline void line::rewind(unsigned) + { + calc_orthogonal(m_thickness*0.5, m_x1, m_y1, m_x2, m_y2, &m_dx, &m_dy); + m_vertex = 0; + } + + + + inline unsigned line::vertex(double* x, double* y) + { + switch(m_vertex) + { + case 0: + *x = m_x1 - m_dx; + *y = m_y1 - m_dy; + m_vertex++; + return path_cmd_move_to; + + case 1: + *x = m_x2 - m_dx; + *y = m_y2 - m_dy; + m_vertex++; + return path_cmd_line_to; + + case 2: + *x = m_x2 + m_dx; + *y = m_y2 + m_dy; + m_vertex++; + return path_cmd_line_to; + + case 3: + *x = m_x1 + m_dx; + *y = m_y1 + m_dy; + m_vertex++; + return path_cmd_line_to; + } + return path_cmd_stop; + } + + + + class solid_wedge + { + public: + solid_wedge() : + m_x1(0.0), m_y1(0.0), m_x2(1.0), m_y2(0.0), m_thickness(0.1) + { + } + + solid_wedge(double x1, double y1, double x2, double y2, double thickness) : + m_x1(x1), m_y1(y1), m_x2(x2), m_y2(y2), m_thickness(thickness) + { + } + + void init(double x1, double y1, double x2, double y2) + { + m_x1 = x1; + m_y1 = y1; + m_x2 = x2; + m_y2 = y2; + } + + void thickness(double th) + { + m_thickness = th; + } + + void rewind(unsigned start); + unsigned vertex(double* x, double* y); + + private: + double m_x1; + double m_y1; + double m_x2; + double m_y2; + double m_dx; + double m_dy; + double m_thickness; + unsigned m_vertex; + }; + + + + inline void solid_wedge::rewind(unsigned) + { + calc_orthogonal(m_thickness*2.0, m_x1, m_y1, m_x2, m_y2, &m_dx, &m_dy); + m_vertex = 0; + } + + + + inline unsigned solid_wedge::vertex(double* x, double* y) + { + switch(m_vertex) + { + case 0: + *x = m_x1; + *y = m_y1; + m_vertex++; + return path_cmd_move_to; + + case 1: + *x = m_x2 - m_dx; + *y = m_y2 - m_dy; + m_vertex++; + return path_cmd_line_to; + + case 2: + *x = m_x2 + m_dx; + *y = m_y2 + m_dy; + m_vertex++; + return path_cmd_line_to; + } + return path_cmd_stop; + } + + + + + + + + + + class dashed_wedge + { + public: + dashed_wedge() : + m_x1(0.0), m_y1(0.0), m_x2(1.0), m_y2(0.0), + m_thickness(0.1), + m_num_dashes(8) + { + } + + dashed_wedge(double x1, double y1, double x2, double y2, + double thickness, unsigned num_dashes=8) : + m_x1(x2), m_y1(y2), m_x2(x1), m_y2(y1), + m_thickness(thickness), + m_num_dashes(num_dashes) + { + } + + void init(double x1, double y1, double x2, double y2) + { + m_x1 = x2; + m_y1 = y2; + m_x2 = x1; + m_y2 = y1; + } + + void num_dashes(unsigned nd) + { + m_num_dashes = nd; + } + + void thickness(double th) + { + m_thickness = th; + } + + void rewind(unsigned start); + unsigned vertex(double* x, double* y); + + private: + double m_x1; + double m_y1; + double m_x2; + double m_y2; + double m_xt2; + double m_yt2; + double m_xt3; + double m_yt3; + double m_xd[4]; + double m_yd[4]; + double m_thickness; + unsigned m_num_dashes; + unsigned m_vertex; + }; + + + + void dashed_wedge::rewind(unsigned) + { + double dx; + double dy; + calc_orthogonal(m_thickness*2.0, m_x1, m_y1, m_x2, m_y2, &dx, &dy); + m_xt2 = m_x2 - dx; + m_yt2 = m_y2 - dy; + m_xt3 = m_x2 + dx; + m_yt3 = m_y2 + dy; + m_vertex = 0; + } + + + unsigned dashed_wedge::vertex(double* x, double* y) + { + if(m_vertex < m_num_dashes * 4) + { + if((m_vertex % 4) == 0) + { + double k1 = double(m_vertex / 4) / double(m_num_dashes); + double k2 = k1 + 0.4 / double(m_num_dashes); + + m_xd[0] = m_x1 + (m_xt2 - m_x1) * k1; + m_yd[0] = m_y1 + (m_yt2 - m_y1) * k1; + m_xd[1] = m_x1 + (m_xt2 - m_x1) * k2; + m_yd[1] = m_y1 + (m_yt2 - m_y1) * k2; + m_xd[2] = m_x1 + (m_xt3 - m_x1) * k2; + m_yd[2] = m_y1 + (m_yt3 - m_y1) * k2; + m_xd[3] = m_x1 + (m_xt3 - m_x1) * k1; + m_yd[3] = m_y1 + (m_yt3 - m_y1) * k1; + *x = m_xd[0]; + *y = m_yd[0]; + m_vertex++; + return path_cmd_move_to; + } + else + { + *x = m_xd[m_vertex % 4]; + *y = m_yd[m_vertex % 4]; + m_vertex++; + return path_cmd_line_to; + } + } + return path_cmd_stop; + } + + + + + + + + + + + +} + + + + + + +class bond_vertex_generator +{ + enum bond_style_e + { + bond_single, + bond_wedged_solid, + bond_wedged_dashed, + bond_double, + bond_double_left, + bond_double_right, + bond_triple + }; + +public: + bond_vertex_generator(const bond_type& bond, double thickness) : + m_bond(bond), + m_thickness(thickness), + m_style(bond_single) + { + if(bond.order == 1) + { + if(bond.stereo == 1) m_style = bond_wedged_solid; + if(bond.stereo == 6) m_style = bond_wedged_dashed; + } + if(bond.order == 2) + { + m_style = bond_double; + if(bond.topology == 1) m_style = bond_double_left; + if(bond.topology == 2) m_style = bond_double_right; + } + if(bond.order == 3) m_style = bond_triple; + m_line1.thickness(thickness); + m_line2.thickness(thickness); + m_line3.thickness(thickness); + m_solid_wedge.thickness(thickness); + m_dashed_wedge.thickness(thickness); + } + + void rewind(unsigned) + { + double dx, dy, dx1, dy1, dx2, dy2; + + switch(m_style) + { + case bond_wedged_solid: + m_solid_wedge.init(m_bond.x1, m_bond.y1, m_bond.x2, m_bond.y2); + m_solid_wedge.rewind(0); + break; + + case bond_wedged_dashed: + m_dashed_wedge.init(m_bond.x1, m_bond.y1, m_bond.x2, m_bond.y2); + m_dashed_wedge.rewind(0); + break; + + case bond_double: + case bond_double_left: + case bond_double_right: + agg::calc_orthogonal(m_thickness, + m_bond.x1, m_bond.y1, + m_bond.x2, m_bond.y2, + &dx, &dy); + dx1 = dy1 = 0; + + // To Do: ring perception and the proper drawing + // of the double bonds in the aromatic rings. + //if(m_style == bond_double) + { + dx1 = dx2 = dx; + dy1 = dy2 = dy; + } +/* + else if(m_style == bond_double_left) + { + dx2 = dx * 2.0; + dy2 = dy * 2.0; + } + else + { + dx2 = -dx * 2.0; + dy2 = -dy * 2.0; + } +*/ + + m_line1.init(m_bond.x1 - dx1, + m_bond.y1 - dy1, + m_bond.x2 - dx1, + m_bond.y2 - dy1); + m_line1.rewind(0); + + m_line2.init(m_bond.x1 + dx2, + m_bond.y1 + dy2, + m_bond.x2 + dx2, + m_bond.y2 + dy2); + m_line2.rewind(0); + m_status = 0; + break; + + case bond_triple: + // To Do: triple bonds drawing. + + default: + m_line1.init(m_bond.x1, m_bond.y1, m_bond.x2, m_bond.y2); + m_line1.rewind(0); + break; + } + } + + + unsigned vertex(double* x, double* y) + { + unsigned flag = agg::path_cmd_stop; + switch(m_style) + { + case bond_wedged_solid: + return m_solid_wedge.vertex(x, y); + + case bond_wedged_dashed: + return m_dashed_wedge.vertex(x, y); + + case bond_double_left: + case bond_double_right: + case bond_double: + if(m_status == 0) + { + flag = m_line1.vertex(x, y); + if(flag == agg::path_cmd_stop) + { + m_status = 1; + } + } + + if(m_status == 1) + { + flag = m_line2.vertex(x, y); + } + return flag; + + case bond_triple: + break; + } + return m_line1.vertex(x, y); + } + + + +private: + bond_vertex_generator(const bond_vertex_generator&); + const bond_vertex_generator& operator = (const bond_vertex_generator&); + + const bond_type& m_bond; + double m_thickness; + bond_style_e m_style; + agg::line m_line1; + agg::line m_line2; + agg::line m_line3; + agg::solid_wedge m_solid_wedge; + agg::dashed_wedge m_dashed_wedge; + unsigned m_status; +}; + + + + + + + + + + + +class the_application : public agg::platform_support +{ + molecule* m_molecules; + unsigned m_num_molecules; + unsigned m_cur_molecule; + agg::slider_ctrl m_thickness; + agg::slider_ctrl m_text_size; + double m_pdx; + double m_pdy; + double m_center_x; + double m_center_y; + double m_scale; + double m_prev_scale; + double m_angle; + double m_prev_angle; + bool m_mouse_move; + agg::rgba8 m_atom_colors[end_of_atom_colors]; + + +public: + virtual ~the_application() + { + delete [] m_molecules; + } + + the_application(agg::pix_format_e format, bool flip_y, const char* fname) : + agg::platform_support(format, flip_y), + m_molecules(new molecule [100]), + m_num_molecules(0), + m_cur_molecule(0), + m_thickness(5, 5, start_width-5, 12), + m_text_size(5, 20, start_width-5, 27), + m_pdx(0.0), + m_pdy(0.0), + m_center_x(start_width / 2), + m_center_y(start_height / 2), + m_scale(1.0), + m_prev_scale(1.0), + m_angle(0.0), + m_prev_angle(0.0), + m_mouse_move(false) + { + m_thickness.label("Thickness=%3.2f"); + m_text_size.label("Label Size=%3.2f"); + add_ctrl(m_thickness); + add_ctrl(m_text_size); + + FILE* fd = fopen(full_file_name(fname), "r"); + if(fd) + { + unsigned i; + for(i = 0; i < 100; i++) + { + if(!m_molecules[m_num_molecules].read(fd)) break; + m_num_molecules++; + } + fclose(fd); + } + else + { + char buf[256]; + sprintf(buf, "File not found: '%s'. Download http://www.antigrain.com/%s\n", + fname, fname); + message(buf); + } + memset(m_atom_colors, 0, sizeof(agg::rgba8) * end_of_atom_colors); + m_atom_colors[atom_color_general] = agg::rgba8(0,0,0); + m_atom_colors[atom_color_N] = agg::rgba8(0,0,120); + m_atom_colors[atom_color_O] = agg::rgba8(200,0,0); + m_atom_colors[atom_color_S] = agg::rgba8(120,120,0); + m_atom_colors[atom_color_P] = agg::rgba8(80,50,0); + m_atom_colors[atom_color_halogen] = agg::rgba8(0,200,0); + } + + + virtual void on_init() + { + } + + + virtual void on_draw() + { + double width = initial_width(); + double height = initial_height(); + + agg::rasterizer_scanline_aa<> ras; + agg::scanline_p8 sl; + + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_solid; + + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + renderer_solid rs(rb); + + ras.clip_box(0, 0, rb.width(), rb.height()); + + rb.clear(agg::rgba(1,1,1)); + + const molecule& mol = m_molecules[m_cur_molecule]; + unsigned i; + double min_x = 1e100; + double max_x = -1e100; + double min_y = 1e100; + double max_y = -1e100; + + for(i = 0; i < mol.num_atoms(); i++) + { + if(mol.atom(i).x < min_x) min_x = mol.atom(i).x; + if(mol.atom(i).y < min_y) min_y = mol.atom(i).y; + if(mol.atom(i).x > max_x) max_x = mol.atom(i).x; + if(mol.atom(i).y > max_y) max_y = mol.atom(i).y; + } + + agg::trans_affine mtx; + + mtx *= agg::trans_affine_translation(-(max_x + min_x) * 0.5, -(max_y + min_y) * 0.5); + + double scale = width / (max_x - min_x); + double t = height / (max_y - min_y); + if(scale > t) scale = t; + + double text_size = mol.average_bond_len() * m_text_size.value() / 4.0; + double thickness = mol.average_bond_len() / + sqrt(m_scale < 0.0001 ? 0.0001 : m_scale) / + 8.0; + + mtx *= agg::trans_affine_scaling(scale*0.80, scale*0.80); + mtx *= agg::trans_affine_rotation(m_angle); + mtx *= agg::trans_affine_scaling(m_scale, m_scale); + mtx *= agg::trans_affine_translation(m_center_x, m_center_y); + mtx *= trans_affine_resizing(); + + rs.color(agg::rgba(0,0,0)); + for(i = 0; i < mol.num_bonds(); i++) + { + bond_vertex_generator bond(mol.bond(i), + m_thickness.value() * thickness); + agg::conv_transform tr(bond, mtx); + ras.add_path(tr); + agg::render_scanlines(ras, sl, rs); + } + + + agg::ellipse ell; + agg::conv_transform tr(ell, mtx); + for(i = 0; i < mol.num_atoms(); i++) + { + if(strcmp(mol.atom(i).label, "C") != 0) + { + ell.init(mol.atom(i).x, + mol.atom(i).y, + text_size * 2.5, + text_size * 2.5, + 20); + ras.add_path(tr); + rs.color(agg::rgba(1.0, 1.0, 1.0)); + agg::render_scanlines(ras, sl, rs); + } + } + + + text_size *= 3.0; + + + agg::gsv_text label; + agg::conv_stroke ls(label); + agg::conv_transform > lo(ls, mtx); + ls.line_join(agg::round_join); + ls.line_cap(agg::round_cap); + ls.approximation_scale(mtx.scale()); + for(i = 0; i < mol.num_atoms(); i++) + { + if(strcmp(mol.atom(i).label, "C") != 0) + { + ls.width(m_thickness.value() * thickness); + label.text(mol.atom(i).label); + label.start_point(mol.atom(i).x - text_size/2, mol.atom(i).y - text_size/2); + label.size(text_size); + ras.add_path(lo); + rs.color(m_atom_colors[mol.atom(i).color_idx]); + agg::render_scanlines(ras, sl, rs); + } + } + + + ls.approximation_scale(1.0); + agg::conv_transform > name(ls, trans_affine_resizing()); + ls.width(1.5); + label.text(mol.name()); + label.size(10.0); + label.start_point(10.0, start_height - 20.0); + ras.reset(); + ras.add_path(name); + rs.color(agg::rgba(0,0,0)); + agg::render_scanlines(ras, sl, rs); + + + + agg::render_ctrl(ras, sl, rb, m_thickness); + agg::render_ctrl(ras, sl, rb, m_text_size); + } + + + + + + + + + + + + + + + virtual void on_idle() + { + m_angle += agg::deg2rad(0.1); + force_redraw(); + } + + + + + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + m_mouse_move = true; + double x2 = x; + double y2 = y; + trans_affine_resizing().inverse_transform(&x2, &y2); + + m_pdx = m_center_x - x2; + m_pdy = m_center_y - y2; + m_prev_scale = m_scale; + m_prev_angle = m_angle + agg::pi; + force_redraw(); + } + + + + + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + m_mouse_move = false; + } + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + double x2 = x; + double y2 = y; + trans_affine_resizing().inverse_transform(&x2, &y2); + + if(m_mouse_move && (flags & agg::mouse_left) != 0) + { + double dx = x2 - m_center_x; + double dy = y2 - m_center_y; + m_scale = m_prev_scale * + sqrt(dx * dx + dy * dy) / + sqrt(m_pdx * m_pdx + m_pdy * m_pdy); + + m_angle = m_prev_angle + atan2(dy, dx) - atan2(m_pdy, m_pdx); + force_redraw(); + } + + if(m_mouse_move && (flags & agg::mouse_right) != 0) + { + m_center_x = x2 + m_pdx; + m_center_y = y2 + m_pdy; + force_redraw(); + } + + } + + + + + + + + virtual void on_key(int, int, unsigned key, unsigned) + { + switch(key) + { + case agg::key_left: + case agg::key_up: + case agg::key_page_up: + if(m_cur_molecule) --m_cur_molecule; + force_redraw(); + break; + + case agg::key_right: + case agg::key_down: + case agg::key_page_down: + if(m_cur_molecule < m_num_molecules - 1) ++m_cur_molecule; + force_redraw(); + break; + + case ' ': + wait_mode(!wait_mode()); + break; + } + } + +}; + + + + + +int agg_main(int argc, char* argv[]) +{ + const char* fname = "1.sdf"; + if(argc > 1) + { + fname = argv[1]; + } + + + the_application app(pix_format, flip_y, fname); + app.caption("AGG - A Simple SDF Molecular Viewer"); + + if(app.init(start_width, start_height, agg::window_resize)) + { + return app.run(); + } + + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/multi_clip.cpp b/jni/desmume/src/android/agg/examples/multi_clip.cpp new file mode 100755 index 0000000..6c50940 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/multi_clip.cpp @@ -0,0 +1,370 @@ +#include +#include +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_color_gray.h" +#include "agg_renderer_mclip.h" +#include "agg_renderer_scanline.h" +#include "agg_path_storage.h" +#include "agg_conv_transform.h" +#include "agg_bounding_rect.h" +#include "agg_renderer_outline_aa.h" +#include "agg_renderer_primitives.h" +#include "agg_renderer_markers.h" +#include "agg_span_allocator.h" +#include "agg_span_gradient.h" +#include "agg_span_interpolator_linear.h" +#include "agg_rasterizer_outline_aa.h" +#include "agg_ellipse.h" +#include "ctrl/agg_slider_ctrl.h" +#include "platform/agg_platform_support.h" + + +//#define AGG_GRAY8 +#define AGG_BGR24 +//#define AGG_RGB24 +//#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + +enum flip_y_e { flip_y = true }; + +agg::rasterizer_scanline_aa<> g_rasterizer; +agg::scanline_u8 g_scanline; +agg::path_storage g_path; +agg::rgba8 g_colors[100]; +unsigned g_path_idx[100]; +unsigned g_npaths = 0; +double g_x1 = 0; +double g_y1 = 0; +double g_x2 = 0; +double g_y2 = 0; +double g_base_dx = 0; +double g_base_dy = 0; +double g_angle = 0; +double g_scale = 1.0; +double g_skew_x = 0; +double g_skew_y = 0; +int g_nclick = 0; + + +unsigned parse_lion(agg::path_storage& ps, agg::rgba8* colors, unsigned* path_idx); +void parse_lion() +{ + g_npaths = parse_lion(g_path, g_colors, g_path_idx); + agg::pod_array_adaptor path_idx(g_path_idx, 100); + agg::bounding_rect(g_path, path_idx, 0, g_npaths, &g_x1, &g_y1, &g_x2, &g_y2); + g_base_dx = (g_x2 - g_x1) / 2.0; + g_base_dy = (g_y2 - g_y1) / 2.0; +} + + +namespace agg +{ + // Specializations of the gradient_linear_color for rgba8 and gray8 + // color types. Only for the sake of performance. + + //======================================================================== + template<> struct gradient_linear_color + { + typedef rgba8 color_type; + + gradient_linear_color() {} + gradient_linear_color(const color_type& c1, const color_type& c2) : + m_c1(c1), m_c2(c2) {} + + static unsigned size() { return 256; } + color_type operator [] (unsigned v) const + { + color_type c; + c.r = (int8u)((((m_c2.r - m_c1.r) * int(v)) + (m_c1.r << 8)) >> 8); + c.g = (int8u)((((m_c2.g - m_c1.g) * int(v)) + (m_c1.g << 8)) >> 8); + c.b = (int8u)((((m_c2.b - m_c1.b) * int(v)) + (m_c1.b << 8)) >> 8); + c.a = (int8u)((((m_c2.a - m_c1.a) * int(v)) + (m_c1.a << 8)) >> 8); + return c; + } + + void colors(const color_type& c1, const color_type& c2) + { + m_c1 = c1; + m_c2 = c2; + } + + color_type m_c1; + color_type m_c2; + }; + + + //======================================================================== + template<> struct gradient_linear_color + { + typedef gray8 color_type; + + gradient_linear_color() {} + gradient_linear_color(const color_type& c1, const color_type& c2) : + m_c1(c1), m_c2(c2) {} + + static unsigned size() { return 256; } + color_type operator [] (unsigned v) const + { + color_type c; + c.v = (int8u)((((m_c2.v - m_c1.v) * int(v)) + (m_c1.v << 8)) >> 8); + c.a = (int8u)((((m_c2.a - m_c1.a) * int(v)) + (m_c1.a << 8)) >> 8); + return c; + } + + void colors(const color_type& c1, const color_type& c2) + { + m_c1 = c1; + m_c2 = c2; + } + + color_type m_c1; + color_type m_c2; + }; + +} + + + + +class the_application : public agg::platform_support +{ + agg::slider_ctrl m_num_cb; + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_num_cb(5, 5, 150, 12, !flip_y) + { + parse_lion(); + add_ctrl(m_num_cb); + m_num_cb.range(2, 10); + //m_num_cb.num_steps(8); + m_num_cb.label("N=%.2f"); + m_num_cb.no_transform(); + } + + virtual void on_draw() + { + unsigned i; + int width = rbuf_window().width(); + int height = rbuf_window().height(); + + pixfmt pf(rbuf_window()); + typedef agg::renderer_mclip base_ren_type; + + base_ren_type r(pf); + agg::renderer_scanline_aa_solid rs(r); + + agg::trans_affine mtx; + mtx *= agg::trans_affine_translation(-g_base_dx, -g_base_dy); + mtx *= agg::trans_affine_scaling(g_scale, g_scale); + mtx *= agg::trans_affine_rotation(g_angle + agg::pi); + mtx *= agg::trans_affine_skewing(g_skew_x/1000.0, g_skew_y/1000.0); + mtx *= agg::trans_affine_translation(width/2, height/2); + + r.clear(agg::rgba(1, 1, 1)); + + + r.reset_clipping(false); // Visibility: "false" means "no visible regions" + int x, y; + double n = m_num_cb.value(); + for(x = 0; x < n; x++) + { + for(y = 0; y < n; y++) + { + int x1 = int(width * x / n); + int y1 = int(height * y / n); + int x2 = int(width * (x + 1) / n); + int y2 = int(height * (y + 1) / n); + r.add_clip_box(x1 + 5, y1 + 5, x2 - 5, y2 - 5); + } + } + + + + // Render the lion + agg::conv_transform trans(g_path, mtx); + agg::render_all_paths(g_rasterizer, g_scanline, rs, trans, g_colors, g_path_idx, g_npaths); + + +// The scanline rasterizer allows you to perform clipping to multiple +// regions "manually", like in the following code, but the "embedded" method +// shows much better performance. +// +//for(i = 0; i < g_npaths; i++) +//{ +// g_rasterizer.reset(); +// g_rasterizer.add_path(trans, g_path_idx[i]); +// rs.color(g_colors[i]); +// +// int x, y; +// double n = m_num_cb.value(); +// for(x = 0; x < n; x++) +// { +// for(y = 0; y < n; y++) +// { +// int x1 = int(width * x / n); +// int y1 = int(height * y / n); +// int x2 = int(width * (x + 1) / n); +// int y2 = int(height * (y + 1) / n); +// // r should be of type renderer_base<> +// r.clip_box(agg::rect_i(x1 + 5, y1 + 5, x2 - 5, y2 - 5)); +// agg::render_scanlines(g_rasterizer, g_scanline, rs); +// } +// } +//} + + + + // Render random Bresenham lines and markers + agg::renderer_markers m(r); + for(i = 0; i < 50; i++) + { + m.line_color(agg::rgba8(rand() & 0x7F, + rand() & 0x7F, + rand() & 0x7F, + (rand() & 0x7F) + 0x7F)); + m.fill_color(agg::rgba8(rand() & 0x7F, + rand() & 0x7F, + rand() & 0x7F, + (rand() & 0x7F) + 0x7F)); + + m.line(m.coord(rand() % width), m.coord(rand() % height), + m.coord(rand() % width), m.coord(rand() % height)); + + m.marker(rand() % width, rand() % height, rand() % 10 + 5, + agg::marker_e(rand() % agg::end_of_markers)); + } + + + // Render random anti-aliased lines + double w = 5.0; + agg::line_profile_aa profile; + profile.width(w); + + typedef agg::renderer_outline_aa renderer_type; + renderer_type ren(r, profile); + + typedef agg::rasterizer_outline_aa rasterizer_type; + rasterizer_type ras(ren); + ras.round_cap(true); + + for(i = 0; i < 50; i++) + { + ren.color(agg::rgba8(rand() & 0x7F, + rand() & 0x7F, + rand() & 0x7F, + (rand() & 0x7F) + 0x7F)); + ras.move_to_d(rand() % width, rand() % height); + ras.line_to_d(rand() % width, rand() % height); + ras.render(false); + } + + + // Render random circles with gradient + typedef agg::gradient_linear_color grad_color; + typedef agg::gradient_circle grad_func; + typedef agg::span_interpolator_linear<> interpolator_type; + typedef agg::span_gradient span_grad_type; + + agg::trans_affine grm; + grad_func grf; + grad_color grc(agg::rgba8(0,0,0), agg::rgba8(0,0,0)); + agg::ellipse ell; + agg::span_allocator sa; + interpolator_type inter(grm); + span_grad_type sg(inter, grf, grc, 0, 10); + for(i = 0; i < 50; i++) + { + x = rand() % width; + y = rand() % height; + double radius = rand() % 10 + 5; + grm.reset(); + grm *= agg::trans_affine_scaling(radius / 10.0); + grm *= agg::trans_affine_translation(x, y); + grm.invert(); + grc.colors(agg::rgba8(255, 255, 255, 0), + agg::rgba8(rand() & 0x7F, + rand() & 0x7F, + rand() & 0x7F, + 255)); + sg.color_function(grc); + ell.init(x, y, radius, radius, 32); + g_rasterizer.add_path(ell); + agg::render_scanlines_aa(g_rasterizer, g_scanline, r, sa, sg); + } + + r.reset_clipping(true); // "true" means "all rendering buffer is visible". + agg::render_ctrl(g_rasterizer, g_scanline, r, m_num_cb); + } + + + void transform(double width, double height, double x, double y) + { + x -= width / 2; + y -= height / 2; + g_angle = atan2(y, x); + g_scale = sqrt(y * y + x * x) / 100.0; + } + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + int width = rbuf_window().width(); + int height = rbuf_window().height(); + transform(width, height, x, y); + force_redraw(); + } + + if(flags & agg::mouse_right) + { + g_skew_x = x; + g_skew_y = y; + force_redraw(); + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + on_mouse_button_down(x, y, flags); + } + +}; + + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Clipping to multiple rectangle regions"); + + if(app.init(512, 400, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + + + + + diff --git a/jni/desmume/src/android/agg/examples/parse_lion.cpp b/jni/desmume/src/android/agg/examples/parse_lion.cpp new file mode 100755 index 0000000..62e8450 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/parse_lion.cpp @@ -0,0 +1,215 @@ +#include +#include +#include +#include "agg_color_rgba.h" +#include "agg_path_storage.h" +#include "agg_bounding_rect.h" + +static char g_lion[] = +"f2cc99\n" +"M 69,18 L 82,8 L 99,3 L 118,5 L 135,12 L 149,21 L 156,13 L 165,9 L 177,13 L 183,28 L 180,50 L 164,91 L 155,107 L 154,114 L 151,121 L 141,127 L 139,136 L 155,206 L 157,251 L 126,342 L 133,357 L 128,376 L 83,376 L 75,368 L 67,350 L 61,350 L 53,369 L 4,369 L 2,361 L 5,354 L 12,342 L 16,321 L 4,257 L 4,244 L 7,218 L 9,179 L 26,127 L 43,93 L 32,77 L 30,70 L 24,67 L 16,49 L 17,35 L 18,23 L 30,12 L 40,7 L 53,7 L 62,12 L 69,18 L 69,18 L 69,18\n" +"e5b27f\n" +"M 142,79 L 136,74 L 138,82 L 133,78 L 133,84 L 127,78 L 128,85 L 124,80 L 125,87 L 119,82 L 119,90 L 125,99 L 125,96 L 128,100 L 128,94 L 131,98 L 132,93 L 135,97 L 136,93 L 138,97 L 139,94 L 141,98 L 143,94 L 144,85 L 142,79 L 142,79 L 142,79\n" +"eb8080\n" +"M 127,101 L 132,100 L 137,99 L 144,101 L 143,105 L 135,110 L 127,101 L 127,101 L 127,101\n" +"f2cc99\n" +"M 178,229 L 157,248 L 139,296 L 126,349 L 137,356 L 158,357 L 183,342 L 212,332 L 235,288 L 235,261 L 228,252 L 212,250 L 188,251 L 178,229 L 178,229 L 178,229\n" +"9c826b\n" +"M 56,229 L 48,241 L 48,250 L 57,281 L 63,325 L 71,338 L 81,315 L 76,321 L 79,311 L 83,301 L 75,308 L 80,298 L 73,303 L 76,296 L 71,298 L 74,292 L 69,293 L 74,284 L 78,278 L 71,278 L 74,274 L 68,273 L 70,268 L 66,267 L 68,261 L 60,266 L 62,259 L 65,253 L 57,258 L 59,251 L 55,254 L 55,248 L 60,237 L 54,240 L 58,234 L 54,236 L 56,229 L 56,229 L 56,229\n" +"M 74,363 L 79,368 L 81,368 L 85,362 L 89,363 L 92,370 L 96,373 L 101,372 L 108,361 L 110,371 L 113,373 L 116,371 L 120,358 L 122,363 L 123,371 L 126,371 L 129,367 L 132,357 L 135,361 L 130,376 L 127,377 L 94,378 L 84,376 L 76,371 L 74,363 L 74,363 L 74,363\n" +"M 212,250 L 219,251 L 228,258 L 236,270 L 235,287 L 225,304 L 205,332 L 177,343 L 171,352 L 158,357 L 166,352 L 168,346 L 168,339 L 165,333 L 155,327 L 155,323 L 161,320 L 165,316 L 169,316 L 167,312 L 171,313 L 168,308 L 173,309 L 170,306 L 177,306 L 175,308 L 177,311 L 174,311 L 176,316 L 171,315 L 174,319 L 168,320 L 168,323 L 175,327 L 179,332 L 183,326 L 184,332 L 189,323 L 190,328 L 194,320 L 194,325 L 199,316 L 201,320 L 204,313 L 206,316 L 208,310 L 211,305 L 219,298 L 226,288 L 229,279 L 228,266 L 224,259 L 217,253 L 212,250 L 212,250 L 212,250\n" +"M 151,205 L 151,238 L 149,252 L 141,268 L 128,282 L 121,301 L 130,300 L 126,313 L 118,324 L 116,337 L 120,346 L 133,352 L 133,340 L 137,333 L 145,329 L 156,327 L 153,319 L 153,291 L 157,271 L 170,259 L 178,277 L 193,250 L 174,216 L 151,205 L 151,205 L 151,205\n" +"M 78,127 L 90,142 L 95,155 L 108,164 L 125,167 L 139,175 L 150,206 L 152,191 L 141,140 L 121,148 L 100,136 L 78,127 L 78,127 L 78,127\n" +"M 21,58 L 35,63 L 38,68 L 32,69 L 42,74 L 40,79 L 47,80 L 54,83 L 45,94 L 34,81 L 32,73 L 24,66 L 21,58 L 21,58 L 21,58\n" +"M 71,34 L 67,34 L 66,27 L 59,24 L 54,17 L 48,17 L 39,22 L 30,26 L 28,31 L 31,39 L 38,46 L 29,45 L 36,54 L 41,61 L 41,70 L 50,69 L 54,71 L 55,58 L 67,52 L 76,43 L 76,39 L 68,44 L 71,34 L 71,34 L 71,34\n" +"M 139,74 L 141,83 L 143,89 L 144,104 L 148,104 L 155,106 L 154,86 L 157,77 L 155,72 L 150,77 L 144,77 L 139,74 L 139,74 L 139,74\n" +"M 105,44 L 102,53 L 108,58 L 111,62 L 112,55 L 105,44 L 105,44 L 105,44\n" +"M 141,48 L 141,54 L 144,58 L 139,62 L 137,66 L 136,59 L 137,52 L 141,48 L 141,48 L 141,48\n" +"M 98,135 L 104,130 L 105,134 L 108,132 L 108,135 L 112,134 L 113,137 L 116,136 L 116,139 L 119,139 L 124,141 L 128,140 L 133,138 L 140,133 L 139,140 L 126,146 L 104,144 L 98,135 L 98,135 L 98,135\n" +"M 97,116 L 103,119 L 103,116 L 111,118 L 116,117 L 122,114 L 127,107 L 135,111 L 142,107 L 141,114 L 145,118 L 149,121 L 145,125 L 140,124 L 127,121 L 113,125 L 100,124 L 97,116 L 97,116 L 97,116\n" +"M 147,33 L 152,35 L 157,34 L 153,31 L 160,31 L 156,28 L 161,28 L 159,24 L 163,25 L 163,21 L 165,22 L 170,23 L 167,17 L 172,21 L 174,18 L 175,23 L 176,22 L 177,28 L 177,33 L 174,37 L 176,39 L 174,44 L 171,49 L 168,53 L 164,57 L 159,68 L 156,70 L 154,60 L 150,51 L 146,43 L 144,35 L 147,33 L 147,33 L 147,33\n" +"M 85,72 L 89,74 L 93,75 L 100,76 L 105,75 L 102,79 L 94,79 L 88,76 L 85,72 L 85,72 L 85,72\n" +"M 86,214 L 79,221 L 76,232 L 82,225 L 78,239 L 82,234 L 78,245 L 81,243 L 79,255 L 84,250 L 84,267 L 87,254 L 90,271 L 90,257 L 95,271 L 93,256 L 95,249 L 92,252 L 93,243 L 89,253 L 89,241 L 86,250 L 87,236 L 83,245 L 87,231 L 82,231 L 90,219 L 84,221 L 86,214 L 86,214 L 86,214\n" +"ffcc7f\n" +"M 93,68 L 96,72 L 100,73 L 106,72 L 108,66 L 105,63 L 100,62 L 93,68 L 93,68 L 93,68\n" +"M 144,64 L 142,68 L 142,73 L 146,74 L 150,73 L 154,64 L 149,62 L 144,64 L 144,64 L 144,64\n" +"9c826b\n" +"M 57,91 L 42,111 L 52,105 L 41,117 L 53,112 L 46,120 L 53,116 L 50,124 L 57,119 L 55,127 L 61,122 L 60,130 L 67,126 L 66,134 L 71,129 L 72,136 L 77,130 L 76,137 L 80,133 L 82,138 L 86,135 L 96,135 L 94,129 L 86,124 L 83,117 L 77,123 L 79,117 L 73,120 L 75,112 L 68,116 L 71,111 L 65,114 L 69,107 L 63,110 L 68,102 L 61,107 L 66,98 L 61,103 L 63,97 L 57,99 L 57,91 L 57,91 L 57,91\n" +"M 83,79 L 76,79 L 67,82 L 75,83 L 65,88 L 76,87 L 65,92 L 76,91 L 68,96 L 77,95 L 70,99 L 80,98 L 72,104 L 80,102 L 76,108 L 85,103 L 92,101 L 87,98 L 93,96 L 86,94 L 91,93 L 85,91 L 93,89 L 99,89 L 105,93 L 107,85 L 102,82 L 92,80 L 83,79 L 83,79 L 83,79\n" +"M 109,77 L 111,83 L 109,89 L 113,94 L 117,90 L 117,81 L 114,78 L 109,77 L 109,77 L 109,77\n" +"M 122,128 L 127,126 L 134,127 L 136,129 L 134,130 L 130,128 L 124,129 L 122,128 L 122,128 L 122,128\n" +"M 78,27 L 82,32 L 80,33 L 82,36 L 78,37 L 82,40 L 78,42 L 81,46 L 76,47 L 78,49 L 74,50 L 82,52 L 87,50 L 83,48 L 91,46 L 86,45 L 91,42 L 88,40 L 92,37 L 86,34 L 90,31 L 86,29 L 89,26 L 78,27 L 78,27 L 78,27\n" +"M 82,17 L 92,20 L 79,21 L 90,25 L 81,25 L 94,28 L 93,26 L 101,30 L 101,26 L 107,33 L 108,28 L 111,40 L 113,34 L 115,45 L 117,39 L 119,54 L 121,46 L 124,58 L 126,47 L 129,59 L 130,49 L 134,58 L 133,44 L 137,48 L 133,37 L 137,40 L 133,32 L 126,20 L 135,26 L 132,19 L 138,23 L 135,17 L 142,18 L 132,11 L 116,6 L 94,6 L 78,11 L 92,12 L 80,14 L 90,16 L 82,17 L 82,17 L 82,17\n" +"M 142,234 L 132,227 L 124,223 L 115,220 L 110,225 L 118,224 L 127,229 L 135,236 L 122,234 L 115,237 L 113,242 L 121,238 L 139,243 L 121,245 L 111,254 L 95,254 L 102,244 L 104,235 L 110,229 L 100,231 L 104,224 L 113,216 L 122,215 L 132,217 L 141,224 L 145,230 L 149,240 L 142,234 L 142,234 L 142,234\n" +"M 115,252 L 125,248 L 137,249 L 143,258 L 134,255 L 125,254 L 115,252 L 115,252 L 115,252\n" +"M 114,212 L 130,213 L 140,219 L 147,225 L 144,214 L 137,209 L 128,207 L 114,212 L 114,212 L 114,212\n" +"M 102,263 L 108,258 L 117,257 L 131,258 L 116,260 L 109,265 L 102,263 L 102,263 L 102,263\n" +"M 51,241 L 35,224 L 40,238 L 23,224 L 31,242 L 19,239 L 28,247 L 17,246 L 25,250 L 37,254 L 39,263 L 44,271 L 47,294 L 48,317 L 51,328 L 60,351 L 60,323 L 53,262 L 47,246 L 51,241 L 51,241 L 51,241\n" +"M 2,364 L 9,367 L 14,366 L 18,355 L 20,364 L 26,366 L 31,357 L 35,364 L 39,364 L 42,357 L 47,363 L 53,360 L 59,357 L 54,369 L 7,373 L 2,364 L 2,364 L 2,364\n" +"M 7,349 L 19,345 L 25,339 L 18,341 L 23,333 L 28,326 L 23,326 L 27,320 L 23,316 L 25,311 L 20,298 L 15,277 L 12,264 L 9,249 L 10,223 L 3,248 L 5,261 L 15,307 L 17,326 L 11,343 L 7,349 L 7,349 L 7,349\n" +"M 11,226 L 15,231 L 25,236 L 18,227 L 11,226 L 11,226 L 11,226\n" +"M 13,214 L 19,217 L 32,227 L 23,214 L 16,208 L 15,190 L 24,148 L 31,121 L 24,137 L 14,170 L 8,189 L 13,214 L 13,214 L 13,214\n" +"M 202,254 L 195,258 L 199,260 L 193,263 L 197,263 L 190,268 L 196,268 L 191,273 L 188,282 L 200,272 L 194,272 L 201,266 L 197,265 L 204,262 L 200,258 L 204,256 L 202,254 L 202,254 L 202,254\n" +"845433\n" +"M 151,213 L 165,212 L 179,225 L 189,246 L 187,262 L 179,275 L 176,263 L 177,247 L 171,233 L 163,230 L 165,251 L 157,264 L 146,298 L 145,321 L 133,326 L 143,285 L 154,260 L 153,240 L 151,213 L 151,213 L 151,213\n" +"M 91,132 L 95,145 L 97,154 L 104,148 L 107,155 L 109,150 L 111,158 L 115,152 L 118,159 L 120,153 L 125,161 L 126,155 L 133,164 L 132,154 L 137,163 L 137,152 L 142,163 L 147,186 L 152,192 L 148,167 L 141,143 L 124,145 L 105,143 L 91,132 L 91,132 L 91,132\n" +"9c826b\n" +"M 31,57 L 23,52 L 26,51 L 20,44 L 23,42 L 21,36 L 22,29 L 25,23 L 24,32 L 30,43 L 26,41 L 30,50 L 26,48 L 31,57 L 31,57 L 31,57\n" +"M 147,21 L 149,28 L 155,21 L 161,16 L 167,14 L 175,15 L 173,11 L 161,9 L 147,21 L 147,21 L 147,21\n" +"M 181,39 L 175,51 L 169,57 L 171,65 L 165,68 L 165,75 L 160,76 L 162,91 L 171,71 L 180,51 L 181,39 L 181,39 L 181,39\n" +"M 132,346 L 139,348 L 141,346 L 142,341 L 147,342 L 143,355 L 133,350 L 132,346 L 132,346 L 132,346\n" +"M 146,355 L 151,352 L 155,348 L 157,343 L 160,349 L 151,356 L 147,357 L 146,355 L 146,355 L 146,355\n" +"M 99,266 L 100,281 L 94,305 L 86,322 L 78,332 L 72,346 L 73,331 L 91,291 L 99,266 L 99,266 L 99,266\n" +"M 20,347 L 32,342 L 45,340 L 54,345 L 45,350 L 42,353 L 38,350 L 31,353 L 29,356 L 23,350 L 19,353 L 15,349 L 20,347 L 20,347 L 20,347\n" +"M 78,344 L 86,344 L 92,349 L 88,358 L 84,352 L 78,344 L 78,344 L 78,344\n" +"M 93,347 L 104,344 L 117,345 L 124,354 L 121,357 L 116,351 L 112,351 L 108,355 L 102,351 L 93,347 L 93,347 L 93,347\n" +"000000\n" +"M 105,12 L 111,18 L 113,24 L 113,29 L 119,34 L 116,23 L 112,16 L 105,12 L 105,12 L 105,12\n" +"M 122,27 L 125,34 L 127,43 L 128,34 L 125,29 L 122,27 L 122,27 L 122,27\n" +"M 115,13 L 122,19 L 122,15 L 113,10 L 115,13 L 115,13 L 115,13\n" +"ffe5b2\n" +"M 116,172 L 107,182 L 98,193 L 98,183 L 90,199 L 89,189 L 84,207 L 88,206 L 87,215 L 95,206 L 93,219 L 91,230 L 98,216 L 97,226 L 104,214 L 112,209 L 104,208 L 113,202 L 126,200 L 139,207 L 132,198 L 142,203 L 134,192 L 142,195 L 134,187 L 140,185 L 130,181 L 136,177 L 126,177 L 125,171 L 116,180 L 116,172 L 116,172 L 116,172\n" +"M 74,220 L 67,230 L 67,221 L 59,235 L 63,233 L 60,248 L 70,232 L 65,249 L 71,243 L 67,256 L 73,250 L 69,262 L 73,259 L 71,267 L 76,262 L 72,271 L 78,270 L 76,275 L 82,274 L 78,290 L 86,279 L 86,289 L 92,274 L 88,275 L 87,264 L 82,270 L 82,258 L 77,257 L 78,247 L 73,246 L 77,233 L 72,236 L 74,220 L 74,220 L 74,220\n" +"M 133,230 L 147,242 L 148,250 L 145,254 L 138,247 L 129,246 L 142,245 L 138,241 L 128,237 L 137,238 L 133,230 L 133,230 L 133,230\n" +"M 133,261 L 125,261 L 116,263 L 111,267 L 125,265 L 133,261 L 133,261 L 133,261\n" +"M 121,271 L 109,273 L 103,279 L 99,305 L 92,316 L 85,327 L 83,335 L 89,340 L 97,341 L 94,336 L 101,336 L 96,331 L 103,330 L 97,327 L 108,325 L 99,322 L 109,321 L 100,318 L 110,317 L 105,314 L 110,312 L 107,310 L 113,308 L 105,306 L 114,303 L 105,301 L 115,298 L 107,295 L 115,294 L 108,293 L 117,291 L 109,289 L 117,286 L 109,286 L 118,283 L 112,281 L 118,279 L 114,278 L 119,276 L 115,274 L 121,271 L 121,271 L 121,271\n" +"M 79,364 L 74,359 L 74,353 L 76,347 L 80,351 L 83,356 L 82,360 L 79,364 L 79,364 L 79,364\n" +"M 91,363 L 93,356 L 97,353 L 103,355 L 105,360 L 103,366 L 99,371 L 94,368 L 91,363 L 91,363 L 91,363\n" +"M 110,355 L 114,353 L 118,357 L 117,363 L 113,369 L 111,362 L 110,355 L 110,355 L 110,355\n" +"M 126,354 L 123,358 L 124,367 L 126,369 L 129,361 L 129,357 L 126,354 L 126,354 L 126,354\n" +"M 30,154 L 24,166 L 20,182 L 23,194 L 29,208 L 37,218 L 41,210 L 41,223 L 46,214 L 46,227 L 52,216 L 52,227 L 61,216 L 59,225 L 68,213 L 73,219 L 70,207 L 77,212 L 69,200 L 77,202 L 70,194 L 78,197 L 68,187 L 76,182 L 64,182 L 58,175 L 58,185 L 53,177 L 50,186 L 46,171 L 44,182 L 39,167 L 36,172 L 36,162 L 30,166 L 30,154 L 30,154 L 30,154\n" +"M 44,130 L 41,137 L 45,136 L 43,150 L 48,142 L 48,157 L 53,150 L 52,164 L 60,156 L 61,169 L 64,165 L 66,175 L 70,167 L 74,176 L 77,168 L 80,183 L 85,172 L 90,182 L 93,174 L 98,181 L 99,173 L 104,175 L 105,169 L 114,168 L 102,163 L 95,157 L 94,166 L 90,154 L 87,162 L 82,149 L 75,159 L 72,148 L 68,155 L 67,143 L 62,148 L 62,138 L 58,145 L 56,133 L 52,142 L 52,128 L 49,134 L 47,125 L 44,130 L 44,130 L 44,130\n" +"M 13,216 L 19,219 L 36,231 L 22,223 L 16,222 L 22,227 L 12,224 L 13,220 L 16,220 L 13,216 L 13,216 L 13,216\n" +"M 10,231 L 14,236 L 25,239 L 27,237 L 19,234 L 10,231 L 10,231 L 10,231\n" +"M 9,245 L 14,242 L 25,245 L 13,245 L 9,245 L 9,245 L 9,245\n" +"M 33,255 L 26,253 L 18,254 L 25,256 L 18,258 L 27,260 L 18,263 L 27,265 L 19,267 L 29,270 L 21,272 L 29,276 L 21,278 L 30,281 L 22,283 L 31,287 L 24,288 L 32,292 L 23,293 L 34,298 L 26,299 L 37,303 L 32,305 L 39,309 L 33,309 L 39,314 L 34,314 L 40,318 L 34,317 L 40,321 L 34,321 L 41,326 L 33,326 L 40,330 L 33,332 L 39,333 L 33,337 L 42,337 L 54,341 L 49,337 L 52,335 L 47,330 L 50,330 L 45,325 L 49,325 L 45,321 L 48,321 L 45,316 L 46,306 L 45,286 L 43,274 L 36,261 L 33,255 L 33,255 L 33,255\n" +"M 7,358 L 9,351 L 14,351 L 17,359 L 11,364 L 7,358 L 7,358 L 7,358\n" +"M 44,354 L 49,351 L 52,355 L 49,361 L 44,354 L 44,354 L 44,354\n" +"M 32,357 L 37,353 L 40,358 L 36,361 L 32,357 L 32,357 L 32,357\n" +"M 139,334 L 145,330 L 154,330 L 158,334 L 154,341 L 152,348 L 145,350 L 149,340 L 147,336 L 141,339 L 139,345 L 136,342 L 136,339 L 139,334 L 139,334 L 139,334\n" +"M 208,259 L 215,259 L 212,255 L 220,259 L 224,263 L 225,274 L 224,283 L 220,292 L 208,300 L 206,308 L 203,304 L 199,315 L 197,309 L 195,318 L 193,313 L 190,322 L 190,316 L 185,325 L 182,318 L 180,325 L 172,321 L 178,320 L 176,313 L 186,312 L 180,307 L 188,307 L 184,303 L 191,302 L 186,299 L 195,294 L 187,290 L 197,288 L 192,286 L 201,283 L 194,280 L 203,277 L 198,275 L 207,271 L 200,269 L 209,265 L 204,265 L 212,262 L 208,259 L 208,259 L 208,259\n" +"M 106,126 L 106,131 L 109,132 L 111,134 L 115,132 L 115,135 L 119,133 L 118,137 L 123,137 L 128,137 L 133,134 L 136,130 L 136,127 L 132,124 L 118,128 L 112,128 L 106,126 L 106,126 L 106,126\n" +"M 107,114 L 101,110 L 98,102 L 105,97 L 111,98 L 119,102 L 121,108 L 118,112 L 113,115 L 107,114 L 107,114 L 107,114\n" +"M 148,106 L 145,110 L 146,116 L 150,118 L 152,111 L 151,107 L 148,106 L 148,106 L 148,106\n" +"M 80,55 L 70,52 L 75,58 L 63,57 L 72,61 L 57,61 L 67,66 L 57,67 L 62,69 L 54,71 L 61,73 L 54,77 L 63,78 L 53,85 L 60,84 L 56,90 L 69,84 L 63,82 L 75,76 L 70,75 L 77,72 L 72,71 L 78,69 L 72,66 L 81,67 L 78,64 L 82,63 L 80,60 L 86,62 L 80,55 L 80,55 L 80,55\n" +"M 87,56 L 91,52 L 96,50 L 102,56 L 98,56 L 92,60 L 87,56 L 87,56 L 87,56\n" +"M 85,68 L 89,73 L 98,76 L 106,74 L 96,73 L 91,70 L 85,68 L 85,68 L 85,68\n" +"M 115,57 L 114,64 L 111,64 L 115,75 L 122,81 L 122,74 L 126,79 L 126,74 L 131,78 L 130,72 L 133,77 L 131,68 L 126,61 L 119,57 L 115,57 L 115,57 L 115,57\n" +"M 145,48 L 143,53 L 147,59 L 151,59 L 150,55 L 145,48 L 145,48 L 145,48\n" +"M 26,22 L 34,15 L 43,10 L 52,10 L 59,16 L 47,15 L 32,22 L 26,22 L 26,22 L 26,22\n" +"M 160,19 L 152,26 L 149,34 L 154,33 L 152,30 L 157,30 L 155,26 L 158,27 L 157,23 L 161,23 L 160,19 L 160,19 L 160,19\n" +"000000\n" +"M 98,117 L 105,122 L 109,122 L 105,117 L 113,120 L 121,120 L 130,112 L 128,108 L 123,103 L 123,99 L 128,101 L 132,106 L 135,109 L 142,105 L 142,101 L 145,101 L 145,91 L 148,101 L 145,105 L 136,112 L 135,116 L 143,124 L 148,120 L 150,122 L 142,128 L 133,122 L 121,125 L 112,126 L 103,125 L 100,129 L 96,124 L 98,117 L 98,117 L 98,117\n" +"M 146,118 L 152,118 L 152,115 L 149,115 L 146,118 L 146,118 L 146,118\n" +"M 148,112 L 154,111 L 154,109 L 149,109 L 148,112 L 148,112 L 148,112\n" +"M 106,112 L 108,115 L 114,116 L 118,114 L 106,112 L 106,112 L 106,112\n" +"M 108,108 L 111,110 L 116,110 L 119,108 L 108,108 L 108,108 L 108,108\n" +"M 106,104 L 109,105 L 117,106 L 115,104 L 106,104 L 106,104 L 106,104\n" +"M 50,25 L 41,26 L 34,33 L 39,43 L 49,58 L 36,51 L 47,68 L 55,69 L 54,59 L 61,57 L 74,46 L 60,52 L 67,42 L 57,48 L 61,40 L 54,45 L 60,36 L 59,29 L 48,38 L 52,30 L 47,32 L 50,25 L 50,25 L 50,25\n" +"M 147,34 L 152,41 L 155,49 L 161,53 L 157,47 L 164,47 L 158,43 L 168,44 L 159,40 L 164,37 L 169,37 L 164,33 L 169,34 L 165,28 L 170,30 L 170,25 L 173,29 L 175,27 L 176,32 L 173,36 L 175,39 L 172,42 L 172,46 L 168,49 L 170,55 L 162,57 L 158,63 L 155,58 L 153,50 L 149,46 L 147,34 L 147,34 L 147,34\n" +"M 155,71 L 159,80 L 157,93 L 157,102 L 155,108 L 150,101 L 149,93 L 154,101 L 152,91 L 151,83 L 155,79 L 155,71 L 155,71 L 155,71\n" +"M 112,78 L 115,81 L 114,91 L 112,87 L 113,82 L 112,78 L 112,78 L 112,78\n" +"M 78,28 L 64,17 L 58,11 L 47,9 L 36,10 L 28,16 L 21,26 L 18,41 L 20,51 L 23,61 L 33,65 L 28,68 L 37,74 L 36,81 L 43,87 L 48,90 L 43,100 L 40,98 L 39,90 L 31,80 L 30,72 L 22,71 L 17,61 L 14,46 L 16,28 L 23,17 L 33,9 L 45,6 L 54,6 L 65,12 L 78,28 L 78,28 L 78,28\n" +"M 67,18 L 76,9 L 87,5 L 101,2 L 118,3 L 135,8 L 149,20 L 149,26 L 144,19 L 132,12 L 121,9 L 105,7 L 89,8 L 76,14 L 70,20 L 67,18 L 67,18 L 67,18\n" +"M 56,98 L 48,106 L 56,103 L 47,112 L 56,110 L 52,115 L 57,113 L 52,121 L 62,115 L 58,123 L 65,119 L 63,125 L 69,121 L 68,127 L 74,125 L 74,129 L 79,128 L 83,132 L 94,135 L 93,129 L 85,127 L 81,122 L 76,126 L 75,121 L 71,124 L 71,117 L 66,121 L 66,117 L 62,117 L 64,112 L 60,113 L 60,110 L 57,111 L 61,105 L 57,107 L 60,101 L 55,102 L 56,98 L 56,98 L 56,98\n" +"M 101,132 L 103,138 L 106,134 L 106,139 L 112,136 L 111,142 L 115,139 L 114,143 L 119,142 L 125,145 L 131,142 L 135,138 L 140,134 L 140,129 L 143,135 L 145,149 L 150,171 L 149,184 L 145,165 L 141,150 L 136,147 L 132,151 L 131,149 L 126,152 L 125,150 L 121,152 L 117,148 L 111,152 L 110,148 L 105,149 L 104,145 L 98,150 L 96,138 L 94,132 L 94,130 L 98,132 L 101,132 L 101,132 L 101,132\n" +"M 41,94 L 32,110 L 23,132 L 12,163 L 6,190 L 7,217 L 5,236 L 3,247 L 9,230 L 12,211 L 12,185 L 18,160 L 26,134 L 35,110 L 43,99 L 41,94 L 41,94 L 41,94\n" +"M 32,246 L 41,250 L 50,257 L 52,267 L 53,295 L 53,323 L 59,350 L 54,363 L 51,365 L 44,366 L 42,360 L 40,372 L 54,372 L 59,366 L 62,353 L 71,352 L 75,335 L 73,330 L 66,318 L 68,302 L 64,294 L 67,288 L 63,286 L 63,279 L 59,275 L 58,267 L 56,262 L 50,247 L 42,235 L 44,246 L 32,236 L 35,244 L 32,246 L 32,246 L 32,246\n" +"M 134,324 L 146,320 L 159,322 L 173,327 L 179,337 L 179,349 L 172,355 L 158,357 L 170,350 L 174,343 L 170,333 L 163,328 L 152,326 L 134,329 L 134,324 L 134,324 L 134,324\n" +"M 173,339 L 183,334 L 184,338 L 191,329 L 194,332 L 199,323 L 202,325 L 206,318 L 209,320 L 213,309 L 221,303 L 228,296 L 232,289 L 234,279 L 233,269 L 230,262 L 225,256 L 219,253 L 208,252 L 198,252 L 210,249 L 223,250 L 232,257 L 237,265 L 238,277 L 238,291 L 232,305 L 221,323 L 218,335 L 212,342 L 200,349 L 178,348 L 173,339 L 173,339 L 173,339\n" +"M 165,296 L 158,301 L 156,310 L 156,323 L 162,324 L 159,318 L 162,308 L 162,304 L 165,296 L 165,296 L 165,296\n" +"M 99,252 L 105,244 L 107,234 L 115,228 L 121,228 L 131,235 L 122,233 L 113,235 L 109,246 L 121,239 L 133,243 L 121,243 L 110,251 L 99,252 L 99,252 L 99,252\n" +"M 117,252 L 124,247 L 134,249 L 136,253 L 126,252 L 117,252 L 117,252 L 117,252\n" +"M 117,218 L 132,224 L 144,233 L 140,225 L 132,219 L 117,218 L 117,218 L 117,218\n" +"M 122,212 L 134,214 L 143,221 L 141,213 L 132,210 L 122,212 L 122,212 L 122,212\n" +"M 69,352 L 70,363 L 76,373 L 86,378 L 97,379 L 108,379 L 120,377 L 128,378 L 132,373 L 135,361 L 133,358 L 132,366 L 127,375 L 121,374 L 121,362 L 119,367 L 117,374 L 110,376 L 110,362 L 107,357 L 106,371 L 104,375 L 97,376 L 90,375 L 90,368 L 86,362 L 83,364 L 86,369 L 85,373 L 78,370 L 73,362 L 71,351 L 69,352 L 69,352 L 69,352\n" +"M 100,360 L 96,363 L 99,369 L 102,364 L 100,360 L 100,360 L 100,360\n" +"M 115,360 L 112,363 L 114,369 L 117,364 L 115,360 L 115,360 L 115,360\n" +"M 127,362 L 125,364 L 126,369 L 128,365 L 127,362 L 127,362 L 127,362\n" +"M 5,255 L 7,276 L 11,304 L 15,320 L 13,334 L 6,348 L 2,353 L 0,363 L 5,372 L 12,374 L 25,372 L 38,372 L 44,369 L 42,367 L 36,368 L 31,369 L 30,360 L 27,368 L 20,370 L 16,361 L 15,368 L 10,369 L 3,366 L 3,359 L 6,352 L 11,348 L 17,331 L 19,316 L 12,291 L 9,274 L 5,255 L 5,255 L 5,255\n" +"M 10,358 L 7,362 L 10,366 L 11,362 L 10,358 L 10,358 L 10,358\n" +"M 25,357 L 22,360 L 24,366 L 27,360 L 25,357 L 25,357 L 25,357\n" +"M 37,357 L 34,361 L 36,365 L 38,361 L 37,357 L 37,357 L 37,357\n" +"M 49,356 L 46,359 L 47,364 L 50,360 L 49,356 L 49,356 L 49,356\n" +"M 130,101 L 132,102 L 135,101 L 139,102 L 143,103 L 142,101 L 137,100 L 133,100 L 130,101 L 130,101 L 130,101\n" +"M 106,48 L 105,52 L 108,56 L 109,52 L 106,48 L 106,48 L 106,48\n" +"M 139,52 L 139,56 L 140,60 L 142,58 L 141,56 L 139,52 L 139,52 L 139,52\n" +"M 25,349 L 29,351 L 30,355 L 33,350 L 37,348 L 42,351 L 45,347 L 49,345 L 44,343 L 36,345 L 25,349 L 25,349 L 25,349\n" +"M 98,347 L 105,351 L 107,354 L 109,349 L 115,349 L 120,353 L 118,349 L 113,346 L 104,346 L 98,347 L 98,347 L 98,347\n" +"M 83,348 L 87,352 L 87,357 L 89,351 L 87,348 L 83,348 L 83,348 L 83,348\n" +"M 155,107 L 163,107 L 170,107 L 186,108 L 175,109 L 155,109 L 155,107 L 155,107 L 155,107\n" +"M 153,114 L 162,113 L 175,112 L 192,114 L 173,114 L 154,115 L 153,114 L 153,114 L 153,114\n" +"M 152,118 L 164,120 L 180,123 L 197,129 L 169,123 L 151,120 L 152,118 L 152,118 L 152,118\n" +"M 68,109 L 87,106 L 107,106 L 106,108 L 88,108 L 68,109 L 68,109 L 68,109\n" +"M 105,111 L 95,112 L 79,114 L 71,116 L 85,115 L 102,113 L 105,111 L 105,111 L 105,111\n" +"M 108,101 L 98,99 L 87,99 L 78,99 L 93,100 L 105,102 L 108,101 L 108,101 L 108,101\n" +"M 85,63 L 91,63 L 97,60 L 104,60 L 108,62 L 111,69 L 112,75 L 110,74 L 108,71 L 103,73 L 106,69 L 105,65 L 103,64 L 103,67 L 102,70 L 99,70 L 97,66 L 94,67 L 97,72 L 88,67 L 84,66 L 85,63 L 85,63 L 85,63\n" +"M 140,74 L 141,66 L 144,61 L 150,61 L 156,62 L 153,70 L 150,73 L 152,65 L 150,65 L 151,68 L 149,71 L 146,71 L 144,66 L 143,70 L 143,74 L 140,74 L 140,74 L 140,74\n" +"M 146,20 L 156,11 L 163,9 L 172,9 L 178,14 L 182,18 L 184,32 L 182,42 L 182,52 L 177,58 L 176,67 L 171,76 L 165,90 L 157,105 L 160,92 L 164,85 L 168,78 L 167,73 L 173,66 L 172,62 L 175,59 L 174,55 L 177,53 L 180,46 L 181,29 L 179,21 L 173,13 L 166,11 L 159,13 L 153,18 L 148,23 L 146,20 L 146,20 L 146,20\n" +"M 150,187 L 148,211 L 150,233 L 153,247 L 148,267 L 135,283 L 125,299 L 136,292 L 131,313 L 122,328 L 122,345 L 129,352 L 133,359 L 133,367 L 137,359 L 148,356 L 140,350 L 131,347 L 129,340 L 132,332 L 140,328 L 137,322 L 140,304 L 154,265 L 157,244 L 155,223 L 161,220 L 175,229 L 186,247 L 185,260 L 176,275 L 178,287 L 185,277 L 188,261 L 196,253 L 189,236 L 174,213 L 150,187 L 150,187 L 150,187\n" +"M 147,338 L 142,341 L 143,345 L 141,354 L 147,343 L 147,338 L 147,338 L 147,338\n" +"M 157,342 L 156,349 L 150,356 L 157,353 L 163,346 L 162,342 L 157,342 L 157,342 L 157,342\n" +"M 99,265 L 96,284 L 92,299 L 73,339 L 73,333 L 87,300 L 99,265 L 99,265 L 99,265\n"; + + + +unsigned parse_lion(agg::path_storage& path, agg::rgba8* colors, unsigned* path_idx) +{ + // Parse the lion and then detect its bounding + // box and arrange polygons orientations (make all polygons + // oriented clockwise or counterclockwise) + + const char* ptr = g_lion; + unsigned npaths = 0; + + while(*ptr) + { + if(*ptr != 'M' && isalnum(*ptr)) + { + unsigned c = 0; + sscanf(ptr, "%x", &c); + + // New color. Every new color creates new path in the path object. + path.close_polygon(); + colors[npaths] = agg::rgb8_packed(c); + path_idx[npaths] = path.start_new_path(); + npaths++; + while(*ptr && *ptr != '\n') ptr++; + if(*ptr == '\n') ptr++; + } + else + { + double x = 0.0; + double y = 0.0; + + while(*ptr && *ptr != '\n') + { + int c = *ptr; + + while(*ptr && !isdigit(*ptr)) ptr++; + x = atof(ptr); + + while(*ptr && isdigit(*ptr)) ptr++; + while(*ptr && !isdigit(*ptr)) ptr++; + y = atof(ptr); + + if(c == 'M') + { + path.close_polygon(); + path.move_to(x, y); + } + else + { + path.line_to(x, y); + } + + while(*ptr && isdigit(*ptr)) ptr++; + while(*ptr && *ptr != '\n' && !isalpha(*ptr)) ptr++; + } + if(*ptr == '\n') ptr++; + } + } + path.arrange_orientations_all_paths(agg::path_flags_cw); + return npaths; +} + diff --git a/jni/desmume/src/android/agg/examples/pattern_fill.cpp b/jni/desmume/src/android/agg/examples/pattern_fill.cpp new file mode 100755 index 0000000..1c5815e --- /dev/null +++ b/jni/desmume/src/android/agg/examples/pattern_fill.cpp @@ -0,0 +1,381 @@ +#include +#include +#include +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_path_storage.h" +#include "agg_trans_affine.h" +#include "agg_conv_transform.h" +#include "agg_conv_smooth_poly1.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_span_allocator.h" +#include "agg_span_pattern_gray.h" +#include "agg_span_pattern_rgb.h" +#include "agg_span_pattern_rgba.h" +#include "agg_image_accessors.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "platform/agg_platform_support.h" + +enum flip_y_e { flip_y = true }; + +//#define AGG_GRAY8 +//#define AGG_BGR24 +//#define AGG_RGB24 +#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + + + + +class the_application : public agg::platform_support +{ + agg::slider_ctrl m_polygon_angle; + agg::slider_ctrl m_polygon_scale; + + agg::slider_ctrl m_pattern_angle; + agg::slider_ctrl m_pattern_size; + + agg::slider_ctrl m_pattern_alpha; + + agg::cbox_ctrl m_rotate_polygon; + agg::cbox_ctrl m_rotate_pattern; + agg::cbox_ctrl m_tie_pattern; + + double m_polygon_cx; + double m_polygon_cy; + + double m_dx; + double m_dy; + + int m_flag; + + agg::int8u* m_pattern; + agg::rendering_buffer m_pattern_rbuf; + + agg::rasterizer_scanline_aa<> m_ras; + agg::scanline_p8 m_sl; + agg::path_storage m_ps; + + +public: + //------------------------------------------------------------------------ + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_polygon_angle(5, 5, 145, 12, !flip_y), + m_polygon_scale(5, 5+14, 145, 12+14, !flip_y), + m_pattern_angle(155, 5, 300, 12, !flip_y), + m_pattern_size (155, 5+14, 300, 12+14, !flip_y), + m_pattern_alpha(310, 5, 460, 12, !flip_y), + m_rotate_polygon(5, 5+14+14, "Rotate Polygon", !flip_y), + m_rotate_pattern(5, 5+14+14+14, "Rotate Pattern", !flip_y), + m_tie_pattern (155, 5+14+14, "Tie pattern to polygon", !flip_y), + m_flag(0), + m_pattern(0) + { + add_ctrl(m_polygon_angle); + add_ctrl(m_polygon_scale); + add_ctrl(m_pattern_angle); + add_ctrl(m_pattern_size); + add_ctrl(m_pattern_alpha); + add_ctrl(m_rotate_polygon); + add_ctrl(m_rotate_pattern); + add_ctrl(m_tie_pattern); + + m_polygon_angle.label("Polygon Angle=%3.2f"); + m_polygon_angle.range(-180.0, 180.0); + + m_polygon_scale.label("Polygon Scale=%3.2f"); + m_polygon_scale.range(0.1, 5.0); + m_polygon_scale.value(1.0); + + m_pattern_angle.label("Pattern Angle=%3.2f"); + m_pattern_angle.range(-180.0, 180.0); + + m_pattern_size.label("Pattern Size=%3.2f"); + m_pattern_size.range(10, 40); + m_pattern_size.value(30); + + m_pattern_alpha.label("Background Alpha=%.2f"); + m_pattern_alpha.value(0.1); + } + + //------------------------------------------------------------------------ + virtual ~the_application() + { + delete [] m_pattern; + } + + + //------------------------------------------------------------------------ + void create_star(double xc, double yc, + double r1, double r2, + unsigned n, double start_angle = 0.0) + { + m_ps.remove_all(); + unsigned i; + start_angle *= agg::pi / 180.0; + for(i = 0; i < n; i++) + { + double a = agg::pi * 2.0 * i / n - agg::pi / 2.0; + double dx = cos(a + start_angle); + double dy = sin(a + start_angle); + + if(i & 1) + { + m_ps.line_to(xc + dx * r1, yc + dy * r1); + } + else + { + if(i) m_ps.line_to(xc + dx * r2, yc + dy * r2); + else m_ps.move_to(xc + dx * r2, yc + dy * r2); + } + } + m_ps.close_polygon(); + } + + + //------------------------------------------------------------------------ + void generate_pattern() + { + unsigned size = unsigned(m_pattern_size.value()); + + create_star(m_pattern_size.value() / 2.0, + m_pattern_size.value() / 2.0, + m_pattern_size.value() / 2.5, + m_pattern_size.value() / 6.0, + 6, + m_pattern_angle.value()); + + agg::conv_smooth_poly1_curve smooth(m_ps); + agg::conv_stroke > stroke(smooth); + + smooth.smooth_value(1.0); + smooth.approximation_scale(4.0); + stroke.width(m_pattern_size.value() / 15.0); + + delete [] m_pattern; + m_pattern = new agg::int8u[size * size * 4]; + m_pattern_rbuf.attach(m_pattern, size, size, size*4); + + pixfmt pixf(m_pattern_rbuf); + agg::renderer_base rb(pixf); + agg::renderer_scanline_aa_solid > rs(rb); + + rb.clear(agg::rgba_pre(0.4, 0.0, 0.1, m_pattern_alpha.value())); // Pattern background color + + m_ras.add_path(smooth); + rs.color(agg::rgba8(110,130,50)); + agg::render_scanlines(m_ras, m_sl, rs); + + m_ras.add_path(stroke); + rs.color(agg::rgba8(0,50,80)); + agg::render_scanlines(m_ras, m_sl, rs); + } + + + //------------------------------------------------------------------------ + virtual void on_init() + { + m_polygon_cx = initial_width() / 2.0; + m_polygon_cy = initial_height() / 2.0; + generate_pattern(); + } + + + //------------------------------------------------------------------------ + virtual void on_draw() + { + double width = rbuf_window().width(); + double height = rbuf_window().height(); + + typedef agg::renderer_base renderer_base; + typedef agg::renderer_base renderer_base_pre; + + pixfmt pixf(rbuf_window()); + pixfmt_pre pixf_pre(rbuf_window()); + + renderer_base rb(pixf); + renderer_base_pre rb_pre(pixf_pre); + + rb.clear(agg::rgba(1.0, 1.0, 1.0)); + + agg::trans_affine polygon_mtx; + + polygon_mtx *= agg::trans_affine_translation(-m_polygon_cx, -m_polygon_cy); + polygon_mtx *= agg::trans_affine_rotation(m_polygon_angle.value() * agg::pi / 180.0); + polygon_mtx *= agg::trans_affine_scaling(m_polygon_scale.value()); + polygon_mtx *= agg::trans_affine_translation(m_polygon_cx, m_polygon_cy); + + double r = initial_width() / 3.0 - 8.0; + create_star(m_polygon_cx, m_polygon_cy, r, r / 1.45, 14); + + agg::conv_transform tr(m_ps, polygon_mtx); + + typedef agg::wrap_mode_reflect_auto_pow2 wrap_x_type; + typedef agg::wrap_mode_reflect_auto_pow2 wrap_y_type; + typedef agg::image_accessor_wrap img_source_type; + typedef agg::span_pattern_rgba span_gen_type; + + unsigned offset_x = 0; + unsigned offset_y = 0; + + if(m_tie_pattern.status()) + { + offset_x = unsigned(width-m_polygon_cx); + offset_y = unsigned(height-m_polygon_cy); + } + + agg::span_allocator sa; + pixfmt img_pixf(m_pattern_rbuf); + img_source_type img_src(img_pixf); + span_gen_type sg(img_src, offset_x, offset_y); + + // Alpha is meaningful for RGB only because RGBA has its own + sg.alpha(span_gen_type::value_type(m_pattern_alpha.value() * 255.0)); + + m_ras.add_path(tr); + agg::render_scanlines_aa(m_ras, m_sl, rb_pre, sa, sg); + + agg::render_ctrl(m_ras, m_sl, rb, m_polygon_angle); + agg::render_ctrl(m_ras, m_sl, rb, m_polygon_scale); + agg::render_ctrl(m_ras, m_sl, rb, m_pattern_angle); + agg::render_ctrl(m_ras, m_sl, rb, m_pattern_size); + agg::render_ctrl(m_ras, m_sl, rb, m_pattern_alpha); + agg::render_ctrl(m_ras, m_sl, rb, m_rotate_polygon); + agg::render_ctrl(m_ras, m_sl, rb, m_rotate_pattern); + agg::render_ctrl(m_ras, m_sl, rb, m_tie_pattern); + } + + + + //------------------------------------------------------------------------ + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + agg::trans_affine polygon_mtx; + + polygon_mtx *= agg::trans_affine_translation(-m_polygon_cx, -m_polygon_cy); + polygon_mtx *= agg::trans_affine_rotation(m_polygon_angle.value() * agg::pi / 180.0); + polygon_mtx *= agg::trans_affine_scaling(m_polygon_scale.value(), m_polygon_scale.value()); + polygon_mtx *= agg::trans_affine_translation(m_polygon_cx, m_polygon_cy); + + double r = initial_width() / 3.0 - 8.0; + create_star(m_polygon_cx, m_polygon_cy, r, r / 1.45, 14); + + agg::conv_transform tr(m_ps, polygon_mtx); + m_ras.add_path(tr); + if(m_ras.hit_test(x, y)) + { + m_dx = x - m_polygon_cx; + m_dy = y - m_polygon_cy; + m_flag = 1; + } + } + } + + + //------------------------------------------------------------------------ + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_flag) + { + m_polygon_cx = x - m_dx; + m_polygon_cy = y - m_dy; + force_redraw(); + } + } + else + { + on_mouse_button_up(x, y, flags); + } + } + + + + //------------------------------------------------------------------------ + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + m_flag = 0; + } + + + + //------------------------------------------------------------------------ + virtual void on_ctrl_change() + { + if(m_rotate_polygon.status() || m_rotate_pattern.status()) + { + wait_mode(false); + } + else + { + wait_mode(true); + } + + generate_pattern(); + force_redraw(); + } + + + //------------------------------------------------------------------------ + virtual void on_idle() + { + bool redraw = false; + if(m_rotate_polygon.status()) + { + m_polygon_angle.value(m_polygon_angle.value() + 0.5); + if(m_polygon_angle.value() >= 180.0) + { + m_polygon_angle.value(m_polygon_angle.value() - 360.0); + } + redraw = true; + } + + if(m_rotate_pattern.status()) + { + m_pattern_angle.value(m_pattern_angle.value() - 0.5); + if(m_pattern_angle.value() <= -180.0) + { + m_pattern_angle.value(m_pattern_angle.value() + 360.0); + } + generate_pattern(); + redraw = true; + } + + if(redraw) force_redraw(); + + } + + +}; + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example: Pattern Filling"); + + if(app.init(640, 480, 0)) + { + return app.run(); + } + return 0; +} + + diff --git a/jni/desmume/src/android/agg/examples/pattern_perspective.cpp b/jni/desmume/src/android/agg/examples/pattern_perspective.cpp new file mode 100755 index 0000000..95ce22f --- /dev/null +++ b/jni/desmume/src/android/agg/examples/pattern_perspective.cpp @@ -0,0 +1,300 @@ +#include +#include +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_path_storage.h" +#include "agg_conv_transform.h" +#include "agg_trans_affine.h" +#include "agg_trans_bilinear.h" +#include "agg_trans_perspective.h" +#include "agg_span_interpolator_linear.h" +#include "agg_span_interpolator_trans.h" +#include "agg_span_allocator.h" +#include "agg_image_accessors.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "platform/agg_platform_support.h" +#include "interactive_polygon.h" + + +#include "agg_pixfmt_rgb.h" +#include "agg_span_image_filter_rgb.h" +#define span_image_filter_2x2 agg::span_image_filter_rgb_2x2 +#define span_image_filter_nn agg::span_image_filter_rgb_nn +#define pix_format agg::pix_format_bgr24 +typedef agg::pixfmt_bgr24 pixfmt; +typedef agg::pixfmt_bgr24_pre pixfmt_pre; +typedef pixfmt::color_type color_type; + +enum flip_y_e { flip_y = true }; + +agg::rasterizer_scanline_aa<> g_rasterizer; +agg::scanline_u8 g_scanline; +double g_x1 = 0; +double g_y1 = 0; +double g_x2 = 0; +double g_y2 = 0; + + +class the_application : public agg::platform_support +{ +public: + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_solid; + typedef agg::renderer_base renderer_base_pre; + + agg::interactive_polygon m_quad; + agg::rbox_ctrl m_trans_type; + bool m_test_flag; + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_quad(4, 5.0), + m_trans_type(460, 5.0, 420+170.0, 60.0, !flip_y), + m_test_flag(false) + { + m_trans_type.text_size(8); + m_trans_type.text_thickness(1); + m_trans_type.add_item("Affine"); + m_trans_type.add_item("Bilinear"); + m_trans_type.add_item("Perspective"); + m_trans_type.cur_item(2); + add_ctrl(m_trans_type); + } + + virtual void on_init() + { + g_x1 = -150; + g_y1 = -150; + g_x2 = 150; + g_y2 = 150; + + double trans_x1 = -200; + double trans_y1 = -200; + double trans_x2 = 200; + double trans_y2 = 200; + + double dx = width() / 2.0 - (trans_x2 + trans_x1) / 2.0; + double dy = height() / 2.0 - (trans_y2 + trans_y1) / 2.0; + m_quad.xn(0) = floor(trans_x1 + dx); + m_quad.yn(0) = floor(trans_y1 + dy); + m_quad.xn(1) = floor(trans_x2 + dx); + m_quad.yn(1) = floor(trans_y1 + dy); + m_quad.xn(2) = floor(trans_x2 + dx); + m_quad.yn(2) = floor(trans_y2 + dy); + m_quad.xn(3) = floor(trans_x1 + dx); + m_quad.yn(3) = floor(trans_y2 + dy); + } + + virtual void on_draw() + { + pixfmt pixf(rbuf_window()); + pixfmt_pre pixf_pre(rbuf_window()); + renderer_base rb(pixf); + renderer_base_pre rb_pre(pixf_pre); + + if(!m_test_flag) + { + rb.clear(agg::rgba(1, 1, 1)); + } + + if(m_trans_type.cur_item() == 0) + { + // For the affine parallelogram transformations we + // calculate the 4-th (implicit) point of the parallelogram + m_quad.xn(3) = m_quad.xn(0) + (m_quad.xn(2) - m_quad.xn(1)); + m_quad.yn(3) = m_quad.yn(0) + (m_quad.yn(2) - m_quad.yn(1)); + } + + if(!m_test_flag) + { + //-------------------------- + // Render the "quad" tool and controls + g_rasterizer.add_path(m_quad); + agg::render_scanlines_aa_solid(g_rasterizer, g_scanline, rb, agg::rgba(0, 0.3, 0.5, 0.6)); + + //-------------------------- + agg::render_ctrl(g_rasterizer, g_scanline, rb, m_trans_type); + } + + // Prepare the polygon to rasterize. Here we need to fill + // the destination (transformed) polygon. + g_rasterizer.clip_box(0, 0, width(), height()); + g_rasterizer.reset(); + g_rasterizer.move_to_d(m_quad.xn(0), m_quad.yn(0)); + g_rasterizer.line_to_d(m_quad.xn(1), m_quad.yn(1)); + g_rasterizer.line_to_d(m_quad.xn(2), m_quad.yn(2)); + g_rasterizer.line_to_d(m_quad.xn(3), m_quad.yn(3)); + + + typedef agg::span_allocator span_alloc_type; + span_alloc_type sa; + agg::image_filter filter; + + typedef agg::wrap_mode_reflect_auto_pow2 remainder_type; + typedef agg::image_accessor_wrap img_source_type; + + pixfmt img_pixf(rbuf_img(0)); + img_source_type img_src(img_pixf); + + enum subdiv_shift_e { subdiv_shift = 2 }; + + switch(m_trans_type.cur_item()) + { + case 0: + { + // Note that we consruct an affine matrix that transforms + // a parallelogram to a rectangle, i.e., it's inverted. + // It's actually the same as: + // tr(g_x1, g_y1, g_x2, g_y2, m_triangle.polygon()); + // tr.invert(); + agg::trans_affine tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); + + // Also note that we can use the linear interpolator instead of + // arbitrary span_interpolator_trans. It works much faster, + // but the transformations must be linear and parellel. + typedef agg::span_interpolator_linear interpolator_type; + interpolator_type interpolator(tr); + + typedef span_image_filter_2x2 span_gen_type; + span_gen_type sg(img_src, interpolator, filter); + agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); + break; + } + + case 1: + { + agg::trans_bilinear tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); + if(tr.is_valid()) + { + typedef agg::span_interpolator_linear interpolator_type; + interpolator_type interpolator(tr); + + typedef span_image_filter_2x2 span_gen_type; + span_gen_type sg(img_src, interpolator, filter); + agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); + } + break; + } + + case 2: + { + agg::trans_perspective tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); + if(tr.is_valid()) + { + typedef agg::span_interpolator_linear_subdiv interpolator_type; + interpolator_type interpolator(tr); + + typedef span_image_filter_2x2 span_gen_type; + span_gen_type sg(img_src, interpolator, filter); + agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); + } + break; + } + } + } + + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_quad.on_mouse_button_down(x, y)) + { + force_redraw(); + } + else + { + start_timer(); + m_test_flag = true; + on_draw(); + on_draw(); + on_draw(); + on_draw(); + char buf[100]; + sprintf(buf, "time=%.3f", elapsed_time()); + m_test_flag = false; + force_redraw(); + message(buf); + } + + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_quad.on_mouse_move(x, y)) + { + force_redraw(); + } + } + if((flags & agg::mouse_left) == 0) + { + on_mouse_button_up(x, y, flags); + } + } + + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + if(m_quad.on_mouse_button_up(x, y)) + { + force_redraw(); + } + } + +}; + + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Pattern Perspective Transformations"); + + const char* img_name = "agg"; + if(argc >= 2) img_name = argv[1]; + if(!app.load_img(0, img_name)) + { + char buf[256]; + if(strcmp(img_name, "agg") == 0) + { + sprintf(buf, "File not found: %s%s. Download http://www.antigrain.com/%s%s\n" + "or copy it from another directory if available.", + img_name, app.img_ext(), img_name, app.img_ext()); + } + else + { + sprintf(buf, "File not found: %s%s", img_name, app.img_ext()); + } + app.message(buf); + return 1; + } + + if(app.init(600, 600, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + + + + + diff --git a/jni/desmume/src/android/agg/examples/pattern_resample.cpp b/jni/desmume/src/android/agg/examples/pattern_resample.cpp new file mode 100755 index 0000000..09f517d --- /dev/null +++ b/jni/desmume/src/android/agg/examples/pattern_resample.cpp @@ -0,0 +1,399 @@ +#include +#include +#include +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_path_storage.h" +#include "agg_conv_transform.h" +#include "agg_trans_affine.h" +#include "agg_span_allocator.h" +#include "agg_span_interpolator_linear.h" +#include "agg_span_interpolator_trans.h" +#include "agg_span_interpolator_persp.h" +#include "agg_span_subdiv_adaptor.h" +#include "agg_image_accessors.h" +#include "agg_gamma_lut.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "ctrl/agg_slider_ctrl.h" +#include "platform/agg_platform_support.h" +#include "interactive_polygon.h" + + +int global_offset = 0; + + +enum flip_y_e { flip_y = true }; + +agg::rasterizer_scanline_aa<> g_rasterizer; +agg::scanline_u8 g_scanline; +double g_x1 = 0; +double g_y1 = 0; +double g_x2 = 0; +double g_y2 = 0; + +#include "agg_pixfmt_rgb.h" +#include "agg_span_image_filter_rgb.h" +#define pix_format agg::pix_format_bgr24 +typedef agg::pixfmt_bgr24 pixfmt; +typedef agg::pixfmt_bgr24_pre pixfmt_pre; +#define span_image_filter_2x2 agg::span_image_filter_rgb_2x2 +#define span_image_resample_affine agg::span_image_resample_rgb_affine +#define span_image_resample agg::span_image_resample_rgb + +typedef pixfmt::color_type color_type; +typedef color_type::value_type value_type; +typedef agg::renderer_base renderer_base; +typedef agg::renderer_base renderer_base_pre; +typedef agg::renderer_scanline_aa_solid renderer_solid; +enum base_scale_e { base_shift = color_type::base_shift }; + +class the_application : public agg::platform_support +{ +public: + agg::gamma_lut m_gamma_lut; + agg::interactive_polygon m_quad; + agg::rbox_ctrl m_trans_type; + agg::slider_ctrl m_gamma; + agg::slider_ctrl m_blur; + double m_old_gamma; + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_gamma_lut(2.0), + m_quad(4, 5.0), + m_trans_type(400, 5.0, 430+170.0, 100.0, !flip_y), + m_gamma(5.0, 5.0+15*0, 400-5, 10.0+15*0, !flip_y), + m_blur (5.0, 5.0+15*1, 400-5, 10.0+15*1, !flip_y), + m_old_gamma(2.0) + { + m_trans_type.text_size(7); + m_trans_type.add_item("Affine No Resample"); + m_trans_type.add_item("Affine Resample"); + m_trans_type.add_item("Perspective No Resample LERP"); + m_trans_type.add_item("Perspective No Resample Exact"); + m_trans_type.add_item("Perspective Resample LERP"); + m_trans_type.add_item("Perspective Resample Exact"); + m_trans_type.cur_item(4); + add_ctrl(m_trans_type); + + m_gamma.range(0.5, 3.0); + m_gamma.value(2.0); + m_gamma.label("Gamma=%.3f"); + add_ctrl(m_gamma); + + m_blur.range(0.5, 2.0); + m_blur.value(1.0); + m_blur.label("Blur=%.3f"); + add_ctrl(m_blur); + } + + + virtual void on_init() + { + g_x1 = -150; + g_y1 = -150; + g_x2 = 150; + g_y2 = 150; + + double trans_x1 = -200; + double trans_y1 = -200; + double trans_x2 = 200; + double trans_y2 = 200; + + double dx = width() / 2.0 - (trans_x2 + trans_x1) / 2.0; + double dy = height() / 2.0 - (trans_y2 + trans_y1) / 2.0; + m_quad.xn(0) = floor(trans_x1 + dx); + m_quad.yn(0) = floor(trans_y1 + dy); + m_quad.xn(1) = floor(trans_x2 + dx); + m_quad.yn(1) = floor(trans_y1 + dy); + m_quad.xn(2) = floor(trans_x2 + dx); + m_quad.yn(2) = floor(trans_y2 + dy); + m_quad.xn(3) = floor(trans_x1 + dx); + m_quad.yn(3) = floor(trans_y2 + dy); + + pixfmt pixf(rbuf_img(0)); + pixf.apply_gamma_dir(m_gamma_lut); + } + + virtual void on_draw() + { + if(m_gamma.value() != m_old_gamma) + { + m_gamma_lut.gamma(m_gamma.value()); + load_img(0, "agg"); + pixfmt pixf(rbuf_img(0)); + pixf.apply_gamma_dir(m_gamma_lut); + m_old_gamma = m_gamma.value(); + } + + pixfmt pixf(rbuf_window()); + pixfmt_pre pixf_pre(rbuf_window()); + renderer_base rb(pixf); + renderer_base_pre rb_pre(pixf_pre); + + renderer_solid r(rb); + + rb.clear(agg::rgba(1, 1, 1)); + + if(m_trans_type.cur_item() < 2) + { + // For the affine parallelogram transformations we + // calculate the 4-th (implicit) point of the parallelogram + m_quad.xn(3) = m_quad.xn(0) + (m_quad.xn(2) - m_quad.xn(1)); + m_quad.yn(3) = m_quad.yn(0) + (m_quad.yn(2) - m_quad.yn(1)); + } + + //-------------------------- + // Render the "quad" tool and controls + g_rasterizer.add_path(m_quad); + r.color(agg::rgba(0, 0.3, 0.5, 0.1)); + agg::render_scanlines(g_rasterizer, g_scanline, r); + + // Prepare the polygon to rasterize. Here we need to fill + // the destination (transformed) polygon. + g_rasterizer.clip_box(0, 0, width(), height()); + g_rasterizer.reset(); + int b = 0; + g_rasterizer.move_to_d(m_quad.xn(0)-b, m_quad.yn(0)-b); + g_rasterizer.line_to_d(m_quad.xn(1)+b, m_quad.yn(1)-b); + g_rasterizer.line_to_d(m_quad.xn(2)+b, m_quad.yn(2)+b); + g_rasterizer.line_to_d(m_quad.xn(3)-b, m_quad.yn(3)+b); + + typedef agg::span_allocator span_alloc_type; + span_alloc_type sa; + agg::image_filter_hanning filter_kernel; + agg::image_filter_lut filter(filter_kernel, true); + + typedef agg::wrap_mode_reflect_auto_pow2 wrap_type; + typedef agg::image_accessor_wrap img_source_type; + + pixfmt img_pixf(rbuf_img(0)); + img_source_type img_src(img_pixf); + + start_timer(); + switch(m_trans_type.cur_item()) + { + case 0: + { + agg::trans_affine tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); + + typedef agg::span_interpolator_linear interpolator_type; + interpolator_type interpolator(tr); + + typedef span_image_filter_2x2 span_gen_type; + span_gen_type sg(img_src, interpolator, filter); + agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); + break; + } + + case 1: + { + agg::trans_affine tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); + + typedef agg::span_interpolator_linear interpolator_type; + typedef span_image_resample_affine span_gen_type; + interpolator_type interpolator(tr); + span_gen_type sg(img_src, interpolator, filter); + sg.blur(m_blur.value()); + agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); + break; + } + + case 2: + { + agg::trans_perspective tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); + if(tr.is_valid()) + { + typedef agg::span_interpolator_linear_subdiv interpolator_type; + interpolator_type interpolator(tr); + + typedef span_image_filter_2x2 span_gen_type; + span_gen_type sg(img_src, interpolator, filter); + agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); + } + break; + } + + case 3: + { + agg::trans_perspective tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); + if(tr.is_valid()) + { + typedef agg::span_interpolator_trans interpolator_type; + interpolator_type interpolator(tr); + + typedef span_image_filter_2x2 span_gen_type; + span_gen_type sg(img_src, interpolator, filter); + agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); + } + break; + } + + case 4: + { + typedef agg::span_interpolator_persp_lerp<> interpolator_type; + typedef agg::span_subdiv_adaptor subdiv_adaptor_type; + + interpolator_type interpolator(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); + subdiv_adaptor_type subdiv_adaptor(interpolator); + + if(interpolator.is_valid()) + { + typedef span_image_resample span_gen_type; + span_gen_type sg(img_src, subdiv_adaptor, filter); + sg.blur(m_blur.value()); + agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); + } + break; + } + + case 5: + { + typedef agg::span_interpolator_persp_exact<> interpolator_type; + typedef agg::span_subdiv_adaptor subdiv_adaptor_type; + + interpolator_type interpolator(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); + subdiv_adaptor_type subdiv_adaptor(interpolator); + + if(interpolator.is_valid()) + { + typedef span_image_resample span_gen_type; + span_gen_type sg(img_src, subdiv_adaptor, filter); + sg.blur(m_blur.value()); + agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg); + } + break; + } + } + double tm = elapsed_time(); + pixf.apply_gamma_inv(m_gamma_lut); + + char buf[64]; + agg::gsv_text t; + t.size(10.0); + + agg::conv_stroke pt(t); + pt.width(1.5); + + sprintf(buf, "%3.2f ms", tm); + t.start_point(10.0, 70.0); + t.text(buf); + + g_rasterizer.add_path(pt); + r.color(agg::rgba(0,0,0)); + agg::render_scanlines(g_rasterizer, g_scanline, r); + + //-------------------------- + agg::render_ctrl(g_rasterizer, g_scanline, rb, m_trans_type); + agg::render_ctrl(g_rasterizer, g_scanline, rb, m_gamma); + agg::render_ctrl(g_rasterizer, g_scanline, rb, m_blur); + } + + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_quad.on_mouse_button_down(x, y)) + { + force_redraw(); + } + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_quad.on_mouse_move(x, y)) + { + force_redraw(); + } + } + if((flags & agg::mouse_left) == 0) + { + on_mouse_button_up(x, y, flags); + } + } + + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + if(m_quad.on_mouse_button_up(x, y)) + { + force_redraw(); + } + } + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + if(key == ' ') + { + double cx = (m_quad.xn(0) + m_quad.xn(1) + m_quad.xn(2) + m_quad.xn(3)) / 4; + double cy = (m_quad.yn(0) + m_quad.yn(1) + m_quad.yn(2) + m_quad.yn(3)) / 4; + agg::trans_affine tr = agg::trans_affine_translation(-cx, -cy); + tr *= agg::trans_affine_rotation(agg::pi / 2.0); + tr *= agg::trans_affine_translation(cx, cy); + tr.transform(&m_quad.xn(0), &m_quad.yn(0)); + tr.transform(&m_quad.xn(1), &m_quad.yn(1)); + tr.transform(&m_quad.xn(2), &m_quad.yn(2)); + tr.transform(&m_quad.xn(3), &m_quad.yn(3)); + force_redraw(); + } + } + + + +}; + + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Pattern Transformations with Resampling"); + + const char* img_name = "agg"; + if(argc >= 2) img_name = argv[1]; + if(!app.load_img(0, img_name)) + { + char buf[256]; + if(strcmp(img_name, "agg") == 0) + { + sprintf(buf, "File not found: %s%s. Download http://www.antigrain.com/%s%s\n" + "or copy it from another directory if available.", + img_name, app.img_ext(), img_name, app.img_ext()); + } + else + { + sprintf(buf, "File not found: %s%s", img_name, app.img_ext()); + } + app.message(buf); + return 1; + } + + + if(app.init(600, 600, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + + + + + diff --git a/jni/desmume/src/android/agg/examples/perspective.cpp b/jni/desmume/src/android/agg/examples/perspective.cpp new file mode 100755 index 0000000..8eab0a5 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/perspective.cpp @@ -0,0 +1,311 @@ +#include +#include +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_path_storage.h" +#include "agg_conv_transform.h" +#include "agg_conv_clip_polygon.h" +#include "agg_bounding_rect.h" +#include "agg_ellipse.h" +#include "agg_trans_bilinear.h" +#include "agg_trans_perspective.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "platform/agg_platform_support.h" +#include "interactive_polygon.h" + +#define AGG_BGR24 +//#define AGG_RGB24 +//#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + +enum flip_y_e { flip_y = true }; + +agg::rasterizer_scanline_aa<> g_rasterizer; +agg::scanline_p8 g_scanline; +agg::path_storage g_path; +agg::rgba8 g_colors[100]; +unsigned g_path_idx[100]; +unsigned g_npaths = 0; +double g_x1 = 0; +double g_y1 = 0; +double g_x2 = 0; +double g_y2 = 0; +double g_base_dx = 0; +double g_base_dy = 0; +double g_angle = 0; +double g_scale = 1.0; +double g_skew_x = 0; +double g_skew_y = 0; +int g_nclick = 0; + +unsigned parse_lion(agg::path_storage& ps, agg::rgba8* colors, unsigned* path_idx); +void parse_lion() +{ + g_npaths = parse_lion(g_path, g_colors, g_path_idx); + agg::pod_array_adaptor path_idx(g_path_idx, 100); + agg::bounding_rect(g_path, path_idx, 0, g_npaths, &g_x1, &g_y1, &g_x2, &g_y2); + g_base_dx = (g_x2 - g_x1) / 2.0; + g_base_dy = (g_y2 - g_y1) / 2.0; + g_path.flip_x(g_x1, g_x2); + g_path.flip_y(g_y1, g_y2); +} + + + + +namespace agg +{ +} + + + + + + + +class the_application : public agg::platform_support +{ +public: + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_solid; + + agg::interactive_polygon m_quad; + agg::rbox_ctrl m_trans_type; + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_quad(4, 5.0), + m_trans_type(420, 5.0, 420+130.0, 55.0, !flip_y) + { + parse_lion(); + m_quad.xn(0) = g_x1; + m_quad.yn(0) = g_y1; + m_quad.xn(1) = g_x2; + m_quad.yn(1) = g_y1; + m_quad.xn(2) = g_x2; + m_quad.yn(2) = g_y2; + m_quad.xn(3) = g_x1; + m_quad.yn(3) = g_y2; + + m_trans_type.add_item("Bilinear"); + m_trans_type.add_item("Perspective"); + m_trans_type.cur_item(0); + add_ctrl(m_trans_type); + } + + + virtual void on_init() + { + double dx = width() / 2.0 - (m_quad.xn(1) - m_quad.xn(0)) / 2.0; + double dy = height() / 2.0 - (m_quad.yn(2) - m_quad.yn(0)) / 2.0; + m_quad.xn(0) += dx; + m_quad.yn(0) += dy; + m_quad.xn(1) += dx; + m_quad.yn(1) += dy; + m_quad.xn(2) += dx; + m_quad.yn(2) += dy; + m_quad.xn(3) += dx; + m_quad.yn(3) += dy; + } + + virtual void on_draw() + { + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + renderer_solid r(rb); + rb.clear(agg::rgba(1, 1, 1)); + + g_rasterizer.clip_box(0, 0, width(), height()); + + if(m_trans_type.cur_item() == 0) + { + agg::trans_bilinear tr(g_x1, g_y1, g_x2, g_y2, m_quad.polygon()); + if(tr.is_valid()) + { + //-------------------------- + // Render transformed lion + // + agg::conv_transform trans(g_path, tr); + + agg::render_all_paths(g_rasterizer, g_scanline, r, trans, g_colors, g_path_idx, g_npaths); + //-------------------------- + + + + //-------------------------- + // Render transformed ellipse + // + agg::ellipse ell((g_x1 + g_x2) * 0.5, (g_y1 + g_y2) * 0.5, + (g_x2 - g_x1) * 0.5, (g_y2 - g_y1) * 0.5, + 200); + agg::conv_stroke ell_stroke(ell); + ell_stroke.width(3.0); + agg::conv_transform trans_ell(ell, tr); + + agg::conv_transform, + agg::trans_bilinear> trans_ell_stroke(ell_stroke, tr); + + g_rasterizer.add_path(trans_ell); + r.color(agg::rgba(0.5, 0.3, 0.0, 0.3)); + agg::render_scanlines(g_rasterizer, g_scanline, r); + + g_rasterizer.add_path(trans_ell_stroke); + r.color(agg::rgba(0.0, 0.3, 0.2, 1.0)); + agg::render_scanlines(g_rasterizer, g_scanline, r); + //-------------------------- + + } + } + else + { + agg::trans_perspective tr(g_x1, g_y1, g_x2, g_y2, m_quad.polygon()); + if(tr.is_valid()) + { + + //-------------------------- + // Render transformed lion + // + agg::conv_transform trans(g_path, tr); + + agg::render_all_paths(g_rasterizer, g_scanline, r, trans, g_colors, g_path_idx, g_npaths); + + //-------------------------- + + + + //-------------------------- + // Render transformed ellipse + // + agg::ellipse ell((g_x1 + g_x2) * 0.5, (g_y1 + g_y2) * 0.5, + (g_x2 - g_x1) * 0.5, (g_y2 - g_y1) * 0.5, + 200); + + agg::conv_stroke ell_stroke(ell); + ell_stroke.width(3.0); + agg::conv_transform trans_ell(ell, tr); + + + agg::conv_transform, + agg::trans_perspective> trans_ell_stroke(ell_stroke, tr); + + + g_rasterizer.add_path(trans_ell); + r.color(agg::rgba(0.5, 0.3, 0.0, 0.3)); + agg::render_scanlines(g_rasterizer, g_scanline, r); + + g_rasterizer.add_path(trans_ell_stroke); + r.color(agg::rgba(0.0, 0.3, 0.2, 1.0)); + agg::render_scanlines(g_rasterizer, g_scanline, r); + //-------------------------- + + + // Testing the reverse transformations + //agg::trans_perspective tr2(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2); + //if(tr2.is_valid()) + //{ + // double x, y; + // x = m_quad.xn(0); y = m_quad.yn(0); tr2.transform(&x, &y); + // g_rasterizer.move_to_d(x, y); + // x = m_quad.xn(1); y = m_quad.yn(1); tr2.transform(&x, &y); + // g_rasterizer.line_to_d(x, y); + // x = m_quad.xn(2); y = m_quad.yn(2); tr2.transform(&x, &y); + // g_rasterizer.line_to_d(x, y); + // x = m_quad.xn(3); y = m_quad.yn(3); tr2.transform(&x, &y); + // g_rasterizer.line_to_d(x, y); + // r.color(agg::rgba(0.5, 0.0, 0.0, 0.5)); + // agg::render_scanlines(g_rasterizer, g_scanline, r); + //} + //else + //{ + // message("Singularity..."); + //} + } + } + + + + + //-------------------------- + // Render the "quad" tool and controls + g_rasterizer.add_path(m_quad); + r.color(agg::rgba(0, 0.3, 0.5, 0.6)); + agg::render_scanlines(g_rasterizer, g_scanline, r); + agg::render_ctrl(g_rasterizer, g_scanline, rb, m_trans_type); + //-------------------------- + } + + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_quad.on_mouse_button_down(x, y)) + { + force_redraw(); + } + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_quad.on_mouse_move(x, y)) + { + force_redraw(); + } + } + if((flags & agg::mouse_left) == 0) + { + on_mouse_button_up(x, y, flags); + } + } + + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + if(m_quad.on_mouse_button_up(x, y)) + { + force_redraw(); + } + } + +}; + + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Perspective Transformations"); + + if(app.init(600, 600, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + + + + + diff --git a/jni/desmume/src/android/agg/examples/pixel_formats.h b/jni/desmume/src/android/agg/examples/pixel_formats.h new file mode 100755 index 0000000..7497d23 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/pixel_formats.h @@ -0,0 +1,184 @@ +#ifndef PIXEL_FORMATS_INCLUDED +#define PIXEL_FORMATS_INCLUDED + +#if defined(AGG_GRAY8) + +#include "agg_pixfmt_gray.h" +#define pix_format agg::pix_format_gray8 +typedef agg::pixfmt_gray8 pixfmt; +typedef agg::pixfmt_gray8_pre pixfmt_pre; +typedef agg::gray8 color_type; + +#elif defined(AGG_GRAY16) + +#include "agg_pixfmt_gray.h" +#define pix_format agg::pix_format_gray16 +typedef agg::pixfmt_gray16 pixfmt; +typedef agg::pixfmt_gray16_pre pixfmt_pre; +typedef agg::gray16 color_type; + +#elif defined(AGG_BGR24) + +#include "agg_pixfmt_rgb.h" +#define pix_format agg::pix_format_bgr24 +typedef agg::pixfmt_bgr24 pixfmt; +typedef agg::pixfmt_bgr24_pre pixfmt_pre; +#define pixfmt_gamma agg::pixfmt_bgr24_gamma +typedef agg::rgba8 color_type; +typedef agg::order_bgr component_order; + +#elif defined(AGG_RGB24) + +#include "agg_pixfmt_rgb.h" +#define pix_format agg::pix_format_rgb24 +typedef agg::pixfmt_rgb24 pixfmt; +typedef agg::pixfmt_rgb24_pre pixfmt_pre; +#define pixfmt_gamma agg::pixfmt_rgb24_gamma +typedef agg::rgba8 color_type; +typedef agg::order_rgb component_order; + +#elif defined(AGG_BGR48) + +#include "agg_pixfmt_rgb.h" +#define pix_format agg::pix_format_bgr48 +typedef agg::pixfmt_bgr48 pixfmt; +typedef agg::pixfmt_bgr48_pre pixfmt_pre; +#define pixfmt_gamma agg::pixfmt_bgr48_gamma +typedef agg::rgba16 color_type; +typedef agg::order_bgr component_order; + +#elif defined(AGG_RGB48) + +#include "agg_pixfmt_rgb.h" +#define pix_format agg::pix_format_rgb48 +typedef agg::pixfmt_rgb48 pixfmt; +typedef agg::pixfmt_rgb48_pre pixfmt_pre; +#define pixfmt_gamma agg::pixfmt_rgb48_gamma +typedef agg::rgba16 color_type; +typedef agg::order_rgb component_order; + +#elif defined(AGG_BGRA32) + +#include "agg_pixfmt_rgba.h" +#define pix_format agg::pix_format_bgra32 +typedef agg::pixfmt_bgra32 pixfmt; +typedef agg::pixfmt_bgra32_pre pixfmt_pre; +typedef agg::rgba8 color_type; +typedef agg::order_bgra component_order; + +#elif defined(AGG_RGBA32) + +#include "agg_pixfmt_rgba.h" +#define pix_format agg::pix_format_rgba32 +typedef agg::pixfmt_rgba32 pixfmt; +typedef agg::pixfmt_rgba32_pre pixfmt_pre; +typedef agg::rgba8 color_type; +typedef agg::order_rgba component_order; + +#elif defined(AGG_ARGB32) + +#include "agg_pixfmt_rgba.h" +#define pix_format agg::pix_format_argb32 +typedef agg::pixfmt_argb32 pixfmt; +typedef agg::pixfmt_argb32_pre pixfmt_pre; +typedef agg::rgba8 color_type; +typedef agg::order_argb component_order; + +#elif defined(AGG_ABGR32) + +#include "agg_pixfmt_rgba.h" +#define pix_format agg::pix_format_abgr32 +typedef agg::pixfmt_abgr32 pixfmt; +typedef agg::pixfmt_abgr32_pre pixfmt_pre; +typedef agg::rgba8 color_type; +typedef agg::order_argb component_order; + +#elif defined(AGG_BGRA64) + +#include "agg_pixfmt_rgba.h" +#define pix_format agg::pix_format_bgra64 +typedef agg::pixfmt_bgra64 pixfmt; +typedef agg::pixfmt_bgra64_pre pixfmt_pre; +typedef agg::rgba16 color_type; +typedef agg::order_bgra component_order; + +#elif defined(AGG_RGBA64) + +#include "agg_pixfmt_rgba.h" +#define pix_format agg::pix_format_rgba64 +typedef agg::pixfmt_rgba64 pixfmt; +typedef agg::pixfmt_rgba64_pre pixfmt_pre; +typedef agg::rgba16 color_type; +typedef agg::order_rgba component_order; + +#elif defined(AGG_ARGB64) + +#include "agg_pixfmt_rgba.h" +#define pix_format agg::pix_format_argb64 +typedef agg::pixfmt_argb64 pixfmt; +typedef agg::pixfmt_argb64_pre pixfmt_pre; +typedef agg::rgba16 color_type; +typedef agg::order_argb component_order; + +#elif defined(AGG_ABGR64) + +#include "agg_pixfmt_rgba.h" +#define pix_format agg::pix_format_abgr64 +typedef agg::pixfmt_abgr64 pixfmt; +typedef agg::pixfmt_abgr64_pre pixfmt_pre; +typedef agg::rgba16 color_type; +typedef agg::order_argb component_order; + +#elif defined(AGG_RGB565) + +#include "agg_pixfmt_rgb_packed.h" +#define pix_format agg::pix_format_rgb565 +typedef agg::pixfmt_rgb565 pixfmt; +typedef agg::pixfmt_rgb565_pre pixfmt_pre; +typedef agg::rgba8 color_type; + +#elif defined(AGG_RGB555) + +#include "agg_pixfmt_rgb_packed.h" +#define pix_format agg::pix_format_rgb555 +typedef agg::pixfmt_rgb555 pixfmt; +typedef agg::pixfmt_rgb555_pre pixfmt_pre; +typedef agg::rgba8 color_type; + +#elif defined(AGG_RGB_AAA) + +#include "agg_pixfmt_rgb_packed.h" +#define pix_format agg::pix_format_rgbAAA +typedef agg::pixfmt_rgbAAA pixfmt; +typedef agg::pixfmt_rgbAAA_pre pixfmt_pre; +typedef agg::rgba16 color_type; + +#elif defined(AGG_BGR_AAA) + +#include "agg_pixfmt_rgb_packed.h" +#define pix_format agg::pix_format_bgrAAA +typedef agg::pixfmt_bgrAAA pixfmt; +typedef agg::pixfmt_bgrAAA_pre pixfmt_pre; +typedef agg::rgba16 color_type; + +#elif defined(AGG_RGB_BBA) + +#include "agg_pixfmt_rgb_packed.h" +#define pix_format agg::pix_format_rgbBBA +typedef agg::pixfmt_rgbBBA pixfmt; +typedef agg::pixfmt_rgbBBA_pre pixfmt_pre; +typedef agg::rgba16 color_type; + +#elif defined(AGG_BGR_ABB) + +#include "agg_pixfmt_rgb_packed.h" +#define pix_format agg::pix_format_bgrABB +typedef agg::pixfmt_bgrABB pixfmt; +typedef agg::pixfmt_bgrABB_pre pixfmt_pre; +typedef agg::rgba16 color_type; + +#else +#error Please define pixel format: AGG_GRAY8, AGG_BGR24, AGG_RGB24, etc. See this file above +#endif + +#endif diff --git a/jni/desmume/src/android/agg/examples/polymorphic_renderer.cpp b/jni/desmume/src/android/agg/examples/polymorphic_renderer.cpp new file mode 100755 index 0000000..a4f1b02 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/polymorphic_renderer.cpp @@ -0,0 +1,167 @@ +#include +#include +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_rasterizer_outline.h" +#include "agg_scanline_p.h" +#include "agg_path_storage.h" +#include "agg_renderer_scanline.h" +#include "platform/agg_platform_support.h" + +#include "agg_pixfmt_rgb.h" +#include "agg_pixfmt_rgb_packed.h" +#include "agg_pixfmt_rgba.h" + +static int pix_fmt = agg::pix_format_rgb555; +//static int pix_fmt = agg::pix_format_rgb565; +//static int pix_fmt = agg::pix_format_rgb24; +//static int pix_fmt = agg::pix_format_bgr24; +//static int pix_fmt = agg::pix_format_rgba32; +//static int pix_fmt = agg::pix_format_argb32; +//static int pix_fmt = agg::pix_format_abgr32; +//static int pix_fmt = agg::pix_format_bgra32; + + +enum flip_y_e { flip_y = true }; + +namespace agg +{ + //======================================================================== + class polymorphic_renderer_solid_rgba8_base + { + public: + typedef rgba8 color_type; + typedef scanline_p8 scanline_type; + + virtual ~polymorphic_renderer_solid_rgba8_base() {} + + //-------------------------------------------------------------------- + virtual void clear(const color_type& c) = 0; + virtual void color(const color_type& c) = 0; + virtual const color_type& color() const = 0; + virtual void prepare() = 0; + virtual void render(const scanline_type&) = 0; + }; + + + + //======================================================================== + template class polymorphic_renderer_solid_rgba8_adaptor : + public polymorphic_renderer_solid_rgba8_base + { + public: + polymorphic_renderer_solid_rgba8_adaptor(rendering_buffer& rbuf) : + m_pixfmt(rbuf), + m_ren_base(m_pixfmt), + m_ren(m_ren_base) + {} + + //-------------------------------------------------------------------- + virtual void clear(const color_type& c) + { + m_ren_base.clear(c); + } + + virtual void color(const color_type& c) + { + m_ren.color(c); + } + + virtual const color_type& color() const + { + return m_ren.color(); + } + + virtual void prepare() + { + m_ren.prepare(); + } + + virtual void render(const scanline_type& sl) + { + m_ren.render(sl); + } + + private: + PixFmt m_pixfmt; + renderer_base m_ren_base; + renderer_scanline_aa_solid > m_ren; + }; + + +} + + + + + + + +class the_application : public agg::platform_support +{ + double m_x[3]; + double m_y[3]; + +public: + the_application(int format, bool flip_y) : + agg::platform_support((agg::pix_format_e)format, flip_y) + { + m_x[0] = 100; m_y[0] = 60; + m_x[1] = 369; m_y[1] = 170; + m_x[2] = 143; m_y[2] = 310; + } + + virtual void on_draw() + { + agg::path_storage path; + path.move_to(m_x[0], m_y[0]); + path.line_to(m_x[1], m_y[1]); + path.line_to(m_x[2], m_y[2]); + path.close_polygon(); + + agg::polymorphic_renderer_solid_rgba8_base* ren = 0; + + //-- Polymorphic renderer class factory + switch(pix_fmt) + { + case agg::pix_format_rgb555 : ren = new agg::polymorphic_renderer_solid_rgba8_adaptor(rbuf_window()); break; + case agg::pix_format_rgb565 : ren = new agg::polymorphic_renderer_solid_rgba8_adaptor(rbuf_window()); break; + case agg::pix_format_rgb24 : ren = new agg::polymorphic_renderer_solid_rgba8_adaptor(rbuf_window()); break; + case agg::pix_format_bgr24 : ren = new agg::polymorphic_renderer_solid_rgba8_adaptor(rbuf_window()); break; + case agg::pix_format_rgba32 : ren = new agg::polymorphic_renderer_solid_rgba8_adaptor(rbuf_window()); break; + case agg::pix_format_argb32 : ren = new agg::polymorphic_renderer_solid_rgba8_adaptor(rbuf_window()); break; + case agg::pix_format_abgr32 : ren = new agg::polymorphic_renderer_solid_rgba8_adaptor(rbuf_window()); break; + case agg::pix_format_bgra32 : ren = new agg::polymorphic_renderer_solid_rgba8_adaptor(rbuf_window()); break; + } + + agg::rasterizer_scanline_aa<> ras; + agg::scanline_p8 sl; + if(ren) + { + ren->clear(agg::rgba8(255, 255, 255)); + ren->color(agg::rgba8(80, 30, 20)); + ras.add_path(path); + agg::render_scanlines(ras, sl, *ren); + } + delete ren; + } + +}; + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_fmt, flip_y); + app.caption("AGG Example. Polymorphic Renderers"); + + if(app.init(400, 330, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/raster_text.cpp b/jni/desmume/src/android/agg/examples/raster_text.cpp new file mode 100755 index 0000000..a5b2fe9 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/raster_text.cpp @@ -0,0 +1,178 @@ +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_pixfmt_rgb.h" +#include "agg_span_allocator.h" +#include "agg_span_gradient.h" +#include "agg_span_interpolator_linear.h" +#include "agg_glyph_raster_bin.h" +#include "agg_renderer_raster_text.h" +#include "agg_embedded_raster_fonts.h" +#include "platform/agg_platform_support.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" + + +enum flip_y_e { flip_y = true }; + + + + +//------------------------------------------------------------------------ +template class gradient_sine_repeat_adaptor +{ +public: + gradient_sine_repeat_adaptor() : m_periods(agg::pi* 2.0) {} + + void periods(double p) { m_periods = p * agg::pi * 2.0; } + + int calculate(int x, int y, int d) const + { + return int((1.0 + sin(m_gradient.calculate(x, y, d) * m_periods / d)) * d/2); + } + +private: + GradientF m_gradient; + double m_periods; +}; + + + + +//------------------------------------------------------------------------ +class the_application : public agg::platform_support +{ +public: + typedef agg::pixfmt_bgr24 pixfmt; + typedef agg::renderer_base ren_base; + typedef agg::glyph_raster_bin glyph_gen; + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y) + { + } + + + virtual void on_draw() + { + struct font_type + { + const agg::int8u* font; + const char* name; + } + fonts[] = + { + { agg::gse4x6, "gse4x6" }, + { agg::gse4x8, "gse4x8" }, + { agg::gse5x7, "gse5x7" }, + { agg::gse5x9, "gse5x9" }, + { agg::gse6x9, "gse6x9" }, + { agg::gse6x12, "gse6x12" }, + { agg::gse7x11, "gse7x11" }, + { agg::gse7x11_bold, "gse7x11_bold" }, + { agg::gse7x15, "gse7x15" }, + { agg::gse7x15_bold, "gse7x15_bold" }, + { agg::gse8x16, "gse8x16" }, + { agg::gse8x16_bold, "gse8x16_bold" }, + { agg::mcs11_prop, "mcs11_prop" }, + { agg::mcs11_prop_condensed, "mcs11_prop_condensed" }, + { agg::mcs12_prop, "mcs12_prop" }, + { agg::mcs13_prop, "mcs13_prop" }, + { agg::mcs5x10_mono, "mcs5x10_mono" }, + { agg::mcs5x11_mono, "mcs5x11_mono" }, + { agg::mcs6x10_mono, "mcs6x10_mono" }, + { agg::mcs6x11_mono, "mcs6x11_mono" }, + { agg::mcs7x12_mono_high, "mcs7x12_mono_high" }, + { agg::mcs7x12_mono_low, "mcs7x12_mono_low" }, + { agg::verdana12, "verdana12" }, + { agg::verdana12_bold, "verdana12_bold" }, + { agg::verdana13, "verdana13" }, + { agg::verdana13_bold, "verdana13_bold" }, + { agg::verdana14, "verdana14" }, + { agg::verdana14_bold, "verdana14_bold" }, + { agg::verdana16, "verdana16" }, + { agg::verdana16_bold, "verdana16_bold" }, + { agg::verdana17, "verdana17" }, + { agg::verdana17_bold, "verdana17_bold" }, + { agg::verdana18, "verdana18" }, + { agg::verdana18_bold, "verdana18_bold" }, + 0, 0 + }; + + + + glyph_gen glyph(0); + pixfmt pixf(rbuf_window()); + ren_base rb(pixf); + rb.clear(agg::rgba(1,1,1)); + + + agg::renderer_raster_htext_solid rt(rb, glyph); + + int i; + double y = 5; + rt.color(agg::rgba(0,0,0)); + for(i = 0; fonts[i].font; i++) + { + char buf[100]; + strcpy(buf, "A quick brown fox jumps over the lazy dog 0123456789: "); + strcat(buf, fonts[i].name); + + // Testing "wide-char" + unsigned wbuf[100]; + unsigned* wp = wbuf; + const char* p = buf; + while(*p) *wp++ = *(unsigned char*)p++; + *wp++ = 0; + + glyph.font(fonts[i].font); + rt.render_text(5, y, wbuf, !flip_y()); + y += glyph.height() + 1; + } + + + // Rendering raster text with a custom span generator, gradient + + typedef agg::span_interpolator_linear<> interpolator_type; + typedef agg::span_allocator span_alloc_type; + typedef agg::span_gradient, + agg::gradient_linear_color > span_gen_type; + typedef agg::renderer_scanline_aa ren_type; + + agg::trans_affine mtx; + gradient_sine_repeat_adaptor grad_func; + grad_func.periods(5); + agg::gradient_linear_color color_func; + color_func.colors(agg::rgba(1.0,0,0), agg::rgba(0,0.5,0)); + interpolator_type inter(mtx); + span_alloc_type sa; + span_gen_type sg(inter, grad_func, color_func, 0, 150.0); + ren_type ren(rb, sa, sg); + + agg::renderer_raster_htext rt2(ren, glyph); + rt2.render_text(5, 465, (unsigned char*)"RADIAL REPEATING GRADIENT: A quick brown fox jumps over the lazy dog", !flip_y()); + } + +}; + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("AGG Example. Raster Text"); + + if(app.init(640, 480, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/rasterizer_compound.cpp b/jni/desmume/src/android/agg/examples/rasterizer_compound.cpp new file mode 100755 index 0000000..45a1a76 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/rasterizer_compound.cpp @@ -0,0 +1,299 @@ +#include +#include +#include "agg_basics.h" +#include "agg_ellipse.h" +#include "agg_gamma_lut.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_rasterizer_compound_aa.h" +#include "agg_conv_curve.h" +#include "agg_conv_stroke.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_span_allocator.h" +#include "agg_pixfmt_rgba.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "platform/agg_platform_support.h" + + +enum flip_y_e { flip_y = true }; + + +//------------------------------------------------- +class style_handler +{ +public: + style_handler(const agg::rgba8* styles, unsigned count) : + m_transparent(0, 0, 0, 0), + m_styles(styles), + m_count(count) + {} + + bool is_solid(unsigned style) const { return true; } + + const agg::rgba8& color(unsigned style) const + { + if (style < m_count) + return m_styles[style]; + + return m_transparent; + } + + void generate_span(agg::rgba8* span, int x, int y, unsigned len, unsigned style) + { + } + +private: + agg::rgba8 m_transparent; + const agg::rgba8* m_styles; + unsigned m_count; +}; + + +class the_application : public agg::platform_support +{ + agg::slider_ctrl m_width; + agg::slider_ctrl m_alpha1; + agg::slider_ctrl m_alpha2; + agg::slider_ctrl m_alpha3; + agg::slider_ctrl m_alpha4; + agg::cbox_ctrl m_invert_order; + agg::path_storage m_path; + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_width(180 + 10.0, 5.0, 130 + 300.0, 12, !flip_y), + m_alpha1(5, 5, 180, 12, !flip_y), + m_alpha2(5, 25, 180, 32, !flip_y), + m_alpha3(5, 45, 180, 52, !flip_y), + m_alpha4(5, 65, 180, 72, !flip_y), + m_invert_order(190, 25, "Invert Z-Order") + { + add_ctrl(m_width); + m_width.range(-20.0, 50.0); + m_width.value(10.0); + m_width.label("Width=%1.2f"); + + add_ctrl(m_alpha1); + m_alpha1.range(0, 1); + m_alpha1.value(1); + m_alpha1.label("Alpha1=%1.3f"); + + add_ctrl(m_alpha2); + m_alpha2.range(0, 1); + m_alpha2.value(1); + m_alpha2.label("Alpha2=%1.3f"); + + add_ctrl(m_alpha3); + m_alpha3.range(0, 1); + m_alpha3.value(1); + m_alpha3.label("Alpha3=%1.3f"); + + add_ctrl(m_alpha4); + m_alpha4.range(0, 1); + m_alpha4.value(1); + m_alpha4.label("Alpha4=%1.3f"); + + add_ctrl(m_invert_order); + } + + void compose_path() + { + m_path.remove_all(); + m_path.move_to(28.47, 6.45); + m_path.curve3(21.58, 1.12, 19.82, 0.29); + m_path.curve3(17.19, -0.93, 14.21, -0.93); + m_path.curve3(9.57, -0.93, 6.57, 2.25); + m_path.curve3(3.56, 5.42, 3.56, 10.60); + m_path.curve3(3.56, 13.87, 5.03, 16.26); + m_path.curve3(7.03, 19.58, 11.99, 22.51); + m_path.curve3(16.94, 25.44, 28.47, 29.64); + m_path.line_to(28.47, 31.40); + m_path.curve3(28.47, 38.09, 26.34, 40.58); + m_path.curve3(24.22, 43.07, 20.17, 43.07); + m_path.curve3(17.09, 43.07, 15.28, 41.41); + m_path.curve3(13.43, 39.75, 13.43, 37.60); + m_path.line_to(13.53, 34.77); + m_path.curve3(13.53, 32.52, 12.38, 31.30); + m_path.curve3(11.23, 30.08, 9.38, 30.08); + m_path.curve3(7.57, 30.08, 6.42, 31.35); + m_path.curve3(5.27, 32.62, 5.27, 34.81); + m_path.curve3(5.27, 39.01, 9.57, 42.53); + m_path.curve3(13.87, 46.04, 21.63, 46.04); + m_path.curve3(27.59, 46.04, 31.40, 44.04); + m_path.curve3(34.28, 42.53, 35.64, 39.31); + m_path.curve3(36.52, 37.21, 36.52, 30.71); + m_path.line_to(36.52, 15.53); + m_path.curve3(36.52, 9.13, 36.77, 7.69); + m_path.curve3(37.01, 6.25, 37.57, 5.76); + m_path.curve3(38.13, 5.27, 38.87, 5.27); + m_path.curve3(39.65, 5.27, 40.23, 5.62); + m_path.curve3(41.26, 6.25, 44.19, 9.18); + m_path.line_to(44.19, 6.45); + m_path.curve3(38.72, -0.88, 33.74, -0.88); + m_path.curve3(31.35, -0.88, 29.93, 0.78); + m_path.curve3(28.52, 2.44, 28.47, 6.45); + m_path.close_polygon(); + + m_path.move_to(28.47, 9.62); + m_path.line_to(28.47, 26.66); + m_path.curve3(21.09, 23.73, 18.95, 22.51); + m_path.curve3(15.09, 20.36, 13.43, 18.02); + m_path.curve3(11.77, 15.67, 11.77, 12.89); + m_path.curve3(11.77, 9.38, 13.87, 7.06); + m_path.curve3(15.97, 4.74, 18.70, 4.74); + m_path.curve3(22.41, 4.74, 28.47, 9.62); + m_path.close_polygon(); + } + + + + virtual void on_draw() + { + typedef agg::renderer_base ren_base; + typedef agg::renderer_base ren_base_pre; + + agg::gamma_lut lut(2.0); + + agg::pixfmt_bgra32 pixf(rbuf_window()); + ren_base renb(pixf); + + agg::pixfmt_bgra32_pre pixf_pre(rbuf_window()); + ren_base_pre renb_pre(pixf_pre); + + // Clear the window with a gradient + agg::pod_vector gr(pixf_pre.width()); + unsigned i; + for(i = 0; i < pixf.width(); i++) + { + gr.add(agg::rgba8(255, 255, 0).gradient(agg::rgba8(0, 255, 255), + double(i) / pixf.width())); + } + for(i = 0; i < pixf.height(); i++) + { + renb.copy_color_hspan(0, i, pixf.width(), &gr[0]); + } + pixf.apply_gamma_dir(lut); + + + agg::rasterizer_scanline_aa<> ras; + agg::rasterizer_compound_aa rasc; + agg::scanline_u8 sl; + agg::span_allocator alloc; + + // Draw two triangles + ras.move_to_d(0, 0); + ras.line_to_d(width(), 0); + ras.line_to_d(width(), height()); + agg::render_scanlines_aa_solid(ras, sl, renb, + agg::rgba8(lut.dir(0), + lut.dir(100), + lut.dir(0))); + + ras.move_to_d(0, 0); + ras.line_to_d(0, height()); + ras.line_to_d(width(), 0); + agg::render_scanlines_aa_solid(ras, sl, renb, + agg::rgba8(lut.dir(0), + lut.dir(100), + lut.dir(100))); + + agg::trans_affine mtx; + mtx *= agg::trans_affine_scaling(4.0); + mtx *= agg::trans_affine_translation(150, 100); + + agg::conv_transform trans(m_path, mtx); + agg::conv_curve > curve(trans); + + agg::conv_stroke + > > stroke(curve); + + compose_path(); + + agg::rgba8 styles[4]; + + if(m_invert_order.status()) + { + rasc.layer_order(agg::layer_inverse); + } + else + { + rasc.layer_order(agg::layer_direct); + } + + styles[3] = agg::rgba8(lut.dir(255), + lut.dir(0), + lut.dir(108), + 200).premultiply(); + + styles[2] = agg::rgba8(lut.dir(51), + lut.dir(0), + lut.dir(151), + 180).premultiply(); + + styles[1] = agg::rgba8(lut.dir(143), + lut.dir(90), + lut.dir(6), + 200).premultiply(); + + styles[0] = agg::rgba8(lut.dir(0), + lut.dir(0), + lut.dir(255), + 220).premultiply(); + + style_handler sh(styles, 4); + + stroke.width(m_width.value()); + + rasc.reset(); + rasc.master_alpha(3, m_alpha1.value()); + rasc.master_alpha(2, m_alpha2.value()); + rasc.master_alpha(1, m_alpha3.value()); + rasc.master_alpha(0, m_alpha4.value()); + + agg::ellipse ell(220.0, 180.0, 120.0, 10.0, 128, false); + agg::conv_stroke str_ell(ell); + str_ell.width(m_width.value() / 2); + + rasc.styles(3, -1); + rasc.add_path(str_ell); + + rasc.styles(2, -1); + rasc.add_path(ell); + + rasc.styles(1, -1); + rasc.add_path(stroke); + + rasc.styles(0, -1); + rasc.add_path(curve); + + agg::render_scanlines_compound_layered(rasc, sl, renb_pre, alloc, sh); + agg::render_ctrl(ras, sl, renb, m_width); + agg::render_ctrl(ras, sl, renb, m_alpha1); + agg::render_ctrl(ras, sl, renb, m_alpha2); + agg::render_ctrl(ras, sl, renb, m_alpha3); + agg::render_ctrl(ras, sl, renb, m_alpha4); + agg::render_ctrl(ras, sl, renb, m_invert_order); + + pixf.apply_gamma_inv(lut); + } + +}; + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgra32, flip_y); + app.caption("AGG Example. Compound Rasterizer -- Geometry Flattening"); + + if(app.init(440, 330, 0)) + { + return app.run(); + } + return 1; +} diff --git a/jni/desmume/src/android/agg/examples/rasterizers.cpp b/jni/desmume/src/android/agg/examples/rasterizers.cpp new file mode 100755 index 0000000..12f6679 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/rasterizers.cpp @@ -0,0 +1,280 @@ +#include +#include +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_rasterizer_outline.h" +#include "agg_scanline_p.h" +#include "agg_scanline_bin.h" +#include "agg_renderer_scanline.h" +#include "agg_renderer_primitives.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "platform/agg_platform_support.h" + +#define AGG_BGR24 +#include "pixel_formats.h" + + +enum flip_y_e { flip_y = true }; + + + +class the_application : public agg::platform_support +{ + double m_x[3]; + double m_y[3]; + double m_dx; + double m_dy; + int m_idx; + agg::slider_ctrl m_gamma; + agg::slider_ctrl m_alpha; + agg::cbox_ctrl m_test; + agg::rasterizer_scanline_aa<> m_ras; + agg::scanline_p8 m_sl_p8; + agg::scanline_bin m_sl_bin; + + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_idx(-1), + m_gamma(130 + 10.0, 10.0 + 4.0, 130 + 150.0, 10.0 + 8.0 + 4.0, !flip_y), + m_alpha(130 + 150.0 + 10.0, 10.0 + 4.0, 500 - 10.0, 10.0 + 8.0 + 4.0, !flip_y), + m_test(130 + 10.0, 10.0 + 4.0 + 16.0, "Test Performance", !flip_y) + { + m_x[0] = 100 + 120; m_y[0] = 60; + m_x[1] = 369 + 120; m_y[1] = 170; + m_x[2] = 143 + 120; m_y[2] = 310; + + add_ctrl(m_gamma); + m_gamma.range(0.0, 1.0); + m_gamma.value(0.5); + m_gamma.label("Gamma=%1.2f"); + m_gamma.no_transform(); + + add_ctrl(m_alpha); + m_alpha.range(0.0, 1.0); + m_alpha.value(1.0); + m_alpha.label("Alpha=%1.2f"); + m_alpha.no_transform(); + + add_ctrl(m_test); + m_test.no_transform(); + } + + + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_aa; + typedef agg::renderer_scanline_bin_solid renderer_bin; + + + void draw_anti_aliased() + { + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + renderer_aa ren_aa(rb); + + agg::path_storage path; + + path.move_to(m_x[0], m_y[0]); + path.line_to(m_x[1], m_y[1]); + path.line_to(m_x[2], m_y[2]); + path.close_polygon(); + + ren_aa.color(agg::rgba(0.7, 0.5, 0.1, m_alpha.value())); + + m_ras.gamma(agg::gamma_power(m_gamma.value() * 2.0)); + m_ras.add_path(path); + agg::render_scanlines(m_ras, m_sl_p8, ren_aa); + } + + + void draw_aliased() + { + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + renderer_bin ren_bin(rb); + + agg::path_storage path; + + + path.move_to(m_x[0] - 200, m_y[0]); + path.line_to(m_x[1] - 200, m_y[1]); + path.line_to(m_x[2] - 200, m_y[2]); + path.close_polygon(); + + ren_bin.color(agg::rgba(0.1, 0.5, 0.7, m_alpha.value())); + + m_ras.gamma(agg::gamma_threshold(m_gamma.value())); + m_ras.add_path(path); + agg::render_scanlines(m_ras, m_sl_bin, ren_bin); + + //-- Drawing an outline with subpixel accuracy (aliased) + //typedef agg::renderer_primitives renderer_pr; + //renderer_pr ren_pr(rb); + //agg::rasterizer_outline ras_line(ren_pr); + //ren_pr.line_color(agg::rgba(0.0, 0.0, 0.0)); + //ras_line.add_path(path); + } + + virtual void on_draw() + { + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + renderer_aa ren_aa(rb); + + rb.clear(agg::rgba(1, 1, 1)); + + agg::rasterizer_scanline_aa<> ras_aa; + + draw_anti_aliased(); + draw_aliased(); + + agg::render_ctrl(ras_aa, m_sl_p8, rb, m_gamma); + agg::render_ctrl(ras_aa, m_sl_p8, rb, m_alpha); + agg::render_ctrl(ras_aa, m_sl_p8, rb, m_test); + } + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + unsigned i; + for (i = 0; i < 3; i++) + { + if(sqrt( (x-m_x[i]) * (x-m_x[i]) + (y-m_y[i]) * (y-m_y[i]) ) < 20.0 || + sqrt( (x-m_x[i]+200) * (x-m_x[i]+200) + (y-m_y[i]) * (y-m_y[i]) ) < 20) + { + m_dx = x - m_x[i]; + m_dy = y - m_y[i]; + m_idx = i; + break; + } + } + if(i == 3) + { + if(agg::point_in_triangle(m_x[0], m_y[0], + m_x[1], m_y[1], + m_x[2], m_y[2], + x, y) || + agg::point_in_triangle(m_x[0] - 200, m_y[0], + m_x[1] - 200, m_y[1], + m_x[2] - 200, m_y[2], + x, y)) + { + m_dx = x - m_x[0]; + m_dy = y - m_y[0]; + m_idx = 3; + } + + } + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_idx == 3) + { + double dx = x - m_dx; + double dy = y - m_dy; + m_x[1] -= m_x[0] - dx; + m_y[1] -= m_y[0] - dy; + m_x[2] -= m_x[0] - dx; + m_y[2] -= m_y[0] - dy; + m_x[0] = dx; + m_y[0] = dy; + force_redraw(); + return; + } + + if(m_idx >= 0) + { + m_x[m_idx] = x - m_dx; + m_y[m_idx] = y - m_dy; + force_redraw(); + } + } + else + { + on_mouse_button_up(x, y, flags); + } + } + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + m_idx = -1; + } + + + virtual void on_ctrl_change() + { + if(m_test.status()) + { + on_draw(); + update_window(); + m_test.status(false); + + start_timer(); + int i; + for(i = 0; i < 1000; i++) + { + draw_aliased(); + } + double t1 = elapsed_time(); + + start_timer(); + for(i = 0; i < 1000; i++) + { + draw_anti_aliased(); + } + double t2 = elapsed_time(); + + update_window(); + char buf[100]; + sprintf(buf, "Time Aliased=%.2fms Time Anti-Aliased=%.2fms", t1, t2); + message(buf); + } + } + + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + double dx = 0; + double dy = 0; + switch(key) + { + case agg::key_left: dx = -0.1; break; + case agg::key_right: dx = 0.1; break; + case agg::key_up: dy = 0.1; break; + case agg::key_down: dy = -0.1; break; + } + m_x[0] += dx; + m_y[0] += dy; + m_x[1] += dx; + m_y[1] += dy; + force_redraw(); + } + +}; + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Line Join"); + + if(app.init(500, 330, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/rasterizers2.cpp b/jni/desmume/src/android/agg/examples/rasterizers2.cpp new file mode 100755 index 0000000..31d7536 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/rasterizers2.cpp @@ -0,0 +1,549 @@ +#include +#include +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_rasterizer_outline.h" +#include "agg_conv_transform.h" +#include "agg_conv_stroke.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_renderer_primitives.h" +#include "agg_rasterizer_outline.h" +#include "agg_rasterizer_outline_aa.h" +#include "agg_pattern_filters_rgba.h" +#include "agg_renderer_outline_aa.h" +#include "agg_renderer_outline_image.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "platform/agg_platform_support.h" + +#define AGG_BGR24 +//#define AGG_RGB24 +//#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + + +enum flip_y_e { flip_y = true }; + +static const agg::int32u pixmap_chain[] = +{ + 16, 7, + 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xb4c29999, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xb4c29999, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, + 0x00ffffff, 0x00ffffff, 0x0cfbf9f9, 0xff9a5757, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xb4c29999, 0x00ffffff, 0x00ffffff, 0x00ffffff, + 0x00ffffff, 0x5ae0cccc, 0xffa46767, 0xff660000, 0xff975252, 0x7ed4b8b8, 0x5ae0cccc, 0x5ae0cccc, 0x5ae0cccc, 0x5ae0cccc, 0xa8c6a0a0, 0xff7f2929, 0xff670202, 0x9ecaa6a6, 0x5ae0cccc, 0x00ffffff, + 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xa4c7a2a2, 0x3affff00, 0x3affff00, 0xff975151, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, + 0x00ffffff, 0x5ae0cccc, 0xffa46767, 0xff660000, 0xff954f4f, 0x7ed4b8b8, 0x5ae0cccc, 0x5ae0cccc, 0x5ae0cccc, 0x5ae0cccc, 0xa8c6a0a0, 0xff7f2929, 0xff670202, 0x9ecaa6a6, 0x5ae0cccc, 0x00ffffff, + 0x00ffffff, 0x00ffffff, 0x0cfbf9f9, 0xff9a5757, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xb4c29999, 0x00ffffff, 0x00ffffff, 0x00ffffff, + 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xb4c29999, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xb4c29999, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff +}; + + + +namespace agg +{ + class pattern_pixmap_argb32 + { + public: + typedef rgba8 color_type; + + pattern_pixmap_argb32(const int32u* pixmap) : m_pixmap(pixmap) {} + + unsigned width() const { return m_pixmap[0]; } + unsigned height() const { return m_pixmap[1]; } + + rgba8 pixel(int x, int y) const + { + int32u p = m_pixmap[y * width() + x + 2]; + return rgba8((p >> 16) & 0xFF, (p >> 8) & 0xFF, p & 0xFF, p >> 24); + } + private: + const int32u* m_pixmap; + }; +} + + + +class spiral +{ +public: + spiral(double x, double y, double r1, double r2, double step, double start_angle=0) : + m_x(x), + m_y(y), + m_r1(r1), + m_r2(r2), + m_step(step), + m_start_angle(start_angle), + m_angle(start_angle), + m_da(agg::deg2rad(8.0)), + m_dr(m_step / 45.0) + { + } + + void rewind(unsigned) + { + m_angle = m_start_angle; + m_curr_r = m_r1; + m_start = true; + } + + unsigned vertex(double* x, double* y) + { + if(m_curr_r > m_r2) return agg::path_cmd_stop; + + *x = m_x + cos(m_angle) * m_curr_r; + *y = m_y + sin(m_angle) * m_curr_r; + m_curr_r += m_dr; + m_angle += m_da; + if(m_start) + { + m_start = false; + return agg::path_cmd_move_to; + } + return agg::path_cmd_line_to; + } + +private: + double m_x; + double m_y; + double m_r1; + double m_r2; + double m_step; + double m_start_angle; + + double m_angle; + double m_curr_r; + double m_da; + double m_dr; + bool m_start; +}; + + +struct roundoff +{ + void transform(double* x, double* y) const + { + *x = floor(*x); + *y = floor(*y); + } +}; + + +class the_application : public agg::platform_support +{ + agg::slider_ctrl m_step; + agg::slider_ctrl m_width; + agg::cbox_ctrl m_test; + agg::cbox_ctrl m_rotate; + agg::cbox_ctrl m_accurate_joins; + agg::cbox_ctrl m_scale_pattern; + double m_start_angle; + + +public: + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_aa; + typedef agg::renderer_primitives renderer_prim; + typedef agg::rasterizer_outline rasterizer_outline; + typedef agg::rasterizer_scanline_aa<> rasterizer_scanline; + typedef agg::scanline_p8 scanline; + typedef agg::renderer_outline_aa renderer_oaa; + typedef agg::pattern_filter_bilinear_rgba8 pattern_filter; + typedef agg::line_image_pattern_pow2 image_pattern; + typedef agg::renderer_outline_image renderer_img; + typedef agg::rasterizer_outline_aa rasterizer_outline_aa; + typedef agg::rasterizer_outline_aa rasterizer_outline_img; + + + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_step(10.0, 10.0 + 4.0, 150.0, 10.0 + 8.0 + 4.0, !flip_y), + m_width(150.0 + 10.0, 10.0 + 4.0, 400 - 10.0, 10.0 + 8.0 + 4.0, !flip_y), + m_test(10.0, 10.0 + 4.0 + 16.0, "Test Performance", !flip_y), + m_rotate(130 + 10.0, 10.0 + 4.0 + 16.0, "Rotate", !flip_y), + m_accurate_joins(200 + 10.0, 10.0 + 4.0 + 16.0, "Accurate Joins", !flip_y), + m_scale_pattern(310 + 10.0, 10.0 + 4.0 + 16.0, "Scale Pattern", !flip_y), + m_start_angle(0.0) + { + add_ctrl(m_step); + m_step.range(0.0, 2.0); + m_step.value(0.1); + m_step.label("Step=%1.2f"); + m_step.no_transform(); + + add_ctrl(m_width); + m_width.range(0.0, 7.0); + m_width.value(3.0); + m_width.label("Width=%1.2f"); + m_width.no_transform(); + + add_ctrl(m_test); + m_test.text_size(9.0, 7.0); + m_test.no_transform(); + + add_ctrl(m_rotate); + m_rotate.text_size(9.0, 7.0); + m_rotate.no_transform(); + + add_ctrl(m_accurate_joins); + m_accurate_joins.text_size(9.0, 7.0); + m_accurate_joins.no_transform(); + + add_ctrl(m_scale_pattern); + m_scale_pattern.text_size(9.0, 7.0); + m_scale_pattern.no_transform(); + m_scale_pattern.status(true); + } + + + + void draw_aliased_pix_accuracy(rasterizer_outline& ras, renderer_prim& prim) + { + spiral s1(width()/5, height()/4+50, 5, 70, 8, m_start_angle); + roundoff rn; + agg::conv_transform trans(s1, rn); + prim.line_color(agg::rgba(0.4, 0.3, 0.1)); + ras.add_path(trans); + } + + void draw_aliased_subpix_accuracy(rasterizer_outline& ras, renderer_prim& prim) + { + spiral s2(width()/2, height()/4+50, 5, 70, 8, m_start_angle); + prim.line_color(agg::rgba(0.4, 0.3, 0.1)); + ras.add_path(s2); + } + + void draw_anti_aliased_outline(rasterizer_outline_aa& ras, renderer_oaa& ren) + { + spiral s3(width()/5, height() - height()/4 + 20, 5, 70, 8, m_start_angle); + ren.color(agg::rgba(0.4, 0.3, 0.1)); + ras.add_path(s3); + } + + void draw_anti_aliased_scanline(rasterizer_scanline& ras, scanline& sl, renderer_aa& ren) + { + spiral s4(width()/2, height() - height()/4 + 20, 5, 70, 8, m_start_angle); + agg::conv_stroke stroke(s4); + stroke.width(m_width.value()); + stroke.line_cap(agg::round_cap); + ren.color(agg::rgba(0.4, 0.3, 0.1)); + ras.add_path(stroke); + agg::render_scanlines(ras, sl, ren); + } + + void draw_anti_aliased_outline_img(rasterizer_outline_img& ras, renderer_img& ren) + { + spiral s5(width() - width()/5, height() - height()/4 + 20, 5, 70, 8, m_start_angle); + ras.add_path(s5); + } + + + + void text(rasterizer_scanline& ras, + scanline& sl, + renderer_aa& ren, + double x, double y, const char* txt) + { + agg::gsv_text t; + t.size(8); + t.text(txt); + t.start_point(x, y); + agg::conv_stroke stroke(t); + stroke.width(0.7); + ras.add_path(stroke); + ren.color(agg::rgba(0,0,0)); + agg::render_scanlines(ras, sl, ren); + } + + + + + virtual void on_draw() + { + pixfmt pf(rbuf_window()); + renderer_base ren_base(pf); + renderer_aa ren_aa(ren_base); + renderer_prim ren_prim(ren_base); + rasterizer_scanline ras_aa; + scanline sl; + rasterizer_outline ras_al(ren_prim); + agg::line_profile_aa prof; + prof.width(m_width.value()); + renderer_oaa ren_oaa(ren_base, prof); + rasterizer_outline_aa ras_oaa(ren_oaa); + ras_oaa.line_join(m_accurate_joins.status() ? + agg::outline_miter_accurate_join : + agg::outline_round_join); + ras_oaa.round_cap(true); + + pattern_filter filter; + agg::pattern_pixmap_argb32 src(pixmap_chain); + agg::line_image_scale src_scaled(src, m_width.value()); + image_pattern pattern(filter); + if(m_scale_pattern.status()) + { + pattern.create(src_scaled); + } + else + { + pattern.create(src); + } + renderer_img ren_img(ren_base, pattern); + if(m_scale_pattern.status()) + { + ren_img.scale_x(m_width.value() / src.height()); + } + rasterizer_outline_img ras_img(ren_img); + + ren_base.clear(agg::rgba(1.0, 1.0, 0.95)); + + draw_aliased_pix_accuracy(ras_al, ren_prim); + draw_aliased_subpix_accuracy(ras_al, ren_prim); + draw_anti_aliased_outline(ras_oaa, ren_oaa); + draw_anti_aliased_scanline(ras_aa, sl, ren_aa); + draw_anti_aliased_outline_img(ras_img, ren_img); + + text(ras_aa, sl, ren_aa, 50, 80, "Bresenham lines,\n\nregular accuracy"); + text(ras_aa, sl, ren_aa, width()/2-50, 80, "Bresenham lines,\n\nsubpixel accuracy"); + text(ras_aa, sl, ren_aa, 50, height()/2+50, "Anti-aliased lines"); + text(ras_aa, sl, ren_aa, width()/2-50, height()/2+50, "Scanline rasterizer"); + text(ras_aa, sl, ren_aa, width() - width()/5 - 50, height()/2+50, "Arbitrary Image Pattern"); + + + agg::render_ctrl(ras_aa, sl, ren_base, m_step); + agg::render_ctrl(ras_aa, sl, ren_base, m_width); + agg::render_ctrl(ras_aa, sl, ren_base, m_test); + agg::render_ctrl(ras_aa, sl, ren_base, m_rotate); + agg::render_ctrl(ras_aa, sl, ren_base, m_accurate_joins); + agg::render_ctrl(ras_aa, sl, ren_base, m_scale_pattern); + + + +/* +// An example of using anti-aliased outline rasterizer. +// Uncomment it to see the result +// + +// Includes: +//#include "agg_pixfmt_rgb.h" // or another +//#include "agg_renderer_outline_aa.h" +//#include "agg_rasterizer_outline_aa.h" + +typedef agg::renderer_base base_ren_type; +typedef agg::renderer_outline_aa renderer_type; +typedef agg::rasterizer_outline_aa rasterizer_type; + +double width = 5.0; +//-- create with specifying width +//-- min_width=1.0, smoother_width=1.0 +//agg::line_profile_aa(width, agg::gamma_none()); + +//-- create uninitialized and set parameters +agg::line_profile_aa profile; +profile.gamma(agg::gamma_power(1.2)); //optional +profile.min_width(0.75); //optional +profile.smoother_width(3.0); //optional +profile.width(width); //mandatory! + +agg::pixfmt_bgr24 pixf(rbuf_window()); //or another +base_ren_type base_ren(pixf); +renderer_type ren(base_ren, profile); +ren.color(agg::rgba8(0,0,0)); //mandatory! +rasterizer_type ras(ren); +ras.round_cap(true); //optional +ras.accurate_join(true); //optional + +//-- move_to/line_to interface +ras.move_to_d(100, 100); +ras.line_to_d(150, 200); +ras.render(false); //false means "don't close + //the polygon", i.e. polyline + +//-- add_path interface +//-- doesn't require invoking render() +//ras.add_path(some_path); +*/ + + + + +/* +// An example of using image pattern outline rasterizer +// Uncomment it to see the result +// + +// Includes: +//#include "agg_pixfmt_rgb.h" // or another +//#include "agg_pattern_filters_rgba.h" // for all rgba-8-bit color formats +//#include "agg_renderer_outline_image.h" +//#include "agg_rasterizer_outline_aa.h" + + +agg::pattern_filter_bilinear_rgba8 fltr; // Filtering functor + +agg::pattern_pixmap_argb32 patt_src(pixmap_chain); // Source. Must have an interface: + // width() const + // height() const + // pixel(int x, int y) const + // Any agg::renderer_base<> or derived + // is good for the use as a source. + +// agg::line_image_pattern is the main container for the patterns. It creates +// a copy of the patterns extended according to the needs of the filter. +// agg::line_image_pattern can operate with arbitrary image width, but if the +// width of the pattern is power of 2, it's better to use the modified +// version agg::line_image_pattern_pow2 because it works about 15-25 percent +// faster than agg::line_image_pattern (because of using simple masking instead +// of expensive '%' operation). +typedef agg::line_image_pattern_pow2 pattern_type; + +typedef agg::renderer_base base_ren_type; +typedef agg::renderer_outline_image renderer_type; +typedef agg::rasterizer_outline_aa rasterizer_type; + +//-- Create with specifying the source +pattern_type patt(fltr, src); + +//-- Create uninitialized and set the source +//pattern_type patt(fltr); +//patt.create(src); + +agg::pixfmt_bgr24 pixf(rbuf_window()); //or another +base_ren_type base_ren(pixf); +renderer_type ren(base_ren, patt); +//ren.scale_x(1.3); // Optional +rasterizer_type ras(ren); + +//-- move_to/line_to interface +ras.move_to_d(100, 150); +ras.line_to_d(0, 0); +ras.line_to_d(300, 200); +//ras.line_to_d(10, 10); +ras.render(false); //false means "don't close + //the polygon", i.e. polyline + +//-- add_path interface +//-- doesn't require invoking render() +//ras.add_path(some_path); +*/ + + } + + + virtual void on_idle() + { + m_start_angle += agg::deg2rad(m_step.value()); + if(m_start_angle > agg::deg2rad(360.0)) m_start_angle -= agg::deg2rad(360.0); + force_redraw(); + } + + virtual void on_ctrl_change() + { + wait_mode(!m_rotate.status()); + + if(m_test.status()) + { + on_draw(); + update_window(); + + pixfmt pf(rbuf_window()); + renderer_base ren_base(pf); + renderer_aa ren_aa(ren_base); + renderer_prim ren_prim(ren_base); + rasterizer_scanline ras_aa; + scanline sl; + rasterizer_outline ras_al(ren_prim); + agg::line_profile_aa prof; + prof.width(m_width.value()); + renderer_oaa ren_oaa(ren_base, prof); + rasterizer_outline_aa ras_oaa(ren_oaa); + ras_oaa.line_join(m_accurate_joins.status() ? + agg::outline_miter_accurate_join : + agg::outline_round_join); + ras_oaa.round_cap(true); + + pattern_filter filter; + agg::pattern_pixmap_argb32 src(pixmap_chain); + agg::line_image_scale src_scaled(src, m_width.value()); + image_pattern pattern(filter); + if(m_scale_pattern.status()) + { + pattern.create(src_scaled); + } + else + { + pattern.create(src); + } + renderer_img ren_img(ren_base, pattern); + if(m_scale_pattern.status()) + { + ren_img.scale_x(src.height() / m_width.value()); + } + rasterizer_outline_img ras_img(ren_img); + + unsigned i; + + start_timer(); + for(i = 0; i < 200; i++) + { + draw_aliased_subpix_accuracy(ras_al, ren_prim); + m_start_angle += agg::deg2rad(m_step.value()); + } + double t2 = elapsed_time(); + + start_timer(); + for(i = 0; i < 200; i++) + { + draw_anti_aliased_outline(ras_oaa, ren_oaa); + m_start_angle += agg::deg2rad(m_step.value()); + } + double t3 = elapsed_time(); + + start_timer(); + for(i = 0; i < 200; i++) + { + draw_anti_aliased_scanline(ras_aa, sl, ren_aa); + m_start_angle += agg::deg2rad(m_step.value()); + } + double t4 = elapsed_time(); + + start_timer(); + for(i = 0; i < 200; i++) + { + draw_anti_aliased_outline_img(ras_img, ren_img); + m_start_angle += agg::deg2rad(m_step.value()); + } + double t5 = elapsed_time(); + + m_test.status(false); + force_redraw(); + char buf[256]; + sprintf(buf, "Aliased=%1.2fms, Anti-Aliased=%1.2fms, Scanline=%1.2fms, Image-Pattern=%1.2fms", + t2, t3, t4, t5); + message(buf); + } + } +}; + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Line Join"); + + if(app.init(500, 450, 0)) + { + return app.run(); + } + + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/rounded_rect.cpp b/jni/desmume/src/android/agg/examples/rounded_rect.cpp new file mode 100755 index 0000000..94927cf --- /dev/null +++ b/jni/desmume/src/android/agg/examples/rounded_rect.cpp @@ -0,0 +1,172 @@ +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_pixfmt_rgb.h" +#include "agg_gamma_lut.h" +#include "agg_ellipse.h" +#include "agg_rounded_rect.h" +#include "agg_conv_stroke.h" +#include "platform/agg_platform_support.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" + + +enum flip_y_e { flip_y = true }; + + +class the_application : public agg::platform_support +{ + double m_x[2]; + double m_y[2]; + double m_dx; + double m_dy; + int m_idx; + agg::slider_ctrl m_radius; + agg::slider_ctrl m_gamma; + agg::slider_ctrl m_offset; + agg::cbox_ctrl m_white_on_black; + + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_idx(-1), + m_radius(10, 10, 600-10, 19, !flip_y), + m_gamma(10, 10+20, 600-10, 19+20, !flip_y), + m_offset(10, 10+40, 600-10, 19+40, !flip_y), + m_white_on_black(10, 10+60, "White on black") + { + m_x[0] = 100; m_y[0] = 100; + m_x[1] = 500; m_y[1] = 350; + add_ctrl(m_radius); + add_ctrl(m_gamma); + add_ctrl(m_offset); + add_ctrl(m_white_on_black); + m_gamma.label("gamma=%4.3f"); + m_gamma.range(0.0, 3.0); + m_gamma.value(1.8); + + m_radius.label("radius=%4.3f"); + m_radius.range(0.0, 50.0); + m_radius.value(25.0); + + m_offset.label("subpixel offset=%4.3f"); + m_offset.range(-2.0, 3.0); + + m_white_on_black.text_color(agg::rgba8(127, 127, 127)); + m_white_on_black.inactive_color(agg::rgba8(127, 127, 127)); + } + + + virtual void on_draw() + { + typedef agg::gamma_lut gamma_lut_type; + typedef agg::pixfmt_bgr24_gamma pixfmt; + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_solid; + + gamma_lut_type gamma(m_gamma.value()); + pixfmt pixf(rbuf_window(), gamma); + renderer_base rb(pixf); + renderer_solid ren(rb); + + rb.clear(m_white_on_black.status() ? agg::rgba(0,0,0) : agg::rgba(1,1,1)); + + agg::rasterizer_scanline_aa<> ras; + agg::scanline_p8 sl; + + agg::ellipse e; + + // Render two "control" circles + ren.color(agg::rgba8(127,127,127)); + e.init(m_x[0], m_y[0], 3, 3, 16); + ras.add_path(e); + agg::render_scanlines(ras, sl, ren); + e.init(m_x[1], m_y[1], 3, 3, 16); + ras.add_path(e); + agg::render_scanlines(ras, sl, ren); + + double d = m_offset.value(); + + // Creating a rounded rectangle + agg::rounded_rect r(m_x[0]+d, m_y[0]+d, m_x[1]+d, m_y[1]+d, m_radius.value()); + r.normalize_radius(); + + // Drawing as an outline + agg::conv_stroke p(r); + p.width(1.0); + ras.add_path(p); + ren.color(m_white_on_black.status() ? agg::rgba(1,1,1) : agg::rgba(0,0,0)); + agg::render_scanlines(ras, sl, ren); + + ras.gamma(agg::gamma_none()); + + // Render the controls + agg::render_ctrl(ras, sl, rb, m_radius); + agg::render_ctrl(ras, sl, rb, m_gamma); + agg::render_ctrl(ras, sl, rb, m_offset); + agg::render_ctrl(ras, sl, rb, m_white_on_black); + } + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + unsigned i; + for (i = 0; i < 2; i++) + { + if(sqrt( (x-m_x[i]) * (x-m_x[i]) + (y-m_y[i]) * (y-m_y[i]) ) < 5.0) + { + m_dx = x - m_x[i]; + m_dy = y - m_y[i]; + m_idx = i; + break; + } + } + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_idx >= 0) + { + m_x[m_idx] = x - m_dx; + m_y[m_idx] = y - m_dy; + force_redraw(); + } + } + else + { + on_mouse_button_up(x, y, flags); + } + } + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + m_idx = -1; + } + + +}; + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("AGG Example. Rounded rectangle with gamma-correction & stuff"); + + if(app.init(600, 400, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/scanline_boolean.cpp b/jni/desmume/src/android/agg/examples/scanline_boolean.cpp new file mode 100755 index 0000000..e893645 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/scanline_boolean.cpp @@ -0,0 +1,279 @@ +#include +#include +#include +#include "agg_basics.h" +#include "agg_array.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_p.h" +#include "agg_scanline_u.h" +#include "agg_scanline_bin.h" +#include "agg_scanline_boolean_algebra.h" +#include "agg_scanline_storage_aa.h" +#include "agg_scanline_storage_bin.h" +#include "agg_renderer_scanline.h" +#include "agg_path_storage.h" +#include "agg_conv_transform.h" +#include "agg_ellipse.h" +#include "ctrl/agg_rbox_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "ctrl/agg_slider_ctrl.h" +#include "platform/agg_platform_support.h" +#include "interactive_polygon.h" + +#define AGG_BGR24 +//#define AGG_RGB24 +//#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + +enum flip_y_e { flip_y = true }; + + + + + + + + + +void generate_circles(agg::path_storage& ps, + const double* quad, + unsigned num_circles, + double radius) +{ + ps.remove_all(); + unsigned i; + for(i = 0; i < 4; ++i) + { + unsigned n1 = i * 2; + unsigned n2 = (i < 3) ? i * 2 + 2 : 0; + unsigned j; + for(j = 0; j < num_circles; j++) + { + agg::ellipse ell(quad[n1] + (quad[n2] - quad[n1]) * j / num_circles, + quad[n1 + 1] + (quad[n2 + 1] - quad[n1 + 1]) * j / num_circles, + radius, radius, 100); + ps.concat_path(ell); + } + } +} + + + + + +class the_application : public agg::platform_support +{ +public: + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_solid; + typedef agg::scanline_p8 scanline_type; + + agg::interactive_polygon m_quad1; + agg::interactive_polygon m_quad2; + agg::rbox_ctrl m_trans_type; + agg::cbox_ctrl m_reset; + agg::slider_ctrl m_mul1; + agg::slider_ctrl m_mul2; + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_quad1(4, 5.0), + m_quad2(4, 5.0), + m_trans_type(420, 5.0, 420+130.0, 145.0, !flip_y), + m_reset (350, 5.0, "Reset", !flip_y), + m_mul1 (5.0, 5.0, 340.0, 12.0, !flip_y), + m_mul2 (5.0, 20.0, 340.0, 27.0, !flip_y) + { + m_trans_type.add_item("Union"); + m_trans_type.add_item("Intersection"); + m_trans_type.add_item("Linear XOR"); + m_trans_type.add_item("Saddle XOR"); + m_trans_type.add_item("Abs Diff XOR"); + m_trans_type.add_item("A-B"); + m_trans_type.add_item("B-A"); + m_trans_type.cur_item(0); + add_ctrl(m_trans_type); + add_ctrl(m_reset); + add_ctrl(m_mul1); + add_ctrl(m_mul2); + m_mul1.value(1.0); + m_mul2.value(1.0); + m_mul1.label("Opacity1=%.3f"); + m_mul2.label("Opacity2=%.3f"); + } + + + virtual void on_init() + { + m_quad1.xn(0) = 50; + m_quad1.yn(0) = 200 - 20; + m_quad1.xn(1) = width() / 2 - 25; + m_quad1.yn(1) = 200; + m_quad1.xn(2) = width() / 2 - 25; + m_quad1.yn(2) = height() - 50 - 20; + m_quad1.xn(3) = 50; + m_quad1.yn(3) = height() - 50; + + m_quad2.xn(0) = width() / 2 + 25; + m_quad2.yn(0) = 200 - 20; + m_quad2.xn(1) = width() - 50; + m_quad2.yn(1) = 200; + m_quad2.xn(2) = width() - 50; + m_quad2.yn(2) = height() - 50 - 20; + m_quad2.xn(3) = width() / 2 + 25; + m_quad2.yn(3) = height() - 50; + } + + + + + virtual void on_draw() + { + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + renderer_solid r(rb); + rb.clear(agg::rgba(1, 1, 1)); + + scanline_type sl; + agg::rasterizer_scanline_aa<> ras; + agg::rasterizer_scanline_aa<> ras1; + agg::rasterizer_scanline_aa<> ras2; + + agg::sbool_op_e op = (agg::sbool_op_e)m_trans_type.cur_item(); + + ras1.gamma(agg::gamma_multiply(m_mul1.value())); + ras2.gamma(agg::gamma_multiply(m_mul2.value())); + + ras.clip_box(0, 0, width(), height()); + + agg::path_storage ps1; + generate_circles(ps1, m_quad1.polygon(), 5, 20); + + agg::path_storage ps2; + generate_circles(ps2, m_quad2.polygon(), 5, 20); + + ras1.filling_rule(agg::fill_even_odd); + + + r.color(agg::rgba8(240, 255, 200, 100)); + ras1.add_path(ps1); + agg::render_scanlines(ras1, sl, r); + + r.color(agg::rgba8(255, 240, 240, 100)); + ras2.add_path(ps2); + agg::render_scanlines(ras2, sl, r); + + + + typedef agg::scanline_p8 sbool_scanline_type; + typedef agg::renderer_scanline_aa_solid sbool_renderer_type; + + sbool_scanline_type sl_result; + sbool_scanline_type sl1; + sbool_scanline_type sl2; + sbool_renderer_type sren(rb); + + sren.color(agg::rgba8(0, 0, 0)); + + agg::sbool_combine_shapes_aa(op, ras1, ras2, sl1, sl2, sl_result, sren); + + //-------------------------- + // Render the "quad" tools and controls + r.color(agg::rgba(0, 0.3, 0.5, 0.6)); + ras.add_path(m_quad1); + agg::render_scanlines(ras, sl, r); + ras.add_path(m_quad2); + agg::render_scanlines(ras, sl, r); + agg::render_ctrl(ras, sl, rb, m_trans_type); + agg::render_ctrl(ras, sl, rb, m_reset); + agg::render_ctrl(ras, sl, rb, m_mul1); + agg::render_ctrl(ras, sl, rb, m_mul2); + //-------------------------- + + } + + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_quad1.on_mouse_button_down(x, y) || + m_quad2.on_mouse_button_down(x, y) ) + { + force_redraw(); + } + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_quad1.on_mouse_move(x, y) || + m_quad2.on_mouse_move(x, y) ) + { + force_redraw(); + } + } + if((flags & agg::mouse_left) == 0) + { + on_mouse_button_up(x, y, flags); + } + } + + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + if(m_quad1.on_mouse_button_up(x, y) || + m_quad2.on_mouse_button_up(x, y) ) + { + force_redraw(); + } + } + + + virtual void on_ctrl_change() + { + if(m_reset.status()) + { + on_init(); + m_reset.status(false); + force_redraw(); + } + } +}; + + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Scanline Boolean"); + + if(app.init(800, 600, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + + + + + + + + + diff --git a/jni/desmume/src/android/agg/examples/scanline_boolean2.cpp b/jni/desmume/src/android/agg/examples/scanline_boolean2.cpp new file mode 100755 index 0000000..83ce676 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/scanline_boolean2.cpp @@ -0,0 +1,675 @@ +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_scanline_p.h" +#include "agg_scanline_bin.h" +#include "agg_renderer_scanline.h" +#include "agg_renderer_primitives.h" +#include "agg_span_solid.h" +#include "agg_conv_curve.h" +#include "agg_conv_stroke.h" +#include "agg_gsv_text.h" +#include "agg_pixfmt_rgb.h" +#include "agg_scanline_boolean_algebra.h" +#include "agg_scanline_storage_aa.h" +#include "agg_scanline_storage_bin.h" +#include "platform/agg_platform_support.h" + +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" + + +enum flip_y_e { flip_y = true }; + + + + +class spiral +{ +public: + spiral(double x, double y, double r1, double r2, double step, double start_angle=0) : + m_x(x), + m_y(y), + m_r1(r1), + m_r2(r2), + m_step(step), + m_start_angle(start_angle), + m_angle(start_angle), + m_da(agg::deg2rad(4.0)), + m_dr(m_step / 90.0) + { + } + + void rewind(unsigned) + { + m_angle = m_start_angle; + m_curr_r = m_r1; + m_start = true; + } + + unsigned vertex(double* x, double* y) + { + if(m_curr_r > m_r2) return agg::path_cmd_stop; + + *x = m_x + cos(m_angle) * m_curr_r; + *y = m_y + sin(m_angle) * m_curr_r; + m_curr_r += m_dr; + m_angle += m_da; + if(m_start) + { + m_start = false; + return agg::path_cmd_move_to; + } + return agg::path_cmd_line_to; + } + +private: + double m_x; + double m_y; + double m_r1; + double m_r2; + double m_step; + double m_start_angle; + + double m_angle; + double m_curr_r; + double m_da; + double m_dr; + bool m_start; +}; + + + +template +unsigned count_spans(Rasterizer& ras, Scanline& sl) +{ + unsigned n = 0; + if(ras.rewind_scanlines()) + { + sl.reset(ras.min_x(), ras.max_x()); + while(ras.sweep_scanline(sl)) + { + n += sl.num_spans(); + } + } + return n; +} + + + +void make_gb_poly(agg::path_storage& ps); +void make_arrows(agg::path_storage& ps); + + +class the_application : public agg::platform_support +{ + typedef agg::pixfmt_bgr24 pixfmt_type; + + agg::rbox_ctrl m_polygons; + agg::rbox_ctrl m_fill_rule; + agg::rbox_ctrl m_scanline_type; + agg::rbox_ctrl m_operation; + double m_x; + double m_y; + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_polygons (5.0, 5.0, 5.0+205.0, 110.0, !flip_y), + m_fill_rule (200, 5.0, 200+105.0, 50.0, !flip_y), + m_scanline_type(300, 5.0, 300+115.0, 70.0, !flip_y), + m_operation (535.0, 5.0, 535.0+115.0, 145.0, !flip_y) + { + m_operation.add_item("None"); + m_operation.add_item("OR"); + m_operation.add_item("AND"); + m_operation.add_item("XOR Linear"); + m_operation.add_item("XOR Saddle"); + m_operation.add_item("A-B"); + m_operation.add_item("B-A"); + m_operation.cur_item(2); + add_ctrl(m_operation); + m_operation.no_transform(); + + m_fill_rule.add_item("Even-Odd"); + m_fill_rule.add_item("Non Zero"); + m_fill_rule.cur_item(1); + add_ctrl(m_fill_rule); + m_fill_rule.no_transform(); + + m_scanline_type.add_item("scanline_p"); + m_scanline_type.add_item("scanline_u"); + m_scanline_type.add_item("scanline_bin"); + m_scanline_type.cur_item(1); + add_ctrl(m_scanline_type); + m_scanline_type.no_transform(); + + m_polygons.add_item("Two Simple Paths"); + m_polygons.add_item("Closed Stroke"); + m_polygons.add_item("Great Britain and Arrows"); + m_polygons.add_item("Great Britain and Spiral"); + m_polygons.add_item("Spiral and Glyph"); + m_polygons.cur_item(3); + add_ctrl(m_polygons); + m_polygons.no_transform(); + } + + + + + template + void render_scanline_boolean(Rasterizer& ras1, Rasterizer& ras2) + { + if(m_operation.cur_item() > 0) + { + agg::sbool_op_e op; + switch(m_operation.cur_item()) + { + case 1: op = agg::sbool_or; break; + case 2: op = agg::sbool_and; break; + case 3: op = agg::sbool_xor; break; + case 4: op = agg::sbool_xor_saddle;break; + case 5: op = agg::sbool_a_minus_b; break; + case 6: op = agg::sbool_b_minus_a; break; + } + + typedef agg::renderer_base renderer_base; + pixfmt_type pixf(rbuf_window()); + renderer_base rb(pixf); + + double t1 = 0.0; + double t2 = 0.0; + unsigned num_spans = 0; + + switch(m_scanline_type.cur_item()) + { + case 0: + { + typedef agg::renderer_scanline_aa_solid renderer_solid; + typedef agg::scanline_p8 scanline_type; + + renderer_solid ren(rb); + + scanline_type sl; + scanline_type sl1; + scanline_type sl2; + + // The intermediate storage is used only to test the perfoprmance, + // the short variant can be as follows: + // ------------------------ + // ren.color(agg::rgba(0.5, 0.0, 0, 0.5)); + // agg::sbool_combine_shapes_aa(op, ras1, ras2, sl1, sl2, sl, ren); + + agg::scanline_storage_aa8 storage; + agg::scanline_storage_aa8 storage1; + agg::scanline_storage_aa8 storage2; + + agg::render_scanlines(ras1, sl, storage1); + agg::render_scanlines(ras2, sl, storage2); + + start_timer(); + for(int i = 0; i < 10; i++) + { + agg::sbool_combine_shapes_aa(op, storage1, storage2, sl1, sl2, sl, storage); + } + t1 = elapsed_time() / 10.0; + + start_timer(); + ren.color(agg::rgba(0.5, 0.0, 0, 0.5)); + agg::render_scanlines(storage, sl, ren); + t2 = elapsed_time(); + + num_spans = count_spans(storage, sl); + } + break; + + case 1: + { + typedef agg::renderer_scanline_aa_solid renderer_solid; + typedef agg::scanline_u8 scanline_type; + + renderer_solid ren(rb); + + scanline_type sl; + scanline_type sl1; + scanline_type sl2; + agg::scanline_storage_aa8 storage; + agg::scanline_storage_aa8 storage1; + agg::scanline_storage_aa8 storage2; + + agg::render_scanlines(ras1, sl, storage1); + agg::render_scanlines(ras2, sl, storage2); + + start_timer(); + for(int i = 0; i < 10; i++) + { + agg::sbool_combine_shapes_aa(op, storage1, storage2, sl1, sl2, sl, storage); + } + t1 = elapsed_time() / 10.0; + + start_timer(); + ren.color(agg::rgba(0.5, 0.0, 0, 0.5)); + agg::render_scanlines(storage, sl, ren); + t2 = elapsed_time(); + + num_spans = count_spans(storage, sl); + } + break; + + + case 2: + { + typedef agg::renderer_scanline_bin_solid renderer_solid; + typedef agg::scanline_bin scanline_type; + + renderer_solid ren(rb); + + scanline_type sl; + scanline_type sl1; + scanline_type sl2; + + agg::scanline_storage_bin storage; + agg::scanline_storage_bin storage1; + agg::scanline_storage_bin storage2; + + agg::render_scanlines(ras1, sl, storage1); + agg::render_scanlines(ras2, sl, storage2); + + start_timer(); + for(int i = 0; i < 10; i++) + { + agg::sbool_combine_shapes_bin(op, storage1, storage2, sl1, sl2, sl, storage); + } + t1 = elapsed_time() / 10.0; + + start_timer(); + ren.color(agg::rgba(0.5, 0.0, 0, 0.5)); + agg::render_scanlines(storage, sl, ren); + t2 = elapsed_time(); + + num_spans = count_spans(storage, sl); + } + break; + + } + + + char buf[100]; + sprintf(buf, "Combine=%.3fms\n\nRender=%.3fms\n\nnum_spans=%d", t1, t2, num_spans); + agg::renderer_scanline_aa_solid ren(rb); + agg::scanline_p8 sl; + agg::gsv_text txt; + agg::conv_stroke txt_stroke(txt); + txt_stroke.width(1.0); + txt_stroke.line_cap(agg::round_cap); + txt.size(8.0); + txt.start_point(420, 40); + txt.text(buf); + ras1.add_path(txt_stroke); + ren.color(agg::rgba(0.0, 0.0, 0.0)); + agg::render_scanlines(ras1, sl, ren); + + + } + } + + + + + template + unsigned render_sbool(Rasterizer& ras1, Rasterizer& ras2) + { + pixfmt_type pf(rbuf_window()); + agg::renderer_base rb(pf); + agg::renderer_scanline_aa_solid > ren(rb); + agg::scanline_p8 sl; + + ras1.filling_rule(m_fill_rule.cur_item() ? agg::fill_non_zero : agg::fill_even_odd); + ras2.filling_rule(m_fill_rule.cur_item() ? agg::fill_non_zero : agg::fill_even_odd); + + switch(m_polygons.cur_item()) + { + case 0: + { + //------------------------------------ + // Two simple paths + // + agg::path_storage ps1; + agg::path_storage ps2; + + double x = m_x - initial_width()/2 + 100; + double y = m_y - initial_height()/2 + 100; + ps1.move_to(x+140, y+145); + ps1.line_to(x+225, y+44); + ps1.line_to(x+296, y+219); + ps1.close_polygon(); + + ps1.line_to(x+226, y+289); + ps1.line_to(x+82, y+292); + + ps1.move_to(x+220, y+222); + ps1.line_to(x+363, y+249); + ps1.line_to(x+265, y+331); + + ps1.move_to(x+242, y+243); + ps1.line_to(x+325, y+261); + ps1.line_to(x+268, y+309); + + ps1.move_to(x+259, y+259); + ps1.line_to(x+273, y+288); + ps1.line_to(x+298, y+266); + + ps2.move_to(100+32, 100+77); + ps2.line_to(100+473, 100+263); + ps2.line_to(100+351, 100+290); + ps2.line_to(100+354, 100+374); + + ras1.reset(); + ras1.add_path(ps1); + ren.color(agg::rgba(0, 0, 0, 0.1)); + agg::render_scanlines(ras1, sl, ren); + + ras2.reset(); + ras2.add_path(ps2); + ren.color(agg::rgba(0, 0.6, 0, 0.1)); + agg::render_scanlines(ras2, sl, ren); + + render_scanline_boolean(ras1, ras2); + } + break; + + case 1: + { + //------------------------------------ + // Closed stroke + // + agg::path_storage ps1; + agg::path_storage ps2; + agg::conv_stroke stroke(ps2); + stroke.width(15.0); + + double x = m_x - initial_width()/2 + 100; + double y = m_y - initial_height()/2 + 100; + ps1.move_to(x+140, y+145); + ps1.line_to(x+225, y+44); + ps1.line_to(x+296, y+219); + ps1.close_polygon(); + + ps1.line_to(x+226, y+289); + ps1.line_to(x+82, y+292); + + ps1.move_to(x+220-50, y+222); + ps1.line_to(x+363-50, y+249); + ps1.line_to(x+265-50, y+331); + ps1.close_polygon(); + + ps2.move_to(100+32, 100+77); + ps2.line_to(100+473, 100+263); + ps2.line_to(100+351, 100+290); + ps2.line_to(100+354, 100+374); + ps2.close_polygon(); + + ras1.reset(); + ras1.add_path(ps1); + ren.color(agg::rgba(0, 0, 0, 0.1)); + agg::render_scanlines(ras1, sl, ren); + + ras2.reset(); + ras2.add_path(stroke); + ren.color(agg::rgba(0, 0.6, 0, 0.1)); + agg::render_scanlines(ras2, sl, ren); + + render_scanline_boolean(ras1, ras2); + } + break; + + + case 2: + { + //------------------------------------ + // Great Britain and Arrows + // + agg::path_storage gb_poly; + agg::path_storage arrows; + make_gb_poly(gb_poly); + make_arrows(arrows); + + agg::trans_affine mtx1; + agg::trans_affine mtx2; + mtx1 *= agg::trans_affine_translation(-1150, -1150); + mtx1 *= agg::trans_affine_scaling(2.0); + + mtx2 = mtx1; + mtx2 *= agg::trans_affine_translation(m_x - initial_width()/2, + m_y - initial_height()/2); + + agg::conv_transform trans_gb_poly(gb_poly, mtx1); + agg::conv_transform trans_arrows(arrows, mtx2); + + ras2.add_path(trans_gb_poly); + ren.color(agg::rgba(0.5, 0.5, 0, 0.1)); + agg::render_scanlines(ras2, sl, ren); + + agg::conv_stroke > stroke_gb_poly(trans_gb_poly); + stroke_gb_poly.width(0.1); + ras1.add_path(stroke_gb_poly); + ren.color(agg::rgba(0, 0, 0)); + agg::render_scanlines(ras1, sl, ren); + + ras2.add_path(trans_arrows); + ren.color(agg::rgba(0.0, 0.5, 0.5, 0.1)); + agg::render_scanlines(ras2, sl, ren); + + ras1.reset(); + ras1.add_path(trans_gb_poly); + + render_scanline_boolean(ras1, ras2); + } + break; + + + case 3: + { + //------------------------------------ + // Great Britain and a Spiral + // + spiral sp(m_x, m_y, 10, 150, 30, 0.0); + agg::conv_stroke stroke(sp); + stroke.width(15.0); + + agg::path_storage gb_poly; + make_gb_poly(gb_poly); + + agg::trans_affine mtx; + mtx *= agg::trans_affine_translation(-1150, -1150); + mtx *= agg::trans_affine_scaling(2.0); + mtx *= trans_affine_resizing(); + + agg::conv_transform trans_gb_poly(gb_poly, mtx); + + + ras1.add_path(trans_gb_poly); + ren.color(agg::rgba(0.5, 0.5, 0, 0.1)); + agg::render_scanlines(ras1, sl, ren); + + agg::conv_stroke > stroke_gb_poly(trans_gb_poly); + stroke_gb_poly.width(0.1); + ras1.reset(); + ras1.add_path(stroke_gb_poly); + ren.color(agg::rgba(0, 0, 0)); + agg::render_scanlines(ras1, sl, ren); + + ras2.reset(); + ras2.add_path(stroke); + ren.color(agg::rgba(0.0, 0.5, 0.5, 0.1)); + agg::render_scanlines(ras2, sl, ren); + + ras1.reset(); + ras1.add_path(trans_gb_poly); + render_scanline_boolean(ras1, ras2); + } + break; + + + case 4: + { + //------------------------------------ + // Spiral and glyph + // + spiral sp(m_x, m_y, 10, 150, 30, 0.0); + agg::conv_stroke stroke(sp); + stroke.width(15.0); + + agg::path_storage glyph; + glyph.move_to(28.47, 6.45); + glyph.curve3(21.58, 1.12, 19.82, 0.29); + glyph.curve3(17.19, -0.93, 14.21, -0.93); + glyph.curve3(9.57, -0.93, 6.57, 2.25); + glyph.curve3(3.56, 5.42, 3.56, 10.60); + glyph.curve3(3.56, 13.87, 5.03, 16.26); + glyph.curve3(7.03, 19.58, 11.99, 22.51); + glyph.curve3(16.94, 25.44, 28.47, 29.64); + glyph.line_to(28.47, 31.40); + glyph.curve3(28.47, 38.09, 26.34, 40.58); + glyph.curve3(24.22, 43.07, 20.17, 43.07); + glyph.curve3(17.09, 43.07, 15.28, 41.41); + glyph.curve3(13.43, 39.75, 13.43, 37.60); + glyph.line_to(13.53, 34.77); + glyph.curve3(13.53, 32.52, 12.38, 31.30); + glyph.curve3(11.23, 30.08, 9.38, 30.08); + glyph.curve3(7.57, 30.08, 6.42, 31.35); + glyph.curve3(5.27, 32.62, 5.27, 34.81); + glyph.curve3(5.27, 39.01, 9.57, 42.53); + glyph.curve3(13.87, 46.04, 21.63, 46.04); + glyph.curve3(27.59, 46.04, 31.40, 44.04); + glyph.curve3(34.28, 42.53, 35.64, 39.31); + glyph.curve3(36.52, 37.21, 36.52, 30.71); + glyph.line_to(36.52, 15.53); + glyph.curve3(36.52, 9.13, 36.77, 7.69); + glyph.curve3(37.01, 6.25, 37.57, 5.76); + glyph.curve3(38.13, 5.27, 38.87, 5.27); + glyph.curve3(39.65, 5.27, 40.23, 5.62); + glyph.curve3(41.26, 6.25, 44.19, 9.18); + glyph.line_to(44.19, 6.45); + glyph.curve3(38.72, -0.88, 33.74, -0.88); + glyph.curve3(31.35, -0.88, 29.93, 0.78); + glyph.curve3(28.52, 2.44, 28.47, 6.45); + glyph.close_polygon(); + + glyph.move_to(28.47, 9.62); + glyph.line_to(28.47, 26.66); + glyph.curve3(21.09, 23.73, 18.95, 22.51); + glyph.curve3(15.09, 20.36, 13.43, 18.02); + glyph.curve3(11.77, 15.67, 11.77, 12.89); + glyph.curve3(11.77, 9.38, 13.87, 7.06); + glyph.curve3(15.97, 4.74, 18.70, 4.74); + glyph.curve3(22.41, 4.74, 28.47, 9.62); + glyph.close_polygon(); + + agg::trans_affine mtx; + mtx *= agg::trans_affine_scaling(4.0); + mtx *= agg::trans_affine_translation(220, 200); + agg::conv_transform trans(glyph, mtx); + agg::conv_curve > curve(trans); + + ras1.reset(); + ras1.add_path(stroke); + ren.color(agg::rgba(0, 0, 0, 0.1)); + agg::render_scanlines(ras1, sl, ren); + + ras2.reset(); + ras2.add_path(curve); + ren.color(agg::rgba(0, 0.6, 0, 0.1)); + agg::render_scanlines(ras2, sl, ren); + + render_scanline_boolean(ras1, ras2); + } + break; + } + + return 0; + } + + + virtual void on_init() + { + m_x = width() / 2.0; + m_y = height() / 2.0; + } + + virtual void on_draw() + { + typedef agg::renderer_base base_ren_type; + typedef agg::renderer_scanline_aa_solid renderer_solid; + + agg::pixfmt_bgr24 pf(rbuf_window()); + base_ren_type ren_base(pf); + renderer_solid ren_solid(ren_base); + ren_base.clear(agg::rgba(1,1,1)); + + agg::scanline_u8 sl; + agg::rasterizer_scanline_aa<> ras; + agg::rasterizer_scanline_aa<> ras2; + + agg::render_ctrl(ras, sl, ren_base, m_polygons); + agg::render_ctrl(ras, sl, ren_base, m_fill_rule); + agg::render_ctrl(ras, sl, ren_base, m_scanline_type); + agg::render_ctrl(ras, sl, ren_base, m_operation); + + render_sbool(ras, ras2); + + } + + + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + m_x = x; + m_y = y; + force_redraw(); + } + + if(flags & agg::mouse_right) + { + char buf[100]; + sprintf(buf, "%d %d", x, y); + message(buf); + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + m_x = x; + m_y = y; + force_redraw(); + } + } + + + +}; + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("AGG Example. Scanline Boolean"); + + if(app.init(655, 520, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/simple_blur.cpp b/jni/desmume/src/android/agg/examples/simple_blur.cpp new file mode 100755 index 0000000..255db05 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/simple_blur.cpp @@ -0,0 +1,282 @@ +#include +#include +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_rasterizer_outline.h" +#include "agg_path_storage.h" +#include "agg_conv_stroke.h" +#include "agg_conv_transform.h" +#include "agg_bounding_rect.h" +#include "agg_scanline_u.h" +#include "agg_scanline_p.h" +#include "agg_pixfmt_rgb.h" +#include "agg_renderer_base.h" +#include "agg_renderer_outline_aa.h" +#include "agg_rasterizer_outline_aa.h" +#include "agg_renderer_scanline.h" +#include "agg_span_allocator.h" +#include "agg_ellipse.h" +#include "platform/agg_platform_support.h" + +enum flip_y_e { flip_y = true }; + +agg::path_storage g_path; +agg::rgba8 g_colors[100]; +unsigned g_path_idx[100]; +unsigned g_npaths = 0; +double g_x1 = 0; +double g_y1 = 0; +double g_x2 = 0; +double g_y2 = 0; +double g_base_dx = 0; +double g_base_dy = 0; +double g_angle = 0; +double g_scale = 1.0; +double g_skew_x = 0; +double g_skew_y = 0; +int g_nclick = 0; + + + + +unsigned parse_lion(agg::path_storage& ps, agg::rgba8* colors, unsigned* path_idx); +void parse_lion() +{ + g_npaths = parse_lion(g_path, g_colors, g_path_idx); + agg::pod_array_adaptor path_idx(g_path_idx, 100); + agg::bounding_rect(g_path, path_idx, 0, g_npaths, &g_x1, &g_y1, &g_x2, &g_y2); + g_base_dx = (g_x2 - g_x1) / 2.0; + g_base_dy = (g_y2 - g_y1) / 2.0; +} + + + + + + +namespace agg +{ + template class span_simple_blur_rgb24 + { + public: + //-------------------------------------------------------------------- + typedef rgba8 color_type; + + //-------------------------------------------------------------------- + span_simple_blur_rgb24() : m_source_image(0) {} + + //-------------------------------------------------------------------- + span_simple_blur_rgb24(const rendering_buffer& src) : + m_source_image(&src) {} + + //-------------------------------------------------------------------- + void source_image(const rendering_buffer& src) { m_source_image = &src; } + const rendering_buffer& source_image() const { return *m_source_image; } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, int len) + { + if(y < 1 || y >= int(m_source_image->height() - 1)) + { + do + { + *span++ = rgba8(0,0,0,0); + } + while(--len); + return; + } + + do + { + int color[4]; + color[0] = color[1] = color[2] = color[3] = 0; + if(x > 0 && x < int(m_source_image->width()-1)) + { + int i = 3; + do + { + const int8u* ptr = m_source_image->row_ptr(y - i + 2) + (x - 1) * 3; + + color[0] += *ptr++; + color[1] += *ptr++; + color[2] += *ptr++; + color[3] += 255; + + color[0] += *ptr++; + color[1] += *ptr++; + color[2] += *ptr++; + color[3] += 255; + + color[0] += *ptr++; + color[1] += *ptr++; + color[2] += *ptr++; + color[3] += 255; + } + while(--i); + color[0] /= 9; + color[1] /= 9; + color[2] /= 9; + color[3] /= 9; + } + *span++ = rgba8(color[Order::R], color[Order::G], color[Order::B], color[3]); + ++x; + } + while(--len); + } + + private: + const rendering_buffer* m_source_image; + }; + +} + + + + + + + + + + + + +class the_application : public agg::platform_support +{ + double m_cx; + double m_cy; + +public: + virtual ~the_application() + { + } + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_cx(100), + m_cy(102) + { + parse_lion(); + } + + virtual void on_resize(int cx, int cy) + { + } + + virtual void on_draw() + { + typedef agg::pixfmt_bgr24 pixfmt; + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_aa_solid renderer_solid; + + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + renderer_solid rs(rb); + + rb.clear(agg::rgba(1, 1, 1)); + + agg::trans_affine mtx; + agg::conv_transform trans(g_path, mtx); + + mtx *= agg::trans_affine_translation(-g_base_dx, -g_base_dy); + mtx *= agg::trans_affine_scaling(g_scale, g_scale); + mtx *= agg::trans_affine_rotation(g_angle + agg::pi); + mtx *= agg::trans_affine_skewing(g_skew_x/1000.0, g_skew_y/1000.0); + mtx *= agg::trans_affine_translation(initial_width()/4, initial_height()/2); + mtx *= trans_affine_resizing(); + + agg::rasterizer_scanline_aa<> ras2; + agg::scanline_p8 sl; + agg::scanline_u8 sl2; + + agg::render_all_paths(ras2, sl, rs, trans, g_colors, g_path_idx, g_npaths); + + mtx *= ~trans_affine_resizing(); + mtx *= agg::trans_affine_translation(initial_width()/2, 0); + mtx *= trans_affine_resizing(); + + agg::line_profile_aa profile; + profile.width(1.0); + agg::renderer_outline_aa rp(rb, profile); + agg::rasterizer_outline_aa > ras(rp); + ras.round_cap(true); + + ras.render_all_paths(trans, g_colors, g_path_idx, g_npaths); + + agg::ellipse ell(m_cx, m_cy, 100.0, 100.0, 100); + agg::conv_stroke ell_stroke1(ell); + ell_stroke1.width(6.0); + agg::conv_stroke > ell_stroke2(ell_stroke1); + + ell_stroke2.width(2.0); + rs.color(agg::rgba(0,0.2,0)); + ras2.add_path(ell_stroke2); + agg::render_scanlines(ras2, sl, rs); + + typedef agg::span_simple_blur_rgb24 span_blur_gen; + typedef agg::span_allocator span_blur_alloc; + + span_blur_alloc sa; + span_blur_gen sg; + + sg.source_image(rbuf_img(0)); + ras2.add_path(ell); + + copy_window_to_img(0); + agg::render_scanlines_aa(ras2, sl2, rb, sa, sg); + + // More blur if desired :-) + //copy_window_to_img(0); + //agg::render_scanlines(ras2, sl2, rblur); + //copy_window_to_img(0); + //agg::render_scanlines(ras2, sl2, rblur); + //copy_window_to_img(0); + //agg::render_scanlines(ras2, sl2, rblur); + } + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + m_cx = x; + m_cy = y; + force_redraw(); + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + on_mouse_button_down(x, y, flags); + } + +}; + + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("AGG Example. Lion with Alpha-Masking"); + + if(app.init(512, 400, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + + + + + diff --git a/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_exception.h b/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_exception.h new file mode 100755 index 0000000..2a49b99 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_exception.h @@ -0,0 +1,69 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.3 +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// SVG exception +// +//---------------------------------------------------------------------------- + +#ifndef AGG_SVG_EXCEPTION_INCLUDED +#define AGG_SVG_EXCEPTION_INCLUDED + +#include +#include +#include + +namespace agg +{ +namespace svg +{ + class exception + { + public: + ~exception() + { + delete [] m_msg; + } + + exception() : m_msg(0) {} + + exception(const char* fmt, ...) : + m_msg(0) + { + if(fmt) + { + m_msg = new char [4096]; + va_list arg; + va_start(arg, fmt); + vsprintf(m_msg, fmt, arg); + va_end(arg); + } + } + + exception(const exception& exc) : + m_msg(exc.m_msg ? new char[strlen(exc.m_msg) + 1] : 0) + { + if(m_msg) strcpy(m_msg, exc.m_msg); + } + + const char* msg() const { return m_msg; } + + private: + char* m_msg; + }; + +} +} + +#endif diff --git a/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_parser.cpp b/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_parser.cpp new file mode 100755 index 0000000..4eeac31 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_parser.cpp @@ -0,0 +1,886 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.3 +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// SVG parser. +// +//---------------------------------------------------------------------------- + +#include +#include +#include +#include "agg_svg_parser.h" +#include "expat.h" + +namespace agg +{ +namespace svg +{ + struct named_color + { + char name[22]; + int8u r, g, b, a; + }; + + named_color colors[] = + { + { "aliceblue",240,248,255, 255 }, + { "antiquewhite",250,235,215, 255 }, + { "aqua",0,255,255, 255 }, + { "aquamarine",127,255,212, 255 }, + { "azure",240,255,255, 255 }, + { "beige",245,245,220, 255 }, + { "bisque",255,228,196, 255 }, + { "black",0,0,0, 255 }, + { "blanchedalmond",255,235,205, 255 }, + { "blue",0,0,255, 255 }, + { "blueviolet",138,43,226, 255 }, + { "brown",165,42,42, 255 }, + { "burlywood",222,184,135, 255 }, + { "cadetblue",95,158,160, 255 }, + { "chartreuse",127,255,0, 255 }, + { "chocolate",210,105,30, 255 }, + { "coral",255,127,80, 255 }, + { "cornflowerblue",100,149,237, 255 }, + { "cornsilk",255,248,220, 255 }, + { "crimson",220,20,60, 255 }, + { "cyan",0,255,255, 255 }, + { "darkblue",0,0,139, 255 }, + { "darkcyan",0,139,139, 255 }, + { "darkgoldenrod",184,134,11, 255 }, + { "darkgray",169,169,169, 255 }, + { "darkgreen",0,100,0, 255 }, + { "darkgrey",169,169,169, 255 }, + { "darkkhaki",189,183,107, 255 }, + { "darkmagenta",139,0,139, 255 }, + { "darkolivegreen",85,107,47, 255 }, + { "darkorange",255,140,0, 255 }, + { "darkorchid",153,50,204, 255 }, + { "darkred",139,0,0, 255 }, + { "darksalmon",233,150,122, 255 }, + { "darkseagreen",143,188,143, 255 }, + { "darkslateblue",72,61,139, 255 }, + { "darkslategray",47,79,79, 255 }, + { "darkslategrey",47,79,79, 255 }, + { "darkturquoise",0,206,209, 255 }, + { "darkviolet",148,0,211, 255 }, + { "deeppink",255,20,147, 255 }, + { "deepskyblue",0,191,255, 255 }, + { "dimgray",105,105,105, 255 }, + { "dimgrey",105,105,105, 255 }, + { "dodgerblue",30,144,255, 255 }, + { "firebrick",178,34,34, 255 }, + { "floralwhite",255,250,240, 255 }, + { "forestgreen",34,139,34, 255 }, + { "fuchsia",255,0,255, 255 }, + { "gainsboro",220,220,220, 255 }, + { "ghostwhite",248,248,255, 255 }, + { "gold",255,215,0, 255 }, + { "goldenrod",218,165,32, 255 }, + { "gray",128,128,128, 255 }, + { "green",0,128,0, 255 }, + { "greenyellow",173,255,47, 255 }, + { "grey",128,128,128, 255 }, + { "honeydew",240,255,240, 255 }, + { "hotpink",255,105,180, 255 }, + { "indianred",205,92,92, 255 }, + { "indigo",75,0,130, 255 }, + { "ivory",255,255,240, 255 }, + { "khaki",240,230,140, 255 }, + { "lavender",230,230,250, 255 }, + { "lavenderblush",255,240,245, 255 }, + { "lawngreen",124,252,0, 255 }, + { "lemonchiffon",255,250,205, 255 }, + { "lightblue",173,216,230, 255 }, + { "lightcoral",240,128,128, 255 }, + { "lightcyan",224,255,255, 255 }, + { "lightgoldenrodyellow",250,250,210, 255 }, + { "lightgray",211,211,211, 255 }, + { "lightgreen",144,238,144, 255 }, + { "lightgrey",211,211,211, 255 }, + { "lightpink",255,182,193, 255 }, + { "lightsalmon",255,160,122, 255 }, + { "lightseagreen",32,178,170, 255 }, + { "lightskyblue",135,206,250, 255 }, + { "lightslategray",119,136,153, 255 }, + { "lightslategrey",119,136,153, 255 }, + { "lightsteelblue",176,196,222, 255 }, + { "lightyellow",255,255,224, 255 }, + { "lime",0,255,0, 255 }, + { "limegreen",50,205,50, 255 }, + { "linen",250,240,230, 255 }, + { "magenta",255,0,255, 255 }, + { "maroon",128,0,0, 255 }, + { "mediumaquamarine",102,205,170, 255 }, + { "mediumblue",0,0,205, 255 }, + { "mediumorchid",186,85,211, 255 }, + { "mediumpurple",147,112,219, 255 }, + { "mediumseagreen",60,179,113, 255 }, + { "mediumslateblue",123,104,238, 255 }, + { "mediumspringgreen",0,250,154, 255 }, + { "mediumturquoise",72,209,204, 255 }, + { "mediumvioletred",199,21,133, 255 }, + { "midnightblue",25,25,112, 255 }, + { "mintcream",245,255,250, 255 }, + { "mistyrose",255,228,225, 255 }, + { "moccasin",255,228,181, 255 }, + { "navajowhite",255,222,173, 255 }, + { "navy",0,0,128, 255 }, + { "oldlace",253,245,230, 255 }, + { "olive",128,128,0, 255 }, + { "olivedrab",107,142,35, 255 }, + { "orange",255,165,0, 255 }, + { "orangered",255,69,0, 255 }, + { "orchid",218,112,214, 255 }, + { "palegoldenrod",238,232,170, 255 }, + { "palegreen",152,251,152, 255 }, + { "paleturquoise",175,238,238, 255 }, + { "palevioletred",219,112,147, 255 }, + { "papayawhip",255,239,213, 255 }, + { "peachpuff",255,218,185, 255 }, + { "peru",205,133,63, 255 }, + { "pink",255,192,203, 255 }, + { "plum",221,160,221, 255 }, + { "powderblue",176,224,230, 255 }, + { "purple",128,0,128, 255 }, + { "red",255,0,0, 255 }, + { "rosybrown",188,143,143, 255 }, + { "royalblue",65,105,225, 255 }, + { "saddlebrown",139,69,19, 255 }, + { "salmon",250,128,114, 255 }, + { "sandybrown",244,164,96, 255 }, + { "seagreen",46,139,87, 255 }, + { "seashell",255,245,238, 255 }, + { "sienna",160,82,45, 255 }, + { "silver",192,192,192, 255 }, + { "skyblue",135,206,235, 255 }, + { "slateblue",106,90,205, 255 }, + { "slategray",112,128,144, 255 }, + { "slategrey",112,128,144, 255 }, + { "snow",255,250,250, 255 }, + { "springgreen",0,255,127, 255 }, + { "steelblue",70,130,180, 255 }, + { "tan",210,180,140, 255 }, + { "teal",0,128,128, 255 }, + { "thistle",216,191,216, 255 }, + { "tomato",255,99,71, 255 }, + { "turquoise",64,224,208, 255 }, + { "violet",238,130,238, 255 }, + { "wheat",245,222,179, 255 }, + { "white",255,255,255, 255 }, + { "whitesmoke",245,245,245, 255 }, + { "yellow",255,255,0, 255 }, + { "yellowgreen",154,205,50, 255 }, + { "zzzzzzzzzzz",0,0,0, 0 } + }; + + + //------------------------------------------------------------------------ + parser::~parser() + { + delete [] m_attr_value; + delete [] m_attr_name; + delete [] m_buf; + delete [] m_title; + } + + //------------------------------------------------------------------------ + parser::parser(path_renderer& path) : + m_path(path), + m_tokenizer(), + m_buf(new char[buf_size]), + m_title(new char[256]), + m_title_len(0), + m_title_flag(false), + m_path_flag(false), + m_attr_name(new char[128]), + m_attr_value(new char[1024]), + m_attr_name_len(127), + m_attr_value_len(1023) + { + m_title[0] = 0; + } + + //------------------------------------------------------------------------ + void parser::parse(const char* fname) + { + char msg[1024]; + XML_Parser p = XML_ParserCreate(NULL); + if(p == 0) + { + throw exception("Couldn't allocate memory for parser"); + } + + XML_SetUserData(p, this); + XML_SetElementHandler(p, start_element, end_element); + XML_SetCharacterDataHandler(p, content); + + FILE* fd = fopen(fname, "r"); + if(fd == 0) + { + sprintf(msg, "Couldn't open file %s", fname); + throw exception(msg); + } + + bool done = false; + do + { + size_t len = fread(m_buf, 1, buf_size, fd); + done = len < buf_size; + if(!XML_Parse(p, m_buf, len, done)) + { + sprintf(msg, + "%s at line %d\n", + XML_ErrorString(XML_GetErrorCode(p)), + XML_GetCurrentLineNumber(p)); + throw exception(msg); + } + } + while(!done); + fclose(fd); + XML_ParserFree(p); + + char* ts = m_title; + while(*ts) + { + if(*ts < ' ') *ts = ' '; + ++ts; + } + } + + + //------------------------------------------------------------------------ + void parser::start_element(void* data, const char* el, const char** attr) + { + parser& self = *(parser*)data; + + if(strcmp(el, "title") == 0) + { + self.m_title_flag = true; + } + else + if(strcmp(el, "g") == 0) + { + self.m_path.push_attr(); + self.parse_attr(attr); + } + else + if(strcmp(el, "path") == 0) + { + if(self.m_path_flag) + { + throw exception("start_element: Nested path"); + } + self.m_path.begin_path(); + self.parse_path(attr); + self.m_path.end_path(); + self.m_path_flag = true; + } + else + if(strcmp(el, "rect") == 0) + { + self.parse_rect(attr); + } + else + if(strcmp(el, "line") == 0) + { + self.parse_line(attr); + } + else + if(strcmp(el, "polyline") == 0) + { + self.parse_poly(attr, false); + } + else + if(strcmp(el, "polygon") == 0) + { + self.parse_poly(attr, true); + } + //else + //if(strcmp(el, "") == 0) + //{ + //} + // . . . + } + + + //------------------------------------------------------------------------ + void parser::end_element(void* data, const char* el) + { + parser& self = *(parser*)data; + + if(strcmp(el, "title") == 0) + { + self.m_title_flag = false; + } + else + if(strcmp(el, "g") == 0) + { + self.m_path.pop_attr(); + } + else + if(strcmp(el, "path") == 0) + { + self.m_path_flag = false; + } + //else + //if(strcmp(el, "") == 0) + //{ + //} + // . . . + } + + + //------------------------------------------------------------------------ + void parser::content(void* data, const char* s, int len) + { + parser& self = *(parser*)data; + + // m_title_flag signals that the tag is being parsed now. + // The following code concatenates the pieces of content of the <title> tag. + if(self.m_title_flag) + { + if(len + self.m_title_len > 255) len = 255 - self.m_title_len; + if(len > 0) + { + memcpy(self.m_title + self.m_title_len, s, len); + self.m_title_len += len; + self.m_title[self.m_title_len] = 0; + } + } + } + + + //------------------------------------------------------------------------ + void parser::parse_attr(const char** attr) + { + int i; + for(i = 0; attr[i]; i += 2) + { + if(strcmp(attr[i], "style") == 0) + { + parse_style(attr[i + 1]); + } + else + { + parse_attr(attr[i], attr[i + 1]); + } + } + } + + //------------------------------------------------------------- + void parser::parse_path(const char** attr) + { + int i; + + for(i = 0; attr[i]; i += 2) + { + // The <path> tag can consist of the path itself ("d=") + // as well as of other parameters like "style=", "transform=", etc. + // In the last case we simply rely on the function of parsing + // attributes (see 'else' branch). + if(strcmp(attr[i], "d") == 0) + { + m_tokenizer.set_path_str(attr[i + 1]); + m_path.parse_path(m_tokenizer); + } + else + { + // Create a temporary single pair "name-value" in order + // to avoid multiple calls for the same attribute. + const char* tmp[4]; + tmp[0] = attr[i]; + tmp[1] = attr[i + 1]; + tmp[2] = 0; + tmp[3] = 0; + parse_attr(tmp); + } + } + } + + + //------------------------------------------------------------- + int cmp_color(const void* p1, const void* p2) + { + return strcmp(((named_color*)p1)->name, ((named_color*)p2)->name); + } + + //------------------------------------------------------------- + rgba8 parse_color(const char* str) + { + while(*str == ' ') ++str; + unsigned c = 0; + if(*str == '#') + { + sscanf(str + 1, "%x", &c); + return rgb8_packed(c); + } + else + { + named_color c; + unsigned len = strlen(str); + if(len > sizeof(c.name) - 1) + { + throw exception("parse_color: Invalid color name '%s'", str); + } + strcpy(c.name, str); + const void* p = bsearch(&c, + colors, + sizeof(colors) / sizeof(colors[0]), + sizeof(colors[0]), + cmp_color); + if(p == 0) + { + throw exception("parse_color: Invalid color name '%s'", str); + } + const named_color* pc = (const named_color*)p; + return rgba8(pc->r, pc->g, pc->b, pc->a); + } + } + + double parse_double(const char* str) + { + while(*str == ' ') ++str; + return atof(str); + } + + + + //------------------------------------------------------------- + bool parser::parse_attr(const char* name, const char* value) + { + if(strcmp(name, "style") == 0) + { + parse_style(value); + } + else + if(strcmp(name, "fill") == 0) + { + if(strcmp(value, "none") == 0) + { + m_path.fill_none(); + } + else + { + m_path.fill(parse_color(value)); + } + } + else + if(strcmp(name, "fill-opacity") == 0) + { + m_path.fill_opacity(parse_double(value)); + } + else + if(strcmp(name, "stroke") == 0) + { + if(strcmp(value, "none") == 0) + { + m_path.stroke_none(); + } + else + { + m_path.stroke(parse_color(value)); + } + } + else + if(strcmp(name, "stroke-width") == 0) + { + m_path.stroke_width(parse_double(value)); + } + else + if(strcmp(name, "stroke-linecap") == 0) + { + if(strcmp(value, "butt") == 0) m_path.line_cap(butt_cap); + else if(strcmp(value, "round") == 0) m_path.line_cap(round_cap); + else if(strcmp(value, "square") == 0) m_path.line_cap(square_cap); + } + else + if(strcmp(name, "stroke-linejoin") == 0) + { + if(strcmp(value, "miter") == 0) m_path.line_join(miter_join); + else if(strcmp(value, "round") == 0) m_path.line_join(round_join); + else if(strcmp(value, "bevel") == 0) m_path.line_join(bevel_join); + } + else + if(strcmp(name, "stroke-miterlimit") == 0) + { + m_path.miter_limit(parse_double(value)); + } + else + if(strcmp(name, "stroke-opacity") == 0) + { + m_path.stroke_opacity(parse_double(value)); + } + else + if(strcmp(name, "transform") == 0) + { + parse_transform(value); + } + //else + //if(strcmp(el, "<OTHER_ATTRIBUTES>") == 0) + //{ + //} + // . . . + else + { + return false; + } + return true; + } + + + + //------------------------------------------------------------- + void parser::copy_name(const char* start, const char* end) + { + unsigned len = unsigned(end - start); + if(m_attr_name_len == 0 || len > m_attr_name_len) + { + delete [] m_attr_name; + m_attr_name = new char[len + 1]; + m_attr_name_len = len; + } + if(len) memcpy(m_attr_name, start, len); + m_attr_name[len] = 0; + } + + + + //------------------------------------------------------------- + void parser::copy_value(const char* start, const char* end) + { + unsigned len = unsigned(end - start); + if(m_attr_value_len == 0 || len > m_attr_value_len) + { + delete [] m_attr_value; + m_attr_value = new char[len + 1]; + m_attr_value_len = len; + } + if(len) memcpy(m_attr_value, start, len); + m_attr_value[len] = 0; + } + + + //------------------------------------------------------------- + bool parser::parse_name_value(const char* nv_start, const char* nv_end) + { + const char* str = nv_start; + while(str < nv_end && *str != ':') ++str; + + const char* val = str; + + // Right Trim + while(str > nv_start && + (*str == ':' || isspace(*str))) --str; + ++str; + + copy_name(nv_start, str); + + while(val < nv_end && (*val == ':' || isspace(*val))) ++val; + + copy_value(val, nv_end); + return parse_attr(m_attr_name, m_attr_value); + } + + + + //------------------------------------------------------------- + void parser::parse_style(const char* str) + { + while(*str) + { + // Left Trim + while(*str && isspace(*str)) ++str; + const char* nv_start = str; + while(*str && *str != ';') ++str; + const char* nv_end = str; + + // Right Trim + while(nv_end > nv_start && + (*nv_end == ';' || isspace(*nv_end))) --nv_end; + ++nv_end; + + parse_name_value(nv_start, nv_end); + if(*str) ++str; + } + + } + + + //------------------------------------------------------------- + void parser::parse_rect(const char** attr) + { + int i; + double x = 0.0; + double y = 0.0; + double w = 0.0; + double h = 0.0; + + m_path.begin_path(); + for(i = 0; attr[i]; i += 2) + { + if(!parse_attr(attr[i], attr[i + 1])) + { + if(strcmp(attr[i], "x") == 0) x = parse_double(attr[i + 1]); + if(strcmp(attr[i], "y") == 0) y = parse_double(attr[i + 1]); + if(strcmp(attr[i], "width") == 0) w = parse_double(attr[i + 1]); + if(strcmp(attr[i], "height") == 0) h = parse_double(attr[i + 1]); + // rx - to be implemented + // ry - to be implemented + } + } + + + if(w != 0.0 && h != 0.0) + { + if(w < 0.0) throw exception("parse_rect: Invalid width: %f", w); + if(h < 0.0) throw exception("parse_rect: Invalid height: %f", h); + + m_path.move_to(x, y); + m_path.line_to(x + w, y); + m_path.line_to(x + w, y + h); + m_path.line_to(x, y + h); + m_path.close_subpath(); + } + m_path.end_path(); + } + + + //------------------------------------------------------------- + void parser::parse_line(const char** attr) + { + int i; + double x1 = 0.0; + double y1 = 0.0; + double x2 = 0.0; + double y2 = 0.0; + + m_path.begin_path(); + for(i = 0; attr[i]; i += 2) + { + if(!parse_attr(attr[i], attr[i + 1])) + { + if(strcmp(attr[i], "x1") == 0) x1 = parse_double(attr[i + 1]); + if(strcmp(attr[i], "y1") == 0) y1 = parse_double(attr[i + 1]); + if(strcmp(attr[i], "x2") == 0) x2 = parse_double(attr[i + 1]); + if(strcmp(attr[i], "y2") == 0) y2 = parse_double(attr[i + 1]); + } + } + + m_path.move_to(x1, y1); + m_path.line_to(x2, y2); + m_path.end_path(); + } + + + //------------------------------------------------------------- + void parser::parse_poly(const char** attr, bool close_flag) + { + int i; + double x = 0.0; + double y = 0.0; + + m_path.begin_path(); + for(i = 0; attr[i]; i += 2) + { + if(!parse_attr(attr[i], attr[i + 1])) + { + if(strcmp(attr[i], "points") == 0) + { + m_tokenizer.set_path_str(attr[i + 1]); + if(!m_tokenizer.next()) + { + throw exception("parse_poly: Too few coordinates"); + } + x = m_tokenizer.last_number(); + if(!m_tokenizer.next()) + { + throw exception("parse_poly: Too few coordinates"); + } + y = m_tokenizer.last_number(); + m_path.move_to(x, y); + while(m_tokenizer.next()) + { + x = m_tokenizer.last_number(); + if(!m_tokenizer.next()) + { + throw exception("parse_poly: Odd number of coordinates"); + } + y = m_tokenizer.last_number(); + m_path.line_to(x, y); + } + } + } + } + if(close_flag) + { + m_path.close_subpath(); + } + m_path.end_path(); + } + + //------------------------------------------------------------- + void parser::parse_transform(const char* str) + { + while(*str) + { + if(islower(*str)) + { + if(strncmp(str, "matrix", 6) == 0) str += parse_matrix(str); else + if(strncmp(str, "translate", 9) == 0) str += parse_translate(str); else + if(strncmp(str, "rotate", 6) == 0) str += parse_rotate(str); else + if(strncmp(str, "scale", 5) == 0) str += parse_scale(str); else + if(strncmp(str, "skewX", 5) == 0) str += parse_skew_x(str); else + if(strncmp(str, "skewY", 5) == 0) str += parse_skew_y(str); else + { + ++str; + } + } + else + { + ++str; + } + } + } + + + //------------------------------------------------------------- + static bool is_numeric(char c) + { + return strchr("0123456789+-.eE", c) != 0; + } + + //------------------------------------------------------------- + static unsigned parse_transform_args(const char* str, + double* args, + unsigned max_na, + unsigned* na) + { + *na = 0; + const char* ptr = str; + while(*ptr && *ptr != '(') ++ptr; + if(*ptr == 0) + { + throw exception("parse_transform_args: Invalid syntax"); + } + const char* end = ptr; + while(*end && *end != ')') ++end; + if(*end == 0) + { + throw exception("parse_transform_args: Invalid syntax"); + } + + while(ptr < end) + { + if(is_numeric(*ptr)) + { + if(*na >= max_na) + { + throw exception("parse_transform_args: Too many arguments"); + } + args[(*na)++] = atof(ptr); + while(ptr < end && is_numeric(*ptr)) ++ptr; + } + else + { + ++ptr; + } + } + return unsigned(end - str); + } + + //------------------------------------------------------------- + unsigned parser::parse_matrix(const char* str) + { + double args[6]; + unsigned na = 0; + unsigned len = parse_transform_args(str, args, 6, &na); + if(na != 6) + { + throw exception("parse_matrix: Invalid number of arguments"); + } + m_path.transform().premultiply(trans_affine(args[0], args[1], args[2], args[3], args[4], args[5])); + return len; + } + + //------------------------------------------------------------- + unsigned parser::parse_translate(const char* str) + { + double args[2]; + unsigned na = 0; + unsigned len = parse_transform_args(str, args, 2, &na); + if(na == 1) args[1] = 0.0; + m_path.transform().premultiply(trans_affine_translation(args[0], args[1])); + return len; + } + + //------------------------------------------------------------- + unsigned parser::parse_rotate(const char* str) + { + double args[3]; + unsigned na = 0; + unsigned len = parse_transform_args(str, args, 3, &na); + if(na == 1) + { + m_path.transform().premultiply(trans_affine_rotation(deg2rad(args[0]))); + } + else if(na == 3) + { + trans_affine t = trans_affine_translation(-args[1], -args[2]); + t *= trans_affine_rotation(deg2rad(args[0])); + t *= trans_affine_translation(args[1], args[2]); + m_path.transform().premultiply(t); + } + else + { + throw exception("parse_rotate: Invalid number of arguments"); + } + return len; + } + + //------------------------------------------------------------- + unsigned parser::parse_scale(const char* str) + { + double args[2]; + unsigned na = 0; + unsigned len = parse_transform_args(str, args, 2, &na); + if(na == 1) args[1] = args[0]; + m_path.transform().premultiply(trans_affine_scaling(args[0], args[1])); + return len; + } + + //------------------------------------------------------------- + unsigned parser::parse_skew_x(const char* str) + { + double arg; + unsigned na = 0; + unsigned len = parse_transform_args(str, &arg, 1, &na); + m_path.transform().premultiply(trans_affine_skewing(deg2rad(arg), 0.0)); + return len; + } + + //------------------------------------------------------------- + unsigned parser::parse_skew_y(const char* str) + { + double arg; + unsigned na = 0; + unsigned len = parse_transform_args(str, &arg, 1, &na); + m_path.transform().premultiply(trans_affine_skewing(0.0, deg2rad(arg))); + return len; + } + +} +} + + diff --git a/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_parser.h b/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_parser.h new file mode 100755 index 0000000..4d40936 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_parser.h @@ -0,0 +1,85 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.3 +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// SVG parser. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_SVG_PARSER_INCLUDED +#define AGG_SVG_PARSER_INCLUDED + +#include "agg_svg_path_tokenizer.h" +#include "agg_svg_path_renderer.h" + +namespace agg +{ +namespace svg +{ + + class parser + { + enum buf_size_e { buf_size = BUFSIZ }; + public: + + ~parser(); + parser(path_renderer& path); + + void parse(const char* fname); + const char* title() const { return m_title; } + + private: + // XML event handlers + static void start_element(void* data, const char* el, const char** attr); + static void end_element(void* data, const char* el); + static void content(void* data, const char* s, int len); + + void parse_attr(const char** attr); + void parse_path(const char** attr); + void parse_poly(const char** attr, bool close_flag); + void parse_rect(const char** attr); + void parse_line(const char** attr); + void parse_style(const char* str); + void parse_transform(const char* str); + + unsigned parse_matrix(const char* str); + unsigned parse_translate(const char* str); + unsigned parse_rotate(const char* str); + unsigned parse_scale(const char* str); + unsigned parse_skew_x(const char* str); + unsigned parse_skew_y(const char* str); + + bool parse_attr(const char* name, const char* value); + bool parse_name_value(const char* nv_start, const char* nv_end); + void copy_name(const char* start, const char* end); + void copy_value(const char* start, const char* end); + + private: + path_renderer& m_path; + path_tokenizer m_tokenizer; + char* m_buf; + char* m_title; + unsigned m_title_len; + bool m_title_flag; + bool m_path_flag; + char* m_attr_name; + char* m_attr_value; + unsigned m_attr_name_len; + unsigned m_attr_value_len; + }; + +} +} + +#endif diff --git a/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_path_renderer.cpp b/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_path_renderer.cpp new file mode 100755 index 0000000..65954bc --- /dev/null +++ b/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_path_renderer.cpp @@ -0,0 +1,359 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.3 +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// SVG path renderer. +// +//---------------------------------------------------------------------------- + +#include <stdio.h> +#include "agg_svg_path_renderer.h" + +namespace agg +{ +namespace svg +{ + + //------------------------------------------------------------------------ + path_renderer::path_renderer() : + m_curved(m_storage), + m_curved_count(m_curved), + + m_curved_stroked(m_curved_count), + m_curved_stroked_trans(m_curved_stroked, m_transform), + + m_curved_trans(m_curved_count, m_transform), + m_curved_trans_contour(m_curved_trans) + { + m_curved_trans_contour.auto_detect_orientation(false); + } + + + //------------------------------------------------------------------------ + void path_renderer::remove_all() + { + m_storage.remove_all(); + m_attr_storage.remove_all(); + m_attr_stack.remove_all(); + m_transform.reset(); + } + + //------------------------------------------------------------------------ + void path_renderer::begin_path() + { + push_attr(); + unsigned idx = m_storage.start_new_path(); + m_attr_storage.add(path_attributes(cur_attr(), idx)); + } + + //------------------------------------------------------------------------ + void path_renderer::end_path() + { + if(m_attr_storage.size() == 0) + { + throw exception("end_path : The path was not begun"); + } + path_attributes attr = cur_attr(); + unsigned idx = m_attr_storage[m_attr_storage.size() - 1].index; + attr.index = idx; + m_attr_storage[m_attr_storage.size() - 1] = attr; + pop_attr(); + } + + //------------------------------------------------------------------------ + void path_renderer::move_to(double x, double y, bool rel) // M, m + { + if(rel) m_storage.rel_to_abs(&x, &y); + m_storage.move_to(x, y); + } + + //------------------------------------------------------------------------ + void path_renderer::line_to(double x, double y, bool rel) // L, l + { + if(rel) m_storage.rel_to_abs(&x, &y); + m_storage.line_to(x, y); + } + + //------------------------------------------------------------------------ + void path_renderer::hline_to(double x, bool rel) // H, h + { + double x2 = 0.0; + double y2 = 0.0; + if(m_storage.total_vertices()) + { + m_storage.vertex(m_storage.total_vertices() - 1, &x2, &y2); + if(rel) x += x2; + m_storage.line_to(x, y2); + } + } + + //------------------------------------------------------------------------ + void path_renderer::vline_to(double y, bool rel) // V, v + { + double x2 = 0.0; + double y2 = 0.0; + if(m_storage.total_vertices()) + { + m_storage.vertex(m_storage.total_vertices() - 1, &x2, &y2); + if(rel) y += y2; + m_storage.line_to(x2, y); + } + } + + //------------------------------------------------------------------------ + void path_renderer::curve3(double x1, double y1, // Q, q + double x, double y, bool rel) + { + if(rel) + { + m_storage.rel_to_abs(&x1, &y1); + m_storage.rel_to_abs(&x, &y); + } + m_storage.curve3(x1, y1, x, y); + } + + //------------------------------------------------------------------------ + void path_renderer::curve3(double x, double y, bool rel) // T, t + { +// throw exception("curve3(x, y) : NOT IMPLEMENTED YET"); + if(rel) + { + m_storage.curve3_rel(x, y); + } else + { + m_storage.curve3(x, y); + } + } + + //------------------------------------------------------------------------ + void path_renderer::curve4(double x1, double y1, // C, c + double x2, double y2, + double x, double y, bool rel) + { + if(rel) + { + m_storage.rel_to_abs(&x1, &y1); + m_storage.rel_to_abs(&x2, &y2); + m_storage.rel_to_abs(&x, &y); + } + m_storage.curve4(x1, y1, x2, y2, x, y); + } + + //------------------------------------------------------------------------ + void path_renderer::curve4(double x2, double y2, // S, s + double x, double y, bool rel) + { + //throw exception("curve4(x2, y2, x, y) : NOT IMPLEMENTED YET"); + if(rel) + { + m_storage.curve4_rel(x2, y2, x, y); + } else + { + m_storage.curve4(x2, y2, x, y); + } + } + + //------------------------------------------------------------------------ + void path_renderer::close_subpath() + { + m_storage.end_poly(path_flags_close); + } + + //------------------------------------------------------------------------ + path_attributes& path_renderer::cur_attr() + { + if(m_attr_stack.size() == 0) + { + throw exception("cur_attr : Attribute stack is empty"); + } + return m_attr_stack[m_attr_stack.size() - 1]; + } + + //------------------------------------------------------------------------ + void path_renderer::push_attr() + { + m_attr_stack.add(m_attr_stack.size() ? + m_attr_stack[m_attr_stack.size() - 1] : + path_attributes()); + } + + //------------------------------------------------------------------------ + void path_renderer::pop_attr() + { + if(m_attr_stack.size() == 0) + { + throw exception("pop_attr : Attribute stack is empty"); + } + m_attr_stack.remove_last(); + } + + //------------------------------------------------------------------------ + void path_renderer::fill(const rgba8& f) + { + path_attributes& attr = cur_attr(); + attr.fill_color = f; + attr.fill_flag = true; + } + + //------------------------------------------------------------------------ + void path_renderer::stroke(const rgba8& s) + { + path_attributes& attr = cur_attr(); + attr.stroke_color = s; + attr.stroke_flag = true; + } + + //------------------------------------------------------------------------ + void path_renderer::even_odd(bool flag) + { + cur_attr().even_odd_flag = flag; + } + + //------------------------------------------------------------------------ + void path_renderer::stroke_width(double w) + { + cur_attr().stroke_width = w; + } + + //------------------------------------------------------------------------ + void path_renderer::fill_none() + { + cur_attr().fill_flag = false; + } + + //------------------------------------------------------------------------ + void path_renderer::stroke_none() + { + cur_attr().stroke_flag = false; + } + + //------------------------------------------------------------------------ + void path_renderer::fill_opacity(double op) + { + cur_attr().fill_color.opacity(op); + } + + //------------------------------------------------------------------------ + void path_renderer::stroke_opacity(double op) + { + cur_attr().stroke_color.opacity(op); + } + + //------------------------------------------------------------------------ + void path_renderer::line_join(line_join_e join) + { + cur_attr().line_join = join; + } + + //------------------------------------------------------------------------ + void path_renderer::line_cap(line_cap_e cap) + { + cur_attr().line_cap = cap; + } + + //------------------------------------------------------------------------ + void path_renderer::miter_limit(double ml) + { + cur_attr().miter_limit = ml; + } + + //------------------------------------------------------------------------ + trans_affine& path_renderer::transform() + { + return cur_attr().transform; + } + + //------------------------------------------------------------------------ + void path_renderer::parse_path(path_tokenizer& tok) + { + while(tok.next()) + { + double arg[10]; + char cmd = tok.last_command(); + unsigned i; + switch(cmd) + { + case 'M': case 'm': + arg[0] = tok.last_number(); + arg[1] = tok.next(cmd); + move_to(arg[0], arg[1], cmd == 'm'); + break; + + case 'L': case 'l': + arg[0] = tok.last_number(); + arg[1] = tok.next(cmd); + line_to(arg[0], arg[1], cmd == 'l'); + break; + + case 'V': case 'v': + vline_to(tok.last_number(), cmd == 'v'); + break; + + case 'H': case 'h': + hline_to(tok.last_number(), cmd == 'h'); + break; + + case 'Q': case 'q': + arg[0] = tok.last_number(); + for(i = 1; i < 4; i++) + { + arg[i] = tok.next(cmd); + } + curve3(arg[0], arg[1], arg[2], arg[3], cmd == 'q'); + break; + + case 'T': case 't': + arg[0] = tok.last_number(); + arg[1] = tok.next(cmd); + curve3(arg[0], arg[1], cmd == 't'); + break; + + case 'C': case 'c': + arg[0] = tok.last_number(); + for(i = 1; i < 6; i++) + { + arg[i] = tok.next(cmd); + } + curve4(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], cmd == 'c'); + break; + + case 'S': case 's': + arg[0] = tok.last_number(); + for(i = 1; i < 4; i++) + { + arg[i] = tok.next(cmd); + } + curve4(arg[0], arg[1], arg[2], arg[3], cmd == 's'); + break; + + case 'A': case 'a': + throw exception("parse_path: Command A: NOT IMPLEMENTED YET"); + + case 'Z': case 'z': + close_subpath(); + break; + + default: + { + char buf[100]; + sprintf(buf, "parse_path: Invalid Command %c", cmd); + throw exception(buf); + } + } + } + } + +} +} + diff --git a/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_path_renderer.h b/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_path_renderer.h new file mode 100755 index 0000000..fd1983a --- /dev/null +++ b/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_path_renderer.h @@ -0,0 +1,321 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.3 +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// SVG path renderer. +// +//---------------------------------------------------------------------------- +#ifndef AGG_SVG_PATH_RENDERER_INCLUDED +#define AGG_SVG_PATH_RENDERER_INCLUDED + +#include "agg_path_storage.h" +#include "agg_conv_transform.h" +#include "agg_conv_stroke.h" +#include "agg_conv_contour.h" +#include "agg_conv_curve.h" +#include "agg_color_rgba.h" +#include "agg_renderer_scanline.h" +#include "agg_bounding_rect.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_svg_path_tokenizer.h" + +namespace agg +{ +namespace svg +{ + template<class VertexSource> class conv_count + { + public: + conv_count(VertexSource& vs) : m_source(&vs), m_count(0) {} + + void count(unsigned n) { m_count = n; } + unsigned count() const { return m_count; } + + void rewind(unsigned path_id) { m_source->rewind(path_id); } + unsigned vertex(double* x, double* y) + { + ++m_count; + return m_source->vertex(x, y); + } + + private: + VertexSource* m_source; + unsigned m_count; + }; + + + + + //============================================================================ + // Basic path attributes + struct path_attributes + { + unsigned index; + rgba8 fill_color; + rgba8 stroke_color; + bool fill_flag; + bool stroke_flag; + bool even_odd_flag; + line_join_e line_join; + line_cap_e line_cap; + double miter_limit; + double stroke_width; + trans_affine transform; + + // Empty constructor + path_attributes() : + index(0), + fill_color(rgba(0,0,0)), + stroke_color(rgba(0,0,0)), + fill_flag(true), + stroke_flag(false), + even_odd_flag(false), + line_join(miter_join), + line_cap(butt_cap), + miter_limit(4.0), + stroke_width(1.0), + transform() + { + } + + // Copy constructor + path_attributes(const path_attributes& attr) : + index(attr.index), + fill_color(attr.fill_color), + stroke_color(attr.stroke_color), + fill_flag(attr.fill_flag), + stroke_flag(attr.stroke_flag), + even_odd_flag(attr.even_odd_flag), + line_join(attr.line_join), + line_cap(attr.line_cap), + miter_limit(attr.miter_limit), + stroke_width(attr.stroke_width), + transform(attr.transform) + { + } + + // Copy constructor with new index value + path_attributes(const path_attributes& attr, unsigned idx) : + index(idx), + fill_color(attr.fill_color), + stroke_color(attr.stroke_color), + fill_flag(attr.fill_flag), + stroke_flag(attr.stroke_flag), + even_odd_flag(attr.even_odd_flag), + line_join(attr.line_join), + line_cap(attr.line_cap), + miter_limit(attr.miter_limit), + stroke_width(attr.stroke_width), + transform(attr.transform) + { + } + }; + + + //============================================================================ + // Path container and renderer. + class path_renderer + { + public: + typedef pod_bvector<path_attributes> attr_storage; + + typedef conv_curve<path_storage> curved; + typedef conv_count<curved> curved_count; + + typedef conv_stroke<curved_count> curved_stroked; + typedef conv_transform<curved_stroked> curved_stroked_trans; + + typedef conv_transform<curved_count> curved_trans; + typedef conv_contour<curved_trans> curved_trans_contour; + + path_renderer(); + + void remove_all(); + + // Use these functions as follows: + // begin_path() when the XML tag <path> comes ("start_element" handler) + // parse_path() on "d=" tag attribute + // end_path() when parsing of the entire tag is done. + void begin_path(); + void parse_path(path_tokenizer& tok); + void end_path(); + + // The following functions are essentially a "reflection" of + // the respective SVG path commands. + void move_to(double x, double y, bool rel=false); // M, m + void line_to(double x, double y, bool rel=false); // L, l + void hline_to(double x, bool rel=false); // H, h + void vline_to(double y, bool rel=false); // V, v + void curve3(double x1, double y1, // Q, q + double x, double y, bool rel=false); + void curve3(double x, double y, bool rel=false); // T, t + void curve4(double x1, double y1, // C, c + double x2, double y2, + double x, double y, bool rel=false); + void curve4(double x2, double y2, // S, s + double x, double y, bool rel=false); + void close_subpath(); // Z, z + +// template<class VertexSource> +// void add_path(VertexSource& vs, +// unsigned path_id = 0, +// bool solid_path = true) +// { +// m_storage.add_path(vs, path_id, solid_path); +// } + + + unsigned vertex_count() const { return m_curved_count.count(); } + + + // Call these functions on <g> tag (start_element, end_element respectively) + void push_attr(); + void pop_attr(); + + // Attribute setting functions. + void fill(const rgba8& f); + void stroke(const rgba8& s); + void even_odd(bool flag); + void stroke_width(double w); + void fill_none(); + void stroke_none(); + void fill_opacity(double op); + void stroke_opacity(double op); + void line_join(line_join_e join); + void line_cap(line_cap_e cap); + void miter_limit(double ml); + trans_affine& transform(); + + // Make all polygons CCW-oriented + void arrange_orientations() + { + m_storage.arrange_orientations_all_paths(path_flags_ccw); + } + + // Expand all polygons + void expand(double value) + { + m_curved_trans_contour.width(value); + } + + unsigned operator [](unsigned idx) + { + m_transform = m_attr_storage[idx].transform; + return m_attr_storage[idx].index; + } + + void bounding_rect(double* x1, double* y1, double* x2, double* y2) + { + agg::conv_transform<agg::path_storage> trans(m_storage, m_transform); + agg::bounding_rect(trans, *this, 0, m_attr_storage.size(), x1, y1, x2, y2); + } + + // Rendering. One can specify two additional parameters: + // trans_affine and opacity. They can be used to transform the whole + // image and/or to make it translucent. + template<class Rasterizer, class Scanline, class Renderer> + void render(Rasterizer& ras, + Scanline& sl, + Renderer& ren, + const trans_affine& mtx, + const rect_i& cb, + double opacity=1.0) + { + unsigned i; + + ras.clip_box(cb.x1, cb.y1, cb.x2, cb.y2); + m_curved_count.count(0); + + for(i = 0; i < m_attr_storage.size(); i++) + { + const path_attributes& attr = m_attr_storage[i]; + m_transform = attr.transform; + m_transform *= mtx; + double scl = m_transform.scale(); + //m_curved.approximation_method(curve_inc); + m_curved.approximation_scale(scl); + m_curved.angle_tolerance(0.0); + + rgba8 color; + + if(attr.fill_flag) + { + ras.reset(); + ras.filling_rule(attr.even_odd_flag ? fill_even_odd : fill_non_zero); + if(fabs(m_curved_trans_contour.width()) < 0.0001) + { + ras.add_path(m_curved_trans, attr.index); + } + else + { + m_curved_trans_contour.miter_limit(attr.miter_limit); + ras.add_path(m_curved_trans_contour, attr.index); + } + + color = attr.fill_color; + color.opacity(color.opacity() * opacity); + ren.color(color); + agg::render_scanlines(ras, sl, ren); + } + + if(attr.stroke_flag) + { + m_curved_stroked.width(attr.stroke_width); + //m_curved_stroked.line_join((attr.line_join == miter_join) ? miter_join_round : attr.line_join); + m_curved_stroked.line_join(attr.line_join); + m_curved_stroked.line_cap(attr.line_cap); + m_curved_stroked.miter_limit(attr.miter_limit); + m_curved_stroked.inner_join(inner_round); + m_curved_stroked.approximation_scale(scl); + + // If the *visual* line width is considerable we + // turn on processing of curve cusps. + //--------------------- + if(attr.stroke_width * scl > 1.0) + { + m_curved.angle_tolerance(0.2); + } + ras.reset(); + ras.filling_rule(fill_non_zero); + ras.add_path(m_curved_stroked_trans, attr.index); + color = attr.stroke_color; + color.opacity(color.opacity() * opacity); + ren.color(color); + agg::render_scanlines(ras, sl, ren); + } + } + } + + private: + path_attributes& cur_attr(); + + path_storage m_storage; + attr_storage m_attr_storage; + attr_storage m_attr_stack; + trans_affine m_transform; + + curved m_curved; + curved_count m_curved_count; + + curved_stroked m_curved_stroked; + curved_stroked_trans m_curved_stroked_trans; + + curved_trans m_curved_trans; + curved_trans_contour m_curved_trans_contour; + }; + +} +} + +#endif diff --git a/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_path_tokenizer.cpp b/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_path_tokenizer.cpp new file mode 100755 index 0000000..324c93b --- /dev/null +++ b/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_path_tokenizer.cpp @@ -0,0 +1,144 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.3 +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// SVG path tokenizer. +// +//---------------------------------------------------------------------------- +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include "agg_svg_exception.h" +#include "agg_svg_path_tokenizer.h" + + +namespace agg +{ +namespace svg +{ + + //------------------------------------------------------------------------ + const char path_tokenizer::s_commands[] = "+-MmZzLlHhVvCcSsQqTtAaFfPp"; + const char path_tokenizer::s_numeric[] = ".Ee0123456789"; + const char path_tokenizer::s_separators[] = " ,\t\n\r"; + + //------------------------------------------------------------------------ + path_tokenizer::path_tokenizer() + : m_path(0), m_last_command(0), m_last_number(0.0) + { + init_char_mask(m_commands_mask, s_commands); + init_char_mask(m_numeric_mask, s_numeric); + init_char_mask(m_separators_mask, s_separators); + } + + + //------------------------------------------------------------------------ + void path_tokenizer::set_path_str(const char* str) + { + m_path = str; + m_last_command = 0; + m_last_number = 0.0; + } + + + //------------------------------------------------------------------------ + void path_tokenizer::init_char_mask(char* mask, const char* char_set) + { + memset(mask, 0, 256/8); + while(*char_set) + { + unsigned c = unsigned(*char_set++) & 0xFF; + mask[c >> 3] |= 1 << (c & 7); + } + } + + + //------------------------------------------------------------------------ + bool path_tokenizer::next() + { + if(m_path == 0) return false; + + // Skip all white spaces and other garbage + while(*m_path && !is_command(*m_path) && !is_numeric(*m_path)) + { + if(!is_separator(*m_path)) + { + char buf[100]; + sprintf(buf, "path_tokenizer::next : Invalid Character %c", *m_path); + throw exception(buf); + } + m_path++; + } + + if(*m_path == 0) return false; + + if(is_command(*m_path)) + { + // Check if the command is a numeric sign character + if(*m_path == '-' || *m_path == '+') + { + return parse_number(); + } + m_last_command = *m_path++; + while(*m_path && is_separator(*m_path)) m_path++; + if(*m_path == 0) return true; + } + return parse_number(); + } + + + + //------------------------------------------------------------------------ + double path_tokenizer::next(char cmd) + { + if(!next()) throw exception("parse_path: Unexpected end of path"); + if(last_command() != cmd) + { + char buf[100]; + sprintf(buf, "parse_path: Command %c: bad or missing parameters", cmd); + throw exception(buf); + } + return last_number(); + } + + + //------------------------------------------------------------------------ + bool path_tokenizer::parse_number() + { + char buf[256]; // Should be enough for any number + char* buf_ptr = buf; + + // Copy all sign characters + while(buf_ptr < buf+255 && *m_path == '-' || *m_path == '+') + { + *buf_ptr++ = *m_path++; + } + + // Copy all numeric characters + while(buf_ptr < buf+255 && is_numeric(*m_path)) + { + *buf_ptr++ = *m_path++; + } + *buf_ptr = 0; + m_last_number = atof(buf); + return true; + } + + +} //namespace svg +} //namespace agg + + + + diff --git a/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_path_tokenizer.h b/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_path_tokenizer.h new file mode 100755 index 0000000..591ec0e --- /dev/null +++ b/jni/desmume/src/android/agg/examples/svg_viewer/agg_svg_path_tokenizer.h @@ -0,0 +1,114 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.3 +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// SVG path tokenizer. +// +//---------------------------------------------------------------------------- +#ifndef AGG_SVG_PATH_TOKENIZER_INCLUDED +#define AGG_SVG_PATH_TOKENIZER_INCLUDED + +#include "agg_svg_exception.h" + +namespace agg +{ +namespace svg +{ + // SVG path tokenizer. + // Example: + // + // agg::svg::path_tokenizer tok; + // + // tok.set_str("M-122.304 84.285L-122.304 84.285 122.203 86.179 "); + // while(tok.next()) + // { + // printf("command='%c' number=%f\n", + // tok.last_command(), + // tok.last_number()); + // } + // + // The tokenizer does all the routine job of parsing the SVG paths. + // It doesn't recognize any graphical primitives, it even doesn't know + // anything about pairs of coordinates (X,Y). The purpose of this class + // is to tokenize the numeric values and commands. SVG paths can + // have single numeric values for Horizontal or Vertical line_to commands + // as well as more than two coordinates (4 or 6) for Bezier curves + // depending on the semantics of the command. + // The behaviour is as follows: + // + // Each call to next() returns true if there's new command or new numeric + // value or false when the path ends. How to interpret the result + // depends on the sematics of the command. For example, command "C" + // (cubic Bezier curve) implies 6 floating point numbers preceded by this + // command. If the command assumes no arguments (like z or Z) the + // the last_number() values won't change, that is, last_number() always + // returns the last recognized numeric value, so does last_command(). + //=============================================================== + class path_tokenizer + { + public: + path_tokenizer(); + + void set_path_str(const char* str); + bool next(); + + double next(char cmd); + + char last_command() const { return m_last_command; } + double last_number() const { return m_last_number; } + + + private: + static void init_char_mask(char* mask, const char* char_set); + + bool contains(const char* mask, unsigned c) const + { + return (mask[(c >> 3) & (256/8-1)] & (1 << (c & 7))) != 0; + } + + bool is_command(unsigned c) const + { + return contains(m_commands_mask, c); + } + + bool is_numeric(unsigned c) const + { + return contains(m_numeric_mask, c); + } + + bool is_separator(unsigned c) const + { + return contains(m_separators_mask, c); + } + + bool parse_number(); + + char m_separators_mask[256/8]; + char m_commands_mask[256/8]; + char m_numeric_mask[256/8]; + + const char* m_path; + double m_last_number; + char m_last_command; + + static const char s_commands[]; + static const char s_numeric[]; + static const char s_separators[]; + }; + +} //namespace svg +} //namespace agg + + +#endif diff --git a/jni/desmume/src/android/agg/examples/svg_viewer/svg_test.cpp b/jni/desmume/src/android/agg/examples/svg_viewer/svg_test.cpp new file mode 100755 index 0000000..b28e13a --- /dev/null +++ b/jni/desmume/src/android/agg/examples/svg_viewer/svg_test.cpp @@ -0,0 +1,261 @@ +#include <stdio.h> +#include <stdlib.h> +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_pixfmt_rgba.h" +#include "platform/agg_platform_support.h" +#include "ctrl/agg_slider_ctrl.h" +#include "agg_svg_parser.h" + +//#include "agg_gamma_lut.h" + +enum { flip_y = false }; + + +class the_application : public agg::platform_support +{ + agg::svg::path_renderer m_path; + + agg::slider_ctrl<agg::rgba8> m_expand; + agg::slider_ctrl<agg::rgba8> m_gamma; + agg::slider_ctrl<agg::rgba8> m_scale; + agg::slider_ctrl<agg::rgba8> m_rotate; + + double m_min_x; + double m_min_y; + double m_max_x; + double m_max_y; + + double m_x; + double m_y; + double m_dx; + double m_dy; + bool m_drag_flag; + +public: + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_path(), + m_expand(5, 5, 256-5, 11, !flip_y), + m_gamma (5, 5+15, 256-5, 11+15, !flip_y), + m_scale (256+5, 5, 512-5, 11, !flip_y), + m_rotate(256+5, 5+15, 512-5, 11+15, !flip_y), + m_min_x(0.0), + m_min_y(0.0), + m_max_x(0.0), + m_max_y(0.0), + m_x(0.0), + m_y(0.0), + m_dx(0.0), + m_dy(0.0), + m_drag_flag(false) + { + add_ctrl(m_expand); + add_ctrl(m_gamma); + add_ctrl(m_scale); + add_ctrl(m_rotate); + + m_expand.label("Expand=%3.2f"); + m_expand.range(-1, 1.2); + m_expand.value(0.0); + + m_gamma.label("Gamma=%3.2f"); + m_gamma.range(0.0, 3.0); + m_gamma.value(1.0); + + m_scale.label("Scale=%3.2f"); + m_scale.range(0.2, 10.0); + m_scale.value(1.0); + + m_rotate.label("Rotate=%3.2f"); + m_rotate.range(-180.0, 180.0); + m_rotate.value(0.0); + } + + void parse_svg(const char* fname) + { + agg::svg::parser p(m_path); + p.parse(fname); + m_path.arrange_orientations(); + m_path.bounding_rect(&m_min_x, &m_min_y, &m_max_x, &m_max_y); + caption(p.title()); + } + + virtual void on_resize(int cx, int cy) + { + } + + virtual void on_draw() + { + typedef agg::pixfmt_bgra32 pixfmt; + typedef agg::renderer_base<pixfmt> renderer_base; + typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_solid; + + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + renderer_solid ren(rb); + + rb.clear(agg::rgba(1,1,1)); + + agg::rasterizer_scanline_aa<> ras; + agg::scanline_p8 sl; + agg::trans_affine mtx; + + ras.gamma(agg::gamma_power(m_gamma.value())); + mtx *= agg::trans_affine_translation((m_min_x + m_max_x) * -0.5, (m_min_y + m_max_y) * -0.5); + mtx *= agg::trans_affine_scaling(m_scale.value()); + mtx *= agg::trans_affine_rotation(agg::deg2rad(m_rotate.value())); + mtx *= agg::trans_affine_translation((m_min_x + m_max_x) * 0.5 + m_x, (m_min_y + m_max_y) * 0.5 + m_y + 30); + + m_path.expand(m_expand.value()); + start_timer(); + m_path.render(ras, sl, ren, mtx, rb.clip_box(), 1.0); + double tm = elapsed_time(); + unsigned vertex_count = m_path.vertex_count(); + + ras.gamma(agg::gamma_none()); + agg::render_ctrl(ras, sl, rb, m_expand); + agg::render_ctrl(ras, sl, rb, m_gamma); + agg::render_ctrl(ras, sl, rb, m_scale); + agg::render_ctrl(ras, sl, rb, m_rotate); + + + char buf[128]; + agg::gsv_text t; + t.size(10.0); + t.flip(true); + + agg::conv_stroke<agg::gsv_text> pt(t); + pt.width(1.5); + + sprintf(buf, "Vertices=%d Time=%.3f ms", vertex_count, tm); + + t.start_point(10.0, 40.0); + t.text(buf); + + ras.add_path(pt); + ren.color(agg::rgba(0,0,0)); + agg::render_scanlines(ras, sl, ren); + + + //agg::gamma_lut<> gl(m_gamma.value()); + //unsigned x, y; + //unsigned w = unsigned(width()); + //unsigned h = unsigned(height()); + //for(y = 0; y < h; y++) + //{ + // for(x = 0; x < w; x++) + // { + // agg::rgba8 c = rb.pixel(x, y); + // c.r = gl.inv(c.r); + // c.g = gl.inv(c.g); + // c.b = gl.inv(c.b); + // rb.copy_pixel(x, y, c); + // } + //} + } + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + m_dx = x - m_x; + m_dy = y - m_y; + m_drag_flag = true; + } + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags == 0) + { + m_drag_flag = false; + } + + if(m_drag_flag) + { + m_x = x - m_dx; + m_y = y - m_dy; + force_redraw(); + } + } + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + m_drag_flag = false; + } + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + if(key == ' ') + { + + agg::trans_affine mtx; + mtx *= agg::trans_affine_translation((m_min_x + m_max_x) * -0.5, (m_min_y + m_max_y) * -0.5); + mtx *= agg::trans_affine_scaling(m_scale.value()); + mtx *= agg::trans_affine_rotation(agg::deg2rad(m_rotate.value())); + mtx *= agg::trans_affine_translation((m_min_x + m_max_x) * 0.5, (m_min_y + m_max_y) * 0.5); + mtx *= agg::trans_affine_translation(m_x, m_y); + + double m[6]; + mtx.store_to(m); + + char buf[128]; + sprintf(buf, "%3.3f, %3.3f, %3.3f, %3.3f, %3.3f, %3.3f", + m[0], m[1], m[2], m[3], m[4], m[5]); + + message(buf); + FILE* fd = fopen(full_file_name("transform.txt"), "a"); + fprintf(fd, "%s\n", buf); + fclose(fd); + } + } + + + +}; + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgra32, flip_y); + + const char* fname = "tiger.svg"; + if(argc <= 1) + { + FILE* fd = fopen(app.full_file_name(fname), "r"); + if(fd == 0) + { + app.message("Usage: svg_test <svg_file>\n" + "Download http://antigrain.com/svg/tiger.svg"); + return 1; + } + fclose(fd); + } + else + { + fname = argv[1]; + } + + try + { + app.parse_svg(app.full_file_name(fname)); + } + catch(agg::svg::exception& e) + { + app.message(e.msg()); + return 1; + } + + if(app.init(512, 600, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + + diff --git a/jni/desmume/src/android/agg/examples/trans_curve1.cpp b/jni/desmume/src/android/agg/examples/trans_curve1.cpp new file mode 100755 index 0000000..e43c1e1 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/trans_curve1.cpp @@ -0,0 +1,325 @@ +#include <stdlib.h> +#include <ctype.h> +#include <stdio.h> +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_conv_bspline.h" +#include "agg_conv_segmentator.h" +#include "agg_font_win32_tt.h" +#include "agg_trans_single_path.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "ctrl/agg_slider_ctrl.h" +#include "platform/agg_platform_support.h" +#include "interactive_polygon.h" + +#define AGG_BGR24 +//#define AGG_RGB24 +//#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + +enum flip_y_e { flip_y = true }; + + + + +static char text[] = +"Anti-Grain Geometry is designed as a set of loosely coupled " +"algorithms and class templates united with a common idea, " +"so that all the components can be easily combined. Also, " +"the template based design allows you to replace any part of " +"the library without the necessity to modify a single byte in " +"the existing code. "; + + + + +class the_application : public agg::platform_support +{ +public: + typedef agg::renderer_base<pixfmt> renderer_base; + typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_solid; + typedef agg::scanline_p8 scanline_type; + typedef agg::font_engine_win32_tt_int16 font_engine_type; + typedef agg::font_cache_manager<font_engine_type> font_manager_type; + + font_engine_type m_feng; + font_manager_type m_fman; + agg::interactive_polygon m_poly; + agg::slider_ctrl<agg::rgba8> m_num_points; + agg::cbox_ctrl<agg::rgba8> m_close; + agg::cbox_ctrl<agg::rgba8> m_preserve_x_scale; + agg::cbox_ctrl<agg::rgba8> m_fixed_len; + agg::cbox_ctrl<agg::rgba8> m_animate; + double m_dx[6]; + double m_dy[6]; + bool m_prev_animate; + + the_application(HDC dc, agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_feng(dc), + m_fman(m_feng), + m_poly(6, 5.0), + m_num_points (5.0, 5.0, 340.0, 12.0, !flip_y), + m_close (350, 5.0, "Close", !flip_y), + m_preserve_x_scale(460, 5.0, "Preserve X scale", !flip_y), + m_fixed_len (350, 25.0, "Fixed Length", !flip_y), + m_animate (460, 25.0, "Animate", !flip_y), + m_prev_animate(false) + { + add_ctrl(m_close); + add_ctrl(m_preserve_x_scale); + add_ctrl(m_fixed_len); + add_ctrl(m_animate); + m_preserve_x_scale.status(true); + m_fixed_len.status(true); + m_num_points.range(10.0, 400.0); + m_num_points.value(200.0); + m_num_points.label("Number of intermediate Points = %.3f"); + add_ctrl(m_num_points); + } + + + virtual void on_init() + { + m_poly.xn(0) = 50; + m_poly.yn(0) = 50; + m_poly.xn(1) = 150 + 20; + m_poly.yn(1) = 150 - 20; + m_poly.xn(2) = 250 - 20; + m_poly.yn(2) = 250 + 20; + m_poly.xn(3) = 350 + 20; + m_poly.yn(3) = 350 - 20; + m_poly.xn(4) = 450 - 20; + m_poly.yn(4) = 450 + 20; + m_poly.xn(5) = 550; + m_poly.yn(5) = 550; + } + + + + + virtual void on_draw() + { + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + renderer_solid r(rb); + rb.clear(agg::rgba(1, 1, 1)); + + scanline_type sl; + agg::rasterizer_scanline_aa<> ras; + + m_poly.close(m_close.status()); + agg::simple_polygon_vertex_source path(m_poly.polygon(), + m_poly.num_points(), + false, + m_close.status()); + + typedef agg::conv_bspline<agg::simple_polygon_vertex_source> conv_bspline_type; + conv_bspline_type bspline(path); + bspline.interpolation_step(1.0 / m_num_points.value()); + + agg::trans_single_path tcurve; + tcurve.add_path(bspline); + tcurve.preserve_x_scale(m_preserve_x_scale.status()); + if(m_fixed_len.status()) tcurve.base_length(1120); + + typedef agg::conv_curve<font_manager_type::path_adaptor_type> conv_font_curve_type; + typedef agg::conv_segmentator<conv_font_curve_type> conv_font_segm_type; + typedef agg::conv_transform<conv_font_segm_type, agg::trans_single_path> conv_font_trans_type; + conv_font_curve_type fcurves(m_fman.path_adaptor()); + + conv_font_segm_type fsegm(fcurves); + conv_font_trans_type ftrans(fsegm, tcurve); + fsegm.approximation_scale(3.0); + fcurves.approximation_scale(2.0); + + m_feng.height(40.0); + //m_feng.italic(true); + + if(m_feng.create_font("Times New Roman", agg::glyph_ren_outline)) + { + double x = 0.0; + double y = 3.0; + const char* p = text; + + while(*p) + { + const agg::glyph_cache* glyph = m_fman.glyph(*p); + if(glyph) + { + if(x > tcurve.total_length()) break; + + m_fman.add_kerning(&x, &y); + m_fman.init_embedded_adaptors(glyph, x, y); + + if(glyph->data_type == agg::glyph_data_outline) + { + ras.reset(); + ras.add_path(ftrans); + r.color(agg::rgba8(0, 0, 0)); + agg::render_scanlines(ras, sl, r); + } + + // increment pen position + x += glyph->advance_x; + y += glyph->advance_y; + } + ++p; + } + + } + + + + typedef agg::conv_stroke<conv_bspline_type> conv_stroke_type; + conv_stroke_type stroke(bspline); + + stroke.width(2.0); + + r.color(agg::rgba8(170, 50, 20, 100)); + ras.add_path(stroke); + agg::render_scanlines(ras, sl, r); + + //-------------------------- + // Render the "poly" tool and controls + r.color(agg::rgba(0, 0.3, 0.5, 0.3)); + ras.add_path(m_poly); + agg::render_scanlines(ras, sl, r); + + agg::render_ctrl(ras, sl, rb, m_close); + agg::render_ctrl(ras, sl, rb, m_preserve_x_scale); + agg::render_ctrl(ras, sl, rb, m_fixed_len); + agg::render_ctrl(ras, sl, rb, m_animate); + agg::render_ctrl(ras, sl, rb, m_num_points); + //-------------------------- + + } + + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_poly.on_mouse_button_down(x, y)) + { + force_redraw(); + } + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_poly.on_mouse_move(x, y)) + { + force_redraw(); + } + } + if((flags & agg::mouse_left) == 0) + { + on_mouse_button_up(x, y, flags); + } + } + + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + if(m_poly.on_mouse_button_up(x, y)) + { + force_redraw(); + } + } + + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + } + + + virtual void on_ctrl_change() + { + if(m_animate.status() != m_prev_animate) + { + if(m_animate.status()) + { + on_init(); + int i; + for(i = 0; i < 6; i++) + { + m_dx[i] = ((rand() % 1000) - 500) * 0.01; + m_dy[i] = ((rand() % 1000) - 500) * 0.01; + } + wait_mode(false); + } + else + { + wait_mode(true); + } + m_prev_animate = m_animate.status(); + } + } + + + void move_point(double& x, double& y, double& dx, double& dy) + { + if(x < 0.0) { x = 0.0; dx = -dx; } + if(x > width()) { x = width(); dx = -dx; } + if(y < 0.0) { y = 0.0; dy = -dy; } + if(y > height()) { y = height(); dy = -dy; } + x += dx; + y += dy; + } + + + + virtual void on_idle() + { + int i; + for(i = 0; i < 6; i++) + { + move_point(m_poly.xn(i), m_poly.yn(i), m_dx[i], m_dy[i]); + } + force_redraw(); + } + + +}; + + + + + + +int agg_main(int argc, char* argv[]) +{ + HDC dc = ::GetDC(0); + the_application app(dc, pix_format, flip_y); + app.caption("AGG Example. Non-linear \"Along-A-Curve\" Transformer"); + + if(app.init(600, 600, agg::window_resize)) + { + return app.run(); + } + ::ReleaseDC(0, dc); + return 1; +} + + + + + + + + + + diff --git a/jni/desmume/src/android/agg/examples/trans_curve1_ft.cpp b/jni/desmume/src/android/agg/examples/trans_curve1_ft.cpp new file mode 100755 index 0000000..0283dd5 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/trans_curve1_ft.cpp @@ -0,0 +1,327 @@ +#include <stdlib.h> +#include <ctype.h> +#include <stdio.h> +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_conv_bspline.h" +#include "agg_conv_segmentator.h" +#include "agg_font_freetype.h" +#include "agg_trans_single_path.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "ctrl/agg_slider_ctrl.h" +#include "platform/agg_platform_support.h" +#include "interactive_polygon.h" + +#define AGG_BGR24 +//#define AGG_RGB24 +//#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + +enum flip_y_e { flip_y = true }; + + + + +static char text[] = +"Anti-Grain Geometry is designed as a set of loosely coupled " +"algorithms and class templates united with a common idea, " +"so that all the components can be easily combined. Also, " +"the template based design allows you to replace any part of " +"the library without the necessity to modify a single byte in " +"the existing code. "; + + + + +class the_application : public agg::platform_support +{ +public: + typedef agg::renderer_base<pixfmt> renderer_base; + typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_solid; + typedef agg::scanline_p8 scanline_type; + typedef agg::font_engine_freetype_int16 font_engine_type; + typedef agg::font_cache_manager<font_engine_type> font_manager_type; + + font_engine_type m_feng; + font_manager_type m_fman; + agg::interactive_polygon m_poly; + agg::slider_ctrl<agg::rgba8> m_num_points; + agg::cbox_ctrl<agg::rgba8> m_close; + agg::cbox_ctrl<agg::rgba8> m_preserve_x_scale; + agg::cbox_ctrl<agg::rgba8> m_fixed_len; + agg::cbox_ctrl<agg::rgba8> m_animate; + double m_dx[6]; + double m_dy[6]; + bool m_prev_animate; + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_feng(), + m_fman(m_feng), + m_poly(6, 5.0), + m_num_points (5.0, 5.0, 340.0, 12.0, !flip_y), + m_close (350, 5.0, "Close", !flip_y), + m_preserve_x_scale(460, 5.0, "Preserve X scale", !flip_y), + m_fixed_len (350, 25.0, "Fixed Length", !flip_y), + m_animate (460, 25.0, "Animate", !flip_y), + m_prev_animate(false) + { + add_ctrl(m_close); + add_ctrl(m_preserve_x_scale); + add_ctrl(m_fixed_len); + add_ctrl(m_animate); + m_preserve_x_scale.status(true); + m_fixed_len.status(true); + m_num_points.range(10.0, 400.0); + m_num_points.value(200.0); + m_num_points.label("Number of intermediate Points = %.3f"); + add_ctrl(m_num_points); + } + + + virtual void on_init() + { + m_poly.xn(0) = 50; + m_poly.yn(0) = 50; + m_poly.xn(1) = 150 + 20; + m_poly.yn(1) = 150 - 20; + m_poly.xn(2) = 250 - 20; + m_poly.yn(2) = 250 + 20; + m_poly.xn(3) = 350 + 20; + m_poly.yn(3) = 350 - 20; + m_poly.xn(4) = 450 - 20; + m_poly.yn(4) = 450 + 20; + m_poly.xn(5) = 550; + m_poly.yn(5) = 550; + } + + + + + virtual void on_draw() + { + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + renderer_solid r(rb); + rb.clear(agg::rgba(1, 1, 1)); + + scanline_type sl; + agg::rasterizer_scanline_aa<> ras; + + m_poly.close(m_close.status()); + agg::simple_polygon_vertex_source path(m_poly.polygon(), + m_poly.num_points(), + false, + m_close.status()); + + typedef agg::conv_bspline<agg::simple_polygon_vertex_source> conv_bspline_type; + conv_bspline_type bspline(path); + bspline.interpolation_step(1.0 / m_num_points.value()); + + agg::trans_single_path tcurve; + tcurve.add_path(bspline); + tcurve.preserve_x_scale(m_preserve_x_scale.status()); + if(m_fixed_len.status()) tcurve.base_length(1120); + + typedef agg::conv_curve<font_manager_type::path_adaptor_type> conv_font_curve_type; + typedef agg::conv_segmentator<conv_font_curve_type> conv_font_segm_type; + typedef agg::conv_transform<conv_font_segm_type, agg::trans_single_path> conv_font_trans_type; + conv_font_curve_type fcurves(m_fman.path_adaptor()); + + conv_font_segm_type fsegm(fcurves); + conv_font_trans_type ftrans(fsegm, tcurve); + fsegm.approximation_scale(3.0); + fcurves.approximation_scale(2.0); + + if(m_feng.load_font(full_file_name("timesi.ttf"), 0, agg::glyph_ren_outline)) + { + double x = 0.0; + double y = 3.0; + const char* p = text; + + m_feng.hinting(false); + m_feng.height(40); + + while(*p) + { + const agg::glyph_cache* glyph = m_fman.glyph(*p); + if(glyph) + { + if(x > tcurve.total_length()) break; + + m_fman.add_kerning(&x, &y); + m_fman.init_embedded_adaptors(glyph, x, y); + + if(glyph->data_type == agg::glyph_data_outline) + { + ras.reset(); + ras.add_path(ftrans); + r.color(agg::rgba8(0, 0, 0)); + agg::render_scanlines(ras, sl, r); + } + + // increment pen position + x += glyph->advance_x; + y += glyph->advance_y; + } + ++p; + } + } + else + { + message("Please copy file timesi.ttf to the current directory\n" + "or download it from http://www.antigrain.com/timesi.zip"); + } + + + + typedef agg::conv_stroke<conv_bspline_type> conv_stroke_type; + conv_stroke_type stroke(bspline); + + stroke.width(2.0); + + r.color(agg::rgba8(170, 50, 20, 100)); + ras.add_path(stroke); + agg::render_scanlines(ras, sl, r); + + //-------------------------- + // Render the "poly" tool and controls + r.color(agg::rgba(0, 0.3, 0.5, 0.3)); + ras.add_path(m_poly); + agg::render_scanlines(ras, sl, r); + + agg::render_ctrl(ras, sl, rb, m_close); + agg::render_ctrl(ras, sl, rb, m_preserve_x_scale); + agg::render_ctrl(ras, sl, rb, m_fixed_len); + agg::render_ctrl(ras, sl, rb, m_animate); + agg::render_ctrl(ras, sl, rb, m_num_points); + //-------------------------- + + } + + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_poly.on_mouse_button_down(x, y)) + { + force_redraw(); + } + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_poly.on_mouse_move(x, y)) + { + force_redraw(); + } + } + if((flags & agg::mouse_left) == 0) + { + on_mouse_button_up(x, y, flags); + } + } + + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + if(m_poly.on_mouse_button_up(x, y)) + { + force_redraw(); + } + } + + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + } + + + virtual void on_ctrl_change() + { + if(m_animate.status() != m_prev_animate) + { + if(m_animate.status()) + { + on_init(); + int i; + for(i = 0; i < 6; i++) + { + m_dx[i] = ((rand() % 1000) - 500) * 0.01; + m_dy[i] = ((rand() % 1000) - 500) * 0.01; + } + wait_mode(false); + } + else + { + wait_mode(true); + } + m_prev_animate = m_animate.status(); + } + } + + + void move_point(double& x, double& y, double& dx, double& dy) + { + if(x < 0.0) { x = 0.0; dx = -dx; } + if(x > width()) { x = width(); dx = -dx; } + if(y < 0.0) { y = 0.0; dy = -dy; } + if(y > height()) { y = height(); dy = -dy; } + x += dx; + y += dy; + } + + + + virtual void on_idle() + { + int i; + for(i = 0; i < 6; i++) + { + move_point(m_poly.xn(i), m_poly.yn(i), m_dx[i], m_dy[i]); + } + force_redraw(); + } + + +}; + + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Non-linear \"Along-A-Curve\" Transformer"); + + if(app.init(600, 600, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + + + + + + + + + diff --git a/jni/desmume/src/android/agg/examples/trans_curve2.cpp b/jni/desmume/src/android/agg/examples/trans_curve2.cpp new file mode 100755 index 0000000..f8281b4 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/trans_curve2.cpp @@ -0,0 +1,392 @@ +#include <stdlib.h> +#include <ctype.h> +#include <stdio.h> +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_conv_bspline.h" +#include "agg_conv_segmentator.h" +#include "agg_font_win32_tt.h" +#include "agg_trans_double_path.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "ctrl/agg_slider_ctrl.h" +#include "platform/agg_platform_support.h" +#include "interactive_polygon.h" + +#define AGG_BGR24 +//#define AGG_RGB24 +//#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + +enum flip_y_e { flip_y = true }; + + + + +static char text[] = +"Anti-Grain Geometry is designed as a set of loosely coupled " +"algorithms and class templates united with a common idea, " +"so that all the components can be easily combined. Also, " +"the template based design allows you to replace any part of " +"the library without the necessity to modify a single byte in " +"the existing code. "; + + + + +class the_application : public agg::platform_support +{ +public: + typedef agg::renderer_base<pixfmt> renderer_base; + typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_solid; + typedef agg::scanline_p8 scanline_type; + typedef agg::font_engine_win32_tt_int16 font_engine_type; + typedef agg::font_cache_manager<font_engine_type> font_manager_type; + + font_engine_type m_feng; + font_manager_type m_fman; + agg::interactive_polygon m_poly1; + agg::interactive_polygon m_poly2; + agg::slider_ctrl<agg::rgba8> m_num_points; + agg::cbox_ctrl<agg::rgba8> m_fixed_len; + agg::cbox_ctrl<agg::rgba8> m_preserve_x_scale; + agg::cbox_ctrl<agg::rgba8> m_animate; + double m_dx1[6]; + double m_dy1[6]; + double m_dx2[6]; + double m_dy2[6]; + bool m_prev_animate; + + the_application(HDC dc, agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_feng(dc), + m_fman(m_feng), + m_poly1(6, 5.0), + m_poly2(6, 5.0), + m_num_points (5.0, 5.0, 340.0, 12.0, !flip_y), + m_fixed_len (350, 5.0, "Fixed Length", !flip_y), + m_preserve_x_scale(465, 5.0, "Preserve X scale", !flip_y), + m_animate (350, 25.0, "Animate", !flip_y), + m_prev_animate(false) + { + add_ctrl(m_fixed_len); + add_ctrl(m_preserve_x_scale); + add_ctrl(m_animate); + m_fixed_len.status(true); + m_preserve_x_scale.status(true); + m_num_points.range(10.0, 400.0); + m_num_points.value(200.0); + m_num_points.label("Number of intermediate Points = %.3f"); + add_ctrl(m_num_points); + + m_poly1.close(false); + m_poly2.close(false); + } + + + virtual void on_init() + { + m_poly1.xn(0) = 10 + 50; + m_poly1.yn(0) = -10 + 50; + m_poly1.xn(1) = 10 + 150 + 20; + m_poly1.yn(1) = -10 + 150 - 20; + m_poly1.xn(2) = 10 + 250 - 20; + m_poly1.yn(2) = -10 + 250 + 20; + m_poly1.xn(3) = 10 + 350 + 20; + m_poly1.yn(3) = -10 + 350 - 20; + m_poly1.xn(4) = 10 + 450 - 20; + m_poly1.yn(4) = -10 + 450 + 20; + m_poly1.xn(5) = 10 + 550; + m_poly1.yn(5) = -10 + 550; + + m_poly2.xn(0) = -10 + 50; + m_poly2.yn(0) = 10 + 50; + m_poly2.xn(1) = -10 + 150 + 20; + m_poly2.yn(1) = 10 + 150 - 20; + m_poly2.xn(2) = -10 + 250 - 20; + m_poly2.yn(2) = 10 + 250 + 20; + m_poly2.xn(3) = -10 + 350 + 20; + m_poly2.yn(3) = 10 + 350 - 20; + m_poly2.xn(4) = -10 + 450 - 20; + m_poly2.yn(4) = 10 + 450 + 20; + m_poly2.xn(5) = -10 + 550; + m_poly2.yn(5) = 10 + 550; + } + + + + + virtual void on_draw() + { + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + renderer_solid r(rb); + rb.clear(agg::rgba(1, 1, 1)); + + scanline_type sl; + agg::rasterizer_scanline_aa<> ras; + + agg::simple_polygon_vertex_source path1(m_poly1.polygon(), + m_poly1.num_points(), + false, + false); + + agg::simple_polygon_vertex_source path2(m_poly2.polygon(), + m_poly2.num_points(), + false, + false); + + + typedef agg::conv_bspline<agg::simple_polygon_vertex_source> conv_bspline_type; + conv_bspline_type bspline1(path1); + conv_bspline_type bspline2(path2); + bspline1.interpolation_step(1.0 / m_num_points.value()); + bspline2.interpolation_step(1.0 / m_num_points.value()); + + + typedef agg::conv_curve<font_manager_type::path_adaptor_type> conv_font_curve_type; + typedef agg::conv_segmentator<conv_font_curve_type> conv_font_segm_type; + typedef agg::conv_transform<conv_font_segm_type, agg::trans_double_path> conv_font_trans_type; + + agg::trans_double_path tcurve; + conv_font_curve_type fcurves(m_fman.path_adaptor()); + conv_font_segm_type fsegm(fcurves); + conv_font_trans_type ftrans(fsegm, tcurve); + + tcurve.preserve_x_scale(m_preserve_x_scale.status()); + if(m_fixed_len.status()) tcurve.base_length(1140.0); + tcurve.base_height(30.0); + + tcurve.add_paths(bspline1, bspline2); + fsegm.approximation_scale(3.0); + fcurves.approximation_scale(5.0); + + + + m_feng.height(40.0); + m_feng.hinting(false); + m_feng.italic(true); + + if(m_feng.create_font("Times New Roman", agg::glyph_ren_outline)) + { + double x = 0.0; + double y = 3.0; + const char* p = text; + + while(*p) + { + const agg::glyph_cache* glyph = m_fman.glyph(*p); + if(glyph) + { + if(x > tcurve.total_length1()) break; + + m_fman.add_kerning(&x, &y); + m_fman.init_embedded_adaptors(glyph, x, y); + + if(glyph->data_type == agg::glyph_data_outline) + { + ras.reset(); + ras.add_path(ftrans); + r.color(agg::rgba8(0, 0, 0)); + agg::render_scanlines(ras, sl, r); + } + + // increment pen position + x += glyph->advance_x; + y += glyph->advance_y; + } + ++p; + } + + } + + + + typedef agg::conv_stroke<conv_bspline_type> conv_stroke_type; + conv_stroke_type stroke1(bspline1); + conv_stroke_type stroke2(bspline2); + + stroke1.width(2.0); + stroke2.width(2.0); + + r.color(agg::rgba8(170, 50, 20, 100)); + ras.add_path(stroke1); + agg::render_scanlines(ras, sl, r); + + ras.add_path(stroke2); + agg::render_scanlines(ras, sl, r); + + + //-------------------------- + // Render the "poly" tool and controls + r.color(agg::rgba(0, 0.3, 0.5, 0.2)); + ras.add_path(m_poly1); + agg::render_scanlines(ras, sl, r); + + ras.add_path(m_poly2); + agg::render_scanlines(ras, sl, r); + + + agg::render_ctrl(ras, sl, rb, m_fixed_len); + agg::render_ctrl(ras, sl, rb, m_preserve_x_scale); + agg::render_ctrl(ras, sl, rb, m_animate); + agg::render_ctrl(ras, sl, rb, m_num_points); + //-------------------------- + + } + + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_poly1.on_mouse_button_down(x, y)) + { + force_redraw(); + } + if(m_poly2.on_mouse_button_down(x, y)) + { + force_redraw(); + } + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_poly1.on_mouse_move(x, y)) + { + force_redraw(); + } + if(m_poly2.on_mouse_move(x, y)) + { + force_redraw(); + } + } + if((flags & agg::mouse_left) == 0) + { + on_mouse_button_up(x, y, flags); + } + } + + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + if(m_poly1.on_mouse_button_up(x, y)) + { + force_redraw(); + } + if(m_poly2.on_mouse_button_up(x, y)) + { + force_redraw(); + } + } + + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + } + + + virtual void on_ctrl_change() + { + if(m_animate.status() != m_prev_animate) + { + if(m_animate.status()) + { + on_init(); + int i; + for(i = 0; i < 6; i++) + { + m_dx1[i] = ((rand() % 1000) - 500) * 0.01; + m_dy1[i] = ((rand() % 1000) - 500) * 0.01; + m_dx2[i] = ((rand() % 1000) - 500) * 0.01; + m_dy2[i] = ((rand() % 1000) - 500) * 0.01; + } + wait_mode(false); + } + else + { + wait_mode(true); + } + m_prev_animate = m_animate.status(); + } + } + + + void move_point(double& x, double& y, double& dx, double& dy) + { + if(x < 0.0) { x = 0.0; dx = -dx; } + if(x > width()) { x = width(); dx = -dx; } + if(y < 0.0) { y = 0.0; dy = -dy; } + if(y > height()) { y = height(); dy = -dy; } + x += dx; + y += dy; + } + + + void normalize_point(unsigned i) + { + double d = agg::calc_distance(m_poly1.xn(i), m_poly1.yn(i), + m_poly2.xn(i), m_poly2.yn(i)); + // 28.8 is 20 * sqrt(2) + if(d > 28.28) + { + m_poly2.xn(i) = m_poly1.xn(i) + (m_poly2.xn(i) - m_poly1.xn(i)) * 28.28 / d; + m_poly2.yn(i) = m_poly1.yn(i) + (m_poly2.yn(i) - m_poly1.yn(i)) * 28.28 / d; + } + } + + + + virtual void on_idle() + { + int i; + for(i = 0; i < 6; i++) + { + move_point(m_poly1.xn(i), m_poly1.yn(i), m_dx1[i], m_dy1[i]); + move_point(m_poly2.xn(i), m_poly2.yn(i), m_dx2[i], m_dy2[i]); + normalize_point(i); + } + force_redraw(); + } + +}; + + + + + + +int agg_main(int argc, char* argv[]) +{ + HDC dc = ::GetDC(0); + the_application app(dc, pix_format, flip_y); + app.caption("AGG Example. Non-linear \"Along-A-Curve\" Transformer"); + + if(app.init(600, 600, agg::window_resize)) + { + return app.run(); + } + ::ReleaseDC(0, dc); + return 1; +} + + + + + + + + + + diff --git a/jni/desmume/src/android/agg/examples/trans_curve2_ft.cpp b/jni/desmume/src/android/agg/examples/trans_curve2_ft.cpp new file mode 100755 index 0000000..0eb0699 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/trans_curve2_ft.cpp @@ -0,0 +1,391 @@ +#include <stdlib.h> +#include <ctype.h> +#include <stdio.h> +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_conv_bspline.h" +#include "agg_conv_segmentator.h" +#include "agg_font_freetype.h" +#include "agg_trans_double_path.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "ctrl/agg_slider_ctrl.h" +#include "platform/agg_platform_support.h" +#include "interactive_polygon.h" + +#define AGG_BGR24 +//#define AGG_RGB24 +//#define AGG_BGRA32 +//#define AGG_RGBA32 +//#define AGG_ARGB32 +//#define AGG_ABGR32 +//#define AGG_RGB565 +//#define AGG_RGB555 +#include "pixel_formats.h" + +enum flip_y_e { flip_y = true }; + + + + +static char text[] = +"Anti-Grain Geometry is designed as a set of loosely coupled " +"algorithms and class templates united with a common idea, " +"so that all the components can be easily combined. Also, " +"the template based design allows you to replace any part of " +"the library without the necessity to modify a single byte in " +"the existing code. "; + + + + +class the_application : public agg::platform_support +{ +public: + typedef agg::renderer_base<pixfmt> renderer_base; + typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_solid; + typedef agg::scanline_p8 scanline_type; + typedef agg::font_engine_freetype_int16 font_engine_type; + typedef agg::font_cache_manager<font_engine_type> font_manager_type; + + font_engine_type m_feng; + font_manager_type m_fman; + agg::interactive_polygon m_poly1; + agg::interactive_polygon m_poly2; + agg::slider_ctrl<agg::rgba8> m_num_points; + agg::cbox_ctrl<agg::rgba8> m_fixed_len; + agg::cbox_ctrl<agg::rgba8> m_preserve_x_scale; + agg::cbox_ctrl<agg::rgba8> m_animate; + double m_dx1[6]; + double m_dy1[6]; + double m_dx2[6]; + double m_dy2[6]; + bool m_prev_animate; + + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_feng(), + m_fman(m_feng), + m_poly1(6, 5.0), + m_poly2(6, 5.0), + m_num_points (5.0, 5.0, 340.0, 12.0, !flip_y), + m_fixed_len (350, 5.0, "Fixed Length", !flip_y), + m_preserve_x_scale(465, 5.0, "Preserve X scale", !flip_y), + m_animate (350, 25.0, "Animate", !flip_y), + m_prev_animate(false) + { + add_ctrl(m_fixed_len); + add_ctrl(m_preserve_x_scale); + add_ctrl(m_animate); + m_fixed_len.status(true); + m_preserve_x_scale.status(true); + m_num_points.range(10.0, 400.0); + m_num_points.value(200.0); + m_num_points.label("Number of intermediate Points = %.3f"); + add_ctrl(m_num_points); + + m_poly1.close(false); + m_poly2.close(false); + } + + + virtual void on_init() + { + m_poly1.xn(0) = 10 + 50; + m_poly1.yn(0) = -10 + 50; + m_poly1.xn(1) = 10 + 150 + 20; + m_poly1.yn(1) = -10 + 150 - 20; + m_poly1.xn(2) = 10 + 250 - 20; + m_poly1.yn(2) = -10 + 250 + 20; + m_poly1.xn(3) = 10 + 350 + 20; + m_poly1.yn(3) = -10 + 350 - 20; + m_poly1.xn(4) = 10 + 450 - 20; + m_poly1.yn(4) = -10 + 450 + 20; + m_poly1.xn(5) = 10 + 550; + m_poly1.yn(5) = -10 + 550; + + m_poly2.xn(0) = -10 + 50; + m_poly2.yn(0) = 10 + 50; + m_poly2.xn(1) = -10 + 150 + 20; + m_poly2.yn(1) = 10 + 150 - 20; + m_poly2.xn(2) = -10 + 250 - 20; + m_poly2.yn(2) = 10 + 250 + 20; + m_poly2.xn(3) = -10 + 350 + 20; + m_poly2.yn(3) = 10 + 350 - 20; + m_poly2.xn(4) = -10 + 450 - 20; + m_poly2.yn(4) = 10 + 450 + 20; + m_poly2.xn(5) = -10 + 550; + m_poly2.yn(5) = 10 + 550; + } + + + + + virtual void on_draw() + { + pixfmt pixf(rbuf_window()); + renderer_base rb(pixf); + renderer_solid r(rb); + rb.clear(agg::rgba(1, 1, 1)); + + scanline_type sl; + agg::rasterizer_scanline_aa<> ras; + + agg::simple_polygon_vertex_source path1(m_poly1.polygon(), + m_poly1.num_points(), + false, + false); + + agg::simple_polygon_vertex_source path2(m_poly2.polygon(), + m_poly2.num_points(), + false, + false); + + + typedef agg::conv_bspline<agg::simple_polygon_vertex_source> conv_bspline_type; + conv_bspline_type bspline1(path1); + conv_bspline_type bspline2(path2); + bspline1.interpolation_step(1.0 / m_num_points.value()); + bspline2.interpolation_step(1.0 / m_num_points.value()); + + + typedef agg::conv_curve<font_manager_type::path_adaptor_type> conv_font_curve_type; + typedef agg::conv_segmentator<conv_font_curve_type> conv_font_segm_type; + typedef agg::conv_transform<conv_font_segm_type, agg::trans_double_path> conv_font_trans_type; + + agg::trans_double_path tcurve; + conv_font_curve_type fcurves(m_fman.path_adaptor()); + conv_font_segm_type fsegm(fcurves); + conv_font_trans_type ftrans(fsegm, tcurve); + + tcurve.preserve_x_scale(m_preserve_x_scale.status()); + if(m_fixed_len.status()) tcurve.base_length(1140.0); + tcurve.base_height(30.0); + + tcurve.add_paths(bspline1, bspline2); + fsegm.approximation_scale(3.0); + fcurves.approximation_scale(5.0); + + if(m_feng.load_font(full_file_name("timesi.ttf"), 0, agg::glyph_ren_outline)) + { + double x = 0.0; + double y = 3.0; + const char* p = text; + + m_feng.hinting(false); + m_feng.height(40); + + while(*p) + { + const agg::glyph_cache* glyph = m_fman.glyph(*p); + if(glyph) + { + if(x > tcurve.total_length1()) break; + + m_fman.add_kerning(&x, &y); + m_fman.init_embedded_adaptors(glyph, x, y); + + if(glyph->data_type == agg::glyph_data_outline) + { + ras.reset(); + ras.add_path(ftrans); + r.color(agg::rgba8(0, 0, 0)); + agg::render_scanlines(ras, sl, r); + } + + // increment pen position + x += glyph->advance_x; + y += glyph->advance_y; + } + ++p; + } + } + else + { + message("Please copy file timesi.ttf to the current directory\n" + "or download it from http://www.antigrain.com/timesi.zip"); + } + + + + typedef agg::conv_stroke<conv_bspline_type> conv_stroke_type; + conv_stroke_type stroke1(bspline1); + conv_stroke_type stroke2(bspline2); + + stroke1.width(2.0); + stroke2.width(2.0); + + r.color(agg::rgba8(170, 50, 20, 100)); + ras.add_path(stroke1); + agg::render_scanlines(ras, sl, r); + + ras.add_path(stroke2); + agg::render_scanlines(ras, sl, r); + + + //-------------------------- + // Render the "poly" tool and controls + r.color(agg::rgba(0, 0.3, 0.5, 0.2)); + ras.add_path(m_poly1); + agg::render_scanlines(ras, sl, r); + + ras.add_path(m_poly2); + agg::render_scanlines(ras, sl, r); + + + agg::render_ctrl(ras, sl, rb, m_fixed_len); + agg::render_ctrl(ras, sl, rb, m_preserve_x_scale); + agg::render_ctrl(ras, sl, rb, m_animate); + agg::render_ctrl(ras, sl, rb, m_num_points); + //-------------------------- + + } + + + + virtual void on_mouse_button_down(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_poly1.on_mouse_button_down(x, y)) + { + force_redraw(); + } + if(m_poly2.on_mouse_button_down(x, y)) + { + force_redraw(); + } + } + } + + + virtual void on_mouse_move(int x, int y, unsigned flags) + { + if(flags & agg::mouse_left) + { + if(m_poly1.on_mouse_move(x, y)) + { + force_redraw(); + } + if(m_poly2.on_mouse_move(x, y)) + { + force_redraw(); + } + } + if((flags & agg::mouse_left) == 0) + { + on_mouse_button_up(x, y, flags); + } + } + + + virtual void on_mouse_button_up(int x, int y, unsigned flags) + { + if(m_poly1.on_mouse_button_up(x, y)) + { + force_redraw(); + } + if(m_poly2.on_mouse_button_up(x, y)) + { + force_redraw(); + } + } + + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + } + + + virtual void on_ctrl_change() + { + if(m_animate.status() != m_prev_animate) + { + if(m_animate.status()) + { + on_init(); + int i; + for(i = 0; i < 6; i++) + { + m_dx1[i] = ((rand() % 1000) - 500) * 0.01; + m_dy1[i] = ((rand() % 1000) - 500) * 0.01; + m_dx2[i] = ((rand() % 1000) - 500) * 0.01; + m_dy2[i] = ((rand() % 1000) - 500) * 0.01; + } + wait_mode(false); + } + else + { + wait_mode(true); + } + m_prev_animate = m_animate.status(); + } + } + + + void move_point(double& x, double& y, double& dx, double& dy) + { + if(x < 0.0) { x = 0.0; dx = -dx; } + if(x > width()) { x = width(); dx = -dx; } + if(y < 0.0) { y = 0.0; dy = -dy; } + if(y > height()) { y = height(); dy = -dy; } + x += dx; + y += dy; + } + + + void normalize_point(unsigned i) + { + double d = agg::calc_distance(m_poly1.xn(i), m_poly1.yn(i), + m_poly2.xn(i), m_poly2.yn(i)); + // 28.8 is 20 * sqrt(2) + if(d > 28.28) + { + m_poly2.xn(i) = m_poly1.xn(i) + (m_poly2.xn(i) - m_poly1.xn(i)) * 28.28 / d; + m_poly2.yn(i) = m_poly1.yn(i) + (m_poly2.yn(i) - m_poly1.yn(i)) * 28.28 / d; + } + } + + + + virtual void on_idle() + { + int i; + for(i = 0; i < 6; i++) + { + move_point(m_poly1.xn(i), m_poly1.yn(i), m_dx1[i], m_dy1[i]); + move_point(m_poly2.xn(i), m_poly2.yn(i), m_dx2[i], m_dy2[i]); + normalize_point(i); + } + force_redraw(); + } + +}; + + + + + + +int agg_main(int argc, char* argv[]) +{ + the_application app(pix_format, flip_y); + app.caption("AGG Example. Non-linear \"Along-A-Curve\" Transformer"); + + if(app.init(600, 600, agg::window_resize)) + { + return app.run(); + } + return 1; +} + + + + + + + + + + diff --git a/jni/desmume/src/android/agg/examples/trans_polar.cpp b/jni/desmume/src/android/agg/examples/trans_polar.cpp new file mode 100755 index 0000000..2481181 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/trans_polar.cpp @@ -0,0 +1,199 @@ +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_pixfmt_rgb.h" +#include "agg_trans_affine.h" +#include "agg_conv_transform.h" +#include "agg_conv_segmentator.h" +#include "platform/agg_platform_support.h" +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" + + +enum flip_y_e { flip_y = true }; + + +namespace agg +{ + + + template<class ColorT, class Ctrl, class Pipeline> class transformed_control + { + public: + transformed_control(Ctrl& ctrl, Pipeline& pl) : + m_ctrl(ctrl), + m_pipeline(pl) + {} + + unsigned num_paths() { return m_ctrl.num_paths(); } + void rewind(unsigned path_id) { m_pipeline.rewind(path_id); } + unsigned vertex(double* x, double* y) { return m_pipeline.vertex(x, y); } + const ColorT& color(unsigned i) const { return m_ctrl.color(i); } + + private: + Ctrl& m_ctrl; + Pipeline& m_pipeline; + }; + + + + + class trans_polar + { + public: + trans_polar() : + m_base_angle(1.0), + m_base_scale(1.0), + m_base_x(0.0), + m_base_y(0.0), + m_translation_x(0.0), + m_translation_y(0.0), + m_spiral(0.0) + {} + + void base_scale(double v) { m_base_scale = v; } + void full_circle(double v) { m_base_angle = 2.0 * pi / v; } + void base_offset(double dx, double dy) { m_base_x = dx; m_base_y = dy; } + void translation(double dx, double dy) { m_translation_x = dx; m_translation_y = dy;} + void spiral(double v) { m_spiral = v; } + + void transform(double* x, double* y) const + { + double x1 = (*x + m_base_x) * m_base_angle; + double y1 = (*y + m_base_y) * m_base_scale + (*x * m_spiral); + *x = cos(x1) * y1 + m_translation_x; + *y = sin(x1) * y1 + m_translation_y; + } + + private: + double m_base_angle; + double m_base_scale; + double m_base_x; + double m_base_y; + double m_translation_x; + double m_translation_y; + double m_spiral; + }; + + + + + + + + +} + + + + + + + + + + + + + + + +class the_application : public agg::platform_support +{ + agg::slider_ctrl<agg::rgba8> m_slider1; + agg::slider_ctrl<agg::rgba8> m_slider_spiral; + agg::slider_ctrl<agg::rgba8> m_slider_base_y; + +public: + the_application(agg::pix_format_e format, bool flip_y) : + agg::platform_support(format, flip_y), + m_slider1 (10, 10, 600-10, 17, !flip_y), + m_slider_spiral(10, 10+20, 600-10, 17+20, !flip_y), + m_slider_base_y(10, 10+40, 600-10, 17+40, !flip_y) + { + add_ctrl(m_slider1); + m_slider1.range(0.0, 100.0); + m_slider1.num_steps(5); + m_slider1.value(32.0); + m_slider1.label("Some Value=%1.0f"); + + add_ctrl(m_slider_spiral); + m_slider_spiral.label("Spiral=%.3f"); + m_slider_spiral.range(-0.1, 0.1); + m_slider_spiral.value(0.0); + + add_ctrl(m_slider_base_y); + m_slider_base_y.label("Base Y=%.3f"); + m_slider_base_y.range(50.0, 200.0); + m_slider_base_y.value(120.0); + } + + + virtual ~the_application() + { + } + + + virtual void on_init() + { + } + + + virtual void on_draw() + { + typedef agg::renderer_base<agg::pixfmt_bgr24> ren_base; + typedef agg::renderer_scanline_aa_solid<ren_base> renderer; + + agg::pixfmt_bgr24 pixf(rbuf_window()); + ren_base rb(pixf); + renderer ren(rb); + agg::scanline_u8 sl; + + rb.clear(agg::rgba(1,1,1)); + + agg::rasterizer_scanline_aa<> ras; + + agg::render_ctrl(ras, sl, rb, m_slider1); + agg::render_ctrl(ras, sl, rb, m_slider_spiral); + agg::render_ctrl(ras, sl, rb, m_slider_base_y); + + + typedef agg::conv_segmentator<agg::slider_ctrl<agg::rgba8> > conv_segmentator_type; + typedef agg::conv_transform<conv_segmentator_type, agg::trans_polar> conv_transform_type; + + agg::trans_polar trans; + trans.full_circle(-600); + trans.base_scale(-1.0); + trans.base_offset(0.0, m_slider_base_y.value()); + trans.translation(width() / 2.0, height() / 2.0 + 30.0); + trans.spiral(-m_slider_spiral.value()); + + conv_segmentator_type segm(m_slider1); + conv_transform_type pipeline(segm, trans); + + agg::transformed_control<agg::rgba8, + agg::slider_ctrl<agg::rgba8>, + conv_transform_type> ctrl(m_slider1, pipeline); + + + agg::render_ctrl(ras, sl, rb, ctrl); + } + + +}; + + +int agg_main(int argc, char* argv[]) +{ + the_application app(agg::pix_format_bgr24, flip_y); + app.caption("AGG Example. Polar Transformer"); + + if(app.init(600, 400, agg::window_resize)) + { + return app.run(); + } + return 1; +} + diff --git a/jni/desmume/src/android/agg/examples/truetype_test.cpp b/jni/desmume/src/android/agg/examples/truetype_test.cpp new file mode 100755 index 0000000..5462d2d --- /dev/null +++ b/jni/desmume/src/android/agg/examples/truetype_test.cpp @@ -0,0 +1,466 @@ +#include <stdio.h> +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_scanline_u.h" +#include "agg_scanline_bin.h" +#include "agg_renderer_scanline.h" +#include "agg_renderer_primitives.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_conv_curve.h" +#include "agg_conv_contour.h" +#include "agg_pixfmt_rgb.h" +#include "agg_gamma_lut.h" +#include "agg_font_win32_tt.h" +#include "platform/agg_platform_support.h" + +#include "ctrl/agg_slider_ctrl.h" +#include "ctrl/agg_cbox_ctrl.h" +#include "ctrl/agg_rbox_ctrl.h" + + +enum flip_y_e { flip = true }; + +typedef char char_type; + +static char_type text[] = +//"0123456789ABCDEFGHIJKLMNOPRSTUVWXYZabcdefghijklmnoprstuvwxyz " +" Anti-Grain Geometry is designed as a set of loosely coupled " +"algorithms and class templates united with a common idea, " +"so that all the components can be easily combined. Also, " +"the template based design allows you to replace any part of " +"the library without the necessity to modify a single byte in " +"the existing code. " +"AGG is designed keeping in mind extensibility and flexibility. " +"Basically I just wanted to create a toolkit that would allow me " +"(and anyone else) to add new fancy algorithms very easily. " +"AGG does not dictate you any style of its use, you are free to " +"use any part of it. However, AGG is often associated with a tool " +"for rendering images in memory. That is not quite true, but it can " +"be a good starting point in studying. The tutorials describe the " +"use of AGG starting from the low level functionality that deals with " +"frame buffers and pixels. Then you will gradually understand how to " +"abstract different parts of the library and how to use them separately. " +"Remember, the raster picture is often not the only thing you want to " +"obtain, you will probably want to print your graphics with highest " +"possible quality and in this case you can easily combine the \"vectorial\" " +"part of the library with some API like Windows GDI, having a common " +"external interface. If that API can render multi-polygons with non-zero " +"and even-odd filling rules it's all you need to incorporate AGG into " +"your application. For example, Windows API PolyPolygon perfectly fits " +"these needs, except certain advanced things like gradient filling, " +"Gouraud shading, image transformations, and so on. Or, as an alternative, " +"you can use all AGG algorithms producing high resolution pixel images and " +"then to send the result to the printer as a pixel map." +"Below is a typical brief scheme of the AGG rendering pipeline. " +"Please note that any component between the Vertex Source " +"and Screen Output is not mandatory. It all depends on your " +"particular needs. For example, you can use your own rasterizer, " +"based on Windows API. In this case you won't need the AGG rasterizer " +"and renderers. Or, if you need to draw only lines, you can use the " +"AGG outline rasterizer that has certain restrictions but works faster. " +"The number of possibilities is endless. " +"Vertex Source is some object that produces polygons or polylines as " +"a set of consecutive 2D vertices with commands like MoveTo, LineTo. " +"It can be a container or some other object that generates vertices " +"on demand. " +"Coordinate conversion pipeline consists of a number of coordinate " +"converters. It always works with vectorial data (X,Y) represented " +"as floating point numbers (double). For example, it can contain an " +"affine transformer, outline (stroke) generator, some marker " +"generator (like arrowheads/arrowtails), dashed lines generator, " +"and so on. The pipeline can have branches and you also can have " +"any number of different pipelines. You also can write your own " +"converter and include it into the pipeline. " +"Scanline Rasterizer converts vectorial data into a number of " +"horizontal scanlines. The scanlines usually (but not obligatory) " +"carry information about Anti-Aliasing as coverage values. " +"Renderers render scanlines, sorry for the tautology. The simplest " +"example is solid filling. The renderer just adds a color to the " +"scanline and writes the result into the rendering buffer. " +"More complex renderers can produce multi-color result, " +"like gradients, Gouraud shading, image transformations, " +"patterns, and so on. Rendering Buffer is a buffer in memory " +"that will be displayed afterwards. Usually but not obligatory " +"it contains pixels in format that fits your video system. " +"For example, 24 bits B-G-R, 32 bits B-G-R-A, or 15 " +"bits R-G-B-555 for Windows. But in general, there're no " +"restrictions on pixel formats or color space if you write " +"your own low level class that supports that format. " +"Colors in AGG appear only in renderers, that is, when you " +"actually put some data to the rendering buffer. In general, " +"there's no general purpose structure or class like color, " +"instead, AGG always operates with concrete color space. " +"There are plenty of color spaces in the world, like RGB, " +"HSV, CMYK, etc., and all of them have certain restrictions. " +"For example, the RGB color space is just a poor subset of " +"colors that a human eye can recognize. If you look at the full " +"CIE Chromaticity Diagram, you will see that the RGB triangle " +"is just a little part of it. " +"In other words there are plenty of colors in the real world " +"that cannot be reproduced with RGB, CMYK, HSV, etc. Any color " +"space except the one existing in Nature is restrictive. Thus, " +"it was decided not to introduce such an object like color in " +"order not to restrict the possibilities in advance. Instead, " +"there are objects that operate with concrete color spaces. " +"Currently there are agg::rgba and agg::rgba8 that operate " +"with the most popular RGB color space (strictly speaking there's " +"RGB plus Alpha). The RGB color space is used with different " +"pixel formats, like 24-bit RGB or 32-bit RGBA with different " +"order of color components. But the common property of all of " +"them is that they are essentially RGB. Although, AGG doesn't " +"explicitly support any other color spaces, there is at least " +"a potential possibility of adding them. It means that all " +"class and function templates that depend on the color type " +"are parameterized with the ColorT argument. " +"Basically, AGG operates with coordinates of the output device. " +"On your screen there are pixels. But unlike many other libraries " +"and APIs AGG initially supports Subpixel Accuracy. It means " +"that the coordinates are represented as doubles, where fractional " +"values actually take effect. AGG doesn't have an embedded " +"conversion mechanism from world to screen coordinates in order " +"not to restrict your freedom. It's very important where and when " +"you do that conversion, so, different applications can require " +"different approaches. AGG just provides you a transformer of " +"that kind, namely, that can convert your own view port to the " +"device one. And it's your responsibility to include it into " +"the proper place of the pipeline. You can also write your " +"own very simple class that will allow you to operate with " +"millimeters, inches, or any other physical units. " +"Internally, the rasterizers use integer coordinates of the " +"format 24.8 bits, that is, 24 bits for the integer part and 8 " +"bits for the fractional one. In other words, all the internal " +"coordinates are multiplied by 256. If you intend to use AGG in " +"some embedded system that has inefficient floating point " +"processing, you still can use the rasterizers with their " +"integer interfaces. Although, you won't be able to use the " +"floating point coordinate pipelines in this case. "; + + + + +bool text_flip = false; + + +class the_application : public agg::platform_support +{ + typedef agg::gamma_lut<agg::int8u, agg::int16u, 8, 16> gamma_type; + typedef agg::pixfmt_bgr24_gamma<gamma_type> pixfmt_type; + typedef agg::renderer_base<pixfmt_type> base_ren_type; + typedef agg::renderer_scanline_aa_solid<base_ren_type> renderer_solid; + typedef agg::renderer_scanline_bin_solid<base_ren_type> renderer_bin; + typedef agg::font_engine_win32_tt_int32 font_engine_type; + typedef agg::font_cache_manager<font_engine_type> font_manager_type; + + agg::rbox_ctrl<agg::rgba8> m_ren_type; + agg::slider_ctrl<agg::rgba8> m_height; + agg::slider_ctrl<agg::rgba8> m_width; + agg::slider_ctrl<agg::rgba8> m_weight; + agg::slider_ctrl<agg::rgba8> m_gamma; + agg::cbox_ctrl<agg::rgba8> m_hinting; + agg::cbox_ctrl<agg::rgba8> m_kerning; + agg::cbox_ctrl<agg::rgba8> m_performance; + font_engine_type m_feng; + font_manager_type m_fman; + double m_old_height; + gamma_type m_gamma_lut; + + // Pipeline to process the vectors glyph paths (curves + contour) + typedef agg::conv_curve<font_manager_type::path_adaptor_type> conv_curve_type; + typedef agg::conv_contour<conv_curve_type> conv_contour_type; + + conv_curve_type m_curves; + conv_contour_type m_contour; + +public: + the_application(HDC dc, agg::pix_format_e format, bool flip) : + agg::platform_support(format, flip), + m_ren_type (5.0, 5.0, 5.0+150.0, 110.0, !flip), + m_height (160, 10.0, 640-5.0, 18.0, !flip), + m_width (160, 30.0, 640-5.0, 38.0, !flip), + m_weight (160, 50.0, 640-5.0, 58.0, !flip), + m_gamma (260, 70.0, 640-5.0, 78.0, !flip), + m_hinting (160, 65.0, "Hinting", !flip), + m_kerning (160, 80.0, "Kerning", !flip), + m_performance (160, 95.0, "Test Performance", !flip), + m_feng(dc), + m_fman(m_feng), + m_old_height(0.0), + m_curves(m_fman.path_adaptor()), + m_contour(m_curves) + { + m_ren_type.add_item("Native Mono"); + m_ren_type.add_item("Native Gray 8"); + m_ren_type.add_item("Outline"); + m_ren_type.add_item("AGG Mono"); + m_ren_type.add_item("AGG Gray 8"); + m_ren_type.cur_item(1); + add_ctrl(m_ren_type); + m_ren_type.no_transform(); + + m_height.label("Font Height=%.2f"); + m_height.range(8, 32); + m_height.num_steps(32-8); + m_height.value(18); + m_height.text_thickness(1.5); + add_ctrl(m_height); + m_height.no_transform(); + + m_width.label("Font Width=%.2f"); + m_width.range(8, 32); + m_width.num_steps(32-8); + m_width.text_thickness(1.5); + m_width.value(18); + add_ctrl(m_width); + m_width.no_transform(); + + m_weight.label("Font Weight=%.2f"); + m_weight.range(-2, 2); + m_weight.text_thickness(1.5); + add_ctrl(m_weight); + m_weight.no_transform(); + + m_gamma.label("Gamma=%.2f"); + m_gamma.range(0.1, 2.0); + m_gamma.value(1.0); + m_gamma.text_thickness(1.5); + add_ctrl(m_gamma); + m_gamma.no_transform(); + + add_ctrl(m_hinting); + m_hinting.status(true); + m_hinting.no_transform(); + + add_ctrl(m_kerning); + m_kerning.status(true); + m_kerning.no_transform(); + + add_ctrl(m_performance); + m_performance.no_transform(); + +// m_curves.approximation_method(agg::curve_div); +// m_curves.approximation_scale(0.5); +// m_curves.angle_tolerance(0.3); + m_contour.auto_detect_orientation(false); + } + + + template<class Rasterizer, class Scanline, class RenSolid, class RenBin> + unsigned draw_text(Rasterizer& ras, Scanline& sl, + RenSolid& ren_solid, RenBin& ren_bin) + { + agg::glyph_rendering gren = agg::glyph_ren_native_mono; + switch(m_ren_type.cur_item()) + { + case 0: gren = agg::glyph_ren_native_mono; break; + case 1: gren = agg::glyph_ren_native_gray8; break; + case 2: gren = agg::glyph_ren_outline; break; + case 3: gren = agg::glyph_ren_agg_mono; break; + case 4: gren = agg::glyph_ren_agg_gray8; break; + } + + unsigned num_glyphs = 0; + + m_contour.width(-m_weight.value() * m_height.value() * 0.05); + + m_feng.hinting(m_hinting.status()); + m_feng.height(m_height.value()); + + // Font width in Windows is strange. MSDN says, + // "specifies the average width", but there's no clue what + // this "average width" means. It'd be logical to specify + // the width with regard to the font height, like it's done in + // FreeType. That is, width == height should mean the "natural", + // not distorted glyphs. In Windows you have to specify + // the absolute width, which is very stupid and hard to use + // in practice. + //------------------------- + m_feng.width((m_width.value() == m_height.value()) ? 0.0 : m_width.value() / 2.4); + m_feng.italic(true); + m_feng.flip_y(text_flip); + + agg::trans_affine mtx; + //mtx *= agg::trans_affine_skewing(-0.3, 0); + mtx *= agg::trans_affine_rotation(agg::deg2rad(-4.0)); + m_feng.transform(mtx); + + if(m_feng.create_font("Arial", gren)) + { + m_fman.precache(' ', 127); + + double x = 10.0; + double y0 = height() - m_height.value() - 10.0; + double y = y0; + const char_type* p = text; + + while(*p) + { + const agg::glyph_cache* glyph = m_fman.glyph(*p); + if(glyph) + { + if(m_kerning.status()) + { + m_fman.add_kerning(&x, &y); + } + + if(x >= width() - m_height.value()) + { + x = 10.0; + y0 -= m_height.value(); + if(y0 <= 120) break; + y = y0; + } + + m_fman.init_embedded_adaptors(glyph, x, y); + + switch(glyph->data_type) + { + case agg::glyph_data_mono: + ren_bin.color(agg::rgba8(0, 0, 0)); + agg::render_scanlines(m_fman.mono_adaptor(), + m_fman.mono_scanline(), + ren_bin); + break; + + case agg::glyph_data_gray8: + ren_solid.color(agg::rgba8(0, 0, 0)); + agg::render_scanlines(m_fman.gray8_adaptor(), + m_fman.gray8_scanline(), + ren_solid); + break; + + case agg::glyph_data_outline: + ras.reset(); + if(fabs(m_weight.value()) <= 0.01) + { + // For the sake of efficiency skip the + // contour converter if the weight is about zero. + //----------------------- + ras.add_path(m_curves); + } + else + { + ras.add_path(m_contour); + } + ren_solid.color(agg::rgba8(0, 0, 0)); + agg::render_scanlines(ras, sl, ren_solid); + break; + } + + // increment pen position + x += glyph->advance_x; + y += glyph->advance_y; + ++num_glyphs; + } + ++p; + } + } + return num_glyphs; + } + + + virtual void on_draw() + { + pixfmt_type pf(rbuf_window(), m_gamma_lut); + base_ren_type ren_base(pf); + renderer_solid ren_solid(ren_base); + renderer_bin ren_bin(ren_base); + ren_base.clear(agg::rgba(1,1,1)); + + agg::scanline_u8 sl; + agg::rasterizer_scanline_aa<> ras; + + if(m_height.value() != m_old_height) + { + m_width.value(m_old_height = m_height.value()); + } + + if(m_ren_type.cur_item() == 3) + { + // When rendering in mono format, + // Set threshold gamma = 0.5 + //------------------- + m_feng.gamma(agg::gamma_threshold(m_gamma.value() / 2.0)); + } + else + { + m_feng.gamma(agg::gamma_none()); + m_gamma_lut.gamma(m_gamma.value()); + } + + draw_text(ras, sl, ren_solid, ren_bin); + + ras.gamma(agg::gamma_power(1.0)); + + agg::render_ctrl(ras, sl, ren_base, m_ren_type); + agg::render_ctrl(ras, sl, ren_base, m_height); + agg::render_ctrl(ras, sl, ren_base, m_width); + agg::render_ctrl(ras, sl, ren_base, m_weight); + agg::render_ctrl(ras, sl, ren_base, m_gamma); + agg::render_ctrl(ras, sl, ren_base, m_hinting); + agg::render_ctrl(ras, sl, ren_base, m_kerning); + agg::render_ctrl(ras, sl, ren_base, m_performance); + } + + + + + virtual void on_ctrl_change() + { + if(m_performance.status()) + { + pixfmt_type pf(rbuf_window(), m_gamma_lut); + base_ren_type ren_base(pf); + renderer_solid ren_solid(ren_base); + renderer_bin ren_bin(ren_base); + ren_base.clear(agg::rgba(1,1,1)); + + agg::scanline_u8 sl; + agg::rasterizer_scanline_aa<> ras; + + unsigned num_glyphs = 0; + start_timer(); + for(int i = 0; i < 50; i++) + { + num_glyphs += draw_text(ras, sl, ren_solid, ren_bin); + } + double t = elapsed_time(); + char buf[100]; + sprintf(buf, + "Glyphs=%u, Time=%.3fms, %.3f glyps/sec, %.3f microsecond/glyph", + num_glyphs, + t, + (num_glyphs / t) * 1000.0, + (t / num_glyphs) * 1000.0); + message(buf); + + m_performance.status(false); + force_redraw(); + } + } + + virtual void on_key(int x, int y, unsigned key, unsigned flags) + { + text_flip = !text_flip; + force_redraw(); + } + + +}; + + + +int agg_main(int argc, char* argv[]) +{ + HDC dc = ::GetDC(0); + the_application app(dc, agg::pix_format_bgr24, flip); + app.caption("AGG Example. Rendering TrueType Fonts with WinAPI"); + + if(app.init(640, 520, agg::window_resize)) + { + return app.run(); + } + ::ReleaseDC(0, dc); + return 1; +} + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/Makefile b/jni/desmume/src/android/agg/examples/win32_api/Makefile new file mode 100755 index 0000000..f3062c7 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/Makefile @@ -0,0 +1,106 @@ +# +# This makefile can be used to build Win32 application under Cygwin +# + +all: + cd aa_demo; make + cd aa_test; make + cd alpha_gradient; make + cd alpha_mask; make + cd alpha_mask2; make + cd alpha_mask3; make + cd bezier_div; make + cd bspline; make + cd circles; make + cd compositing; make + cd component_rendering; make + cd conv_contour; make + cd conv_dash_marker; make + cd conv_stroke; make + cd distortions; make + cd gamma_correction; make + cd gamma_ctrl; make + cd gouraud; make + cd gpc_test; make + cd gradients; make + cd graph_test; make + cd idea; make + cd image_alpha; make + cd image_filters; make + cd image_filters2; make + cd image_fltr_graph; make + cd image_transforms; make + cd image_perspective; make + cd image_resample; make + cd images1; make + cd line_patterns; make + cd lion; make + cd lion_lens; make + cd lion_outline; make + cd mol_view; make + cd multi_clip; make + cd pattern_fill; make + cd perspective; make + cd polymorphic_renderer; make + cd raster_text; make + cd rasterizers; make + cd rasterizers2; make + cd rounded_rect; make + cd scanline_boolean; make + cd scanline_boolean2; make + cd simple_blur; make + cd trans_polar; make + cd trans_curve1; make + cd trans_curve2; make + cd truetype_test; make +clean: + cd aa_demo; make clean + cd aa_test; make clean + cd alpha_gradient; make clean + cd alpha_mask; make clean + cd alpha_mask2; make clean + cd alpha_mask3; make clean + cd bezier_div; make clean + cd bspline; make clean + cd circles; make clean + cd compositing; make clean + cd component_rendering; make clean + cd conv_contour; make clean + cd conv_dash_marker; make clean + cd conv_stroke; make clean + cd distortions; make clean + cd gamma_correction; make clean + cd gamma_ctrl; make clean + cd gouraud; make clean + cd gpc_test; make clean + cd gradients; make clean + cd graph_test; make clean + cd idea; make clean + cd image_alpha; make clean + cd image_filters; make clean + cd image_filters2; make clean + cd image_fltr_graph; make clean + cd image_perspective; make clean + cd image_resample; make clean + cd image_transforms; make clean + cd images1; make clean + cd line_patterns; make clean + cd lion; make clean + cd lion_lens; make clean + cd lion_outline; make clean + cd mol_view; make clean + cd multi_clip; make clean + cd pattern_fill; make clean + cd perspective; make clean + cd polymorphic_renderer; make clean + cd raster_text; make clean + cd rasterizers; make clean + cd rasterizers2; make clean + cd rounded_rect; make clean + cd scanline_boolean; make clean + cd scanline_boolean2; make clean + cd simple_blur; make clean + cd trans_polar; make clean + cd trans_curve1; make clean + cd trans_curve2; make clean + cd truetype_test; make clean diff --git a/jni/desmume/src/android/agg/examples/win32_api/aa_demo/Makefile b/jni/desmume/src/android/agg/examples/win32_api/aa_demo/Makefile new file mode 100755 index 0000000..61aac07 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/aa_demo/Makefile @@ -0,0 +1,39 @@ +# +# This makefile can be used to build a Win32 application under Cygwin or MinGW +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=aa_demo +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/aa_demo/aa_demo.dsp b/jni/desmume/src/android/agg/examples/win32_api/aa_demo/aa_demo.dsp new file mode 100755 index 0000000..cb6683c --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/aa_demo/aa_demo.dsp @@ -0,0 +1,139 @@ +# Microsoft Developer Studio Project File - Name="aa_demo" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=aa_demo - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "aa_demo.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "aa_demo.mak" CFG="aa_demo - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "aa_demo - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "aa_demo - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "aa_demo - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./aa_demo.exe" + +!ELSEIF "$(CFG)" == "aa_demo - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "aa_demo - Win32 Release" +# Name "aa_demo - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\aa_demo.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/aa_demo/aa_demo.dsw b/jni/desmume/src/android/agg/examples/win32_api/aa_demo/aa_demo.dsw new file mode 100755 index 0000000..99fc2ad --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/aa_demo/aa_demo.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "aa_demo"=.\aa_demo.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/aa_test/Makefile b/jni/desmume/src/android/agg/examples/win32_api/aa_test/Makefile new file mode 100755 index 0000000..37f718a --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/aa_test/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=aa_test +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/aa_test/aa_test.dsp b/jni/desmume/src/android/agg/examples/win32_api/aa_test/aa_test.dsp new file mode 100755 index 0000000..72fd8c9 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/aa_test/aa_test.dsp @@ -0,0 +1,143 @@ +# Microsoft Developer Studio Project File - Name="aa_test" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=aa_test - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "aa_test.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "aa_test.mak" CFG="aa_test - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "aa_test - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "aa_test - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "aa_test - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./aa_test.exe" + +!ELSEIF "$(CFG)" == "aa_test - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "aa_test - Win32 Release" +# Name "aa_test - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\aa_test.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_dash.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/aa_test/aa_test.dsw b/jni/desmume/src/android/agg/examples/win32_api/aa_test/aa_test.dsw new file mode 100755 index 0000000..b457d8c --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/aa_test/aa_test.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "aa_test"=.\aa_test.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/alpha_gradient/Makefile b/jni/desmume/src/android/agg/examples/win32_api/alpha_gradient/Makefile new file mode 100755 index 0000000..281bf8b --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/alpha_gradient/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=alpha_gradient +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/alpha_gradient/alpha_gradient.dsp b/jni/desmume/src/android/agg/examples/win32_api/alpha_gradient/alpha_gradient.dsp new file mode 100755 index 0000000..7b47ec1 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/alpha_gradient/alpha_gradient.dsp @@ -0,0 +1,151 @@ +# Microsoft Developer Studio Project File - Name="alpha_gradient" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=alpha_gradient - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "alpha_gradient.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "alpha_gradient.mak" CFG="alpha_gradient - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "alpha_gradient - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "alpha_gradient - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "alpha_gradient - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./alpha_gradient.exe" + +!ELSEIF "$(CFG)" == "alpha_gradient - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "alpha_gradient - Win32 Release" +# Name "alpha_gradient - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_spline_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\alpha_gradient.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_span_gradient.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_gradient_alpha.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/alpha_gradient/alpha_gradient.dsw b/jni/desmume/src/android/agg/examples/win32_api/alpha_gradient/alpha_gradient.dsw new file mode 100755 index 0000000..162b841 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/alpha_gradient/alpha_gradient.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "alpha_gradient"=.\alpha_gradient.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/alpha_mask/Makefile b/jni/desmume/src/android/agg/examples/win32_api/alpha_mask/Makefile new file mode 100755 index 0000000..a74936f --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/alpha_mask/Makefile @@ -0,0 +1,41 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=alpha_mask +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../parse_lion.cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/alpha_mask/alpha_mask.dsp b/jni/desmume/src/android/agg/examples/win32_api/alpha_mask/alpha_mask.dsp new file mode 100755 index 0000000..429da95 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/alpha_mask/alpha_mask.dsp @@ -0,0 +1,139 @@ +# Microsoft Developer Studio Project File - Name="alpha_mask" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=alpha_mask - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "alpha_mask.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "alpha_mask.mak" CFG="alpha_mask - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "alpha_mask - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "alpha_mask - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "alpha_mask - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./alpha_mask.exe" + +!ELSEIF "$(CFG)" == "alpha_mask - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "alpha_mask - Win32 Release" +# Name "alpha_mask - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\alpha_mask.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\parse_lion.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/alpha_mask/alpha_mask.dsw b/jni/desmume/src/android/agg/examples/win32_api/alpha_mask/alpha_mask.dsw new file mode 100755 index 0000000..9a2381c --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/alpha_mask/alpha_mask.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "alpha_mask"=.\alpha_mask.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/alpha_mask2/Makefile b/jni/desmume/src/android/agg/examples/win32_api/alpha_mask2/Makefile new file mode 100755 index 0000000..c272264 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/alpha_mask2/Makefile @@ -0,0 +1,41 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=alpha_mask2 +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../parse_lion.cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/alpha_mask2/alpha_mask2.dsp b/jni/desmume/src/android/agg/examples/win32_api/alpha_mask2/alpha_mask2.dsp new file mode 100755 index 0000000..3249310 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/alpha_mask2/alpha_mask2.dsp @@ -0,0 +1,155 @@ +# Microsoft Developer Studio Project File - Name="alpha_mask2" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=alpha_mask2 - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "alpha_mask2.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "alpha_mask2.mak" CFG="alpha_mask2 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "alpha_mask2 - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "alpha_mask2 - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "alpha_mask2 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./alpha_mask2.exe" + +!ELSEIF "$(CFG)" == "alpha_mask2 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "alpha_mask2 - Win32 Release" +# Name "alpha_mask2 - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_line_aa_basics.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_line_profile_aa.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\alpha_mask2.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\parse_lion.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_pixfmt_amask_adaptor.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/alpha_mask2/alpha_mask2.dsw b/jni/desmume/src/android/agg/examples/win32_api/alpha_mask2/alpha_mask2.dsw new file mode 100755 index 0000000..d952cde --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/alpha_mask2/alpha_mask2.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "alpha_mask2"=.\alpha_mask2.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/alpha_mask3/Makefile b/jni/desmume/src/android/agg/examples/win32_api/alpha_mask3/Makefile new file mode 100755 index 0000000..5693472 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/alpha_mask3/Makefile @@ -0,0 +1,42 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=alpha_mask3 +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../make_arrows.cpp \ +../../make_gb_poly.cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../*.o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/alpha_mask3/alpha_mask3.dsp b/jni/desmume/src/android/agg/examples/win32_api/alpha_mask3/alpha_mask3.dsp new file mode 100755 index 0000000..5768b56 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/alpha_mask3/alpha_mask3.dsp @@ -0,0 +1,155 @@ +# Microsoft Developer Studio Project File - Name="alpha_mask3" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=alpha_mask3 - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "alpha_mask3.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "alpha_mask3.mak" CFG="alpha_mask3 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "alpha_mask3 - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "alpha_mask3 - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "alpha_mask3 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /I "../../../gpc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./alpha_mask3.exe" + +!ELSEIF "$(CFG)" == "alpha_mask3 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /I "../../../gpc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "alpha_mask3 - Win32 Release" +# Name "alpha_mask3 - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\alpha_mask3.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\make_arrows.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\make_gb_poly.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/alpha_mask3/alpha_mask3.dsw b/jni/desmume/src/android/agg/examples/win32_api/alpha_mask3/alpha_mask3.dsw new file mode 100755 index 0000000..5ff535e --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/alpha_mask3/alpha_mask3.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "alpha_mask3"=.\alpha_mask3.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/bezier_div/Makefile b/jni/desmume/src/android/agg/examples/win32_api/bezier_div/Makefile new file mode 100755 index 0000000..563fb2c --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/bezier_div/Makefile @@ -0,0 +1,42 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=bezier_div +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../interactive_polygon.cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../interactive_polygon.o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/bezier_div/bezier_div.dsp b/jni/desmume/src/android/agg/examples/win32_api/bezier_div/bezier_div.dsp new file mode 100755 index 0000000..b05562d --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/bezier_div/bezier_div.dsp @@ -0,0 +1,175 @@ +# Microsoft Developer Studio Project File - Name="bezier_div" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=bezier_div - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "bezier_div.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "bezier_div.mak" CFG="bezier_div - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "bezier_div - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "bezier_div - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "bezier_div - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 /out:"./bezier_div.exe" + +!ELSEIF "$(CFG)" == "bezier_div - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "bezier_div - Win32 Release" +# Name "bezier_div - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_bezier_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_line_aa_basics.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_line_profile_aa.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_polygon_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_dash.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\bezier_div.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/bezier_div/bezier_div.dsw b/jni/desmume/src/android/agg/examples/win32_api/bezier_div/bezier_div.dsw new file mode 100755 index 0000000..90da71e --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/bezier_div/bezier_div.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "bezier_div"=.\bezier_div.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/blend_color/Makefile b/jni/desmume/src/android/agg/examples/win32_api/blend_color/Makefile new file mode 100755 index 0000000..8f7cb14 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/blend_color/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=blend_color +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/blend_color/blend_color.dsp b/jni/desmume/src/android/agg/examples/win32_api/blend_color/blend_color.dsp new file mode 100755 index 0000000..de2141f --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/blend_color/blend_color.dsp @@ -0,0 +1,163 @@ +# Microsoft Developer Studio Project File - Name="blend_color" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=blend_color - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "blend_color.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "blend_color.mak" CFG="blend_color - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "blend_color - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "blend_color - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "blend_color - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./blend_color.exe" + +!ELSEIF "$(CFG)" == "blend_color - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "blend_color - Win32 Release" +# Name "blend_color - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_arrowhead.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_polygon_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_contour.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\blend_color.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/blend_color/blend_color.dsw b/jni/desmume/src/android/agg/examples/win32_api/blend_color/blend_color.dsw new file mode 100755 index 0000000..91ba1b7 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/blend_color/blend_color.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "blend_color"=.\blend_color.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/blur/Makefile b/jni/desmume/src/android/agg/examples/win32_api/blur/Makefile new file mode 100755 index 0000000..b00ffa5 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/blur/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=blur +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/blur/blur.dsp b/jni/desmume/src/android/agg/examples/win32_api/blur/blur.dsp new file mode 100755 index 0000000..95949c4 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/blur/blur.dsp @@ -0,0 +1,163 @@ +# Microsoft Developer Studio Project File - Name="blur" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=blur - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "blur.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "blur.mak" CFG="blur - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "blur - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "blur - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "blur - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./blur.exe" + +!ELSEIF "$(CFG)" == "blur - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "blur - Win32 Release" +# Name "blur - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_arrowhead.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_polygon_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_contour.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\blur.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/blur/blur.dsw b/jni/desmume/src/android/agg/examples/win32_api/blur/blur.dsw new file mode 100755 index 0000000..9e2bf4e --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/blur/blur.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "blur"=.\blur.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/bspline/Makefile b/jni/desmume/src/android/agg/examples/win32_api/bspline/Makefile new file mode 100755 index 0000000..cf885d8 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/bspline/Makefile @@ -0,0 +1,42 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=bspline +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../interactive_polygon.cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../interactive_polygon.o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/bspline/bspline.dsp b/jni/desmume/src/android/agg/examples/win32_api/bspline/bspline.dsp new file mode 100755 index 0000000..7570354 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/bspline/bspline.dsp @@ -0,0 +1,151 @@ +# Microsoft Developer Studio Project File - Name="bspline" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=bspline - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "bspline.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "bspline.mak" CFG="bspline - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "bspline - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "bspline - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "bspline - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./bspline.exe" + +!ELSEIF "$(CFG)" == "bspline - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "bspline - Win32 Release" +# Name "bspline - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\interactive_polygon.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/bspline/bspline.dsw b/jni/desmume/src/android/agg/examples/win32_api/bspline/bspline.dsw new file mode 100755 index 0000000..ca344ed --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/bspline/bspline.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "bspline"=.\bspline.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/circles/Makefile b/jni/desmume/src/android/agg/examples/win32_api/circles/Makefile new file mode 100755 index 0000000..17a10fc --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/circles/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=circles +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/circles/circles.dsp b/jni/desmume/src/android/agg/examples/win32_api/circles/circles.dsp new file mode 100755 index 0000000..880b6f6 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/circles/circles.dsp @@ -0,0 +1,157 @@ +# Microsoft Developer Studio Project File - Name="circles" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=circles - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "circles.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "circles.mak" CFG="circles - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "circles - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "circles - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "circles - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./circles.exe" + +!ELSEIF "$(CFG)" == "circles - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "circles - Win32 Release" +# Name "circles - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_scale_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\circles.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_gsv_text.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\platform\agg_platform_support.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\ctrl\agg_scale_ctrl.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/circles/circles.dsw b/jni/desmume/src/android/agg/examples/win32_api/circles/circles.dsw new file mode 100755 index 0000000..fde69cb --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/circles/circles.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "circles"=.\circles.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/component_rendering/Makefile b/jni/desmume/src/android/agg/examples/win32_api/component_rendering/Makefile new file mode 100755 index 0000000..b85e551 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/component_rendering/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=component_rendering +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/component_rendering/component_rendering.dsp b/jni/desmume/src/android/agg/examples/win32_api/component_rendering/component_rendering.dsp new file mode 100755 index 0000000..81aaf03 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/component_rendering/component_rendering.dsp @@ -0,0 +1,137 @@ +# Microsoft Developer Studio Project File - Name="component_rendering" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=component_rendering - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "component_rendering.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "component_rendering.mak" CFG="component_rendering - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "component_rendering - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "component_rendering - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "component_rendering - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./component_rendering.exe" + +!ELSEIF "$(CFG)" == "component_rendering - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "component_rendering - Win32 Release" +# Name "component_rendering - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\component_rendering.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/component_rendering/component_rendering.dsw b/jni/desmume/src/android/agg/examples/win32_api/component_rendering/component_rendering.dsw new file mode 100755 index 0000000..eae0d30 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/component_rendering/component_rendering.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "component_rendering"=.\component_rendering.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/compositing/Makefile b/jni/desmume/src/android/agg/examples/win32_api/compositing/Makefile new file mode 100755 index 0000000..7ef50d2 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/compositing/Makefile @@ -0,0 +1,39 @@ +# +# This makefile can be used to build a Win32 application under Cygwin or MinGW +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=compositing +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/compositing/compositing.dsp b/jni/desmume/src/android/agg/examples/win32_api/compositing/compositing.dsp new file mode 100755 index 0000000..f41f6e2 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/compositing/compositing.dsp @@ -0,0 +1,159 @@ +# Microsoft Developer Studio Project File - Name="compositing" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=compositing - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "compositing.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "compositing.mak" CFG="compositing - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "compositing - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "compositing - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "compositing - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./compositing.exe" + +!ELSEIF "$(CFG)" == "compositing - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "compositing - Win32 Release" +# Name "compositing - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_rounded_rect.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\compositing.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_pixfmt_rgba.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_rendering_buffer_dynarow.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/compositing/compositing.dsw b/jni/desmume/src/android/agg/examples/win32_api/compositing/compositing.dsw new file mode 100755 index 0000000..f26e02d --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/compositing/compositing.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "compositing"=.\compositing.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/compositing/readme b/jni/desmume/src/android/agg/examples/win32_api/compositing/readme new file mode 100755 index 0000000..6c39253 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/compositing/readme @@ -0,0 +1 @@ +Download http://www.antigrain.com/compositing.bmp before running this example. diff --git a/jni/desmume/src/android/agg/examples/win32_api/compositing2/Makefile b/jni/desmume/src/android/agg/examples/win32_api/compositing2/Makefile new file mode 100755 index 0000000..7ef50d2 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/compositing2/Makefile @@ -0,0 +1,39 @@ +# +# This makefile can be used to build a Win32 application under Cygwin or MinGW +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=compositing +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/compositing2/compositing2.dsp b/jni/desmume/src/android/agg/examples/win32_api/compositing2/compositing2.dsp new file mode 100755 index 0000000..d1d15fa --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/compositing2/compositing2.dsp @@ -0,0 +1,163 @@ +# Microsoft Developer Studio Project File - Name="compositing2" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=compositing2 - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "compositing2.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "compositing2.mak" CFG="compositing2 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "compositing2 - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "compositing2 - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "compositing2 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./compositing2.exe" + +!ELSEIF "$(CFG)" == "compositing2 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "compositing2 - Win32 Release" +# Name "compositing2 - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_rounded_rect.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\compositing2.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_pixfmt_rgba.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_rendering_buffer_dynarow.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/compositing2/compositing2.dsw b/jni/desmume/src/android/agg/examples/win32_api/compositing2/compositing2.dsw new file mode 100755 index 0000000..8155708 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/compositing2/compositing2.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "compositing2"=.\compositing2.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/conv_contour/Makefile b/jni/desmume/src/android/agg/examples/win32_api/conv_contour/Makefile new file mode 100755 index 0000000..353a2ca --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/conv_contour/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=conv_contour +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/conv_contour/conv_contour.dsp b/jni/desmume/src/android/agg/examples/win32_api/conv_contour/conv_contour.dsp new file mode 100755 index 0000000..a228ef6 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/conv_contour/conv_contour.dsp @@ -0,0 +1,159 @@ +# Microsoft Developer Studio Project File - Name="conv_contour" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=conv_contour - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "conv_contour.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "conv_contour.mak" CFG="conv_contour - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "conv_contour - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "conv_contour - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "conv_contour - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./conv_contour.exe" + +!ELSEIF "$(CFG)" == "conv_contour - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "conv_contour - Win32 Release" +# Name "conv_contour - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_arrowhead.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_contour.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\conv_contour.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/conv_contour/conv_contour.dsw b/jni/desmume/src/android/agg/examples/win32_api/conv_contour/conv_contour.dsw new file mode 100755 index 0000000..fcde274 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/conv_contour/conv_contour.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "conv_contour"=.\conv_contour.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/conv_dash_marker/Makefile b/jni/desmume/src/android/agg/examples/win32_api/conv_dash_marker/Makefile new file mode 100755 index 0000000..1c171c0 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/conv_dash_marker/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=conv_dash_marker +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/conv_dash_marker/conv_dash_marker.dsp b/jni/desmume/src/android/agg/examples/win32_api/conv_dash_marker/conv_dash_marker.dsp new file mode 100755 index 0000000..4d8c744 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/conv_dash_marker/conv_dash_marker.dsp @@ -0,0 +1,175 @@ +# Microsoft Developer Studio Project File - Name="conv_dash_marker" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=conv_dash_marker - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "conv_dash_marker.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "conv_dash_marker.mak" CFG="conv_dash_marker - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "conv_dash_marker - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "conv_dash_marker - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "conv_dash_marker - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./conv_dash_marker.exe" + +!ELSEIF "$(CFG)" == "conv_dash_marker - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "conv_dash_marker - Win32 Release" +# Name "conv_dash_marker - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_arrowhead.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_rounded_rect.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_contour.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_dash.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_markers_term.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_smooth_poly1.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\conv_dash_marker.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/conv_dash_marker/conv_dash_marker.dsw b/jni/desmume/src/android/agg/examples/win32_api/conv_dash_marker/conv_dash_marker.dsw new file mode 100755 index 0000000..43a9333 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/conv_dash_marker/conv_dash_marker.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "conv_dash_marker"=.\conv_dash_marker.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/conv_stroke/Makefile b/jni/desmume/src/android/agg/examples/win32_api/conv_stroke/Makefile new file mode 100755 index 0000000..292ba01 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/conv_stroke/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=conv_stroke +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/conv_stroke/conv_stroke.dsp b/jni/desmume/src/android/agg/examples/win32_api/conv_stroke/conv_stroke.dsp new file mode 100755 index 0000000..95269ca --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/conv_stroke/conv_stroke.dsp @@ -0,0 +1,171 @@ +# Microsoft Developer Studio Project File - Name="conv_stroke" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=conv_stroke - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "conv_stroke.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "conv_stroke.mak" CFG="conv_stroke - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "conv_stroke - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "conv_stroke - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "conv_stroke - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./conv_stroke.exe" + +!ELSEIF "$(CFG)" == "conv_stroke - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "conv_stroke - Win32 Release" +# Name "conv_stroke - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_arrowhead.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_rounded_rect.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_contour.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_dash.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_markers_term.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_smooth_poly1.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\conv_stroke.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/conv_stroke/conv_stroke.dsw b/jni/desmume/src/android/agg/examples/win32_api/conv_stroke/conv_stroke.dsw new file mode 100755 index 0000000..5e5ec7d --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/conv_stroke/conv_stroke.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "conv_stroke"=.\conv_stroke.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/distortions/Makefile b/jni/desmume/src/android/agg/examples/win32_api/distortions/Makefile new file mode 100755 index 0000000..c99b799 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/distortions/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=distortions +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/distortions/distortions.dsp b/jni/desmume/src/android/agg/examples/win32_api/distortions/distortions.dsp new file mode 100755 index 0000000..5c6ccdb --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/distortions/distortions.dsp @@ -0,0 +1,161 @@ +# Microsoft Developer Studio Project File - Name="distortions" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=distortions - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "distortions.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "distortions.mak" CFG="distortions - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "distortions - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "distortions - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "distortions - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./distortions.exe" +# SUBTRACT LINK32 /profile + +!ELSEIF "$(CFG)" == "distortions - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MD /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "distortions - Win32 Release" +# Name "distortions - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_image_filters.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\distortions.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_span_interpolator_adaptor.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=..\..\..\include\agg_gouraud_attr.h +# End Source File +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/distortions/distortions.dsw b/jni/desmume/src/android/agg/examples/win32_api/distortions/distortions.dsw new file mode 100755 index 0000000..3ef4757 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/distortions/distortions.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "distortions"=.\distortions.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/distortions/readme b/jni/desmume/src/android/agg/examples/win32_api/distortions/readme new file mode 100755 index 0000000..f6e9dcd --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/distortions/readme @@ -0,0 +1,5 @@ +Download http://www.antigrain.com/spheres.bmp before running this example +Use the sliders and the radio-buttons to change the parameters of +the distortions. Drag the center of the distortions. +Don't try to understand the shamanic manipulations with affine matrices +because I composed it using the "hit-and-miss" method :-) diff --git a/jni/desmume/src/android/agg/examples/win32_api/examples.dsw b/jni/desmume/src/android/agg/examples/win32_api/examples.dsw new file mode 100755 index 0000000..ccc142b --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/examples.dsw @@ -0,0 +1,761 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "aa_demo"=".\aa_demo\aa_demo.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "aa_test"=".\aa_test\aa_test.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "alpha_gradient"=".\alpha_gradient\alpha_gradient.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "alpha_mask"=".\alpha_mask\alpha_mask.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "alpha_mask2"=".\alpha_mask2\alpha_mask2.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "alpha_mask3"=".\alpha_mask3\alpha_mask3.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "bezier_div"=".\bezier_div\bezier_div.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "blend_color"=".\blend_color\blend_color.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "blur"=".\blur\blur.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "bspline"=".\bspline\bspline.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "circles"=".\circles\circles.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "component_rendering"=".\component_rendering\component_rendering.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "compositing"=".\compositing\compositing.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "compositing2"=".\compositing2\compositing2.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "conv_contour"=".\conv_contour\conv_contour.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "conv_dash_marker"=".\conv_dash_marker\conv_dash_marker.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "conv_stroke"=".\conv_stroke\conv_stroke.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "distortions"=".\distortions\distortions.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "flash_rasterizer"=".\flash_rasterizer\flash_rasterizer.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "flash_rasterizer2"=".\flash_rasterizer2\flash_rasterizer2.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "gamma_correction"=".\gamma_correction\gamma_correction.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "gamma_ctrl"=".\gamma_ctrl\gamma_ctrl.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "gamma_tuner"=".\gamma_tuner\gamma_tuner.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "gouraud"=".\gouraud\gouraud.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "gouraud_mesh"=".\gouraud_mesh\gouraud_mesh.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "gpc_test"=".\gpc_test\gpc_test.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "gradient_focal"=".\gradient_focal\gradient_focal.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "gradients"=".\gradients\gradients.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "graph_test"=".\graph_test\graph_test.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "idea"=".\idea\idea.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "image1"=".\image1\image1.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "image_alpha"=".\image_alpha\image_alpha.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "image_filters"=".\image_filters\image_filters.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "image_filters2"=".\image_filters2\image_filters2.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "image_fltr_graph"=".\image_fltr_graph\image_fltr_graph.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "image_perspective"=".\image_perspective\image_perspective.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "image_resample"=".\image_resample\image_resample.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "image_transforms"=".\image_transforms\image_transforms.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "line_patterns"=".\line_patterns\line_patterns.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "line_patterns_clip"=".\line_patterns_clip\line_patterns_clip.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "lion"=".\lion\lion.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "lion_lens"=".\lion_lens\lion_lens.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "lion_outline"=".\lion_outline\lion_outline.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "mol_view"=".\mol_view\mol_view.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "multi_clip"=".\multi_clip\multi_clip.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "pattern_fill"=".\pattern_fill\pattern_fill.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "pattern_perspective"=".\pattern_perspective\pattern_perspective.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "perspective"=".\perspective\perspective.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "polymorphic_renderer"=".\polymorphic_renderer\polymorphic_renderer.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "pure_api"=".\pure_api\pure_api.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "raster_text"=".\raster_text\raster_text.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "rasterizer_compound"=".\rasterizer_compound\rasterizer_compound.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "rasterizers"=".\rasterizers\rasterizers.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "rasterizers2"=".\rasterizers2\rasterizers2.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "rounded_rect"=".\rounded_rect\rounded_rect.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "scanline_boolean"=".\scanline_boolean\scanline_boolean.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "scanline_boolean2"=".\scanline_boolean2\scanline_boolean2.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "simple_blur"=".\simple_blur\simple_blur.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "trans_curve1"=".\trans_curve1\trans_curve1.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "trans_curve2"=".\trans_curve2\trans_curve2.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "trans_polar"=".\trans_polar\trans_polar.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "truetype_test"=".\truetype_test\truetype_test.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/flash_rasterizer/Makefile b/jni/desmume/src/android/agg/examples/win32_api/flash_rasterizer/Makefile new file mode 100755 index 0000000..3e5cd8a --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/flash_rasterizer/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=flash_rasterizer +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/flash_rasterizer/flash_rasterizer.dsp b/jni/desmume/src/android/agg/examples/win32_api/flash_rasterizer/flash_rasterizer.dsp new file mode 100755 index 0000000..1c1593f --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/flash_rasterizer/flash_rasterizer.dsp @@ -0,0 +1,147 @@ +# Microsoft Developer Studio Project File - Name="flash_rasterizer" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=flash_rasterizer - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "flash_rasterizer.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "flash_rasterizer.mak" CFG="flash_rasterizer - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "flash_rasterizer - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "flash_rasterizer - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "flash_rasterizer - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 /out:"./flash_rasterizer.exe" + +!ELSEIF "$(CFG)" == "flash_rasterizer - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "flash_rasterizer - Win32 Release" +# Name "flash_rasterizer - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_polygon_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\flash_rasterizer.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_color_gray.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/flash_rasterizer/flash_rasterizer.dsw b/jni/desmume/src/android/agg/examples/win32_api/flash_rasterizer/flash_rasterizer.dsw new file mode 100755 index 0000000..859988f --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/flash_rasterizer/flash_rasterizer.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "flash_rasterizer"=.\flash_rasterizer.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/flash_rasterizer2/Makefile b/jni/desmume/src/android/agg/examples/win32_api/flash_rasterizer2/Makefile new file mode 100755 index 0000000..b231094 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/flash_rasterizer2/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=flash_rasterizer2 +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/flash_rasterizer2/flash_rasterizer2.dsp b/jni/desmume/src/android/agg/examples/win32_api/flash_rasterizer2/flash_rasterizer2.dsp new file mode 100755 index 0000000..b56b664 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/flash_rasterizer2/flash_rasterizer2.dsp @@ -0,0 +1,143 @@ +# Microsoft Developer Studio Project File - Name="flash_rasterizer2" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=flash_rasterizer2 - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "flash_rasterizer2.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "flash_rasterizer2.mak" CFG="flash_rasterizer2 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "flash_rasterizer2 - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "flash_rasterizer2 - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "flash_rasterizer2 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 /out:"./flash_rasterizer2.exe" + +!ELSEIF "$(CFG)" == "flash_rasterizer2 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "flash_rasterizer2 - Win32 Release" +# Name "flash_rasterizer2 - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_polygon_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\flash_rasterizer2.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/flash_rasterizer2/flash_rasterizer2.dsw b/jni/desmume/src/android/agg/examples/win32_api/flash_rasterizer2/flash_rasterizer2.dsw new file mode 100755 index 0000000..8afaae1 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/flash_rasterizer2/flash_rasterizer2.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "flash_rasterizer2"=.\flash_rasterizer2.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/freetype_test/Makefile b/jni/desmume/src/android/agg/examples/win32_api/freetype_test/Makefile new file mode 100755 index 0000000..29414b8 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/freetype_test/Makefile @@ -0,0 +1,42 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=scanline_boolean2 +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../make_arrows.cpp \ +../../make_gb_poly.cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../*.o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/freetype_test/freetype_test.dsp b/jni/desmume/src/android/agg/examples/win32_api/freetype_test/freetype_test.dsp new file mode 100755 index 0000000..82fb2f9 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/freetype_test/freetype_test.dsp @@ -0,0 +1,159 @@ +# Microsoft Developer Studio Project File - Name="freetype_test" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=freetype_test - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "freetype_test.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "freetype_test.mak" CFG="freetype_test - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "freetype_test - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "freetype_test - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "freetype_test - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../../include" /I "../../../font_freetype" /I "../../../../freetype2/include" /I "../../../../freetype2/src" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib freetype219.lib /nologo /subsystem:windows /machine:I386 /out:"./freetype_test.exe" /libpath:"../../../../freetype2/objs" + +!ELSEIF "$(CFG)" == "freetype_test - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../../include" /I "../../../font_freetype" /I "../../../../freetype2/include" /I "../../../../freetype2/src" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib freetype219_D.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:"../../../../freetype2/objs" + +!ENDIF + +# Begin Target + +# Name "freetype_test - Win32 Release" +# Name "freetype_test - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\font_freetype\agg_font_freetype.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_contour.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\freetype_test.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\font_freetype\agg_font_freetype.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/freetype_test/freetype_test.dsw b/jni/desmume/src/android/agg/examples/win32_api/freetype_test/freetype_test.dsw new file mode 100755 index 0000000..36b18b8 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/freetype_test/freetype_test.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "freetype_test"=.\freetype_test.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/freetype_test/readme b/jni/desmume/src/android/agg/examples/win32_api/freetype_test/readme new file mode 100755 index 0000000..1b23129 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/freetype_test/readme @@ -0,0 +1,10 @@ +This example demonstrates the use of the FreeType font rendering +engine (http://freetype.org). Please get file "timesi.ttf" before +running this example. You can download it from: +http://www.antigrain.com/timesi.zip + +Note that the building environment expects +FreeType installed into the root directory, that is, "\freetype2". +It supposed to be compiled in "Debug" and "Release" configurations. +If you install FreeType somewhere else please correct the paths +to the include and library directories. diff --git a/jni/desmume/src/android/agg/examples/win32_api/gamma_correction/Makefile b/jni/desmume/src/android/agg/examples/win32_api/gamma_correction/Makefile new file mode 100755 index 0000000..05bb4a6 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gamma_correction/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=gamma_correction +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/gamma_correction/gamma_correction.dsp b/jni/desmume/src/android/agg/examples/win32_api/gamma_correction/gamma_correction.dsp new file mode 100755 index 0000000..4b88e43 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gamma_correction/gamma_correction.dsp @@ -0,0 +1,135 @@ +# Microsoft Developer Studio Project File - Name="gamma_correction" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=gamma_correction - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "gamma_correction.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "gamma_correction.mak" CFG="gamma_correction - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "gamma_correction - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "gamma_correction - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "gamma_correction - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"gamma_correction.exe" + +!ELSEIF "$(CFG)" == "gamma_correction - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "gamma_correction - Win32 Release" +# Name "gamma_correction - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\gamma_correction.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/gamma_correction/gamma_correction.dsw b/jni/desmume/src/android/agg/examples/win32_api/gamma_correction/gamma_correction.dsw new file mode 100755 index 0000000..9b88dbe --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gamma_correction/gamma_correction.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "gamma_correction"=.\gamma_correction.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/gamma_ctrl/Makefile b/jni/desmume/src/android/agg/examples/win32_api/gamma_ctrl/Makefile new file mode 100755 index 0000000..3a241d7 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gamma_ctrl/Makefile @@ -0,0 +1,39 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=gamma_ctrl +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + diff --git a/jni/desmume/src/android/agg/examples/win32_api/gamma_ctrl/gamma_ctrl.dsp b/jni/desmume/src/android/agg/examples/win32_api/gamma_ctrl/gamma_ctrl.dsp new file mode 100755 index 0000000..03df54a --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gamma_ctrl/gamma_ctrl.dsp @@ -0,0 +1,145 @@ +# Microsoft Developer Studio Project File - Name="gamma_ctrl" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=gamma_ctrl - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "gamma_ctrl.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "gamma_ctrl.mak" CFG="gamma_ctrl - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "gamma_ctrl - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "gamma_ctrl - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "gamma_ctrl - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./gamma_ctrl.exe" +# SUBTRACT LINK32 /profile + +!ELSEIF "$(CFG)" == "gamma_ctrl - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MD /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "gamma_ctrl - Win32 Release" +# Name "gamma_ctrl - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_gamma_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_gamma_spline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\gamma_ctrl.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/gamma_ctrl/gamma_ctrl.dsw b/jni/desmume/src/android/agg/examples/win32_api/gamma_ctrl/gamma_ctrl.dsw new file mode 100755 index 0000000..d7bb4d9 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gamma_ctrl/gamma_ctrl.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "gamma_ctrl"=.\gamma_ctrl.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/gamma_tuner/Makefile b/jni/desmume/src/android/agg/examples/win32_api/gamma_tuner/Makefile new file mode 100755 index 0000000..54cfe4d --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gamma_tuner/Makefile @@ -0,0 +1,39 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=gamma_tuner +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + diff --git a/jni/desmume/src/android/agg/examples/win32_api/gamma_tuner/gamma_tuner.dsp b/jni/desmume/src/android/agg/examples/win32_api/gamma_tuner/gamma_tuner.dsp new file mode 100755 index 0000000..2cb23f8 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gamma_tuner/gamma_tuner.dsp @@ -0,0 +1,139 @@ +# Microsoft Developer Studio Project File - Name="gamma_tuner" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=gamma_tuner - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "gamma_tuner.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "gamma_tuner.mak" CFG="gamma_tuner - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "gamma_tuner - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "gamma_tuner - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "gamma_tuner - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"gamma_tuner.exe" + +!ELSEIF "$(CFG)" == "gamma_tuner - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "gamma_tuner - Win32 Release" +# Name "gamma_tuner - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\gamma_tuner.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/gamma_tuner/gamma_tuner.dsw b/jni/desmume/src/android/agg/examples/win32_api/gamma_tuner/gamma_tuner.dsw new file mode 100755 index 0000000..d9781aa --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gamma_tuner/gamma_tuner.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "gamma_tuner"=.\gamma_tuner.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/gouraud/Makefile b/jni/desmume/src/android/agg/examples/win32_api/gouraud/Makefile new file mode 100755 index 0000000..37840ea --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gouraud/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=gouraud +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/gouraud/gouraud.dsp b/jni/desmume/src/android/agg/examples/win32_api/gouraud/gouraud.dsp new file mode 100755 index 0000000..babf4ed --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gouraud/gouraud.dsp @@ -0,0 +1,135 @@ +# Microsoft Developer Studio Project File - Name="gouraud" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=gouraud - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "gouraud.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "gouraud.mak" CFG="gouraud - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "gouraud - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "gouraud - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "gouraud - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./gouraud.exe" + +!ELSEIF "$(CFG)" == "gouraud - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "gouraud - Win32 Release" +# Name "gouraud - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\gouraud.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/gouraud/gouraud.dsw b/jni/desmume/src/android/agg/examples/win32_api/gouraud/gouraud.dsw new file mode 100755 index 0000000..1d9fb2c --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gouraud/gouraud.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "gouraud"=.\gouraud.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/gouraud_mesh/Makefile b/jni/desmume/src/android/agg/examples/win32_api/gouraud_mesh/Makefile new file mode 100755 index 0000000..d0d9377 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gouraud_mesh/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=gouraud_mesh +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/gouraud_mesh/gouraud_mesh.dsp b/jni/desmume/src/android/agg/examples/win32_api/gouraud_mesh/gouraud_mesh.dsp new file mode 100755 index 0000000..e54b70f --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gouraud_mesh/gouraud_mesh.dsp @@ -0,0 +1,155 @@ +# Microsoft Developer Studio Project File - Name="gouraud_mesh" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=gouraud_mesh - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "gouraud_mesh.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "gouraud_mesh.mak" CFG="gouraud_mesh - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "gouraud_mesh - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "gouraud_mesh - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "gouraud_mesh - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "AGG_FISTP" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 /out:"./gouraud_mesh.exe" + +!ELSEIF "$(CFG)" == "gouraud_mesh - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "AGG_QIFIST" /YX /FD /GZ /QIfist /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "gouraud_mesh - Win32 Release" +# Name "gouraud_mesh - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_polygon_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\gouraud_mesh.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_rasterizer_sl_clip.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_gouraud_rgba.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/gouraud_mesh/gouraud_mesh.dsw b/jni/desmume/src/android/agg/examples/win32_api/gouraud_mesh/gouraud_mesh.dsw new file mode 100755 index 0000000..aa80282 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gouraud_mesh/gouraud_mesh.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "gouraud_mesh"=.\gouraud_mesh.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/gpc_test/Makefile b/jni/desmume/src/android/agg/examples/win32_api/gpc_test/Makefile new file mode 100755 index 0000000..6a89af5 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gpc_test/Makefile @@ -0,0 +1,42 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=gpc_test +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include -I../../../gpc \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../make_arrows.cpp \ +../../make_gb_poly.cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../*.o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/gpc_test/gpc_test.dsp b/jni/desmume/src/android/agg/examples/win32_api/gpc_test/gpc_test.dsp new file mode 100755 index 0000000..5215b75 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gpc_test/gpc_test.dsp @@ -0,0 +1,159 @@ +# Microsoft Developer Studio Project File - Name="gpc_test" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=gpc_test - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "gpc_test.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "gpc_test.mak" CFG="gpc_test - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "gpc_test - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "gpc_test - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "gpc_test - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /I "../../../gpc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./gpc_test.exe" + +!ELSEIF "$(CFG)" == "gpc_test - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /I "../../../gpc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "gpc_test - Win32 Release" +# Name "gpc_test - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\gpc\gpc.c +# End Source File +# Begin Source File + +SOURCE=..\..\gpc_test.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\make_arrows.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\make_gb_poly.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/gpc_test/gpc_test.dsw b/jni/desmume/src/android/agg/examples/win32_api/gpc_test/gpc_test.dsw new file mode 100755 index 0000000..47eddaf --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gpc_test/gpc_test.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "gpc_test"=.\gpc_test.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/gradient_focal/Makefile b/jni/desmume/src/android/agg/examples/win32_api/gradient_focal/Makefile new file mode 100755 index 0000000..6aa607f --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gradient_focal/Makefile @@ -0,0 +1,38 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=gradient_focal +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/gradient_focal/gradient_focal.dsp b/jni/desmume/src/android/agg/examples/win32_api/gradient_focal/gradient_focal.dsp new file mode 100755 index 0000000..1fb9200 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gradient_focal/gradient_focal.dsp @@ -0,0 +1,163 @@ +# Microsoft Developer Studio Project File - Name="gradient_focal" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=gradient_focal - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "gradient_focal.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "gradient_focal.mak" CFG="gradient_focal - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "gradient_focal - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "gradient_focal - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "gradient_focal - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /I "../../../gpc" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./gradient_focal.exe" + +!ELSEIF "$(CFG)" == "gradient_focal - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /I "../../../gpc" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "gradient_focal - Win32 Release" +# Name "gradient_focal - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_contour.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\gradient_focal.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_gradient_lut.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_image_filters.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/gradient_focal/gradient_focal.dsw b/jni/desmume/src/android/agg/examples/win32_api/gradient_focal/gradient_focal.dsw new file mode 100755 index 0000000..f524760 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gradient_focal/gradient_focal.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "gradient_focal"=.\gradient_focal.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/gradients/Makefile b/jni/desmume/src/android/agg/examples/win32_api/gradients/Makefile new file mode 100755 index 0000000..e7be5c8 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gradients/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=gradients +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/gradients/gradients.dsp b/jni/desmume/src/android/agg/examples/win32_api/gradients/gradients.dsp new file mode 100755 index 0000000..49e3d44 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gradients/gradients.dsp @@ -0,0 +1,165 @@ +# Microsoft Developer Studio Project File - Name="gradients" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=gradients - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "gradients.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "gradients.mak" CFG="gradients - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "gradients - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "gradients - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "gradients - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./gradients.exe" + +!ELSEIF "$(CFG)" == "gradients - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "gradients - Win32 Release" +# Name "gradients - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_gamma_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_gamma_spline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_spline_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\gradients.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/gradients/gradients.dsw b/jni/desmume/src/android/agg/examples/win32_api/gradients/gradients.dsw new file mode 100755 index 0000000..81e694b --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gradients/gradients.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "gradients"=.\gradients.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/gradients/settings.dat b/jni/desmume/src/android/agg/examples/win32_api/gradients/settings.dat new file mode 100755 index 0000000..d0e6c17 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/gradients/settings.dat @@ -0,0 +1,56 @@ +399.254028 +339.996429 +1.128661 +77.270996 +0.000000 +1.000000 +0.115323 +1.000000 +0.363710 +0.812121 +0.604032 +0.460606 +0.791935 +0.200000 +1.000000 +0.606061 +0.000000 +1.000000 +0.083065 +1.000000 +0.299194 +0.418182 +0.651484 +0.000000 +0.810365 +0.000000 +1.000000 +0.290598 +0.000000 +1.000000 +0.051755 +0.934195 +0.115509 +0.587701 +0.334362 +0.000000 +0.708762 +0.000000 +1.000000 +0.000000 +0.000000 +1.000000 +0.171775 +1.000000 +0.376360 +1.000000 +0.598100 +1.000000 +0.804839 +1.000000 +1.000000 +1.000000 +0.786681 +1.239889 +0.726049 +0.710140 diff --git a/jni/desmume/src/android/agg/examples/win32_api/graph_test/Makefile b/jni/desmume/src/android/agg/examples/win32_api/graph_test/Makefile new file mode 100755 index 0000000..4f87197 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/graph_test/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=graph_test +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/graph_test/graph_test.dsp b/jni/desmume/src/android/agg/examples/win32_api/graph_test/graph_test.dsp new file mode 100755 index 0000000..2827b41 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/graph_test/graph_test.dsp @@ -0,0 +1,180 @@ +# Microsoft Developer Studio Project File - Name="graph_test" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=graph_test - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "graph_test.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "graph_test.mak" CFG="graph_test - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "graph_test - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "graph_test - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "graph_test - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./graph_test.exe" +# SUBTRACT LINK32 /profile + +!ELSEIF "$(CFG)" == "graph_test - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "graph_test - Win32 Release" +# Name "graph_test - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_arrowhead.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_rounded_rect.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_contour.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_dash.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_markers_term.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_smooth_poly1.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\graph_test.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/graph_test/graph_test.dsw b/jni/desmume/src/android/agg/examples/win32_api/graph_test/graph_test.dsw new file mode 100755 index 0000000..b6989e7 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/graph_test/graph_test.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "graph_test"=.\graph_test.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/idea/Makefile b/jni/desmume/src/android/agg/examples/win32_api/idea/Makefile new file mode 100755 index 0000000..9061c9f --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/idea/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=idea +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/idea/idea.dsp b/jni/desmume/src/android/agg/examples/win32_api/idea/idea.dsp new file mode 100755 index 0000000..beafec5 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/idea/idea.dsp @@ -0,0 +1,141 @@ +# Microsoft Developer Studio Project File - Name="idea" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=idea - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "idea.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "idea.mak" CFG="idea - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "idea - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "idea - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "idea - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./idea.exe" + +!ELSEIF "$(CFG)" == "idea - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "idea - Win32 Release" +# Name "idea - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\idea.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/idea/idea.dsw b/jni/desmume/src/android/agg/examples/win32_api/idea/idea.dsw new file mode 100755 index 0000000..0dda051 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/idea/idea.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "idea"=.\idea.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/image1/Makefile b/jni/desmume/src/android/agg/examples/win32_api/image1/Makefile new file mode 100755 index 0000000..d1d3f7d --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image1/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=image1 +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/image1/image1.dsp b/jni/desmume/src/android/agg/examples/win32_api/image1/image1.dsp new file mode 100755 index 0000000..ceed7ad --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image1/image1.dsp @@ -0,0 +1,153 @@ +# Microsoft Developer Studio Project File - Name="image1" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=image1 - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "image1.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "image1.mak" CFG="image1 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "image1 - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "image1 - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "image1 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./image1.exe" +# SUBTRACT LINK32 /profile + +!ELSEIF "$(CFG)" == "image1 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "image1 - Win32 Release" +# Name "image1 - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_image_filters.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_spline_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\image1.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/image1/image1.dsw b/jni/desmume/src/android/agg/examples/win32_api/image1/image1.dsw new file mode 100755 index 0000000..3905d44 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image1/image1.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "image1"=.\image1.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/image1/readme b/jni/desmume/src/android/agg/examples/win32_api/image1/readme new file mode 100755 index 0000000..d823d3d --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image1/readme @@ -0,0 +1 @@ +Download http://www.antigrain.com/spheres.bmp before running this example \ No newline at end of file diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_alpha/Makefile b/jni/desmume/src/android/agg/examples/win32_api/image_alpha/Makefile new file mode 100755 index 0000000..7d70f3c --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_alpha/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=image_alpha +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_alpha/image_alpha.dsp b/jni/desmume/src/android/agg/examples/win32_api/image_alpha/image_alpha.dsp new file mode 100755 index 0000000..508d925 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_alpha/image_alpha.dsp @@ -0,0 +1,149 @@ +# Microsoft Developer Studio Project File - Name="image_alpha" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=image_alpha - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "image_alpha.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "image_alpha.mak" CFG="image_alpha - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "image_alpha - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "image_alpha - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "image_alpha - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./image_alpha.exe" +# SUBTRACT LINK32 /profile + +!ELSEIF "$(CFG)" == "image_alpha - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MD /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "image_alpha - Win32 Release" +# Name "image_alpha - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_image_filters.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_spline_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\image_alpha.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_alpha/image_alpha.dsw b/jni/desmume/src/android/agg/examples/win32_api/image_alpha/image_alpha.dsw new file mode 100755 index 0000000..4fde136 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_alpha/image_alpha.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "image_alpha"=.\image_alpha.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_alpha/readme b/jni/desmume/src/android/agg/examples/win32_api/image_alpha/readme new file mode 100755 index 0000000..8aa31dd --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_alpha/readme @@ -0,0 +1 @@ +Download http://www.antigrain.com/spheres.bmp before running this example. diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_filters/Makefile b/jni/desmume/src/android/agg/examples/win32_api/image_filters/Makefile new file mode 100755 index 0000000..9dba1af --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_filters/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=image_filters +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_filters/image_filters.dsp b/jni/desmume/src/android/agg/examples/win32_api/image_filters/image_filters.dsp new file mode 100755 index 0000000..b0131e7 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_filters/image_filters.dsp @@ -0,0 +1,173 @@ +# Microsoft Developer Studio Project File - Name="image_filters" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=image_filters - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "image_filters.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "image_filters.mak" CFG="image_filters - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "image_filters - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "image_filters - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "image_filters - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./image_filters.exe" +# SUBTRACT LINK32 /profile + +!ELSEIF "$(CFG)" == "image_filters - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MD /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "image_filters - Win32 Release" +# Name "image_filters - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_image_filters.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_spline_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\image_filters.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_span_image_filter_gray.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_image_filter_rgb.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_image_filter_rgba.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_filters/image_filters.dsw b/jni/desmume/src/android/agg/examples/win32_api/image_filters/image_filters.dsw new file mode 100755 index 0000000..eb5813e --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_filters/image_filters.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "image_filters"=.\image_filters.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_filters/readme b/jni/desmume/src/android/agg/examples/win32_api/image_filters/readme new file mode 100755 index 0000000..8aa31dd --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_filters/readme @@ -0,0 +1 @@ +Download http://www.antigrain.com/spheres.bmp before running this example. diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_filters2/Makefile b/jni/desmume/src/android/agg/examples/win32_api/image_filters2/Makefile new file mode 100755 index 0000000..4164ee9 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_filters2/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=image_filters2 +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_filters2/image_filters2.dsp b/jni/desmume/src/android/agg/examples/win32_api/image_filters2/image_filters2.dsp new file mode 100755 index 0000000..5b83bd2 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_filters2/image_filters2.dsp @@ -0,0 +1,161 @@ +# Microsoft Developer Studio Project File - Name="image_filters2" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=image_filters2 - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "image_filters2.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "image_filters2.mak" CFG="image_filters2 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "image_filters2 - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "image_filters2 - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "image_filters2 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./image_filters2.exe" +# SUBTRACT LINK32 /profile + +!ELSEIF "$(CFG)" == "image_filters2 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MD /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "image_filters2 - Win32 Release" +# Name "image_filters2 - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_image_filters.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_spline_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\image_filters2.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_filters2/image_filters2.dsw b/jni/desmume/src/android/agg/examples/win32_api/image_filters2/image_filters2.dsw new file mode 100755 index 0000000..fcc168f --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_filters2/image_filters2.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "image_filters2"=.\image_filters2.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_filters2/readme b/jni/desmume/src/android/agg/examples/win32_api/image_filters2/readme new file mode 100755 index 0000000..8aa31dd --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_filters2/readme @@ -0,0 +1 @@ +Download http://www.antigrain.com/spheres.bmp before running this example. diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_fltr_graph/Makefile b/jni/desmume/src/android/agg/examples/win32_api/image_fltr_graph/Makefile new file mode 100755 index 0000000..92593b4 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_fltr_graph/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=image_fltr_graph +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_fltr_graph/image_fltr_graph.dsp b/jni/desmume/src/android/agg/examples/win32_api/image_fltr_graph/image_fltr_graph.dsp new file mode 100755 index 0000000..f69d424 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_fltr_graph/image_fltr_graph.dsp @@ -0,0 +1,169 @@ +# Microsoft Developer Studio Project File - Name="image_fltr_graph" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=image_fltr_graph - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "image_fltr_graph.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "image_fltr_graph.mak" CFG="image_fltr_graph - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "image_fltr_graph - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "image_fltr_graph - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "image_fltr_graph - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./image_fltr_graph.exe" +# SUBTRACT LINK32 /profile + +!ELSEIF "$(CFG)" == "image_fltr_graph - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MD /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "image_fltr_graph - Win32 Release" +# Name "image_fltr_graph - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_image_filters.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_spline_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\image_fltr_graph.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_span_bgra32_image.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=..\..\..\include\agg_gouraud_attr.h +# End Source File +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_fltr_graph/image_fltr_graph.dsw b/jni/desmume/src/android/agg/examples/win32_api/image_fltr_graph/image_fltr_graph.dsw new file mode 100755 index 0000000..3705197 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_fltr_graph/image_fltr_graph.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "image_fltr_graph"=.\image_fltr_graph.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_perspective/Makefile b/jni/desmume/src/android/agg/examples/win32_api/image_perspective/Makefile new file mode 100755 index 0000000..91025f4 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_perspective/Makefile @@ -0,0 +1,42 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=image_perspective +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../interactive_polygon.cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../interactive_polygon.o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_perspective/image_perspective.dsp b/jni/desmume/src/android/agg/examples/win32_api/image_perspective/image_perspective.dsp new file mode 100755 index 0000000..c96cc23 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_perspective/image_perspective.dsp @@ -0,0 +1,151 @@ +# Microsoft Developer Studio Project File - Name="image_perspective" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=image_perspective - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "image_perspective.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "image_perspective.mak" CFG="image_perspective - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "image_perspective - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "image_perspective - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "image_perspective - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./image_perspective.exe" + +!ELSEIF "$(CFG)" == "image_perspective - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "image_perspective - Win32 Release" +# Name "image_perspective - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_image_filters.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\image_perspective.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\interactive_polygon.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_image_accessors.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_pixfmt_rgba.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_perspective/image_perspective.dsw b/jni/desmume/src/android/agg/examples/win32_api/image_perspective/image_perspective.dsw new file mode 100755 index 0000000..acf817f --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_perspective/image_perspective.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "image_perspective"=.\image_perspective.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_perspective/readme b/jni/desmume/src/android/agg/examples/win32_api/image_perspective/readme new file mode 100755 index 0000000..8aa31dd --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_perspective/readme @@ -0,0 +1 @@ +Download http://www.antigrain.com/spheres.bmp before running this example. diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_resample/Makefile b/jni/desmume/src/android/agg/examples/win32_api/image_resample/Makefile new file mode 100755 index 0000000..267efa4 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_resample/Makefile @@ -0,0 +1,42 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=image_resample +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../interactive_polygon.cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../interactive_polygon.o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_resample/image_resample.dsp b/jni/desmume/src/android/agg/examples/win32_api/image_resample/image_resample.dsp new file mode 100755 index 0000000..77a6385 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_resample/image_resample.dsp @@ -0,0 +1,187 @@ +# Microsoft Developer Studio Project File - Name="image_resample" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=image_resample - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "image_resample.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "image_resample.mak" CFG="image_resample - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "image_resample - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "image_resample - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "image_resample - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./image_resample.exe" + +!ELSEIF "$(CFG)" == "image_resample - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "image_resample - Win32 Release" +# Name "image_resample - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_bezier_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_image_filters.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_polygon_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\image_resample.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\interactive_polygon.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_color_gray.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_image_filter.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_image_filter_gray.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_image_filter_rgb.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_image_filter_rgba.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_interpolator_persp.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_subdiv_adaptor.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_resample/image_resample.dsw b/jni/desmume/src/android/agg/examples/win32_api/image_resample/image_resample.dsw new file mode 100755 index 0000000..c1363fd --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_resample/image_resample.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "image_resample"=.\image_resample.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_resample/readme b/jni/desmume/src/android/agg/examples/win32_api/image_resample/readme new file mode 100755 index 0000000..8aa31dd --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_resample/readme @@ -0,0 +1 @@ +Download http://www.antigrain.com/spheres.bmp before running this example. diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_transforms/Makefile b/jni/desmume/src/android/agg/examples/win32_api/image_transforms/Makefile new file mode 100755 index 0000000..1d88d45 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_transforms/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=image_transforms +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_transforms/image_transforms.dsp b/jni/desmume/src/android/agg/examples/win32_api/image_transforms/image_transforms.dsp new file mode 100755 index 0000000..bcaed82 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_transforms/image_transforms.dsp @@ -0,0 +1,173 @@ +# Microsoft Developer Studio Project File - Name="image_transforms" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=image_transforms - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "image_transforms.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "image_transforms.mak" CFG="image_transforms - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "image_transforms - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "image_transforms - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "image_transforms - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./image_transforms.exe" +# SUBTRACT LINK32 /profile + +!ELSEIF "$(CFG)" == "image_transforms - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MD /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "image_transforms - Win32 Release" +# Name "image_transforms - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_image_filters.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_spline_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\image_transforms.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_span_image_filter_rgb24.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_image_filter_rgba32.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=..\..\..\include\agg_gouraud_attr.h +# End Source File +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_transforms/image_transforms.dsw b/jni/desmume/src/android/agg/examples/win32_api/image_transforms/image_transforms.dsw new file mode 100755 index 0000000..4dbf442 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_transforms/image_transforms.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "image_transforms"=.\image_transforms.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/image_transforms/readme! b/jni/desmume/src/android/agg/examples/win32_api/image_transforms/readme! new file mode 100755 index 0000000..c3e504a --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/image_transforms/readme! @@ -0,0 +1,174 @@ +IMPORTANT! +Download http://www.antigrain.com/spheres.bmp before running this example. + + +Using affine transformations for images looks tricky, but it's not, especially +when you understand the main idea. You can apply any affine transformations +to images of any size and draw any part of the image. + +This example demonstrates the ideas of constructing affine matrices for +images. The example contains 6 variants of scaling/rotation/translation +matrices. Also, there are the following important variables: + +m_polygon_angle; +m_polygon_scale; + +m_image_angle; +m_image_scale; + +m_image_center_x; +m_image_center_y; + +m_polygon_cx; +m_polygon_cy; + +m_image_cx; +m_image_cy; + + +Variables m_polygon_... refer to the source path (star) that will be used to +transform the image, variables m_image_... refer to the image parametres. +Actually, different variants of transformations use different variables +(in some cases m_polygon_... is used to create the image affine matrix). +The meaning of the variables is the following: + +m_polygon_angle; +m_polygon_scale; + +Are actually two slider controls on the left. + +m_polygon_cx; +m_polygon_cy; + +Are the center of the "star", that is the geometric center of the source path. +You can drag the "star" with the left mouse button. + +m_image_angle; +m_image_scale; + +are two respective sliders on the right. + +m_image_cx; +m_image_cy; + +are the coordinates of the green marker. The marker can also be dragged. + +m_image_center_x; +m_image_center_y; + +are the center of the image. You can consider them as constants. +In certain cases it's easier to understand the idea when we have some +"reference point", like the center or the origin of the axes. + +The image transformation matrix doesn't depend on anything else. +It means that the code above the line "// --------------(Example 0)": + + polygon_mtx *= agg::trans_affine_translation(-m_polygon_cx, -m_polygon_cy); + polygon_mtx *= agg::trans_affine_rotation(m_polygon_angle.value() * agg::pi / 180.0); + polygon_mtx *= agg::trans_affine_scaling(m_polygon_scale.value()); + polygon_mtx *= agg::trans_affine_translation(m_polygon_cx, m_polygon_cy); + +affects only the drawn path. So, the only way to shift, rotate, or scale the +image is to use the image affine matrix (image_mtx in this example). + +Another important thing is that due to the nature of the algorithm you +have to use the inverse transformations. The algorithm takes the +coordinates of every destination pixel, applies the transformations and +obtains the coordinates of the pixel to pick it up from the source image. +The coordinates of the destination pixels are always known and they have +regular, pixel accuracy. After transforming they usually fall somewhere " +between" pixels. This fact allows us to apply anti-aliasing filters like +bilinear, bicubic, sinc, blackman, etc. After filtering we know the value of the +destination pixel and we can put it in its place. This is why the algorithm +uses the inverse affine matrix. In other words you prepare the transformation +matrix as usual and then invret it before using: + + image_mtx *= agg::trans_affine_translation(-m_image_center_x, -m_image_center_y); + image_mtx *= agg::trans_affine_rotation(m_polygon_angle.value() * agg::pi / 180.0); + image_mtx *= agg::trans_affine_scaling(m_polygon_scale.value()); + image_mtx *= agg::trans_affine_translation(m_polygon_cx, m_polygon_cy); + image_mtx.invert(); + +This code illustrates the behaviour when we have synchronous transformations +of the source path and the image. + +Well, let us return to example 0. Here we have a "star" that can be dragged with +the left mouse button, a small round green marker, and four sliders. +The marker and the sliders on the right don't affect anything. As it was said, +this example simply copies pixels from the source image to the destination canvas. + +Example 1. The marker and the image sliders on the right still +don't work, but now the image is moved, scaled, and rotated syncronously with +the "star". We simply take the reference point, which is m_image_center_x(y), +rotate and scale the image around it, and then, translate the image to +m_polygon_cx(cy). + + +Example 2 is the same as 1 but instead of using "m_polygon_..." parameters we +use "m_image_..." ones, so the marker and the sliders on the right now work +independently. In other words you can control the image and the "star" separately. + image_mtx *= agg::trans_affine_translation(-m_image_center_x, -m_image_center_y); + image_mtx *= agg::trans_affine_rotation(m_image_angle.value() * agg::pi / 180.0); + image_mtx *= agg::trans_affine_scaling(m_image_scale.value()); + image_mtx *= agg::trans_affine_translation(m_image_cx, m_image_cy); + image_mtx.invert(); + + +Example 3 is the same as the above but instead of using "m_image_cx(cy)" we use +m_polygon_cx(cy). So that, the image is rotated and scaled around its center, +but the marker doesn't have any effect. + image_mtx *= agg::trans_affine_translation(-m_image_center_x, -m_image_center_y); + image_mtx *= agg::trans_affine_rotation(m_image_angle.value() * agg::pi / 180.0); + image_mtx *= agg::trans_affine_scaling(m_image_scale.value()); + image_mtx *= agg::trans_affine_translation(m_polygon_cx, m_polygon_cy); + image_mtx.invert(); + + +Example 4 is the same as 1, but we use m_image_cx(cy) as the source point +in the image. So, the image sliders don't work, the image is transformed +synchronously with the path, but we are able to choose the source point for +image transformations. That is the idea: we take the source point in the +image, perform the transformations around it and then move this source +point to the center of the "star". + image_mtx *= agg::trans_affine_translation(-m_image_cx, -m_image_cy); + image_mtx *= agg::trans_affine_rotation(m_polygon_angle.value() * agg::pi / 180.0); + image_mtx *= agg::trans_affine_scaling(m_polygon_scale.value()); + image_mtx *= agg::trans_affine_translation(m_polygon_cx, m_polygon_cy); + image_mtx.invert(); + + +Example 5 is the same as 2, but there we have a combination of the scaling +and rotation of the "star" and the image. + image_mtx *= agg::trans_affine_translation(-m_image_center_x, -m_image_center_y); + image_mtx *= agg::trans_affine_rotation(m_image_angle.value() * agg::pi / 180.0); + image_mtx *= agg::trans_affine_rotation(m_polygon_angle.value() * agg::pi / 180.0); + image_mtx *= agg::trans_affine_scaling(m_image_scale.value()); + image_mtx *= agg::trans_affine_scaling(m_polygon_scale.value()); + image_mtx *= agg::trans_affine_translation(m_image_cx, m_image_cy); + image_mtx.invert(); +BTW, code above can be simplified like this: + image_mtx *= agg::trans_affine_translation(-m_image_center_x, -m_image_center_y); + image_mtx *= agg::trans_affine_rotation(m_image_angle.value() * agg::pi / 180.0 + + m_polygon_angle.value() * agg::pi / 180.0); + image_mtx *= agg::trans_affine_scaling(m_image_scale.value() * m_polygon_scale.value()); + image_mtx *= agg::trans_affine_translation(m_image_cx, m_image_cy); + image_mtx.invert(); + + +Finally, example 5 is probably not very interesting in practice, but still, it +can simplify understanding of the idea. This example uses only m_image_... +parameters. It shifts the image from m_image_cx(cy) to the origin (0,0), then +applies rotation and scaling, and finally, shifts the image back. So that, +point m_image_cx(cy) is simply the center of the transformations. When the +image angle is 0.0 and the scale is 1.0 dragging this point doesn't have any +effect. + image_mtx *= agg::trans_affine_translation(-m_image_cx, -m_image_cy); + image_mtx *= agg::trans_affine_rotation(m_image_angle.value() * agg::pi / 180.0); + image_mtx *= agg::trans_affine_scaling(m_image_scale.value()); + image_mtx *= agg::trans_affine_translation(m_image_cx, m_image_cy); + image_mtx.invert(); + + +Many thank to you if you read it and many special thanks if you could understand +something. :-) + diff --git a/jni/desmume/src/android/agg/examples/win32_api/line_patterns/Makefile b/jni/desmume/src/android/agg/examples/win32_api/line_patterns/Makefile new file mode 100755 index 0000000..19483a9 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/line_patterns/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=line_patterns +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/line_patterns/line_patterns.dsp b/jni/desmume/src/android/agg/examples/win32_api/line_patterns/line_patterns.dsp new file mode 100755 index 0000000..550f054 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/line_patterns/line_patterns.dsp @@ -0,0 +1,163 @@ +# Microsoft Developer Studio Project File - Name="line_patterns" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=line_patterns - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "line_patterns.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "line_patterns.mak" CFG="line_patterns - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "line_patterns - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "line_patterns - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "line_patterns - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 /out:"./line_patterns.exe" + +!ELSEIF "$(CFG)" == "line_patterns - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "line_patterns - Win32 Release" +# Name "line_patterns - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_bezier_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_line_aa_basics.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_line_profile_aa.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_polygon_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\line_patterns.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/line_patterns/line_patterns.dsw b/jni/desmume/src/android/agg/examples/win32_api/line_patterns/line_patterns.dsw new file mode 100755 index 0000000..5c2a387 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/line_patterns/line_patterns.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "line_patterns"=.\line_patterns.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/line_patterns_clip/Makefile b/jni/desmume/src/android/agg/examples/win32_api/line_patterns_clip/Makefile new file mode 100755 index 0000000..60d8a13 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/line_patterns_clip/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=line_patterns_clip +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/line_patterns_clip/line_patterns_clip.dsp b/jni/desmume/src/android/agg/examples/win32_api/line_patterns_clip/line_patterns_clip.dsp new file mode 100755 index 0000000..e6e998c --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/line_patterns_clip/line_patterns_clip.dsp @@ -0,0 +1,167 @@ +# Microsoft Developer Studio Project File - Name="line_patterns_clip" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=line_patterns_clip - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "line_patterns_clip.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "line_patterns_clip.mak" CFG="line_patterns_clip - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "line_patterns_clip - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "line_patterns_clip - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "line_patterns_clip - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 /out:"./line_patterns_clip.exe" + +!ELSEIF "$(CFG)" == "line_patterns_clip - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "line_patterns_clip - Win32 Release" +# Name "line_patterns_clip - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_bezier_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_line_aa_basics.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_line_profile_aa.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_polygon_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vpgen_clip_polyline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\line_patterns_clip.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/line_patterns_clip/line_patterns_clip.dsw b/jni/desmume/src/android/agg/examples/win32_api/line_patterns_clip/line_patterns_clip.dsw new file mode 100755 index 0000000..0fa9f50 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/line_patterns_clip/line_patterns_clip.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "line_patterns_clip"=.\line_patterns_clip.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/lion/Makefile b/jni/desmume/src/android/agg/examples/win32_api/lion/Makefile new file mode 100755 index 0000000..d7e4764 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/lion/Makefile @@ -0,0 +1,41 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=lion +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../parse_lion.cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/lion/lion.dsp b/jni/desmume/src/android/agg/examples/win32_api/lion/lion.dsp new file mode 100755 index 0000000..91e658f --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/lion/lion.dsp @@ -0,0 +1,143 @@ +# Microsoft Developer Studio Project File - Name="lion" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=lion - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "lion.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "lion.mak" CFG="lion - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "lion - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "lion - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "lion - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./lion.exe" + +!ELSEIF "$(CFG)" == "lion - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "lion - Win32 Release" +# Name "lion - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\lion.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\parse_lion.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_pixfmt_rgba.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/lion/lion.dsw b/jni/desmume/src/android/agg/examples/win32_api/lion/lion.dsw new file mode 100755 index 0000000..419081a --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/lion/lion.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "lion"=.\lion.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/lion_lens/Makefile b/jni/desmume/src/android/agg/examples/win32_api/lion_lens/Makefile new file mode 100755 index 0000000..4403185 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/lion_lens/Makefile @@ -0,0 +1,41 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=lion_lens +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../parse_lion.cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/lion_lens/lion_lens.dsp b/jni/desmume/src/android/agg/examples/win32_api/lion_lens/lion_lens.dsp new file mode 100755 index 0000000..82f0c43 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/lion_lens/lion_lens.dsp @@ -0,0 +1,147 @@ +# Microsoft Developer Studio Project File - Name="lion_lens" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=lion_lens - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "lion_lens.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "lion_lens.mak" CFG="lion_lens - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "lion_lens - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "lion_lens - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "lion_lens - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./lion_lens.exe" + +!ELSEIF "$(CFG)" == "lion_lens - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "lion_lens - Win32 Release" +# Name "lion_lens - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_warp_magnifier.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vpgen_segmentator.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\lion_lens.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\parse_lion.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/lion_lens/lion_lens.dsw b/jni/desmume/src/android/agg/examples/win32_api/lion_lens/lion_lens.dsw new file mode 100755 index 0000000..57293ed --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/lion_lens/lion_lens.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "lion_lens"=.\lion_lens.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/lion_outline/Makefile b/jni/desmume/src/android/agg/examples/win32_api/lion_outline/Makefile new file mode 100755 index 0000000..b300ffc --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/lion_outline/Makefile @@ -0,0 +1,41 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=lion_outline +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../parse_lion.cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/lion_outline/lion_outline.dsp b/jni/desmume/src/android/agg/examples/win32_api/lion_outline/lion_outline.dsp new file mode 100755 index 0000000..5969ab0 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/lion_outline/lion_outline.dsp @@ -0,0 +1,155 @@ +# Microsoft Developer Studio Project File - Name="lion_outline" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=lion_outline - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "lion_outline.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "lion_outline.mak" CFG="lion_outline - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "lion_outline - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "lion_outline - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "lion_outline - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./lion_outline.exe" + +!ELSEIF "$(CFG)" == "lion_outline - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "lion_outline - Win32 Release" +# Name "lion_outline - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_line_aa_basics.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_line_profile_aa.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\lion_outline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\parse_lion.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/lion_outline/lion_outline.dsw b/jni/desmume/src/android/agg/examples/win32_api/lion_outline/lion_outline.dsw new file mode 100755 index 0000000..4a2871d --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/lion_outline/lion_outline.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "lion_outline"=.\lion_outline.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/mol_view/Makefile b/jni/desmume/src/android/agg/examples/win32_api/mol_view/Makefile new file mode 100755 index 0000000..7cc5e0c --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/mol_view/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=mol_view +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/mol_view/mol_view.dsp b/jni/desmume/src/android/agg/examples/win32_api/mol_view/mol_view.dsp new file mode 100755 index 0000000..16e20b8 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/mol_view/mol_view.dsp @@ -0,0 +1,177 @@ +# Microsoft Developer Studio Project File - Name="mol_view" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=mol_view - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mol_view.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mol_view.mak" CFG="mol_view - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mol_view - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "mol_view - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mol_view - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 /out:"./mol_view.exe" + +!ELSEIF "$(CFG)" == "mol_view - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "mol_view - Win32 Release" +# Name "mol_view - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\mol_view.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_gsv_text.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_gsv_text_outline.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_math.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_path_storage.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\platform\agg_platform_support.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_rasterizer_scanline_aa.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_renderer_u8.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\ctrl\agg_scale_ctrl.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_trans_affine.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/mol_view/mol_view.dsw b/jni/desmume/src/android/agg/examples/win32_api/mol_view/mol_view.dsw new file mode 100755 index 0000000..2548625 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/mol_view/mol_view.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "mol_view"=.\mol_view.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/mol_view/readme b/jni/desmume/src/android/agg/examples/win32_api/mol_view/readme new file mode 100755 index 0000000..0155691 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/mol_view/readme @@ -0,0 +1,2 @@ +Download http://www.antigrain.com/1.sdf before running this example. +Press PageUp/PgDown to switch between different molecules. diff --git a/jni/desmume/src/android/agg/examples/win32_api/multi_clip/Makefile b/jni/desmume/src/android/agg/examples/win32_api/multi_clip/Makefile new file mode 100755 index 0000000..a952736 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/multi_clip/Makefile @@ -0,0 +1,41 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=multi_clip +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../parse_lion.cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/multi_clip/multi_clip.dsp b/jni/desmume/src/android/agg/examples/win32_api/multi_clip/multi_clip.dsp new file mode 100755 index 0000000..7e0d1ce --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/multi_clip/multi_clip.dsp @@ -0,0 +1,151 @@ +# Microsoft Developer Studio Project File - Name="multi_clip" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=multi_clip - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "multi_clip.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "multi_clip.mak" CFG="multi_clip - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "multi_clip - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "multi_clip - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "multi_clip - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./multi_clip.exe" + +!ELSEIF "$(CFG)" == "multi_clip - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "multi_clip - Win32 Release" +# Name "multi_clip - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_line_aa_basics.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_line_profile_aa.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\multi_clip.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\parse_lion.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/multi_clip/multi_clip.dsw b/jni/desmume/src/android/agg/examples/win32_api/multi_clip/multi_clip.dsw new file mode 100755 index 0000000..20c3092 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/multi_clip/multi_clip.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "multi_clip"=.\multi_clip.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/pattern_fill/Makefile b/jni/desmume/src/android/agg/examples/win32_api/pattern_fill/Makefile new file mode 100755 index 0000000..1514cbd --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/pattern_fill/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=pattern_fill +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/pattern_fill/pattern_fill.dsp b/jni/desmume/src/android/agg/examples/win32_api/pattern_fill/pattern_fill.dsp new file mode 100755 index 0000000..002b235 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/pattern_fill/pattern_fill.dsp @@ -0,0 +1,169 @@ +# Microsoft Developer Studio Project File - Name="pattern_fill" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=pattern_fill - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "pattern_fill.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "pattern_fill.mak" CFG="pattern_fill - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "pattern_fill - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "pattern_fill - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "pattern_fill - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./pattern_fill.exe" +# SUBTRACT LINK32 /profile + +!ELSEIF "$(CFG)" == "pattern_fill - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MD /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "pattern_fill - Win32 Release" +# Name "pattern_fill - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_spline_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_smooth_poly1.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\pattern_fill.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_span_pattern_gray.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/pattern_fill/pattern_fill.dsw b/jni/desmume/src/android/agg/examples/win32_api/pattern_fill/pattern_fill.dsw new file mode 100755 index 0000000..40c7080 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/pattern_fill/pattern_fill.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "pattern_fill"=.\pattern_fill.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/pattern_perspective/pattern_perspective.dsp b/jni/desmume/src/android/agg/examples/win32_api/pattern_perspective/pattern_perspective.dsp new file mode 100755 index 0000000..a2bf38b --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/pattern_perspective/pattern_perspective.dsp @@ -0,0 +1,171 @@ +# Microsoft Developer Studio Project File - Name="pattern_perspective" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=pattern_perspective - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "pattern_perspective.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "pattern_perspective.mak" CFG="pattern_perspective - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "pattern_perspective - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "pattern_perspective - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "pattern_perspective - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./pattern_perspective.exe" + +!ELSEIF "$(CFG)" == "pattern_perspective - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "pattern_perspective - Win32 Release" +# Name "pattern_perspective - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_image_filters.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\interactive_polygon.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\pattern_perspective.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_span_allocator.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_generator.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_image_filter.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_image_filter_rgba.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_pattern_filter_gray.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_pattern_filter_rgb.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_pattern_filter_rgba.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/pattern_perspective/pattern_perspective.dsw b/jni/desmume/src/android/agg/examples/win32_api/pattern_perspective/pattern_perspective.dsw new file mode 100755 index 0000000..3e9efcb --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/pattern_perspective/pattern_perspective.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "pattern_perspective"=.\pattern_perspective.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/pattern_resample/Makefile b/jni/desmume/src/android/agg/examples/win32_api/pattern_resample/Makefile new file mode 100755 index 0000000..5872723 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/pattern_resample/Makefile @@ -0,0 +1,42 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=pattern_resample +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../interactive_polygon.cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../interactive_polygon.o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/pattern_resample/pattern_resample.dsp b/jni/desmume/src/android/agg/examples/win32_api/pattern_resample/pattern_resample.dsp new file mode 100755 index 0000000..79fb650 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/pattern_resample/pattern_resample.dsp @@ -0,0 +1,179 @@ +# Microsoft Developer Studio Project File - Name="pattern_resample" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=pattern_resample - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "pattern_resample.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "pattern_resample.mak" CFG="pattern_resample - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "pattern_resample - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "pattern_resample - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "pattern_resample - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./pattern_resample.exe" + +!ELSEIF "$(CFG)" == "pattern_resample - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "pattern_resample - Win32 Release" +# Name "pattern_resample - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_bezier_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_image_filters.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_polygon_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\interactive_polygon.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\pattern_resample.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_color_gray.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_image_filter_gray.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_image_filter_rgb.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_interpolator_persp.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_subdiv_adaptor.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/pattern_resample/pattern_resample.dsw b/jni/desmume/src/android/agg/examples/win32_api/pattern_resample/pattern_resample.dsw new file mode 100755 index 0000000..4f1b00d --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/pattern_resample/pattern_resample.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "pattern_resample"=.\pattern_resample.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/perspective/Makefile b/jni/desmume/src/android/agg/examples/win32_api/perspective/Makefile new file mode 100755 index 0000000..2906f55 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/perspective/Makefile @@ -0,0 +1,42 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=perspective +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../parse_lion.cpp \ +../../interactive_polygon.cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/perspective/perspective.dsp b/jni/desmume/src/android/agg/examples/win32_api/perspective/perspective.dsp new file mode 100755 index 0000000..0b25b90 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/perspective/perspective.dsp @@ -0,0 +1,143 @@ +# Microsoft Developer Studio Project File - Name="perspective" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=perspective - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "perspective.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "perspective.mak" CFG="perspective - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "perspective - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "perspective - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "perspective - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./perspective.exe" + +!ELSEIF "$(CFG)" == "perspective - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "perspective - Win32 Release" +# Name "perspective - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\interactive_polygon.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\parse_lion.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\perspective.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/perspective/perspective.dsw b/jni/desmume/src/android/agg/examples/win32_api/perspective/perspective.dsw new file mode 100755 index 0000000..61c2170 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/perspective/perspective.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "perspective"=.\perspective.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/polymorphic_renderer/Makefile b/jni/desmume/src/android/agg/examples/win32_api/polymorphic_renderer/Makefile new file mode 100755 index 0000000..90aec09 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/polymorphic_renderer/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=polymorphic_renderer +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/polymorphic_renderer/polymorphic_renderer.dsp b/jni/desmume/src/android/agg/examples/win32_api/polymorphic_renderer/polymorphic_renderer.dsp new file mode 100755 index 0000000..d09e926 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/polymorphic_renderer/polymorphic_renderer.dsp @@ -0,0 +1,131 @@ +# Microsoft Developer Studio Project File - Name="polymorphic_renderer" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=polymorphic_renderer - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "polymorphic_renderer.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "polymorphic_renderer.mak" CFG="polymorphic_renderer - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "polymorphic_renderer - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "polymorphic_renderer - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "polymorphic_renderer - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 /out:"./polymorphic_renderer.exe" + +!ELSEIF "$(CFG)" == "polymorphic_renderer - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "polymorphic_renderer - Win32 Release" +# Name "polymorphic_renderer - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_contour.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_dash.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\polymorphic_renderer.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/polymorphic_renderer/polymorphic_renderer.dsw b/jni/desmume/src/android/agg/examples/win32_api/polymorphic_renderer/polymorphic_renderer.dsw new file mode 100755 index 0000000..f15a8d4 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/polymorphic_renderer/polymorphic_renderer.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "polymorphic_renderer"=.\polymorphic_renderer.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/pure_api/StdAfx.cpp b/jni/desmume/src/android/agg/examples/win32_api/pure_api/StdAfx.cpp new file mode 100755 index 0000000..1af3124 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/pure_api/StdAfx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// pure_api.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/jni/desmume/src/android/agg/examples/win32_api/pure_api/StdAfx.h b/jni/desmume/src/android/agg/examples/win32_api/pure_api/StdAfx.h new file mode 100755 index 0000000..1e47eff --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/pure_api/StdAfx.h @@ -0,0 +1,32 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_) +#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + + +// Windows Header Files: +#include <windows.h> + +// C RunTime Header Files +#include <stdlib.h> +#include <malloc.h> +#include <memory.h> +#include <tchar.h> + +// Local Header Files + +// TODO: reference additional headers your program requires here + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_) diff --git a/jni/desmume/src/android/agg/examples/win32_api/pure_api/pure_api.cpp b/jni/desmume/src/android/agg/examples/win32_api/pure_api/pure_api.cpp new file mode 100755 index 0000000..79f21ea --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/pure_api/pure_api.cpp @@ -0,0 +1,292 @@ +// pure_api.cpp : Defines the entry point for the application. +// + +#include "stdafx.h" +#include "resource.h" + +#include "agg_scanline_p.h" +#include "agg_renderer_scanline.h" +#include "agg_pixfmt_rgba.h" +#include "agg_rasterizer_scanline_aa.h" + +#define MAX_LOADSTRING 100 + +// Global Variables: +HINSTANCE hInst; // current instance +TCHAR szTitle[MAX_LOADSTRING]; // The title bar text +TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text + +// Foward declarations of functions included in this code module: +ATOM MyRegisterClass(HINSTANCE hInstance); +BOOL InitInstance(HINSTANCE, int); +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); + +int APIENTRY WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) +{ + // TODO: Place code here. + MSG msg; + HACCEL hAccelTable; + + // Initialize global strings + LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); + LoadString(hInstance, IDC_PURE_API, szWindowClass, MAX_LOADSTRING); + MyRegisterClass(hInstance); + + // Perform application initialization: + if (!InitInstance (hInstance, nCmdShow)) + { + return FALSE; + } + + hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_PURE_API); + + // Main message loop: + while (GetMessage(&msg, NULL, 0, 0)) + { + if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + return msg.wParam; +} + + + +// +// FUNCTION: MyRegisterClass() +// +// PURPOSE: Registers the window class. +// +// COMMENTS: +// +// This function and its usage is only necessary if you want this code +// to be compatible with Win32 systems prior to the 'RegisterClassEx' +// function that was added to Windows 95. It is important to call this function +// so that the application will get 'well formed' small icons associated +// with it. +// +ATOM MyRegisterClass(HINSTANCE hInstance) +{ + WNDCLASSEX wcex; + + wcex.cbSize = sizeof(WNDCLASSEX); + + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = (WNDPROC)WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_PURE_API); + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = (LPCSTR)IDC_PURE_API; + wcex.lpszClassName = szWindowClass; + wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); + + return RegisterClassEx(&wcex); +} + +// +// FUNCTION: InitInstance(HANDLE, int) +// +// PURPOSE: Saves instance handle and creates main window +// +// COMMENTS: +// +// In this function, we save the instance handle in a global variable and +// create and display the main program window. +// +BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) +{ + HWND hWnd; + + hInst = hInstance; // Store instance handle in our global variable + + hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); + + if (!hWnd) + { + return FALSE; + } + + ShowWindow(hWnd, nCmdShow); + UpdateWindow(hWnd); + + return TRUE; +} + +// +// FUNCTION: WndProc(HWND, unsigned, WORD, LONG) +// +// PURPOSE: Processes messages for the main window. +// +// WM_COMMAND - process the application menu +// WM_PAINT - Paint the main window +// WM_DESTROY - post a quit message and return +// +// +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int wmId, wmEvent; + PAINTSTRUCT ps; + HDC hdc; + TCHAR szHello[MAX_LOADSTRING]; + LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING); + + switch (message) + { + case WM_COMMAND: + wmId = LOWORD(wParam); + wmEvent = HIWORD(wParam); + // Parse the menu selections: + switch (wmId) + { + case IDM_ABOUT: + DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); + break; + case IDM_EXIT: + DestroyWindow(hWnd); + break; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + break; + case WM_PAINT: + { + hdc = BeginPaint(hWnd, &ps); + RECT rt; + GetClientRect(hWnd, &rt); + + int width = rt.right - rt.left; + int height = rt.bottom - rt.top; + + //============================================================ + //Creating compatible DC and a bitmap to render the image + BITMAPINFO bmp_info; + bmp_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmp_info.bmiHeader.biWidth = width; + bmp_info.bmiHeader.biHeight = height; + bmp_info.bmiHeader.biPlanes = 1; + bmp_info.bmiHeader.biBitCount = 32; + bmp_info.bmiHeader.biCompression = BI_RGB; + bmp_info.bmiHeader.biSizeImage = 0; + bmp_info.bmiHeader.biXPelsPerMeter = 0; + bmp_info.bmiHeader.biYPelsPerMeter = 0; + bmp_info.bmiHeader.biClrUsed = 0; + bmp_info.bmiHeader.biClrImportant = 0; + + HDC mem_dc = ::CreateCompatibleDC(hdc); + + void* buf = 0; + + HBITMAP bmp = ::CreateDIBSection( + mem_dc, + &bmp_info, + DIB_RGB_COLORS, + &buf, + 0, + 0 + ); + + // Selecting the object before doing anything allows you + // to use AGG together with native Windows GDI. + HBITMAP temp = (HBITMAP)::SelectObject(mem_dc, bmp); + + + //============================================================ + // AGG lowest level code. + agg::rendering_buffer rbuf; + rbuf.attach((unsigned char*)buf, width, height, -width*4); // Use negative stride in order + // to keep Y-axis consistent with + // WinGDI, i.e., going down. + + // Pixel format and basic primitives renderer + agg::pixfmt_bgra32 pixf(rbuf); + agg::renderer_base<agg::pixfmt_bgra32> renb(pixf); + + renb.clear(agg::rgba8(255, 255, 255, 255)); + + // Scanline renderer for solid filling. + agg::renderer_scanline_aa_solid<agg::renderer_base<agg::pixfmt_bgra32> > ren(renb); + + // Rasterizer & scanline + agg::rasterizer_scanline_aa<> ras; + agg::scanline_p8 sl; + + // Polygon (triangle) + ras.move_to_d(20.7, 34.15); + ras.line_to_d(398.23, 123.43); + ras.line_to_d(165.45, 401.87); + + // Setting the attrribute (color) & Rendering + ren.color(agg::rgba8(80, 90, 60)); + agg::render_scanlines(ras, sl, ren); + //============================================================ + + + + //------------------------------------------------------------ + // Display the image. If the image is B-G-R-A (32-bits per pixel) + // one can use AlphaBlend instead of BitBlt. In case of AlphaBlend + // one also should clear the image with zero alpha, i.e. rgba8(0,0,0,0) + + ::BitBlt( + hdc, + rt.left, + rt.top, + width, + height, + mem_dc, + 0, + 0, + SRCCOPY + ); + + // Free resources + ::SelectObject(mem_dc, temp); + ::DeleteObject(bmp); + ::DeleteObject(mem_dc); + + EndPaint(hWnd, &ps); + } + break; + + + case WM_ERASEBKGND: // Don't forget to do nothing on Erase Background event :-) + break; + + case WM_DESTROY: + PostQuitMessage(0); + break; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} + +// Mesage handler for about box. +LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG: + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) + { + EndDialog(hDlg, LOWORD(wParam)); + return TRUE; + } + break; + } + return FALSE; +} diff --git a/jni/desmume/src/android/agg/examples/win32_api/pure_api/pure_api.dsp b/jni/desmume/src/android/agg/examples/win32_api/pure_api/pure_api.dsp new file mode 100755 index 0000000..15091f7 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/pure_api/pure_api.dsp @@ -0,0 +1,137 @@ +# Microsoft Developer Studio Project File - Name="pure_api" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=pure_api - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "pure_api.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "pure_api.mak" CFG="pure_api - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "pure_api - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "pure_api - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "pure_api - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 + +!ELSEIF "$(CFG)" == "pure_api - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "pure_api - Win32 Release" +# Name "pure_api - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\pure_api.cpp +# End Source File +# Begin Source File + +SOURCE=.\pure_api.rc +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\pure_api.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\pure_api.ico +# End Source File +# Begin Source File + +SOURCE=.\small.ico +# End Source File +# End Group +# Begin Source File + +SOURCE=.\ReadMe.txt +# End Source File +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/pure_api/pure_api.dsw b/jni/desmume/src/android/agg/examples/win32_api/pure_api/pure_api.dsw new file mode 100755 index 0000000..ac7cbf1 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/pure_api/pure_api.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "pure_api"=.\pure_api.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/pure_api/pure_api.h b/jni/desmume/src/android/agg/examples/win32_api/pure_api/pure_api.h new file mode 100755 index 0000000..fbd3810 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/pure_api/pure_api.h @@ -0,0 +1,12 @@ + +#if !defined(AFX_PURE_API_H__B17A1161_38FE_4F00_8284_B215A497C968__INCLUDED_) +#define AFX_PURE_API_H__B17A1161_38FE_4F00_8284_B215A497C968__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "resource.h" + + +#endif // !defined(AFX_PURE_API_H__B17A1161_38FE_4F00_8284_B215A497C968__INCLUDED_) diff --git a/jni/desmume/src/android/agg/examples/win32_api/pure_api/pure_api.ico b/jni/desmume/src/android/agg/examples/win32_api/pure_api/pure_api.ico new file mode 100755 index 0000000..3868835 Binary files /dev/null and b/jni/desmume/src/android/agg/examples/win32_api/pure_api/pure_api.ico differ diff --git a/jni/desmume/src/android/agg/examples/win32_api/pure_api/pure_api.rc b/jni/desmume/src/android/agg/examples/win32_api/pure_api/pure_api.rc new file mode 100755 index 0000000..6f92fc3 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/pure_api/pure_api.rc @@ -0,0 +1,135 @@ +//Microsoft Visual C++ generated resource script. +// + +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. + +IDI_PURE_API ICON DISCARDABLE "pure_api.ICO" +IDI_SMALL ICON DISCARDABLE "SMALL.ICO" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDC_PURE_API MENU DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "E&xit", IDM_EXIT + END + POPUP "&Help" + BEGIN + MENUITEM "&About ...", IDM_ABOUT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDC_PURE_API ACCELERATORS MOVEABLE PURE +BEGIN + "?", IDM_ABOUT, ASCII, ALT + "/", IDM_ABOUT, ASCII, ALT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 230, 75 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "About" +FONT 8, "System" +BEGIN + ICON IDI_PURE_API,IDC_MYICON,14,9,16,16 + LTEXT "pure_api Version 1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX + LTEXT "Copyright (C) 2002",IDC_STATIC,49,20,119,8 + DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""resource.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDC_PURE_API "PURE_API" + IDS_APP_TITLE "pure_api" + IDS_HELLO "Hello World!" +END + +#endif +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/jni/desmume/src/android/agg/examples/win32_api/pure_api/resource.h b/jni/desmume/src/android/agg/examples/win32_api/pure_api/resource.h new file mode 100755 index 0000000..ddd9069 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/pure_api/resource.h @@ -0,0 +1,27 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by PURE_API.RC +// +#define IDR_MAINFRAME 128 +#define IDD_PURE_API_DIALOG 102 +#define IDD_ABOUTBOX 103 +#define IDS_APP_TITLE 103 +#define IDM_ABOUT 104 +#define IDM_EXIT 105 +#define IDS_HELLO 106 +#define IDI_PURE_API 107 +#define IDI_SMALL 108 +#define IDC_PURE_API 109 +#define IDC_MYICON 2 +#define IDC_STATIC -1 +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS + +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/jni/desmume/src/android/agg/examples/win32_api/pure_api/small.ico b/jni/desmume/src/android/agg/examples/win32_api/pure_api/small.ico new file mode 100755 index 0000000..8f94d9a Binary files /dev/null and b/jni/desmume/src/android/agg/examples/win32_api/pure_api/small.ico differ diff --git a/jni/desmume/src/android/agg/examples/win32_api/raster_text/Makefile b/jni/desmume/src/android/agg/examples/win32_api/raster_text/Makefile new file mode 100755 index 0000000..a3af0cf --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/raster_text/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=raster_text +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/raster_text/raster_text.dsp b/jni/desmume/src/android/agg/examples/win32_api/raster_text/raster_text.dsp new file mode 100755 index 0000000..20c5bea --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/raster_text/raster_text.dsp @@ -0,0 +1,151 @@ +# Microsoft Developer Studio Project File - Name="raster_text" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=raster_text - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "raster_text.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "raster_text.mak" CFG="raster_text - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "raster_text - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "raster_text - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "raster_text - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./raster_text.exe" + +!ELSEIF "$(CFG)" == "raster_text - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "raster_text - Win32 Release" +# Name "raster_text - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_embedded_raster_fonts.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\raster_text.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_embedded_raster_fonts.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_glyph_raster_bin.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_renderer_raster_text.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_span_gradient.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/raster_text/raster_text.dsw b/jni/desmume/src/android/agg/examples/win32_api/raster_text/raster_text.dsw new file mode 100755 index 0000000..3a173c1 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/raster_text/raster_text.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "raster_text"=.\raster_text.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/rasterizer_compound/Makefile b/jni/desmume/src/android/agg/examples/win32_api/rasterizer_compound/Makefile new file mode 100755 index 0000000..8eda3aa --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/rasterizer_compound/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=rasterizer_compound +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/rasterizer_compound/rasterizer_compound.dsp b/jni/desmume/src/android/agg/examples/win32_api/rasterizer_compound/rasterizer_compound.dsp new file mode 100755 index 0000000..5232df1 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/rasterizer_compound/rasterizer_compound.dsp @@ -0,0 +1,159 @@ +# Microsoft Developer Studio Project File - Name="rasterizer_compound" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=rasterizer_compound - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "rasterizer_compound.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "rasterizer_compound.mak" CFG="rasterizer_compound - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "rasterizer_compound - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "rasterizer_compound - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "rasterizer_compound - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./rasterizer_compound.exe" + +!ELSEIF "$(CFG)" == "rasterizer_compound - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "rasterizer_compound - Win32 Release" +# Name "rasterizer_compound - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_arrowhead.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_contour.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\rasterizer_compound.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/rasterizer_compound/rasterizer_compound.dsw b/jni/desmume/src/android/agg/examples/win32_api/rasterizer_compound/rasterizer_compound.dsw new file mode 100755 index 0000000..010b0f3 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/rasterizer_compound/rasterizer_compound.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "rasterizer_compound"=.\rasterizer_compound.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/rasterizers/Makefile b/jni/desmume/src/android/agg/examples/win32_api/rasterizers/Makefile new file mode 100755 index 0000000..6b4c130 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/rasterizers/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=rasterizers +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/rasterizers/rasterizers.dsp b/jni/desmume/src/android/agg/examples/win32_api/rasterizers/rasterizers.dsp new file mode 100755 index 0000000..7fad91c --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/rasterizers/rasterizers.dsp @@ -0,0 +1,151 @@ +# Microsoft Developer Studio Project File - Name="rasterizers" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=rasterizers - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "rasterizers.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "rasterizers.mak" CFG="rasterizers - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "rasterizers - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "rasterizers - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "rasterizers - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 /out:"./rasterizers.exe" + +!ELSEIF "$(CFG)" == "rasterizers - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "rasterizers - Win32 Release" +# Name "rasterizers - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_arrowhead.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_markers_term.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\rasterizers.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/rasterizers/rasterizers.dsw b/jni/desmume/src/android/agg/examples/win32_api/rasterizers/rasterizers.dsw new file mode 100755 index 0000000..e1199df --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/rasterizers/rasterizers.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "rasterizers"=.\rasterizers.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/rasterizers2/Makefile b/jni/desmume/src/android/agg/examples/win32_api/rasterizers2/Makefile new file mode 100755 index 0000000..3e2abcf --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/rasterizers2/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=rasterizers2 +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/rasterizers2/rasterizers2.dsp b/jni/desmume/src/android/agg/examples/win32_api/rasterizers2/rasterizers2.dsp new file mode 100755 index 0000000..2d73ae4 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/rasterizers2/rasterizers2.dsp @@ -0,0 +1,199 @@ +# Microsoft Developer Studio Project File - Name="rasterizers2" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=rasterizers2 - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "rasterizers2.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "rasterizers2.mak" CFG="rasterizers2 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "rasterizers2 - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "rasterizers2 - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "rasterizers2 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /machine:I386 /out:"./rasterizers2.exe" + +!ELSEIF "$(CFG)" == "rasterizers2 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "rasterizers2 - Win32 Release" +# Name "rasterizers2 - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_arrowhead.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_line_aa_basics.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_line_profile_aa.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_rounded_rect.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_contour.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_dash.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_markers_term.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_smooth_poly1.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\rasterizers2.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_line_aa_basics.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_renderer_markers.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_renderer_outline_aa.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\include\agg_renderer_outline_image.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/rasterizers2/rasterizers2.dsw b/jni/desmume/src/android/agg/examples/win32_api/rasterizers2/rasterizers2.dsw new file mode 100755 index 0000000..715e49d --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/rasterizers2/rasterizers2.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "rasterizers2"=.\rasterizers2.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/rounded_rect/Makefile b/jni/desmume/src/android/agg/examples/win32_api/rounded_rect/Makefile new file mode 100755 index 0000000..91a9ba9 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/rounded_rect/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=rounded_rect +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/rounded_rect/rounded_rect.dsp b/jni/desmume/src/android/agg/examples/win32_api/rounded_rect/rounded_rect.dsp new file mode 100755 index 0000000..51ddf54 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/rounded_rect/rounded_rect.dsp @@ -0,0 +1,147 @@ +# Microsoft Developer Studio Project File - Name="rounded_rect" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=rounded_rect - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "rounded_rect.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "rounded_rect.mak" CFG="rounded_rect - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "rounded_rect - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "rounded_rect - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "rounded_rect - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./rounded_rect.exe" + +!ELSEIF "$(CFG)" == "rounded_rect - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "rounded_rect - Win32 Release" +# Name "rounded_rect - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_rounded_rect.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\rounded_rect.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/rounded_rect/rounded_rect.dsw b/jni/desmume/src/android/agg/examples/win32_api/rounded_rect/rounded_rect.dsw new file mode 100755 index 0000000..8a54d4f --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/rounded_rect/rounded_rect.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "rounded_rect"=.\rounded_rect.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/scanline_boolean/Makefile b/jni/desmume/src/android/agg/examples/win32_api/scanline_boolean/Makefile new file mode 100755 index 0000000..ebc9612 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/scanline_boolean/Makefile @@ -0,0 +1,42 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=scanline_boolean +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../interactive_polygon.cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../interactive_polygon.o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/scanline_boolean/scanline_boolean.dsp b/jni/desmume/src/android/agg/examples/win32_api/scanline_boolean/scanline_boolean.dsp new file mode 100755 index 0000000..ab4cac2 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/scanline_boolean/scanline_boolean.dsp @@ -0,0 +1,151 @@ +# Microsoft Developer Studio Project File - Name="scanline_boolean" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=scanline_boolean - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "scanline_boolean.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "scanline_boolean.mak" CFG="scanline_boolean - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "scanline_boolean - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "scanline_boolean - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "scanline_boolean - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./scanline_boolean.exe" + +!ELSEIF "$(CFG)" == "scanline_boolean - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "scanline_boolean - Win32 Release" +# Name "scanline_boolean - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\interactive_polygon.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\scanline_boolean.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_config.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/scanline_boolean/scanline_boolean.dsw b/jni/desmume/src/android/agg/examples/win32_api/scanline_boolean/scanline_boolean.dsw new file mode 100755 index 0000000..a7e3775 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/scanline_boolean/scanline_boolean.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "scanline_boolean"=.\scanline_boolean.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/scanline_boolean2/Makefile b/jni/desmume/src/android/agg/examples/win32_api/scanline_boolean2/Makefile new file mode 100755 index 0000000..29414b8 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/scanline_boolean2/Makefile @@ -0,0 +1,42 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=scanline_boolean2 +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../make_arrows.cpp \ +../../make_gb_poly.cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../*.o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/scanline_boolean2/scanline_boolean2.dsp b/jni/desmume/src/android/agg/examples/win32_api/scanline_boolean2/scanline_boolean2.dsp new file mode 100755 index 0000000..d13b4db --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/scanline_boolean2/scanline_boolean2.dsp @@ -0,0 +1,155 @@ +# Microsoft Developer Studio Project File - Name="scanline_boolean2" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=scanline_boolean2 - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "scanline_boolean2.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "scanline_boolean2.mak" CFG="scanline_boolean2 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "scanline_boolean2 - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "scanline_boolean2 - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "scanline_boolean2 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /I "../../../gpc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./scanline_boolean2.exe" + +!ELSEIF "$(CFG)" == "scanline_boolean2 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /I "../../../gpc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "scanline_boolean2 - Win32 Release" +# Name "scanline_boolean2 - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\make_arrows.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\make_gb_poly.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\scanline_boolean2.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/scanline_boolean2/scanline_boolean2.dsw b/jni/desmume/src/android/agg/examples/win32_api/scanline_boolean2/scanline_boolean2.dsw new file mode 100755 index 0000000..30faeda --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/scanline_boolean2/scanline_boolean2.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "scanline_boolean2"=.\scanline_boolean2.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/simple_blur/Makefile b/jni/desmume/src/android/agg/examples/win32_api/simple_blur/Makefile new file mode 100755 index 0000000..05bf37d --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/simple_blur/Makefile @@ -0,0 +1,41 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=simple_blur +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../parse_lion.cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/simple_blur/simple_blur.dsp b/jni/desmume/src/android/agg/examples/win32_api/simple_blur/simple_blur.dsp new file mode 100755 index 0000000..2cd24c3 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/simple_blur/simple_blur.dsp @@ -0,0 +1,151 @@ +# Microsoft Developer Studio Project File - Name="simple_blur" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=simple_blur - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "simple_blur.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "simple_blur.mak" CFG="simple_blur - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "simple_blur - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "simple_blur - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "simple_blur - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./simple_blur.exe" + +!ELSEIF "$(CFG)" == "simple_blur - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "simple_blur - Win32 Release" +# Name "simple_blur - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_line_aa_basics.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_line_profile_aa.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_sqrt_tables.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\parse_lion.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\simple_blur.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/simple_blur/simple_blur.dsw b/jni/desmume/src/android/agg/examples/win32_api/simple_blur/simple_blur.dsw new file mode 100755 index 0000000..10ca0a0 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/simple_blur/simple_blur.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "simple_blur"=.\simple_blur.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/svg_test/svg_test.dsp b/jni/desmume/src/android/agg/examples/win32_api/svg_test/svg_test.dsp new file mode 100755 index 0000000..3bf9710 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/svg_test/svg_test.dsp @@ -0,0 +1,172 @@ +# Microsoft Developer Studio Project File - Name="svg_test" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=svg_test - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "svg_test.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "svg_test.mak" CFG="svg_test - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "svg_test - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "svg_test - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "svg_test - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /I "../../../../Expat/Source/lib" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libexpat.lib /nologo /subsystem:windows /profile /machine:I386 /out:"./svg_test.exe" /libpath:"../../../../Expat/libs" + +!ELSEIF "$(CFG)" == "svg_test - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /I "../../../../Expat/Source/lib" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libexpat.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:"../../../../Expat/libs" + +!ENDIF + +# Begin Target + +# Name "svg_test - Win32 Release" +# Name "svg_test - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\svg_viewer\agg_svg_parser.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\svg_viewer\agg_svg_path_renderer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\svg_viewer\agg_svg_path_tokenizer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_contour.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\svg_viewer\svg_test.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\svg_viewer\agg_svg_exception.h +# End Source File +# Begin Source File + +SOURCE=..\..\svg_viewer\agg_svg_parser.h +# End Source File +# Begin Source File + +SOURCE=..\..\svg_viewer\agg_svg_path_renderer.h +# End Source File +# Begin Source File + +SOURCE=..\..\svg_viewer\agg_svg_path_tokenizer.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/svg_test/svg_test.dsw b/jni/desmume/src/android/agg/examples/win32_api/svg_test/svg_test.dsw new file mode 100755 index 0000000..95563cd --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/svg_test/svg_test.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "svg_test"=.\svg_test.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/trans_curve1/Makefile b/jni/desmume/src/android/agg/examples/win32_api/trans_curve1/Makefile new file mode 100755 index 0000000..54d441b --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/trans_curve1/Makefile @@ -0,0 +1,46 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=trans_curve1 +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) \ +-I../../../include \ +-I../../../font_win32_tt \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../interactive_polygon.cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp \ +../../../font_win32_tt/agg_font_win32_tt.cpp + + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../interactive_polygon.o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/trans_curve1/trans_curve1.dsp b/jni/desmume/src/android/agg/examples/win32_api/trans_curve1/trans_curve1.dsp new file mode 100755 index 0000000..1eff76c --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/trans_curve1/trans_curve1.dsp @@ -0,0 +1,167 @@ +# Microsoft Developer Studio Project File - Name="trans_curve1" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=trans_curve1 - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "trans_curve1.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "trans_curve1.mak" CFG="trans_curve1 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "trans_curve1 - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "trans_curve1 - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "trans_curve1 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /I "../../../font_win32_tt" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./trans_curve1.exe" + +!ELSEIF "$(CFG)" == "trans_curve1 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /I "../../../font_win32_tt" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "trans_curve1 - Win32 Release" +# Name "trans_curve1 - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\font_win32_tt\agg_font_win32_tt.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_single_path.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vpgen_segmentator.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\interactive_polygon.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\trans_curve1.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/trans_curve1/trans_curve1.dsw b/jni/desmume/src/android/agg/examples/win32_api/trans_curve1/trans_curve1.dsw new file mode 100755 index 0000000..a0f6060 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/trans_curve1/trans_curve1.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "trans_curve1"=.\trans_curve1.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/trans_curve2/Makefile b/jni/desmume/src/android/agg/examples/win32_api/trans_curve2/Makefile new file mode 100755 index 0000000..2cea1fa --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/trans_curve2/Makefile @@ -0,0 +1,46 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=trans_curve2 +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) \ +-I../../../include \ +-I../../../font_win32_tt \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../interactive_polygon.cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp \ +../../../font_win32_tt/agg_font_win32_tt.cpp + + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../interactive_polygon.o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/trans_curve2/trans_curve2.dsp b/jni/desmume/src/android/agg/examples/win32_api/trans_curve2/trans_curve2.dsp new file mode 100755 index 0000000..a173573 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/trans_curve2/trans_curve2.dsp @@ -0,0 +1,171 @@ +# Microsoft Developer Studio Project File - Name="trans_curve2" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=trans_curve2 - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "trans_curve2.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "trans_curve2.mak" CFG="trans_curve2 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "trans_curve2 - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "trans_curve2 - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "trans_curve2 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /I "../../../font_win32_tt" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./trans_curve2.exe" + +!ELSEIF "$(CFG)" == "trans_curve2 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /I "../../../font_win32_tt" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AGG_BMP_NO_ALPHA_BLEND" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "trans_curve2 - Win32 Release" +# Name "trans_curve2 - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\font_win32_tt\agg_font_win32_tt.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_double_path.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_bspline.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vpgen_segmentator.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\interactive_polygon.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\trans_curve2.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\include\agg_trans_double_path.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/trans_curve2/trans_curve2.dsw b/jni/desmume/src/android/agg/examples/win32_api/trans_curve2/trans_curve2.dsw new file mode 100755 index 0000000..1ded9b1 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/trans_curve2/trans_curve2.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "trans_curve2"=.\trans_curve2.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/trans_polar/Makefile b/jni/desmume/src/android/agg/examples/win32_api/trans_polar/Makefile new file mode 100755 index 0000000..f62266e --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/trans_polar/Makefile @@ -0,0 +1,40 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=trans_polar +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) -I../../../include \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/trans_polar/trans_polar.dsp b/jni/desmume/src/android/agg/examples/win32_api/trans_polar/trans_polar.dsp new file mode 100755 index 0000000..25e5547 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/trans_polar/trans_polar.dsp @@ -0,0 +1,143 @@ +# Microsoft Developer Studio Project File - Name="trans_polar" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=trans_polar - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "trans_polar.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "trans_polar.mak" CFG="trans_polar - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "trans_polar - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "trans_polar - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "trans_polar - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./trans_polar.exe" + +!ELSEIF "$(CFG)" == "trans_polar - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "trans_polar - Win32 Release" +# Name "trans_polar - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vpgen_segmentator.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\trans_polar.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/trans_polar/trans_polar.dsw b/jni/desmume/src/android/agg/examples/win32_api/trans_polar/trans_polar.dsw new file mode 100755 index 0000000..61cd539 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/trans_polar/trans_polar.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "trans_polar"=.\trans_polar.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api/truetype_test/Makefile b/jni/desmume/src/android/agg/examples/win32_api/truetype_test/Makefile new file mode 100755 index 0000000..70cbd9e --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/truetype_test/Makefile @@ -0,0 +1,45 @@ +# +# This makefile can be used to build a Win32 application under Cygwin +# + +include ../../../Makefile.in.$(shell uname) + +PROGNAME=truetype_test +OUTNAME=$(PROGNAME) +PLATFORM=win32 + +CXXFLAGS= $(AGGCXXFLAGS) \ +-I../../../include \ +-I../../../font_win32_tt \ +-I/usr/X11R6/include \ +-L/usr/X11R6/lib \ +-L../../../src \ +$(PIXFMT) + +LIBS = $(AGGLIBS) -lm -lgdi32 + +SRC=\ +../../$(PROGNAME).cpp \ +../../../src/platform/$(PLATFORM)/agg_platform_support.cpp \ +../../../src/platform/$(PLATFORM)/agg_win32_bmp.cpp \ +../../../font_win32_tt/agg_font_win32_tt.cpp + + +OBJ= $(SRC:.cpp=.o) + +$(OUTNAME): $(OBJ) + $(CXX) $(CXXFLAGS) $^ -o $(OUTNAME) $(LIBS) + +clean: + rm -f $(OUTNAME) + rm -f ../../$(PROGNAME).o + rm -f ../../interactive_polygon.o + rm -f ../../../src/platform/$(PLATFORM)/agg_platform_support.o + rm -f gamma.txt + rm -f gamma.bin + +%.o: %.cpp + @echo \< $*.cpp \> + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + + diff --git a/jni/desmume/src/android/agg/examples/win32_api/truetype_test/truetype_test.dsp b/jni/desmume/src/android/agg/examples/win32_api/truetype_test/truetype_test.dsp new file mode 100755 index 0000000..5658023 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/truetype_test/truetype_test.dsp @@ -0,0 +1,155 @@ +# Microsoft Developer Studio Project File - Name="truetype_test" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=truetype_test - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "truetype_test.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "truetype_test.mak" CFG="truetype_test - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "truetype_test - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "truetype_test - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "truetype_test - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../../include" /I "../../../font_win32_tt" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"./truetype_test.exe" + +!ELSEIF "$(CFG)" == "truetype_test - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../../include" /I "../../../font_win32_tt" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "truetype_test - Win32 Release" +# Name "truetype_test - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\agg_bezier_arc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_cbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_curves.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\font_win32_tt\agg_font_win32_tt.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_gsv_text.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_platform_support.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_rbox_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\ctrl\agg_slider_ctrl.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_trans_affine.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_contour.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\agg_vcgen_stroke.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\platform\win32\agg_win32_bmp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\truetype_test.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/jni/desmume/src/android/agg/examples/win32_api/truetype_test/truetype_test.dsw b/jni/desmume/src/android/agg/examples/win32_api/truetype_test/truetype_test.dsw new file mode 100755 index 0000000..c41d9e3 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api/truetype_test/truetype_test.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "truetype_test"=.\truetype_test.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/jni/desmume/src/android/agg/examples/win32_api_dmc/Makefile b/jni/desmume/src/android/agg/examples/win32_api_dmc/Makefile new file mode 100755 index 0000000..b9cd218 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api_dmc/Makefile @@ -0,0 +1,593 @@ +#============================================== +# Digital Mars Makefile +# +# Modify this variable if necessary +# +DM = \dm\bin +# + +CXX = $(DM)\dmc.exe -c -I..\..\include -I..\..\gpc -I..\..\font_win32_tt +C = $(DM)\dmc.exe -c -o+speed -I..\..\gpc +LINK = $(DM)\dmc.exe -L$(DM)\link.exe -L/SU:WINDOWS gdi32.lib +LIB = $(DM)\lib.exe + +all: aa_demo.exe \ + aa_test.exe \ + alpha_gradient.exe \ + alpha_mask.exe \ + alpha_mask2.exe \ + alpha_mask3.exe \ + bezier_div.exe \ + blur.exe \ + blend_color.exe \ + bspline.exe \ + circles.exe \ + component_rendering.exe \ + compositing.exe \ + compositing2.exe \ + conv_contour.exe \ + conv_dash_marker.exe \ + conv_stroke.exe \ + distortions.exe \ + flash_rasterizer.exe \ + flash_rasterizer2.exe \ + gamma_correction.exe \ + gamma_ctrl.exe \ + gamma_tuner.exe \ + gouraud.exe \ + gouraud_mesh.exe \ + gpc_test.exe \ + gradient_focal.exe \ + gradients.exe \ + graph_test.exe \ + idea.exe \ + image1.exe \ + image_alpha.exe \ + image_filters.exe \ + image_filters2.exe \ + image_fltr_graph.exe \ + image_perspective.exe \ + image_resample.exe \ + image_transforms.exe \ + line_patterns.exe \ + line_patterns_clip.exe \ + lion.exe \ + lion_lens.exe \ + lion_outline.exe \ + mol_view.exe \ + multi_clip.exe \ + pattern_fill.exe \ + pattern_perspective.exe \ + pattern_resample.exe \ + perspective.exe \ + polymorphic_renderer.exe \ + rasterizers.exe \ + rasterizers2.exe \ + rasterizer_compound.exe \ + raster_text.exe \ + rounded_rect.exe \ + scanline_boolean.exe \ + scanline_boolean2.exe \ + simple_blur.exe \ + trans_curve1.exe \ + trans_curve2.exe \ + trans_polar.exe \ + truetype_test.exe + +aa_demo.exe: aa_demo.obj agg.lib + $(LINK) $** + +aa_demo.obj: ..\aa_demo.cpp + $(CXX) $** -o$@ + +aa_test.exe: aa_test.obj agg.lib + $(LINK) $** + +aa_test.obj: ..\aa_test.cpp + $(CXX) $** -o$@ + +alpha_gradient.exe: alpha_gradient.obj agg.lib + $(LINK) $** + +alpha_gradient.obj: ..\alpha_gradient.cpp + $(CXX) $** -o$@ + +alpha_mask.exe: alpha_mask.obj parse_lion.obj agg.lib + $(LINK) $** + +alpha_mask.obj: ..\alpha_mask.cpp + $(CXX) $** -o$@ + +alpha_mask2.exe: alpha_mask2.obj parse_lion.obj agg.lib + $(LINK) $** + +alpha_mask2.obj: ..\alpha_mask2.cpp + $(CXX) $** -o$@ + +alpha_mask3.exe: alpha_mask3.obj make_arrows.obj make_gb_poly.obj agg.lib + $(LINK) $** + +alpha_mask3.obj: ..\alpha_mask3.cpp + $(CXX) $** -o$@ + +bezier_div.exe: bezier_div.obj agg.lib + $(LINK) $** + +bezier_div.obj: ..\bezier_div.cpp + $(CXX) $** -o$@ + +blur.exe: blur.obj agg.lib + $(LINK) $** + +blur.obj: ..\blur.cpp + $(CXX) $** -o$@ + +blend_color.exe: blend_color.obj agg.lib + $(LINK) $** + +blend_color.obj: ..\blend_color.cpp + $(CXX) $** -o$@ + +bspline.exe: bspline.obj interactive_polygon.obj agg.lib + $(LINK) $** + +bspline.obj: ..\bspline.cpp + $(CXX) $** -o$@ + +circles.exe: circles.obj agg.lib + $(LINK) $** + +circles.obj: ..\circles.cpp + $(CXX) $** -o$@ + +component_rendering.exe: component_rendering.obj agg.lib + $(LINK) $** + +component_rendering.obj: ..\component_rendering.cpp + $(CXX) $** -o$@ + +compositing.exe: compositing.obj agg.lib + $(LINK) $** + +compositing.obj: ..\compositing.cpp + $(CXX) $** -o$@ + +compositing2.exe: compositing2.obj agg.lib + $(LINK) $** + +compositing2.obj: ..\compositing2.cpp + $(CXX) $** -o$@ + +conv_contour.exe: conv_contour.obj agg.lib + $(LINK) $** + +conv_contour.obj: ..\conv_contour.cpp + $(CXX) $** -o$@ + +conv_dash_marker.exe: conv_dash_marker.obj agg.lib + $(LINK) $** + +conv_dash_marker.obj: ..\conv_dash_marker.cpp + $(CXX) $** -o$@ + +conv_stroke.exe: conv_stroke.obj agg.lib + $(LINK) $** + +conv_stroke.obj: ..\conv_stroke.cpp + $(CXX) $** -o$@ + +distortions.exe: distortions.obj agg.lib + $(LINK) $** + +distortions.obj: ..\distortions.cpp + $(CXX) $** -o$@ + +flash_rasterizer.exe: flash_rasterizer.obj agg.lib + $(LINK) $** + +flash_rasterizer.obj: ..\flash_rasterizer.cpp + $(CXX) $** -o$@ + +flash_rasterizer2.exe: flash_rasterizer2.obj agg.lib + $(LINK) $** + +flash_rasterizer2.obj: ..\flash_rasterizer2.cpp + $(CXX) $** -o$@ + +gamma_correction.exe: gamma_correction.obj agg.lib + $(LINK) $** + +gamma_correction.obj: ..\gamma_correction.cpp + $(CXX) $** -o$@ + +gamma_ctrl.exe: gamma_ctrl.obj agg.lib + $(LINK) $** + +gamma_ctrl.obj: ..\gamma_ctrl.cpp + $(CXX) $** -o$@ + +gamma_tuner.exe: gamma_tuner.obj agg.lib + $(LINK) $** + +gamma_tuner.obj: ..\gamma_tuner.cpp + $(CXX) $** -o$@ + +gouraud.exe: gouraud.obj agg.lib + $(LINK) $** + +gouraud.obj: ..\gouraud.cpp + $(CXX) $** -o$@ + +gouraud_mesh.exe: gouraud_mesh.obj agg.lib + $(LINK) $** + +gouraud_mesh.obj: ..\gouraud_mesh.cpp + $(CXX) $** -o$@ + +gpc_test.exe: gpc_test.obj make_arrows.obj make_gb_poly.obj agg.lib + $(LINK) $** + +gpc_test.obj: ..\gpc_test.cpp + $(CXX) $** -o$@ + +gradient_focal.exe: gradient_focal.obj agg.lib + $(LINK) $** + +gradient_focal.obj: ..\gradient_focal.cpp + $(CXX) $** -o$@ + +gradients.exe: gradients.obj agg.lib + $(LINK) $** + +gradients.obj: ..\gradients.cpp + $(CXX) $** -o$@ + +graph_test.exe: graph_test.obj agg.lib + $(LINK) $** + +graph_test.obj: ..\graph_test.cpp + $(CXX) $** -o$@ + +idea.exe: idea.obj agg.lib + $(LINK) $** + +idea.obj: ..\idea.cpp + $(CXX) $** -o$@ + +image1.exe: image1.obj agg.lib + $(LINK) $** + +image1.obj: ..\image1.cpp + $(CXX) $** -o$@ + +image_alpha.exe: image_alpha.obj agg.lib + $(LINK) $** + +image_alpha.obj: ..\image_alpha.cpp + $(CXX) $** -o$@ + +image_filters.exe: image_filters.obj agg.lib + $(LINK) $** + +image_filters.obj: ..\image_filters.cpp + $(CXX) $** -o$@ + +image_filters2.exe: image_filters2.obj agg.lib + $(LINK) $** + +image_filters2.obj: ..\image_filters2.cpp + $(CXX) $** -o$@ + +image_fltr_graph.exe: image_fltr_graph.obj agg.lib + $(LINK) $** + +image_fltr_graph.obj: ..\image_fltr_graph.cpp + $(CXX) $** -o$@ + +image_perspective.exe: image_perspective.obj interactive_polygon.obj agg.lib + $(LINK) $** + +image_perspective.obj: ..\image_perspective.cpp + $(CXX) $** -o$@ + +image_resample.exe: image_resample.obj interactive_polygon.obj agg.lib + $(LINK) $** + +image_resample.obj: ..\image_resample.cpp + $(CXX) $** -o$@ + +image_transforms.exe: image_transforms.obj agg.lib + $(LINK) $** + +image_transforms.obj: ..\image_transforms.cpp + $(CXX) $** -o$@ + +line_patterns.exe: line_patterns.obj agg.lib + $(LINK) $** + +line_patterns.obj: ..\line_patterns.cpp + $(CXX) $** -o$@ + +line_patterns_clip.exe: line_patterns_clip.obj agg.lib + $(LINK) $** + +line_patterns_clip.obj: ..\line_patterns_clip.cpp + $(CXX) $** -o$@ + +lion.exe: lion.obj parse_lion.obj agg.lib + $(LINK) $** + +lion.obj: ..\lion.cpp + $(CXX) $** -o$@ + +lion_lens.exe: lion_lens.obj parse_lion.obj agg.lib + $(LINK) $** + +lion_lens.obj: ..\lion_lens.cpp + $(CXX) $** -o$@ + +lion_outline.exe: lion_outline.obj parse_lion.obj agg.lib + $(LINK) $** + +lion_outline.obj: ..\lion_outline.cpp + $(CXX) $** -o$@ + +mol_view.exe: mol_view.obj agg.lib + $(LINK) $** + +mol_view.obj: ..\mol_view.cpp + $(CXX) $** -o$@ + +multi_clip.exe: multi_clip.obj parse_lion.obj agg.lib + $(LINK) $** + +multi_clip.obj: ..\multi_clip.cpp + $(CXX) $** -o$@ + +pattern_fill.exe: pattern_fill.obj agg.lib + $(LINK) $** + +pattern_fill.obj: ..\pattern_fill.cpp + $(CXX) $** -o$@ + +pattern_perspective.exe: pattern_perspective.obj interactive_polygon.obj agg.lib + $(LINK) $** + +pattern_perspective.obj: ..\pattern_perspective.cpp + $(CXX) $** -o$@ + +pattern_resample.exe: pattern_resample.obj interactive_polygon.obj agg.lib + $(LINK) $** + +pattern_resample.obj: ..\pattern_resample.cpp + $(CXX) $** -o$@ + +perspective.exe: perspective.obj parse_lion.obj interactive_polygon.obj agg.lib + $(LINK) $** + +perspective.obj: ..\perspective.cpp + $(CXX) $** -o$@ + +polymorphic_renderer.exe: polymorphic_renderer.obj agg.lib + $(LINK) $** + +polymorphic_renderer.obj: ..\polymorphic_renderer.cpp + $(CXX) $** -o$@ + +rasterizers.exe: rasterizers.obj agg.lib + $(LINK) $** + +rasterizers.obj: ..\rasterizers.cpp + $(CXX) $** -o$@ + +rasterizers2.exe: rasterizers2.obj agg.lib + $(LINK) $** + +rasterizers2.obj: ..\rasterizers2.cpp + $(CXX) $** -o$@ + +rasterizer_compound.exe: rasterizer_compound.obj agg.lib + $(LINK) $** + +rasterizer_compound.obj: ..\rasterizer_compound.cpp + $(CXX) $** -o$@ + +raster_text.exe: raster_text.obj agg.lib + $(LINK) $** + +raster_text.obj: ..\raster_text.cpp + $(CXX) $** -o$@ + +rounded_rect.exe: rounded_rect.obj agg.lib + $(LINK) $** + +rounded_rect.obj: ..\rounded_rect.cpp + $(CXX) $** -o$@ + +scanline_boolean.exe: scanline_boolean.obj interactive_polygon.obj agg.lib + $(LINK) $** + +scanline_boolean.obj: ..\scanline_boolean.cpp + $(CXX) $** -o$@ + +scanline_boolean2.exe: scanline_boolean2.obj make_arrows.obj make_gb_poly.obj agg.lib + $(LINK) $** + +scanline_boolean2.obj: ..\scanline_boolean2.cpp + $(CXX) $** -o$@ + +simple_blur.exe: simple_blur.obj parse_lion.obj agg.lib + $(LINK) $** + +simple_blur.obj: ..\simple_blur.cpp + $(CXX) $** -o$@ + +trans_curve1.exe: trans_curve1.obj interactive_polygon.obj agg.lib + $(LINK) $** + +trans_curve1.obj: ..\trans_curve1.cpp + $(CXX) $** -o$@ + +trans_curve2.exe: trans_curve2.obj interactive_polygon.obj agg.lib + $(LINK) $** + +trans_curve2.obj: ..\trans_curve2.cpp + $(CXX) $** -o$@ + +trans_polar.exe: trans_polar.obj agg.lib + $(LINK) $** + +trans_polar.obj: ..\trans_polar.cpp + $(CXX) $** -o$@ + +truetype_test.exe: truetype_test.obj agg.lib + $(LINK) $** + +truetype_test.obj: ..\truetype_test.cpp + $(CXX) $** -o$@ + +parse_lion.obj: ..\parse_lion.cpp + $(CXX) $** -o$@ + +make_arrows.obj: ..\make_arrows.cpp + $(CXX) $** -o$@ + +make_gb_poly.obj: ..\make_gb_poly.cpp + $(CXX) $** -o$@ + +interactive_polygon.obj: ..\interactive_polygon.cpp + $(CXX) $** -o$@ + +agg.lib: agg_arc.obj agg_arrowhead.obj agg_bezier_arc.obj agg_bspline.obj agg_curves.obj \ + agg_embedded_raster_fonts.obj agg_gsv_text.obj agg_image_filters.obj \ + agg_line_aa_basics.obj agg_line_profile_aa.obj agg_rounded_rect.obj \ + agg_sqrt_tables.obj agg_trans_affine.obj agg_trans_double_path.obj \ + agg_trans_single_path.obj agg_trans_warp_magnifier.obj agg_vcgen_bspline.obj \ + agg_vcgen_contour.obj agg_vcgen_dash.obj agg_vcgen_markers_term.obj \ + agg_vcgen_smooth_poly1.obj agg_vcgen_stroke.obj agg_vpgen_clip_polygon.obj \ + agg_vpgen_clip_polyline.obj agg_vpgen_segmentator.obj agg_font_win32_tt.obj \ + agg_bezier_ctrl.obj agg_cbox_ctrl.obj agg_gamma_ctrl.obj agg_gamma_spline.obj \ + agg_polygon_ctrl.obj agg_rbox_ctrl.obj agg_scale_ctrl.obj agg_slider_ctrl.obj \ + agg_spline_ctrl.obj agg_platform_support.obj agg_win32_bmp.obj gpc.obj + $(LIB) -c $@ $** + +agg_arc.obj: ..\..\src\agg_arc.cpp + $(CXX) $** -o$@ + +agg_arrowhead.obj: ..\..\src\agg_arrowhead.cpp + $(CXX) $** -o$@ + +agg_bezier_arc.obj: ..\..\src\agg_bezier_arc.cpp + $(CXX) $** -o$@ + +agg_bspline.obj: ..\..\src\agg_bspline.cpp + $(CXX) $** -o$@ + +agg_curves.obj: ..\..\src\agg_curves.cpp + $(CXX) $** -o$@ + +agg_embedded_raster_fonts.obj: ..\..\src\agg_embedded_raster_fonts.cpp + $(CXX) $** -o$@ + +agg_gsv_text.obj: ..\..\src\agg_gsv_text.cpp + $(CXX) $** -o$@ + +agg_image_filters.obj: ..\..\src\agg_image_filters.cpp + $(CXX) $** -o$@ + +agg_line_aa_basics.obj: ..\..\src\agg_line_aa_basics.cpp + $(CXX) $** -o$@ + +agg_line_profile_aa.obj: ..\..\src\agg_line_profile_aa.cpp + $(CXX) $** -o$@ + +agg_rounded_rect.obj: ..\..\src\agg_rounded_rect.cpp + $(CXX) $** -o$@ + +agg_sqrt_tables.obj: ..\..\src\agg_sqrt_tables.cpp + $(CXX) $** -o$@ + +agg_trans_affine.obj: ..\..\src\agg_trans_affine.cpp + $(CXX) $** -o$@ + +agg_trans_double_path.obj: ..\..\src\agg_trans_double_path.cpp + $(CXX) $** -o$@ + +agg_trans_single_path.obj: ..\..\src\agg_trans_single_path.cpp + $(CXX) $** -o$@ + +agg_trans_warp_magnifier.obj: ..\..\src\agg_trans_warp_magnifier.cpp + $(CXX) $** -o$@ + +agg_vcgen_bspline.obj: ..\..\src\agg_vcgen_bspline.cpp + $(CXX) $** -o$@ + +agg_vcgen_contour.obj: ..\..\src\agg_vcgen_contour.cpp + $(CXX) $** -o$@ + +agg_vcgen_dash.obj: ..\..\src\agg_vcgen_dash.cpp + $(CXX) $** -o$@ + +agg_vcgen_markers_term.obj: ..\..\src\agg_vcgen_markers_term.cpp + $(CXX) $** -o$@ + +agg_vcgen_smooth_poly1.obj: ..\..\src\agg_vcgen_smooth_poly1.cpp + $(CXX) $** -o$@ + +agg_vcgen_stroke.obj: ..\..\src\agg_vcgen_stroke.cpp + $(CXX) $** -o$@ + +agg_vpgen_clip_polygon.obj: ..\..\src\agg_vpgen_clip_polygon.cpp + $(CXX) $** -o$@ + +agg_vpgen_clip_polyline.obj: ..\..\src\agg_vpgen_clip_polyline.cpp + $(CXX) $** -o$@ + +agg_vpgen_segmentator.obj: ..\..\src\agg_vpgen_segmentator.cpp + $(CXX) $** -o$@ + +agg_font_win32_tt.obj: ..\..\font_win32_tt\agg_font_win32_tt.cpp + $(CXX) $** -o$@ + +agg_bezier_ctrl.obj: ..\..\src\ctrl\agg_bezier_ctrl.cpp + $(CXX) $** -o$@ + +agg_cbox_ctrl.obj: ..\..\src\ctrl\agg_cbox_ctrl.cpp + $(CXX) $** -o$@ + +agg_gamma_ctrl.obj: ..\..\src\ctrl\agg_gamma_ctrl.cpp + $(CXX) $** -o$@ + +agg_gamma_spline.obj: ..\..\src\ctrl\agg_gamma_spline.cpp + $(CXX) $** -o$@ + +agg_polygon_ctrl.obj: ..\..\src\ctrl\agg_polygon_ctrl.cpp + $(CXX) $** -o$@ + +agg_rbox_ctrl.obj: ..\..\src\ctrl\agg_rbox_ctrl.cpp + $(CXX) $** -o$@ + +agg_scale_ctrl.obj: ..\..\src\ctrl\agg_scale_ctrl.cpp + $(CXX) $** -o$@ + +agg_slider_ctrl.obj: ..\..\src\ctrl\agg_slider_ctrl.cpp + $(CXX) $** -o$@ + +agg_spline_ctrl.obj: ..\..\src\ctrl\agg_spline_ctrl.cpp + $(CXX) $** -o$@ + +agg_platform_support.obj: ..\..\src\platform\win32\agg_platform_support.cpp + $(CXX) $** -o$@ + +agg_win32_bmp.obj: ..\..\src\platform\win32\agg_win32_bmp.cpp + $(CXX) $** -o$@ + +gpc.obj: ..\..\gpc\gpc.c + $(C) $(CFLAGS) $** -o$@ + +clean: + del *.obj + del agg.lib + del *.exe + del *.map + diff --git a/jni/desmume/src/android/agg/examples/win32_api_dmc/readme b/jni/desmume/src/android/agg/examples/win32_api_dmc/readme new file mode 100755 index 0000000..1d0ff49 --- /dev/null +++ b/jni/desmume/src/android/agg/examples/win32_api_dmc/readme @@ -0,0 +1,20 @@ +This is a makefile to build the demo examples with the Digital Mars C++. +Visit http://digitalmars.com/ for more info and to download the compiler. + +The compiler is very easy in use and doesn't require any installation +procedure. You just download and unzip it. + +Suppose you have unzipped it into the root directory: + +\dm\*.* + +That is, the full path to the compiler is \dm\bin\dmc.exe + +Then you simply run: + +\dm\bin\make + +That's it, it should build the examples, except for svg_test and freetype_test. +If you have a different directory with the compiler please modify the Makefile +accordingly (that's pertty easy). + diff --git a/jni/desmume/src/android/agg/font_freetype/Makefile.am b/jni/desmume/src/android/agg/font_freetype/Makefile.am new file mode 100755 index 0000000..8877d51 --- /dev/null +++ b/jni/desmume/src/android/agg/font_freetype/Makefile.am @@ -0,0 +1,11 @@ + +if ENABLE_FT +aggincludedir = $(includedir)/agg2 +agginclude_HEADERS = agg_font_freetype.h +lib_LTLIBRARIES = libaggfontfreetype.la + +libaggfontfreetype_la_LDFLAGS = -version-info @AGG_LIB_VERSION@ @FREETYPE_LIBS@ +libaggfontfreetype_la_SOURCES = agg_font_freetype.cpp +libaggfontfreetype_la_CXXFLAGS = -I$(top_srcdir)/include @FREETYPE_CFLAGS@ +endif + diff --git a/jni/desmume/src/android/agg/font_freetype/agg_font_freetype.cpp b/jni/desmume/src/android/agg/font_freetype/agg_font_freetype.cpp new file mode 100755 index 0000000..d276105 --- /dev/null +++ b/jni/desmume/src/android/agg/font_freetype/agg_font_freetype.cpp @@ -0,0 +1,1155 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <stdio.h> +#include "agg_font_freetype.h" +#include "agg_bitset_iterator.h" +#include "agg_renderer_scanline.h" + + +namespace agg +{ + + //------------------------------------------------------------------------------ + // + // This code implements the AUTODIN II polynomial + // The variable corresponding to the macro argument "crc" should + // be an unsigned long. + // Oroginal code by Spencer Garrett <srg@quick.com> + // + + // generated using the AUTODIN II polynomial + // x^32 + x^26 + x^23 + x^22 + x^16 + + // x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1 + // + //------------------------------------------------------------------------------ + + static const unsigned crc32tab[256] = + { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, + }; + + + //------------------------------------------------------------------------------ + + static unsigned calc_crc32(const unsigned char* buf, unsigned size) + { + unsigned crc = (unsigned)~0; + const unsigned char* p; + unsigned len = 0; + unsigned nr = size; + + for (len += nr, p = buf; nr--; ++p) + { + crc = (crc >> 8) ^ crc32tab[(crc ^ *p) & 0xff]; + } + return ~crc; + } + + //------------------------------------------------------------------------ + static inline int dbl_to_plain_fx(double d) + { + return int(d * 65536.0); + } + + //------------------------------------------------------------------------ + static inline double int26p6_to_dbl(int p) + { + return double(p) / 64.0; + } + + //------------------------------------------------------------------------ + static inline int dbl_to_int26p6(double p) + { + return int(p * 64.0 + 0.5); + } + + + //------------------------------------------------------------------------ + template<class PathStorage> + bool decompose_ft_outline(const FT_Outline& outline, + bool flip_y, + const trans_affine& mtx, + PathStorage& path) + { + typedef typename PathStorage::value_type value_type; + + FT_Vector v_last; + FT_Vector v_control; + FT_Vector v_start; + double x1, y1, x2, y2, x3, y3; + + FT_Vector* point; + FT_Vector* limit; + char* tags; + + int n; // index of contour in outline + int first; // index of first point in contour + char tag; // current point's state + + first = 0; + + for(n = 0; n < outline.n_contours; n++) + { + int last; // index of last point in contour + + last = outline.contours[n]; + limit = outline.points + last; + + v_start = outline.points[first]; + v_last = outline.points[last]; + + v_control = v_start; + + point = outline.points + first; + tags = outline.tags + first; + tag = FT_CURVE_TAG(tags[0]); + + // A contour cannot start with a cubic control point! + if(tag == FT_CURVE_TAG_CUBIC) return false; + + // check first point to determine origin + if( tag == FT_CURVE_TAG_CONIC) + { + // first point is conic control. Yes, this happens. + if(FT_CURVE_TAG(outline.tags[last]) == FT_CURVE_TAG_ON) + { + // start at last point if it is on the curve + v_start = v_last; + limit--; + } + else + { + // if both first and last points are conic, + // start at their middle and record its position + // for closure + v_start.x = (v_start.x + v_last.x) / 2; + v_start.y = (v_start.y + v_last.y) / 2; + + v_last = v_start; + } + point--; + tags--; + } + + x1 = int26p6_to_dbl(v_start.x); + y1 = int26p6_to_dbl(v_start.y); + if(flip_y) y1 = -y1; + mtx.transform(&x1, &y1); + path.move_to(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1))); + + while(point < limit) + { + point++; + tags++; + + tag = FT_CURVE_TAG(tags[0]); + switch(tag) + { + case FT_CURVE_TAG_ON: // emit a single line_to + { + x1 = int26p6_to_dbl(point->x); + y1 = int26p6_to_dbl(point->y); + if(flip_y) y1 = -y1; + mtx.transform(&x1, &y1); + path.line_to(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1))); + //path.line_to(conv(point->x), flip_y ? -conv(point->y) : conv(point->y)); + continue; + } + + case FT_CURVE_TAG_CONIC: // consume conic arcs + { + v_control.x = point->x; + v_control.y = point->y; + + Do_Conic: + if(point < limit) + { + FT_Vector vec; + FT_Vector v_middle; + + point++; + tags++; + tag = FT_CURVE_TAG(tags[0]); + + vec.x = point->x; + vec.y = point->y; + + if(tag == FT_CURVE_TAG_ON) + { + x1 = int26p6_to_dbl(v_control.x); + y1 = int26p6_to_dbl(v_control.y); + x2 = int26p6_to_dbl(vec.x); + y2 = int26p6_to_dbl(vec.y); + if(flip_y) { y1 = -y1; y2 = -y2; } + mtx.transform(&x1, &y1); + mtx.transform(&x2, &y2); + path.curve3(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1)), + value_type(dbl_to_int26p6(x2)), + value_type(dbl_to_int26p6(y2))); + continue; + } + + if(tag != FT_CURVE_TAG_CONIC) return false; + + v_middle.x = (v_control.x + vec.x) / 2; + v_middle.y = (v_control.y + vec.y) / 2; + + x1 = int26p6_to_dbl(v_control.x); + y1 = int26p6_to_dbl(v_control.y); + x2 = int26p6_to_dbl(v_middle.x); + y2 = int26p6_to_dbl(v_middle.y); + if(flip_y) { y1 = -y1; y2 = -y2; } + mtx.transform(&x1, &y1); + mtx.transform(&x2, &y2); + path.curve3(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1)), + value_type(dbl_to_int26p6(x2)), + value_type(dbl_to_int26p6(y2))); + + //path.curve3(conv(v_control.x), + // flip_y ? -conv(v_control.y) : conv(v_control.y), + // conv(v_middle.x), + // flip_y ? -conv(v_middle.y) : conv(v_middle.y)); + + v_control = vec; + goto Do_Conic; + } + + x1 = int26p6_to_dbl(v_control.x); + y1 = int26p6_to_dbl(v_control.y); + x2 = int26p6_to_dbl(v_start.x); + y2 = int26p6_to_dbl(v_start.y); + if(flip_y) { y1 = -y1; y2 = -y2; } + mtx.transform(&x1, &y1); + mtx.transform(&x2, &y2); + path.curve3(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1)), + value_type(dbl_to_int26p6(x2)), + value_type(dbl_to_int26p6(y2))); + + //path.curve3(conv(v_control.x), + // flip_y ? -conv(v_control.y) : conv(v_control.y), + // conv(v_start.x), + // flip_y ? -conv(v_start.y) : conv(v_start.y)); + goto Close; + } + + default: // FT_CURVE_TAG_CUBIC + { + FT_Vector vec1, vec2; + + if(point + 1 > limit || FT_CURVE_TAG(tags[1]) != FT_CURVE_TAG_CUBIC) + { + return false; + } + + vec1.x = point[0].x; + vec1.y = point[0].y; + vec2.x = point[1].x; + vec2.y = point[1].y; + + point += 2; + tags += 2; + + if(point <= limit) + { + FT_Vector vec; + + vec.x = point->x; + vec.y = point->y; + + x1 = int26p6_to_dbl(vec1.x); + y1 = int26p6_to_dbl(vec1.y); + x2 = int26p6_to_dbl(vec2.x); + y2 = int26p6_to_dbl(vec2.y); + x3 = int26p6_to_dbl(vec.x); + y3 = int26p6_to_dbl(vec.y); + if(flip_y) { y1 = -y1; y2 = -y2; y3 = -y3; } + mtx.transform(&x1, &y1); + mtx.transform(&x2, &y2); + mtx.transform(&x3, &y3); + path.curve4(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1)), + value_type(dbl_to_int26p6(x2)), + value_type(dbl_to_int26p6(y2)), + value_type(dbl_to_int26p6(x3)), + value_type(dbl_to_int26p6(y3))); + + //path.curve4(conv(vec1.x), + // flip_y ? -conv(vec1.y) : conv(vec1.y), + // conv(vec2.x), + // flip_y ? -conv(vec2.y) : conv(vec2.y), + // conv(vec.x), + // flip_y ? -conv(vec.y) : conv(vec.y)); + continue; + } + + x1 = int26p6_to_dbl(vec1.x); + y1 = int26p6_to_dbl(vec1.y); + x2 = int26p6_to_dbl(vec2.x); + y2 = int26p6_to_dbl(vec2.y); + x3 = int26p6_to_dbl(v_start.x); + y3 = int26p6_to_dbl(v_start.y); + if(flip_y) { y1 = -y1; y2 = -y2; y3 = -y3; } + mtx.transform(&x1, &y1); + mtx.transform(&x2, &y2); + mtx.transform(&x3, &y3); + path.curve4(value_type(dbl_to_int26p6(x1)), + value_type(dbl_to_int26p6(y1)), + value_type(dbl_to_int26p6(x2)), + value_type(dbl_to_int26p6(y2)), + value_type(dbl_to_int26p6(x3)), + value_type(dbl_to_int26p6(y3))); + + //path.curve4(conv(vec1.x), + // flip_y ? -conv(vec1.y) : conv(vec1.y), + // conv(vec2.x), + // flip_y ? -conv(vec2.y) : conv(vec2.y), + // conv(v_start.x), + // flip_y ? -conv(v_start.y) : conv(v_start.y)); + goto Close; + } + } + } + + path.close_polygon(); + + Close: + first = last + 1; + } + + return true; + } + + + + //------------------------------------------------------------------------ + template<class Scanline, class ScanlineStorage> + void decompose_ft_bitmap_mono(const FT_Bitmap& bitmap, + int x, int y, + bool flip_y, + Scanline& sl, + ScanlineStorage& storage) + { + int i; + const int8u* buf = (const int8u*)bitmap.buffer; + int pitch = bitmap.pitch; + sl.reset(x, x + bitmap.width); + storage.prepare(); + if(flip_y) + { + buf += bitmap.pitch * (bitmap.rows - 1); + y += bitmap.rows; + pitch = -pitch; + } + for(i = 0; i < bitmap.rows; i++) + { + sl.reset_spans(); + bitset_iterator bits(buf, 0); + int j; + for(j = 0; j < bitmap.width; j++) + { + if(bits.bit()) sl.add_cell(x + j, cover_full); + ++bits; + } + buf += pitch; + if(sl.num_spans()) + { + sl.finalize(y - i - 1); + storage.render(sl); + } + } + } + + + + //------------------------------------------------------------------------ + template<class Rasterizer, class Scanline, class ScanlineStorage> + void decompose_ft_bitmap_gray8(const FT_Bitmap& bitmap, + int x, int y, + bool flip_y, + Rasterizer& ras, + Scanline& sl, + ScanlineStorage& storage) + { + int i, j; + const int8u* buf = (const int8u*)bitmap.buffer; + int pitch = bitmap.pitch; + sl.reset(x, x + bitmap.width); + storage.prepare(); + if(flip_y) + { + buf += bitmap.pitch * (bitmap.rows - 1); + y += bitmap.rows; + pitch = -pitch; + } + for(i = 0; i < bitmap.rows; i++) + { + sl.reset_spans(); + const int8u* p = buf; + for(j = 0; j < bitmap.width; j++) + { + if(*p) sl.add_cell(x + j, ras.apply_gamma(*p)); + ++p; + } + buf += pitch; + if(sl.num_spans()) + { + sl.finalize(y - i - 1); + storage.render(sl); + } + } + } + + + + + + + + + + + + + + //------------------------------------------------------------------------ + font_engine_freetype_base::~font_engine_freetype_base() + { + unsigned i; + for(i = 0; i < m_num_faces; ++i) + { + delete [] m_face_names[i]; + FT_Done_Face(m_faces[i]); + } + delete [] m_face_names; + delete [] m_faces; + delete [] m_signature; + if(m_library_initialized) FT_Done_FreeType(m_library); + } + + + //------------------------------------------------------------------------ + font_engine_freetype_base::font_engine_freetype_base(bool flag32, + unsigned max_faces) : + m_flag32(flag32), + m_change_stamp(0), + m_last_error(0), + m_name(0), + m_name_len(256-16-1), + m_face_index(0), + m_char_map(FT_ENCODING_NONE), + m_signature(new char [256+256-16]), + m_height(0), + m_width(0), + m_hinting(true), + m_flip_y(false), + m_library_initialized(false), + m_library(0), + m_faces(new FT_Face [max_faces]), + m_face_names(new char* [max_faces]), + m_num_faces(0), + m_max_faces(max_faces), + m_cur_face(0), + m_resolution(0), + m_glyph_rendering(glyph_ren_native_gray8), + m_glyph_index(0), + m_data_size(0), + m_data_type(glyph_data_invalid), + m_bounds(1,1,0,0), + m_advance_x(0.0), + m_advance_y(0.0), + + m_path16(), + m_path32(), + m_curves16(m_path16), + m_curves32(m_path32), + m_scanline_aa(), + m_scanline_bin(), + m_scanlines_aa(), + m_scanlines_bin(), + m_rasterizer() + { + m_curves16.approximation_scale(4.0); + m_curves32.approximation_scale(4.0); + m_last_error = FT_Init_FreeType(&m_library); + if(m_last_error == 0) m_library_initialized = true; + } + + + + //------------------------------------------------------------------------ + void font_engine_freetype_base::resolution(unsigned dpi) + { + m_resolution = dpi; + update_char_size(); + } + + + //------------------------------------------------------------------------ + int font_engine_freetype_base::find_face(const char* face_name) const + { + unsigned i; + for(i = 0; i < m_num_faces; ++i) + { + if(strcmp(face_name, m_face_names[i]) == 0) return i; + } + return -1; + } + + + //------------------------------------------------------------------------ + double font_engine_freetype_base::ascender() const + { + if(m_cur_face) + { + return m_cur_face->ascender * height() / m_cur_face->height; + } + return 0.0; + } + + //------------------------------------------------------------------------ + double font_engine_freetype_base::descender() const + { + if(m_cur_face) + { + return m_cur_face->descender * height() / m_cur_face->height; + } + return 0.0; + } + + + //------------------------------------------------------------------------ + bool font_engine_freetype_base::load_font(const char* font_name, + unsigned face_index, + glyph_rendering ren_type, + const char* font_mem, + const long font_mem_size) + { + bool ret = false; + + if(m_library_initialized) + { + m_last_error = 0; + + int idx = find_face(font_name); + if(idx >= 0) + { + m_cur_face = m_faces[idx]; + m_name = m_face_names[idx]; + } + else + { + if(m_num_faces >= m_max_faces) + { + delete [] m_face_names[0]; + FT_Done_Face(m_faces[0]); + memcpy(m_faces, + m_faces + 1, + (m_max_faces - 1) * sizeof(FT_Face)); + memcpy(m_face_names, + m_face_names + 1, + (m_max_faces - 1) * sizeof(char*)); + m_num_faces = m_max_faces - 1; + } + + if (font_mem && font_mem_size) + { + m_last_error = FT_New_Memory_Face(m_library, + (const FT_Byte*)font_mem, + font_mem_size, + face_index, + &m_faces[m_num_faces]); + } + else + { + m_last_error = FT_New_Face(m_library, + font_name, + face_index, + &m_faces[m_num_faces]); + } + + if(m_last_error == 0) + { + m_face_names[m_num_faces] = new char [strlen(font_name) + 1]; + strcpy(m_face_names[m_num_faces], font_name); + m_cur_face = m_faces[m_num_faces]; + m_name = m_face_names[m_num_faces]; + ++m_num_faces; + } + else + { + m_face_names[m_num_faces] = 0; + m_cur_face = 0; + m_name = 0; + } + } + + + if(m_last_error == 0) + { + ret = true; + + switch(ren_type) + { + case glyph_ren_native_mono: + m_glyph_rendering = glyph_ren_native_mono; + break; + + case glyph_ren_native_gray8: + m_glyph_rendering = glyph_ren_native_gray8; + break; + + case glyph_ren_outline: + if(FT_IS_SCALABLE(m_cur_face)) + { + m_glyph_rendering = glyph_ren_outline; + } + else + { + m_glyph_rendering = glyph_ren_native_gray8; + } + break; + + case glyph_ren_agg_mono: + if(FT_IS_SCALABLE(m_cur_face)) + { + m_glyph_rendering = glyph_ren_agg_mono; + } + else + { + m_glyph_rendering = glyph_ren_native_mono; + } + break; + + case glyph_ren_agg_gray8: + if(FT_IS_SCALABLE(m_cur_face)) + { + m_glyph_rendering = glyph_ren_agg_gray8; + } + else + { + m_glyph_rendering = glyph_ren_native_gray8; + } + break; + } + update_signature(); + } + } + return ret; + } + + + //------------------------------------------------------------------------ + bool font_engine_freetype_base::attach(const char* file_name) + { + if(m_cur_face) + { + m_last_error = FT_Attach_File(m_cur_face, file_name); + return m_last_error == 0; + } + return false; + } + + //------------------------------------------------------------------------ + unsigned font_engine_freetype_base::num_faces() const + { + if(m_cur_face) + { + return m_cur_face->num_faces; + } + return 0; + } + + //------------------------------------------------------------------------ + bool font_engine_freetype_base::char_map(FT_Encoding char_map) + { + if(m_cur_face) + { + m_last_error = FT_Select_Charmap(m_cur_face, m_char_map); + if(m_last_error == 0) + { + update_signature(); + return true; + } + } + return false; + } + + //------------------------------------------------------------------------ + bool font_engine_freetype_base::height(double h) + { + m_height = int(h * 64.0); + if(m_cur_face) + { + update_char_size(); + return true; + } + return false; + } + + //------------------------------------------------------------------------ + bool font_engine_freetype_base::width(double w) + { + m_width = int(w * 64.0); + if(m_cur_face) + { + update_char_size(); + return true; + } + return false; + } + + //------------------------------------------------------------------------ + void font_engine_freetype_base::hinting(bool h) + { + m_hinting = h; + if(m_cur_face) + { + update_signature(); + } + } + + //------------------------------------------------------------------------ + void font_engine_freetype_base::flip_y(bool f) + { + m_flip_y = f; + if(m_cur_face) + { + update_signature(); + } + } + + //------------------------------------------------------------------------ + void font_engine_freetype_base::transform(const trans_affine& affine) + { + m_affine = affine; + if(m_cur_face) + { + update_signature(); + } + } + + //------------------------------------------------------------------------ + void font_engine_freetype_base::update_signature() + { + if(m_cur_face && m_name) + { + unsigned name_len = strlen(m_name); + if(name_len > m_name_len) + { + delete [] m_signature; + m_signature = new char [name_len + 32 + 256]; + m_name_len = name_len + 32 - 1; + } + + unsigned gamma_hash = 0; + if(m_glyph_rendering == glyph_ren_native_gray8 || + m_glyph_rendering == glyph_ren_agg_mono || + m_glyph_rendering == glyph_ren_agg_gray8) + { + unsigned char gamma_table[rasterizer_scanline_aa<>::aa_scale]; + unsigned i; + for(i = 0; i < rasterizer_scanline_aa<>::aa_scale; ++i) + { + gamma_table[i] = m_rasterizer.apply_gamma(i); + } + gamma_hash = calc_crc32(gamma_table, sizeof(gamma_table)); + } + + sprintf(m_signature, + "%s,%u,%d,%d,%d:%dx%d,%d,%d,%08X", + m_name, + m_char_map, + m_face_index, + int(m_glyph_rendering), + m_resolution, + m_height, + m_width, + int(m_hinting), + int(m_flip_y), + gamma_hash); + if(m_glyph_rendering == glyph_ren_outline || + m_glyph_rendering == glyph_ren_agg_mono || + m_glyph_rendering == glyph_ren_agg_gray8) + { + double mtx[6]; + char buf[100]; + m_affine.store_to(mtx); + sprintf(buf, ",%08X%08X%08X%08X%08X%08X", + dbl_to_plain_fx(mtx[0]), + dbl_to_plain_fx(mtx[1]), + dbl_to_plain_fx(mtx[2]), + dbl_to_plain_fx(mtx[3]), + dbl_to_plain_fx(mtx[4]), + dbl_to_plain_fx(mtx[5])); + strcat(m_signature, buf); + } + ++m_change_stamp; + } + } + + + //------------------------------------------------------------------------ + void font_engine_freetype_base::update_char_size() + { + if(m_cur_face) + { + if(m_resolution) + { + FT_Set_Char_Size(m_cur_face, + m_width, // char_width in 1/64th of points + m_height, // char_height in 1/64th of points + m_resolution, // horizontal device resolution + m_resolution); // vertical device resolution + } + else + { + FT_Set_Pixel_Sizes(m_cur_face, + m_width >> 6, // pixel_width + m_height >> 6); // pixel_height + } + update_signature(); + } + } + + + + + + //------------------------------------------------------------------------ + bool font_engine_freetype_base::prepare_glyph(unsigned glyph_code) + { + m_glyph_index = FT_Get_Char_Index(m_cur_face, glyph_code); + m_last_error = FT_Load_Glyph(m_cur_face, + m_glyph_index, + m_hinting ? FT_LOAD_DEFAULT : FT_LOAD_NO_HINTING); +// m_hinting ? FT_LOAD_FORCE_AUTOHINT : FT_LOAD_NO_HINTING); + if(m_last_error == 0) + { + switch(m_glyph_rendering) + { + case glyph_ren_native_mono: + m_last_error = FT_Render_Glyph(m_cur_face->glyph, FT_RENDER_MODE_MONO); + if(m_last_error == 0) + { + decompose_ft_bitmap_mono(m_cur_face->glyph->bitmap, + m_cur_face->glyph->bitmap_left, + m_flip_y ? -m_cur_face->glyph->bitmap_top : + m_cur_face->glyph->bitmap_top, + m_flip_y, + m_scanline_bin, + m_scanlines_bin); + m_bounds.x1 = m_scanlines_bin.min_x(); + m_bounds.y1 = m_scanlines_bin.min_y(); + m_bounds.x2 = m_scanlines_bin.max_x() + 1; + m_bounds.y2 = m_scanlines_bin.max_y() + 1; + m_data_size = m_scanlines_bin.byte_size(); + m_data_type = glyph_data_mono; + m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); + m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); + return true; + } + break; + + + case glyph_ren_native_gray8: + m_last_error = FT_Render_Glyph(m_cur_face->glyph, FT_RENDER_MODE_NORMAL); + if(m_last_error == 0) + { + decompose_ft_bitmap_gray8(m_cur_face->glyph->bitmap, + m_cur_face->glyph->bitmap_left, + m_flip_y ? -m_cur_face->glyph->bitmap_top : + m_cur_face->glyph->bitmap_top, + m_flip_y, + m_rasterizer, + m_scanline_aa, + m_scanlines_aa); + m_bounds.x1 = m_scanlines_aa.min_x(); + m_bounds.y1 = m_scanlines_aa.min_y(); + m_bounds.x2 = m_scanlines_aa.max_x() + 1; + m_bounds.y2 = m_scanlines_aa.max_y() + 1; + m_data_size = m_scanlines_aa.byte_size(); + m_data_type = glyph_data_gray8; + m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); + m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); + return true; + } + break; + + + case glyph_ren_outline: + if(m_last_error == 0) + { + if(m_flag32) + { + m_path32.remove_all(); + if(decompose_ft_outline(m_cur_face->glyph->outline, + m_flip_y, + m_affine, + m_path32)) + { + rect_d bnd = m_path32.bounding_rect(); + m_data_size = m_path32.byte_size(); + m_data_type = glyph_data_outline; + m_bounds.x1 = int(floor(bnd.x1)); + m_bounds.y1 = int(floor(bnd.y1)); + m_bounds.x2 = int(ceil(bnd.x2)); + m_bounds.y2 = int(ceil(bnd.y2)); + m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); + m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); + m_affine.transform(&m_advance_x, &m_advance_y); + return true; + } + } + else + { + m_path16.remove_all(); + if(decompose_ft_outline(m_cur_face->glyph->outline, + m_flip_y, + m_affine, + m_path16)) + { + rect_d bnd = m_path16.bounding_rect(); + m_data_size = m_path16.byte_size(); + m_data_type = glyph_data_outline; + m_bounds.x1 = int(floor(bnd.x1)); + m_bounds.y1 = int(floor(bnd.y1)); + m_bounds.x2 = int(ceil(bnd.x2)); + m_bounds.y2 = int(ceil(bnd.y2)); + m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); + m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); + m_affine.transform(&m_advance_x, &m_advance_y); + return true; + } + } + } + return false; + + case glyph_ren_agg_mono: + if(m_last_error == 0) + { + m_rasterizer.reset(); + if(m_flag32) + { + m_path32.remove_all(); + decompose_ft_outline(m_cur_face->glyph->outline, + m_flip_y, + m_affine, + m_path32); + m_rasterizer.add_path(m_curves32); + } + else + { + m_path16.remove_all(); + decompose_ft_outline(m_cur_face->glyph->outline, + m_flip_y, + m_affine, + m_path16); + m_rasterizer.add_path(m_curves16); + } + m_scanlines_bin.prepare(); // Remove all + render_scanlines(m_rasterizer, m_scanline_bin, m_scanlines_bin); + m_bounds.x1 = m_scanlines_bin.min_x(); + m_bounds.y1 = m_scanlines_bin.min_y(); + m_bounds.x2 = m_scanlines_bin.max_x() + 1; + m_bounds.y2 = m_scanlines_bin.max_y() + 1; + m_data_size = m_scanlines_bin.byte_size(); + m_data_type = glyph_data_mono; + m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); + m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); + m_affine.transform(&m_advance_x, &m_advance_y); + return true; + } + return false; + + + case glyph_ren_agg_gray8: + if(m_last_error == 0) + { + m_rasterizer.reset(); + if(m_flag32) + { + m_path32.remove_all(); + decompose_ft_outline(m_cur_face->glyph->outline, + m_flip_y, + m_affine, + m_path32); + m_rasterizer.add_path(m_curves32); + } + else + { + m_path16.remove_all(); + decompose_ft_outline(m_cur_face->glyph->outline, + m_flip_y, + m_affine, + m_path16); + m_rasterizer.add_path(m_curves16); + } + m_scanlines_aa.prepare(); // Remove all + render_scanlines(m_rasterizer, m_scanline_aa, m_scanlines_aa); + m_bounds.x1 = m_scanlines_aa.min_x(); + m_bounds.y1 = m_scanlines_aa.min_y(); + m_bounds.x2 = m_scanlines_aa.max_x() + 1; + m_bounds.y2 = m_scanlines_aa.max_y() + 1; + m_data_size = m_scanlines_aa.byte_size(); + m_data_type = glyph_data_gray8; + m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x); + m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y); + m_affine.transform(&m_advance_x, &m_advance_y); + return true; + } + return false; + } + } + return false; + } + + + + + //------------------------------------------------------------------------ + void font_engine_freetype_base::write_glyph_to(int8u* data) const + { + if(data && m_data_size) + { + switch(m_data_type) + { + default: return; + case glyph_data_mono: m_scanlines_bin.serialize(data); break; + case glyph_data_gray8: m_scanlines_aa.serialize(data); break; + case glyph_data_outline: + if(m_flag32) + { + m_path32.serialize(data); + } + else + { + m_path16.serialize(data); + } + break; + case glyph_data_invalid: break; + } + } + } + + + + //------------------------------------------------------------------------ + bool font_engine_freetype_base::add_kerning(unsigned first, unsigned second, + double* x, double* y) + { + if(m_cur_face && first && second && FT_HAS_KERNING(m_cur_face)) + { + FT_Vector delta; + FT_Get_Kerning(m_cur_face, first, second, + FT_KERNING_DEFAULT, &delta); + double dx = int26p6_to_dbl(delta.x); + double dy = int26p6_to_dbl(delta.y); + if(m_glyph_rendering == glyph_ren_outline || + m_glyph_rendering == glyph_ren_agg_mono || + m_glyph_rendering == glyph_ren_agg_gray8) + { + m_affine.transform_2x2(&dx, &dy); + } + *x += dx; + *y += dy; + + return true; + } + return false; + } + + + +} + + diff --git a/jni/desmume/src/android/agg/font_freetype/agg_font_freetype.h b/jni/desmume/src/android/agg/font_freetype/agg_font_freetype.h new file mode 100755 index 0000000..3511007 --- /dev/null +++ b/jni/desmume/src/android/agg/font_freetype/agg_font_freetype.h @@ -0,0 +1,201 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_FONT_FREETYPE_INCLUDED +#define AGG_FONT_FREETYPE_INCLUDED + +#include <ft2build.h> +#include FT_FREETYPE_H + + +#include "agg_scanline_storage_aa.h" +#include "agg_scanline_storage_bin.h" +#include "agg_scanline_u.h" +#include "agg_scanline_bin.h" +#include "agg_path_storage_integer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_conv_curve.h" +#include "agg_font_cache_manager.h" +#include "agg_trans_affine.h" + +namespace agg +{ + + + //-----------------------------------------------font_engine_freetype_base + class font_engine_freetype_base + { + public: + //-------------------------------------------------------------------- + typedef serialized_scanlines_adaptor_aa<int8u> gray8_adaptor_type; + typedef serialized_scanlines_adaptor_bin mono_adaptor_type; + typedef scanline_storage_aa8 scanlines_aa_type; + typedef scanline_storage_bin scanlines_bin_type; + + //-------------------------------------------------------------------- + ~font_engine_freetype_base(); + font_engine_freetype_base(bool flag32, unsigned max_faces = 32); + + // Set font parameters + //-------------------------------------------------------------------- + void resolution(unsigned dpi); + bool load_font(const char* font_name, unsigned face_index, glyph_rendering ren_type, + const char* font_mem = 0, const long font_mem_size = 0); + bool attach(const char* file_name); + bool char_map(FT_Encoding map); + bool height(double h); + bool width(double w); + void hinting(bool h); + void flip_y(bool f); + void transform(const trans_affine& affine); + + // Set Gamma + //-------------------------------------------------------------------- + template<class GammaF> void gamma(const GammaF& f) + { + m_rasterizer.gamma(f); + } + + // Accessors + //-------------------------------------------------------------------- + int last_error() const { return m_last_error; } + unsigned resolution() const { return m_resolution; } + const char* name() const { return m_name; } + unsigned num_faces() const; + FT_Encoding char_map() const { return m_char_map; } + double height() const { return double(m_height) / 64.0; } + double width() const { return double(m_width) / 64.0; } + double ascender() const; + double descender() const; + bool hinting() const { return m_hinting; } + bool flip_y() const { return m_flip_y; } + + + // Interface mandatory to implement for font_cache_manager + //-------------------------------------------------------------------- + const char* font_signature() const { return m_signature; } + int change_stamp() const { return m_change_stamp; } + + bool prepare_glyph(unsigned glyph_code); + unsigned glyph_index() const { return m_glyph_index; } + unsigned data_size() const { return m_data_size; } + glyph_data_type data_type() const { return m_data_type; } + const rect_i& bounds() const { return m_bounds; } + double advance_x() const { return m_advance_x; } + double advance_y() const { return m_advance_y; } + void write_glyph_to(int8u* data) const; + bool add_kerning(unsigned first, unsigned second, + double* x, double* y); + + private: + font_engine_freetype_base(const font_engine_freetype_base&); + const font_engine_freetype_base& operator = (const font_engine_freetype_base&); + + void update_char_size(); + void update_signature(); + int find_face(const char* face_name) const; + + bool m_flag32; + int m_change_stamp; + int m_last_error; + char* m_name; + unsigned m_name_len; + unsigned m_face_index; + FT_Encoding m_char_map; + char* m_signature; + unsigned m_height; + unsigned m_width; + bool m_hinting; + bool m_flip_y; + bool m_library_initialized; + FT_Library m_library; // handle to library + FT_Face* m_faces; // A pool of font faces + char** m_face_names; + unsigned m_num_faces; + unsigned m_max_faces; + FT_Face m_cur_face; // handle to the current face object + int m_resolution; + glyph_rendering m_glyph_rendering; + unsigned m_glyph_index; + unsigned m_data_size; + glyph_data_type m_data_type; + rect_i m_bounds; + double m_advance_x; + double m_advance_y; + trans_affine m_affine; + + path_storage_integer<int16, 6> m_path16; + path_storage_integer<int32, 6> m_path32; + conv_curve<path_storage_integer<int16, 6> > m_curves16; + conv_curve<path_storage_integer<int32, 6> > m_curves32; + scanline_u8 m_scanline_aa; + scanline_bin m_scanline_bin; + scanlines_aa_type m_scanlines_aa; + scanlines_bin_type m_scanlines_bin; + rasterizer_scanline_aa<> m_rasterizer; + }; + + + + + //------------------------------------------------font_engine_freetype_int16 + // This class uses values of type int16 (10.6 format) for the vector cache. + // The vector cache is compact, but when rendering glyphs of height + // more that 200 there integer overflow can occur. + // + class font_engine_freetype_int16 : public font_engine_freetype_base + { + public: + typedef serialized_integer_path_adaptor<int16, 6> path_adaptor_type; + typedef font_engine_freetype_base::gray8_adaptor_type gray8_adaptor_type; + typedef font_engine_freetype_base::mono_adaptor_type mono_adaptor_type; + typedef font_engine_freetype_base::scanlines_aa_type scanlines_aa_type; + typedef font_engine_freetype_base::scanlines_bin_type scanlines_bin_type; + + font_engine_freetype_int16(unsigned max_faces = 32) : + font_engine_freetype_base(false, max_faces) {} + }; + + //------------------------------------------------font_engine_freetype_int32 + // This class uses values of type int32 (26.6 format) for the vector cache. + // The vector cache is twice larger than in font_engine_freetype_int16, + // but it allows you to render glyphs of very large sizes. + // + class font_engine_freetype_int32 : public font_engine_freetype_base + { + public: + typedef serialized_integer_path_adaptor<int32, 6> path_adaptor_type; + typedef font_engine_freetype_base::gray8_adaptor_type gray8_adaptor_type; + typedef font_engine_freetype_base::mono_adaptor_type mono_adaptor_type; + typedef font_engine_freetype_base::scanlines_aa_type scanlines_aa_type; + typedef font_engine_freetype_base::scanlines_bin_type scanlines_bin_type; + + font_engine_freetype_int32(unsigned max_faces = 32) : + font_engine_freetype_base(true, max_faces) {} + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/font_win32_tt/Makefile.am b/jni/desmume/src/android/agg/font_win32_tt/Makefile.am new file mode 100755 index 0000000..f03381c --- /dev/null +++ b/jni/desmume/src/android/agg/font_win32_tt/Makefile.am @@ -0,0 +1,13 @@ +## this needs more work, and is intended to work in a unix cross +## compilation toolchain, or in something like msys + +if ENABLE_WIN32_TT +aggincludedir = $(includedir)/agg2 +agginclude_HEADERS = agg_font_win32_tt.h +lib_LTLIBRARIES = libaggfontwin32tt.la + +libaggfontwin32tt_la_LDFLAGS = -no-undefined -version-info @AGG_LIB_VERSION@ @WINDOWS_LIBS@ ../src/libagg.la +libaggfontwin32tt_la_SOURCES = agg_font_win32_tt.cpp +libaggfontwin32tt_la_CXXFLAGS = -I$(top_srcdir)/include @WINDOWS_CFLAGS@ +endif + diff --git a/jni/desmume/src/android/agg/font_win32_tt/agg_font_win32_tt.cpp b/jni/desmume/src/android/agg/font_win32_tt/agg_font_win32_tt.cpp new file mode 100755 index 0000000..b0f89dc --- /dev/null +++ b/jni/desmume/src/android/agg/font_win32_tt/agg_font_win32_tt.cpp @@ -0,0 +1,946 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <stdio.h> +#include "agg_font_win32_tt.h" +#include "agg_bitset_iterator.h" +#include "agg_renderer_scanline.h" + +#ifdef AGG_WIN9X_COMPLIANT +#define GetGlyphOutlineX GetGlyphOutline +#else +#define GetGlyphOutlineX GetGlyphOutlineW +#endif + +namespace agg +{ + + //------------------------------------------------------------------------------ + // + // This code implements the AUTODIN II polynomial + // The variable corresponding to the macro argument "crc" should + // be an unsigned long. + // Oroginal code by Spencer Garrett <srg@quick.com> + // + + // generated using the AUTODIN II polynomial + // x^32 + x^26 + x^23 + x^22 + x^16 + + // x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1 + // + //------------------------------------------------------------------------------ + + static const unsigned crc32tab[256] = + { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, + }; + + //------------------------------------------------------------------------------ + static unsigned calc_crc32(const unsigned char* buf, unsigned size) + { + unsigned crc = (unsigned)~0; + const unsigned char* p; + unsigned len = 0; + unsigned nr = size; + + for (len += nr, p = buf; nr--; ++p) + { + crc = (crc >> 8) ^ crc32tab[(crc ^ *p) & 0xff]; + } + return ~crc; + } + + //------------------------------------------------------------------------ + static inline FIXED dbl_to_fx(double d) + { + int l; + l = int(d * 65536.0); + return *(FIXED*)&l; + } + + //------------------------------------------------------------------------ + static inline int dbl_to_plain_fx(double d) + { + return int(d * 65536.0); + } + + //------------------------------------------------------------------------ + static inline FIXED negate_fx(const FIXED& fx) + { + int l = -(*(int*)(&fx)); + return *(FIXED*)&l; + } + + //------------------------------------------------------------------------ + static inline double fx_to_dbl(const FIXED& p) + { + return double(p.value) + double(p.fract) * (1.0 / 65536.0); + } + + //------------------------------------------------------------------------ + static inline int fx_to_plain_int(const FIXED& fx) + { + return *(int*)(&fx); + } + + //------------------------------------------------------------------------ + static inline int fx_to_int26p6(const FIXED& p) + { + return (int(p.value) << 6) + (int(p.fract) >> 10); + } + + //------------------------------------------------------------------------ + static inline int dbl_to_int26p6(double p) + { + return int(p * 64.0 + 0.5); + } + + //------------------------------------------------------------------------ + template<class Scanline, class ScanlineStorage> + void decompose_win32_glyph_bitmap_mono(const char* gbuf, + int w, int h, + int x, int y, + bool flip_y, + Scanline& sl, + ScanlineStorage& storage) + { + int i; + int pitch = ((w + 31) >> 5) << 2; + const int8u* buf = (const int8u*)gbuf; + sl.reset(x, x + w); + storage.prepare(); + if(flip_y) + { + buf += pitch * (h - 1); + y += h; + pitch = -pitch; + } + for(i = 0; i < h; i++) + { + sl.reset_spans(); + bitset_iterator bits(buf, 0); + int j; + for(j = 0; j < w; j++) + { + if(bits.bit()) sl.add_cell(x + j, cover_full); + ++bits; + } + buf += pitch; + if(sl.num_spans()) + { + sl.finalize(y - i - 1); + storage.render(sl); + } + } + } + + + + //------------------------------------------------------------------------ + template<class Rasterizer, class Scanline, class ScanlineStorage> + void decompose_win32_glyph_bitmap_gray8(const char* gbuf, + int w, int h, + int x, int y, + bool flip_y, + Rasterizer& ras, + Scanline& sl, + ScanlineStorage& storage) + { + int i, j; + int pitch = ((w + 3) >> 2) << 2; + const int8u* buf = (const int8u*)gbuf; + sl.reset(x, x + w); + storage.prepare(); + if(flip_y) + { + buf += pitch * (h - 1); + y += h; + pitch = -pitch; + } + for(i = 0; i < h; i++) + { + sl.reset_spans(); + const int8u* p = buf; + for(j = 0; j < w; j++) + { + if(*p) + { + unsigned v = *p; + if(v == 64) v = 255; + else v <<= 2; + sl.add_cell(x + j, ras.apply_gamma(v)); + } + ++p; + } + buf += pitch; + if(sl.num_spans()) + { + sl.finalize(y - i - 1); + storage.render(sl); + } + } + } + + + + //------------------------------------------------------------------------ + template<class PathStorage> + bool decompose_win32_glyph_outline(const char* gbuf, + unsigned total_size, + bool flip_y, + const trans_affine& mtx, + PathStorage& path) + { + const char* cur_glyph = gbuf; + const char* end_glyph = gbuf + total_size; + double x, y; + typedef typename PathStorage::value_type value_type; + + while(cur_glyph < end_glyph) + { + const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph; + + const char* end_poly = cur_glyph + th->cb; + const char* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER); + + x = fx_to_dbl(th->pfxStart.x); + y = fx_to_dbl(th->pfxStart.y); + if(flip_y) y = -y; + mtx.transform(&x, &y); + path.move_to(value_type(dbl_to_int26p6(x)), + value_type(dbl_to_int26p6(y))); + + while(cur_poly < end_poly) + { + const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly; + + if (pc->wType == TT_PRIM_LINE) + { + int i; + for (i = 0; i < pc->cpfx; i++) + { + x = fx_to_dbl(pc->apfx[i].x); + y = fx_to_dbl(pc->apfx[i].y); + if(flip_y) y = -y; + mtx.transform(&x, &y); + path.line_to(value_type(dbl_to_int26p6(x)), + value_type(dbl_to_int26p6(y))); + } + } + + if (pc->wType == TT_PRIM_QSPLINE) + { + int u; + for (u = 0; u < pc->cpfx - 1; u++) // Walk through points in spline + { + POINTFX pnt_b = pc->apfx[u]; // B is always the current point + POINTFX pnt_c = pc->apfx[u+1]; + + if (u < pc->cpfx - 2) // If not on last spline, compute C + { + // midpoint (x,y) + *(int*)&pnt_c.x = (*(int*)&pnt_b.x + *(int*)&pnt_c.x) / 2; + *(int*)&pnt_c.y = (*(int*)&pnt_b.y + *(int*)&pnt_c.y) / 2; + } + + double x2, y2; + x = fx_to_dbl(pnt_b.x); + y = fx_to_dbl(pnt_b.y); + x2 = fx_to_dbl(pnt_c.x); + y2 = fx_to_dbl(pnt_c.y); + if(flip_y) { y = -y; y2 = -y2; } + mtx.transform(&x, &y); + mtx.transform(&x2, &y2); + path.curve3(value_type(dbl_to_int26p6(x)), + value_type(dbl_to_int26p6(y)), + value_type(dbl_to_int26p6(x2)), + value_type(dbl_to_int26p6(y2))); + } + } + cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx; + } + cur_glyph += th->cb; + } + return true; + } + + + + + //------------------------------------------------------------------------ + font_engine_win32_tt_base::~font_engine_win32_tt_base() + { + delete [] m_kerning_pairs; + delete [] m_gbuf; + delete [] m_signature; + delete [] m_typeface; + if(m_dc && m_old_font) ::SelectObject(m_dc, m_old_font); + unsigned i; + for(i = 0; i < m_num_fonts; ++i) + { + delete [] m_font_names[i]; + ::DeleteObject(m_fonts[i]); + } + delete [] m_font_names; + delete [] m_fonts; + } + + + + //------------------------------------------------------------------------ + font_engine_win32_tt_base::font_engine_win32_tt_base(bool flag32, + HDC dc, + unsigned max_fonts) : + m_flag32(flag32), + m_dc(dc), + m_old_font(m_dc ? (HFONT)::GetCurrentObject(m_dc, OBJ_FONT) : 0), + m_fonts(new HFONT [max_fonts]), + m_num_fonts(0), + m_max_fonts(max_fonts), + m_font_names(new char* [max_fonts]), + m_cur_font(0), + + m_change_stamp(0), + m_typeface(new char [256-16]), + m_typeface_len(256-16-1), + m_signature(new char [256+256-16]), + m_height(0), + m_width(0), + m_weight(FW_REGULAR), + m_italic(false), + m_char_set(DEFAULT_CHARSET), + m_pitch_and_family(FF_DONTCARE), + m_hinting(true), + m_flip_y(false), + m_font_created(false), + m_resolution(0), + m_glyph_rendering(glyph_ren_native_gray8), + m_glyph_index(0), + m_data_size(0), + m_data_type(glyph_data_invalid), + m_bounds(1,1,0,0), + m_advance_x(0.0), + m_advance_y(0.0), + m_gbuf(new char [buf_size]), + m_kerning_pairs(0), + m_num_kerning_pairs(0), + m_max_kerning_pairs(0), + + m_path16(), + m_path32(), + m_curves16(m_path16), + m_curves32(m_path32), + m_scanline_aa(), + m_scanline_bin(), + m_scanlines_aa(), + m_scanlines_bin(), + m_rasterizer() + { + m_curves16.approximation_scale(4.0); + m_curves32.approximation_scale(4.0); + memset(&m_matrix, 0, sizeof(m_matrix)); + m_matrix.eM11.value = 1; + m_matrix.eM22.value = 1; + } + + + + //------------------------------------------------------------------------ + int font_engine_win32_tt_base::find_font(const char* name) const + { + unsigned i; + for(i = 0; i < m_num_fonts; ++i) + { + if(strcmp(name, m_font_names[i]) == 0) return i; + } + return -1; + } + + //------------------------------------------------------------------------ + bool font_engine_win32_tt_base::create_font(const char* typeface_, + glyph_rendering ren_type) + { + if(m_dc) + { + unsigned len = strlen(typeface_); + if(len > m_typeface_len) + { + delete [] m_signature; + delete [] m_typeface; + m_typeface = new char [len + 32]; + m_signature = new char [len + 32 + 256]; + m_typeface_len = len + 32 - 1; + } + + strcpy(m_typeface, typeface_); + + int h = m_height; + int w = m_width; + + if(m_resolution) + { + h = ::MulDiv(m_height, m_resolution, 72); + w = ::MulDiv(m_width, m_resolution, 72); + } + + m_glyph_rendering = ren_type; + update_signature(); + int idx = find_font(m_signature); + if(idx >= 0) + { + m_cur_font = m_fonts[idx]; + ::SelectObject(m_dc, m_cur_font); + m_num_kerning_pairs = 0; + return true; + } + else + { + m_cur_font = ::CreateFont(-h, // height of font + w, // average character width + 0, // angle of escapement + 0, // base-line orientation angle + m_weight, // font weight + m_italic, // italic attribute option + 0, // underline attribute option + 0, // strikeout attribute option + m_char_set, // character set identifier + OUT_DEFAULT_PRECIS, // output precision + CLIP_DEFAULT_PRECIS, // clipping precision + ANTIALIASED_QUALITY, // output quality + m_pitch_and_family, // pitch and family + m_typeface); // typeface name + if(m_cur_font) + { + if(m_num_fonts >= m_max_fonts) + { + delete [] m_font_names[0]; + if(m_old_font) ::SelectObject(m_dc, m_old_font); + ::DeleteObject(m_fonts[0]); + memcpy(m_fonts, + m_fonts + 1, + (m_max_fonts - 1) * sizeof(HFONT)); + memcpy(m_font_names, + m_font_names + 1, + (m_max_fonts - 1) * sizeof(char*)); + m_num_fonts = m_max_fonts - 1; + } + + update_signature(); + m_font_names[m_num_fonts] = new char[strlen(m_signature) + 1]; + strcpy(m_font_names[m_num_fonts], m_signature); + m_fonts[m_num_fonts] = m_cur_font; + ++m_num_fonts; + ::SelectObject(m_dc, m_cur_font); + m_num_kerning_pairs = 0; + return true; + } + } + } + return false; + } + + + + + + //------------------------------------------------------------------------ + bool font_engine_win32_tt_base::create_font(const char* typeface_, + glyph_rendering ren_type, + double height_, + double width_, + int weight_, + bool italic_, + DWORD char_set_, + DWORD pitch_and_family_) + { + height(height_); + width(width_); + weight(weight_); + italic(italic_); + char_set(char_set_); + pitch_and_family(pitch_and_family_); + return create_font(typeface_, ren_type); + } + + + + + //------------------------------------------------------------------------ + void font_engine_win32_tt_base::update_signature() + { + m_signature[0] = 0; + if(m_dc && m_cur_font) + { + unsigned gamma_hash = 0; + if(m_glyph_rendering == glyph_ren_native_gray8 || + m_glyph_rendering == glyph_ren_agg_mono || + m_glyph_rendering == glyph_ren_agg_gray8) + { + unsigned char gamma_table[rasterizer_scanline_aa<>::aa_scale]; + unsigned i; + for(i = 0; i < rasterizer_scanline_aa<>::aa_scale; ++i) + { + gamma_table[i] = m_rasterizer.apply_gamma(i); + } + gamma_hash = calc_crc32(gamma_table, sizeof(gamma_table)); + } + + sprintf(m_signature, + "%s,%u,%d,%d:%dx%d,%d,%d,%d,%d,%d,%08X", + m_typeface, + m_char_set, + int(m_glyph_rendering), + m_resolution, + m_height, + m_width, + m_weight, + int(m_italic), + int(m_hinting), + int(m_flip_y), + int(m_pitch_and_family), + gamma_hash); + + if(m_glyph_rendering == glyph_ren_outline || + m_glyph_rendering == glyph_ren_agg_mono || + m_glyph_rendering == glyph_ren_agg_gray8) + { + double mtx[6]; + char buf[100]; + m_affine.store_to(mtx); + sprintf(buf, ",%08X%08X%08X%08X%08X%08X", + dbl_to_plain_fx(mtx[0]), + dbl_to_plain_fx(mtx[1]), + dbl_to_plain_fx(mtx[2]), + dbl_to_plain_fx(mtx[3]), + dbl_to_plain_fx(mtx[4]), + dbl_to_plain_fx(mtx[5])); + strcat(m_signature, buf); + } + ++m_change_stamp; + } + } + + + + //------------------------------------------------------------------------ + bool font_engine_win32_tt_base::prepare_glyph(unsigned glyph_code) + { + if(m_dc && m_cur_font) + { + int format = GGO_BITMAP; + + switch(m_glyph_rendering) + { + case glyph_ren_native_gray8: + format = GGO_GRAY8_BITMAP; + break; + + case glyph_ren_outline: + case glyph_ren_agg_mono: + case glyph_ren_agg_gray8: + format = GGO_NATIVE; + break; + } + +#ifndef GGO_UNHINTED // For compatibility with old SDKs. +#define GGO_UNHINTED 0x0100 +#endif + if(!m_hinting) format |= GGO_UNHINTED; + + GLYPHMETRICS gm; + int total_size = GetGlyphOutlineX(m_dc, + glyph_code, + format, + &gm, + buf_size, + (void*)m_gbuf, + &m_matrix); + + if(total_size < 0) + { + // GetGlyphOutline() fails when being called for + // GGO_GRAY8_BITMAP and white space (stupid Microsoft). + // It doesn't even initialize the glyph metrics + // structure. So, we have to query the metrics + // separately (basically we need gmCellIncX). + int total_size = GetGlyphOutlineX(m_dc, + glyph_code, + GGO_METRICS, + &gm, + buf_size, + (void*)m_gbuf, + &m_matrix); + + if(total_size < 0) return false; + gm.gmBlackBoxX = gm.gmBlackBoxY = 0; + total_size = 0; + } + + m_glyph_index = glyph_code; + m_advance_x = gm.gmCellIncX; + m_advance_y = -gm.gmCellIncY; + + switch(m_glyph_rendering) + { + case glyph_ren_native_mono: + decompose_win32_glyph_bitmap_mono(m_gbuf, + gm.gmBlackBoxX, + gm.gmBlackBoxY, + gm.gmptGlyphOrigin.x, + m_flip_y ? -gm.gmptGlyphOrigin.y : + gm.gmptGlyphOrigin.y, + m_flip_y, + m_scanline_bin, + m_scanlines_bin); + m_bounds.x1 = m_scanlines_bin.min_x(); + m_bounds.y1 = m_scanlines_bin.min_y(); + m_bounds.x2 = m_scanlines_bin.max_x() + 1; + m_bounds.y2 = m_scanlines_bin.max_y() + 1; + m_data_size = m_scanlines_bin.byte_size(); + m_data_type = glyph_data_mono; + return true; + + case glyph_ren_native_gray8: + decompose_win32_glyph_bitmap_gray8(m_gbuf, + gm.gmBlackBoxX, + gm.gmBlackBoxY, + gm.gmptGlyphOrigin.x, + m_flip_y ? -gm.gmptGlyphOrigin.y : + gm.gmptGlyphOrigin.y, + m_flip_y, + m_rasterizer, + m_scanline_aa, + m_scanlines_aa); + m_bounds.x1 = m_scanlines_aa.min_x(); + m_bounds.y1 = m_scanlines_aa.min_y(); + m_bounds.x2 = m_scanlines_aa.max_x() + 1; + m_bounds.y2 = m_scanlines_aa.max_y() + 1; + m_data_size = m_scanlines_aa.byte_size(); + m_data_type = glyph_data_gray8; + return true; + + case glyph_ren_outline: + m_affine.transform(&m_advance_x, &m_advance_y); + if(m_flag32) + { + m_path32.remove_all(); + if(decompose_win32_glyph_outline(m_gbuf, + total_size, + m_flip_y, + m_affine, + m_path32)) + { + rect_d bnd = m_path32.bounding_rect(); + m_data_size = m_path32.byte_size(); + m_data_type = glyph_data_outline; + m_bounds.x1 = int(floor(bnd.x1)); + m_bounds.y1 = int(floor(bnd.y1)); + m_bounds.x2 = int(ceil(bnd.x2)); + m_bounds.y2 = int(ceil(bnd.y2)); + return true; + } + } + else + { + m_path16.remove_all(); + if(decompose_win32_glyph_outline(m_gbuf, + total_size, + m_flip_y, + m_affine, + m_path16)) + { + rect_d bnd = m_path16.bounding_rect(); + m_data_size = m_path16.byte_size(); + m_data_type = glyph_data_outline; + m_bounds.x1 = int(floor(bnd.x1)); + m_bounds.y1 = int(floor(bnd.y1)); + m_bounds.x2 = int(ceil(bnd.x2)); + m_bounds.y2 = int(ceil(bnd.y2)); + return true; + } + } + break; + + case glyph_ren_agg_mono: + m_rasterizer.reset(); + m_affine.transform(&m_advance_x, &m_advance_y); + if(m_flag32) + { + m_path32.remove_all(); + decompose_win32_glyph_outline(m_gbuf, + total_size, + m_flip_y, + m_affine, + m_path32); + m_rasterizer.add_path(m_curves32); + } + else + { + m_path16.remove_all(); + decompose_win32_glyph_outline(m_gbuf, + total_size, + m_flip_y, + m_affine, + m_path16); + m_rasterizer.add_path(m_curves16); + } + m_scanlines_bin.prepare(); // Remove all + render_scanlines(m_rasterizer, m_scanline_bin, m_scanlines_bin); + m_bounds.x1 = m_scanlines_bin.min_x(); + m_bounds.y1 = m_scanlines_bin.min_y(); + m_bounds.x2 = m_scanlines_bin.max_x() + 1; + m_bounds.y2 = m_scanlines_bin.max_y() + 1; + m_data_size = m_scanlines_bin.byte_size(); + m_data_type = glyph_data_mono; + return true; + + case glyph_ren_agg_gray8: + m_rasterizer.reset(); + m_affine.transform(&m_advance_x, &m_advance_y); + if(m_flag32) + { + m_path32.remove_all(); + decompose_win32_glyph_outline(m_gbuf, + total_size, + m_flip_y, + m_affine, + m_path32); + m_rasterizer.add_path(m_curves32); + } + else + { + m_path16.remove_all(); + decompose_win32_glyph_outline(m_gbuf, + total_size, + m_flip_y, + m_affine, + m_path16); + m_rasterizer.add_path(m_curves16); + } + m_scanlines_aa.prepare(); // Remove all + render_scanlines(m_rasterizer, m_scanline_aa, m_scanlines_aa); + m_bounds.x1 = m_scanlines_aa.min_x(); + m_bounds.y1 = m_scanlines_aa.min_y(); + m_bounds.x2 = m_scanlines_aa.max_x() + 1; + m_bounds.y2 = m_scanlines_aa.max_y() + 1; + m_data_size = m_scanlines_aa.byte_size(); + m_data_type = glyph_data_gray8; + return true; + } + } + return false; + } + + + + //------------------------------------------------------------------------ + void font_engine_win32_tt_base::write_glyph_to(int8u* data) const + { + if(data && m_data_size) + { + switch(m_data_type) + { + case glyph_data_mono: m_scanlines_bin.serialize(data); break; + case glyph_data_gray8: m_scanlines_aa.serialize(data); break; + case glyph_data_outline: + if(m_flag32) + { + m_path32.serialize(data); + } + else + { + m_path16.serialize(data); + } + break; + } + } + } + + + + //------------------------------------------------------------------------ + static bool pair_less(const KERNINGPAIR& v1, const KERNINGPAIR& v2) + { + if(v1.wFirst != v2.wFirst) return v1.wFirst < v2.wFirst; + return v1.wSecond < v2.wSecond; + } + + + //------------------------------------------------------------------------ + void font_engine_win32_tt_base::sort_kerning_pairs() + { + pod_array_adaptor<KERNINGPAIR> pairs(m_kerning_pairs, m_num_kerning_pairs); + quick_sort(pairs, pair_less); + } + + + + //------------------------------------------------------------------------ + void font_engine_win32_tt_base::load_kerning_pairs() + { + if(m_dc && m_cur_font) + { + if(m_kerning_pairs == 0) + { + m_kerning_pairs = new KERNINGPAIR [16384-16]; + m_max_kerning_pairs = 16384-16; + } + m_num_kerning_pairs = ::GetKerningPairs(m_dc, + m_max_kerning_pairs, + m_kerning_pairs); + + if(m_num_kerning_pairs) + { + // Check to see if the kerning pairs are sorted and + // sort them if they are not. + //---------------- + unsigned i; + for(i = 1; i < m_num_kerning_pairs; ++i) + { + if(!pair_less(m_kerning_pairs[i - 1], m_kerning_pairs[i])) + { + sort_kerning_pairs(); + break; + } + } + } + } + } + + + //------------------------------------------------------------------------ + bool font_engine_win32_tt_base::add_kerning(unsigned first, unsigned second, + double* x, double* y) + { + if(m_dc && m_cur_font) + { + if(m_num_kerning_pairs == 0) + { + load_kerning_pairs(); + } + + int end = m_num_kerning_pairs - 1; + int beg = 0; + KERNINGPAIR t; + t.wFirst = (WORD)first; + t.wSecond = (WORD)second; + while(beg <= end) + { + int mid = (end + beg) / 2; + if(m_kerning_pairs[mid].wFirst == t.wFirst && + m_kerning_pairs[mid].wSecond == t.wSecond) + { + double dx = m_kerning_pairs[mid].iKernAmount; + double dy = 0.0; + if(m_glyph_rendering == glyph_ren_outline || + m_glyph_rendering == glyph_ren_agg_mono || + m_glyph_rendering == glyph_ren_agg_gray8) + { + m_affine.transform_2x2(&dx, &dy); + } + *x += dx; + *y += dy; + return true; + } + else + if(pair_less(t, m_kerning_pairs[mid])) + { + end = mid - 1; + } + else + { + beg = mid + 1; + } + } + return false; + } + return false; + } + + + +} + diff --git a/jni/desmume/src/android/agg/font_win32_tt/agg_font_win32_tt.h b/jni/desmume/src/android/agg/font_win32_tt/agg_font_win32_tt.h new file mode 100755 index 0000000..6f4cd39 --- /dev/null +++ b/jni/desmume/src/android/agg/font_win32_tt/agg_font_win32_tt.h @@ -0,0 +1,223 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_FONT_WIN32_TT_INCLUDED +#define AGG_FONT_WIN32_TT_INCLUDED + +#include <windows.h> +#include "agg_scanline_storage_aa.h" +#include "agg_scanline_storage_bin.h" +#include "agg_scanline_u.h" +#include "agg_scanline_bin.h" +#include "agg_path_storage_integer.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_conv_curve.h" +#include "agg_trans_affine.h" +#include "agg_font_cache_manager.h" + +namespace agg +{ + + //-----------------------------------------------font_engine_win32_tt_base + class font_engine_win32_tt_base + { + enum { buf_size = 32768-32 }; + + public: + //-------------------------------------------------------------------- + typedef serialized_scanlines_adaptor_aa<int8u> gray8_adaptor_type; + typedef serialized_scanlines_adaptor_bin mono_adaptor_type; + typedef scanline_storage_aa8 scanlines_aa_type; + typedef scanline_storage_bin scanlines_bin_type; + + //-------------------------------------------------------------------- + ~font_engine_win32_tt_base(); + font_engine_win32_tt_base(bool flag32, HDC dc, unsigned max_fonts = 32); + + // Set font parameters + //-------------------------------------------------------------------- + void resolution(unsigned dpi) { m_resolution = unsigned(dpi); } + void height(double h) { m_height = unsigned(h); } + void width(double w) { m_width = unsigned(w); } + void weight(int w) { m_weight = w; } + void italic(bool it) { m_italic = it; } + void char_set(DWORD c) { m_char_set = c; } + void pitch_and_family(DWORD p){ m_pitch_and_family = p; } + void flip_y(bool flip) { m_flip_y = flip; } + void hinting(bool h) { m_hinting = h; } + bool create_font(const char* typeface_, glyph_rendering ren_type); + + bool create_font(const char* typeface_, + glyph_rendering ren_type, + double height_, + double width_=0.0, + int weight_=FW_REGULAR, + bool italic_=false, + DWORD char_set_=ANSI_CHARSET, + DWORD pitch_and_family_=FF_DONTCARE); + + // Set Gamma + //-------------------------------------------------------------------- + template<class GammaF> void gamma(const GammaF& f) + { + m_rasterizer.gamma(f); + } + + //-------------------------------------------------------------------- + void transform(const agg::trans_affine& mtx) + { + m_affine = mtx; + } + + // Accessors + //-------------------------------------------------------------------- + unsigned resolution() const { return m_resolution; } + const char* typeface() const { return m_typeface; } + double height() const { return m_height; } + double width() const { return m_width; } + int weight() const { return m_weight; } + bool italic() const { return m_italic; } + DWORD char_set() const { return m_char_set; } + DWORD pitch_and_family() const { return m_pitch_and_family; } + bool hinting() const { return m_hinting; } + bool flip_y() const { return m_flip_y; } + + + // Interface mandatory to implement for font_cache_manager + //-------------------------------------------------------------------- + const char* font_signature() const { return m_signature; } + int change_stamp() const { return m_change_stamp; } + + bool prepare_glyph(unsigned glyph_code); + unsigned glyph_index() const { return m_glyph_index; } + unsigned data_size() const { return m_data_size; } + glyph_data_type data_type() const { return m_data_type; } + const rect_i& bounds() const { return m_bounds; } + double advance_x() const { return m_advance_x; } + double advance_y() const { return m_advance_y; } + void write_glyph_to(int8u* data) const; + bool add_kerning(unsigned first, unsigned second, + double* x, double* y); + + private: + font_engine_win32_tt_base(const font_engine_win32_tt_base&); + const font_engine_win32_tt_base& operator = (const font_engine_win32_tt_base&); + + void update_signature(); + void load_kerning_pairs(); + void sort_kerning_pairs(); + int find_font(const char* name) const; + + bool m_flag32; + HDC m_dc; + HFONT m_old_font; + HFONT* m_fonts; + unsigned m_num_fonts; + unsigned m_max_fonts; + char** m_font_names; + HFONT m_cur_font; + + int m_change_stamp; + char* m_typeface; + unsigned m_typeface_len; + char* m_signature; + unsigned m_height; + unsigned m_width; + int m_weight; + bool m_italic; + DWORD m_char_set; + DWORD m_pitch_and_family; + bool m_hinting; + bool m_flip_y; + + bool m_font_created; + unsigned m_resolution; + glyph_rendering m_glyph_rendering; + unsigned m_glyph_index; + unsigned m_data_size; + glyph_data_type m_data_type; + rect_i m_bounds; + double m_advance_x; + double m_advance_y; + MAT2 m_matrix; + char* m_gbuf; + KERNINGPAIR* m_kerning_pairs; + unsigned m_num_kerning_pairs; + unsigned m_max_kerning_pairs; + trans_affine m_affine; + + path_storage_integer<int16, 6> m_path16; + path_storage_integer<int32, 6> m_path32; + conv_curve<path_storage_integer<int16, 6> > m_curves16; + conv_curve<path_storage_integer<int32, 6> > m_curves32; + scanline_u8 m_scanline_aa; + scanline_bin m_scanline_bin; + scanlines_aa_type m_scanlines_aa; + scanlines_bin_type m_scanlines_bin; + rasterizer_scanline_aa<> m_rasterizer; + }; + + + + + //------------------------------------------------font_engine_win32_tt_int16 + // This class uses values of type int16 (10.6 format) for the vector cache. + // The vector cache is compact, but when rendering glyphs of height + // more that 200 there integer overflow can occur. + // + class font_engine_win32_tt_int16 : public font_engine_win32_tt_base + { + public: + typedef serialized_integer_path_adaptor<int16, 6> path_adaptor_type; + typedef font_engine_win32_tt_base::gray8_adaptor_type gray8_adaptor_type; + typedef font_engine_win32_tt_base::mono_adaptor_type mono_adaptor_type; + typedef font_engine_win32_tt_base::scanlines_aa_type scanlines_aa_type; + typedef font_engine_win32_tt_base::scanlines_bin_type scanlines_bin_type; + + font_engine_win32_tt_int16(HDC dc, unsigned max_fonts = 32) : + font_engine_win32_tt_base(false, dc, max_fonts) {} + }; + + //------------------------------------------------font_engine_win32_tt_int32 + // This class uses values of type int32 (26.6 format) for the vector cache. + // The vector cache is twice larger than in font_engine_win32_tt_int16, + // but it allows you to render glyphs of very large sizes. + // + class font_engine_win32_tt_int32 : public font_engine_win32_tt_base + { + public: + typedef serialized_integer_path_adaptor<int32, 6> path_adaptor_type; + typedef font_engine_win32_tt_base::gray8_adaptor_type gray8_adaptor_type; + typedef font_engine_win32_tt_base::mono_adaptor_type mono_adaptor_type; + typedef font_engine_win32_tt_base::scanlines_aa_type scanlines_aa_type; + typedef font_engine_win32_tt_base::scanlines_bin_type scanlines_bin_type; + + font_engine_win32_tt_int32(HDC dc, unsigned max_fonts = 32) : + font_engine_win32_tt_base(true, dc, max_fonts) {} + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/gpc/Makefile.am b/jni/desmume/src/android/agg/gpc/Makefile.am new file mode 100755 index 0000000..b40648d --- /dev/null +++ b/jni/desmume/src/android/agg/gpc/Makefile.am @@ -0,0 +1,11 @@ +if ENABLE_GPC +lib_LTLIBRARIES = libagggpc.la +include_HEADERS=gpc.h +libagggpc_la_LDFLAGS = -no-undefined -version-info @AGG_LIB_VERSION@ +libagggpc_la_SOURCES = gpc.c + +EXTRA_DIST=copying.txt\ + VERSIONS.TXT\ + gpc.h + +endif diff --git a/jni/desmume/src/android/agg/gpc/VERSIONS.TXT b/jni/desmume/src/android/agg/gpc/VERSIONS.TXT new file mode 100755 index 0000000..8eeee67 --- /dev/null +++ b/jni/desmume/src/android/agg/gpc/VERSIONS.TXT @@ -0,0 +1,123 @@ + +Generic Polygon Clipper (gpc) Revision History +============================================== + + +v2.32 17th Dec 2004 +--------------------- + Fixed occasional memory leak occurring when processing some + degenerate polygon arrangements. + Added explicit type casting to memory allocator in support of + increased code portability. + +v2.31 4th Jun 1999 +--------------------- + Separated edge merging measure based on a user-defined GPC_EPSILON + value from general numeric equality testing and ordering, which now + uses direct arithmetic comparison rather an EPSILON based proximity + test. + Fixed problem with numerical equality test during construction of + local minima and scanbeam tables, leading to occasional crash. + Fixed hole array memory leak in gpc_add_contour. + Fixed uninitialised hole field bug in gpc_polygon_clip result. + +v2.30 11th Apr 1999 +--------------------- + Major re-write. + Minor API change: additional 'hole' array field added to gpc_polygon + datatype to indicate which constituent contours are internal holes, + and which form external boundaries. + Minor API change: additional 'hole' argument to gpc_add_contour + to indicate whether the new contour is a hole or external contour. + Minor API change: additional parameter to gpc_read_polygon and + gpc_write_polygon to indicate whether or not to read or write + contour hole flags. + Fixed NULL pointer bug in add/merge left/right operations. + Fixed numerical problem in intersection table generation. + Fixed zero byte malloc problem. + Fixed problem producing occasional 2 vertex contours. + Added bounding box test optimisations. + Simplified edge bundle creation, detection of scanbeam internal + edge intersections and tristrip scanbeam boundary code. + Renamed 'class' variable to be C++ friendly. + +v2.22 17th Oct 1998 +--------------------- + Re-implemented edge interpolation and intersection calculations + to improve numerical robustness. + Simplified setting of GPC_EPSILON. + +v2.21 19th Aug 1998 +--------------------- + Fixed problem causing occasional incorrect output when processing + self-intersecting polygons (bow-ties etc). + Removed bug which may lead to non-generation of uppermost triangle + in tristrip output. + +v2.20 26th May 1998 +--------------------- + Major re-write. + Added exclusive-or polygon set operation. + Replaced table-based processing of edge intersections with + rule-based system. + Replaced two-pass approach to scanbeam interior processing with + single pass method. + +v2.10a 14th May 1998 +--------------------- + Minor bug-fixes to counter some v2.10 reliability problems. + +v2.10 11th May 1998 +--------------------- + Major re-write. + Incorporated edge bundle processing of AET to overcome coincident + edge problems present in previous releases. + Replaced Vatti's method for processing scanbeam interior regions + with an adapted version of the scanbeam boundary processing + algorithm. + +v2.02 16th Apr 1998 (unreleased) +---------------------------------- + Fixed internal minimum vertex duplication in gpc_polygon_clip + result. + Improved line intersection code discourage superfluous + intersections near line ends. + Removed limited precision number formatting in gpc_write_polygon. + Modification to allow subject or clip polygon to be reused as the + result in gpc_polygon_clip without memory leakage. + +v2.01 23rd Feb 1998 +--------------------- + Removed bug causing duplicated vertices in output polygon. + Fixed scanbeam table index overrun problem. + +v2.00 25th Nov 1997 +--------------------- + Major re-write. + Replaced temporary horizontal edge work-around (using tilting) + with true horizontal edge handling. + Trapezoidal output replaced by tristrips. + gpc_op constants now feature a `GPC_' prefix. + Data structures now passed by reference to gpc functions. + Replaced AET search by proxy addressing in polygon table. + Eliminated most (all?) coincident vertex / edge crashes. + +v1.02 18th Oct 1997 (unreleased) +---------------------------------- + Significantly reduced number of mallocs in build_lmt. + Scanbeam table now built using heapsort rather than insertion + sort. + +v1.01 12th Oct 1997 +--------------------- + Fixed memory leak during output polygon build in + gpc_clip_polygon. + Removed superfluous logfile debug code. + Commented out malloc counts. + Added missing horizontal edge tilt-correction code in + gpc_clip_polygon. + +v1.00 8th Oct 1997 +-------------------- + First release. + diff --git a/jni/desmume/src/android/agg/gpc/copying.txt b/jni/desmume/src/android/agg/gpc/copying.txt new file mode 100755 index 0000000..0160fb4 --- /dev/null +++ b/jni/desmume/src/android/agg/gpc/copying.txt @@ -0,0 +1,22 @@ + + http://www.cs.man.ac.uk/aig/staff/alan/software/ + +Author: Alan Murta (email: gpc@cs.man.ac.uk) +Version: 2.31 +Date: 4th June 1999 + +Copyright: (C) 1997-1999, Advanced Interfaces Group, + University of Manchester. + + This software is free for non-commercial use. It may be copied, + modified, and redistributed provided that this copyright notice + is preserved on all copies. The intellectual property rights of + the algorithms used reside with the University of Manchester + Advanced Interfaces Group. + + You may not use this software, in whole or in part, in support + of any commercial product without the express consent of the + author. + + There is no warranty or other guarantee of fitness of this + software for any purpose. It is provided solely "as is". diff --git a/jni/desmume/src/android/agg/gpc/gpc.c b/jni/desmume/src/android/agg/gpc/gpc.c new file mode 100755 index 0000000..b9cce1b --- /dev/null +++ b/jni/desmume/src/android/agg/gpc/gpc.c @@ -0,0 +1,2472 @@ +/* +=========================================================================== + +Project: Generic Polygon Clipper + + A new algorithm for calculating the difference, intersection, + exclusive-or or union of arbitrary polygon sets. + +File: gpc.c +Author: Alan Murta (email: gpc@cs.man.ac.uk) +Version: 2.32 +Date: 17th December 2004 + +Copyright: (C) 1997-2004, Advanced Interfaces Group, + University of Manchester. + + This software is free for non-commercial use. It may be copied, + modified, and redistributed provided that this copyright notice + is preserved on all copies. The intellectual property rights of + the algorithms used reside with the University of Manchester + Advanced Interfaces Group. + + You may not use this software, in whole or in part, in support + of any commercial product without the express consent of the + author. + + There is no warranty or other guarantee of fitness of this + software for any purpose. It is provided solely "as is". + +=========================================================================== +*/ + + +/* +=========================================================================== + Includes +=========================================================================== +*/ + +#include "gpc.h" +#include <stdlib.h> +#include <float.h> +#include <math.h> + + +/* +=========================================================================== + Constants +=========================================================================== +*/ + +#ifndef TRUE +#define FALSE 0 +#define TRUE 1 +#endif + +#define LEFT 0 +#define RIGHT 1 + +#define ABOVE 0 +#define BELOW 1 + +#define CLIP 0 +#define SUBJ 1 + +#define INVERT_TRISTRIPS FALSE + + +/* +=========================================================================== + Macros +=========================================================================== +*/ + +#define EQ(a, b) (fabs((a) - (b)) <= GPC_EPSILON) + +#define PREV_INDEX(i, n) ((i - 1 + n) % n) +#define NEXT_INDEX(i, n) ((i + 1 ) % n) + +#define OPTIMAL(v, i, n) ((v[PREV_INDEX(i, n)].y != v[i].y) || \ + (v[NEXT_INDEX(i, n)].y != v[i].y)) + +#define FWD_MIN(v, i, n) ((v[PREV_INDEX(i, n)].vertex.y >= v[i].vertex.y) \ + && (v[NEXT_INDEX(i, n)].vertex.y > v[i].vertex.y)) + +#define NOT_FMAX(v, i, n) (v[NEXT_INDEX(i, n)].vertex.y > v[i].vertex.y) + +#define REV_MIN(v, i, n) ((v[PREV_INDEX(i, n)].vertex.y > v[i].vertex.y) \ + && (v[NEXT_INDEX(i, n)].vertex.y >= v[i].vertex.y)) + +#define NOT_RMAX(v, i, n) (v[PREV_INDEX(i, n)].vertex.y > v[i].vertex.y) + +#define VERTEX(e,p,s,x,y) {add_vertex(&((e)->outp[(p)]->v[(s)]), x, y); \ + (e)->outp[(p)]->active++;} + +#define P_EDGE(d,e,p,i,j) {(d)= (e); \ + do {(d)= (d)->prev;} while (!(d)->outp[(p)]); \ + (i)= (d)->bot.x + (d)->dx * ((j)-(d)->bot.y);} + +#define N_EDGE(d,e,p,i,j) {(d)= (e); \ + do {(d)= (d)->next;} while (!(d)->outp[(p)]); \ + (i)= (d)->bot.x + (d)->dx * ((j)-(d)->bot.y);} + +#define MALLOC(p, b, s, t) {if ((b) > 0) { \ + p= (t*)malloc(b); if (!(p)) { \ + fprintf(stderr, "gpc malloc failure: %s\n", s); \ + exit(0);}} else p= NULL;} + +#define FREE(p) {if (p) {free(p); (p)= NULL;}} + + +/* +=========================================================================== + Private Data Types +=========================================================================== +*/ + +typedef enum /* Edge intersection classes */ +{ + NUL, /* Empty non-intersection */ + EMX, /* External maximum */ + ELI, /* External left intermediate */ + TED, /* Top edge */ + ERI, /* External right intermediate */ + RED, /* Right edge */ + IMM, /* Internal maximum and minimum */ + IMN, /* Internal minimum */ + EMN, /* External minimum */ + EMM, /* External maximum and minimum */ + LED, /* Left edge */ + ILI, /* Internal left intermediate */ + BED, /* Bottom edge */ + IRI, /* Internal right intermediate */ + IMX, /* Internal maximum */ + FUL /* Full non-intersection */ +} vertex_type; + +typedef enum /* Horizontal edge states */ +{ + NH, /* No horizontal edge */ + BH, /* Bottom horizontal edge */ + TH /* Top horizontal edge */ +} h_state; + +typedef enum /* Edge bundle state */ +{ + UNBUNDLED, /* Isolated edge not within a bundle */ + BUNDLE_HEAD, /* Bundle head node */ + BUNDLE_TAIL /* Passive bundle tail node */ +} bundle_state; + +typedef struct v_shape /* Internal vertex list datatype */ +{ + double x; /* X coordinate component */ + double y; /* Y coordinate component */ + struct v_shape *next; /* Pointer to next vertex in list */ +} vertex_node; + +typedef struct p_shape /* Internal contour / tristrip type */ +{ + int active; /* Active flag / vertex count */ + int hole; /* Hole / external contour flag */ + vertex_node *v[2]; /* Left and right vertex list ptrs */ + struct p_shape *next; /* Pointer to next polygon contour */ + struct p_shape *proxy; /* Pointer to actual structure used */ +} polygon_node; + +typedef struct edge_shape +{ + gpc_vertex vertex; /* Piggy-backed contour vertex data */ + gpc_vertex bot; /* Edge lower (x, y) coordinate */ + gpc_vertex top; /* Edge upper (x, y) coordinate */ + double xb; /* Scanbeam bottom x coordinate */ + double xt; /* Scanbeam top x coordinate */ + double dx; /* Change in x for a unit y increase */ + int type; /* Clip / subject edge flag */ + int bundle[2][2]; /* Bundle edge flags */ + int bside[2]; /* Bundle left / right indicators */ + bundle_state bstate[2]; /* Edge bundle state */ + polygon_node *outp[2]; /* Output polygon / tristrip pointer */ + struct edge_shape *prev; /* Previous edge in the AET */ + struct edge_shape *next; /* Next edge in the AET */ + struct edge_shape *pred; /* Edge connected at the lower end */ + struct edge_shape *succ; /* Edge connected at the upper end */ + struct edge_shape *next_bound; /* Pointer to next bound in LMT */ +} edge_node; + +typedef struct lmt_shape /* Local minima table */ +{ + double y; /* Y coordinate at local minimum */ + edge_node *first_bound; /* Pointer to bound list */ + struct lmt_shape *next; /* Pointer to next local minimum */ +} lmt_node; + +typedef struct sbt_t_shape /* Scanbeam tree */ +{ + double y; /* Scanbeam node y value */ + struct sbt_t_shape *less; /* Pointer to nodes with lower y */ + struct sbt_t_shape *more; /* Pointer to nodes with higher y */ +} sb_tree; + +typedef struct it_shape /* Intersection table */ +{ + edge_node *ie[2]; /* Intersecting edge (bundle) pair */ + gpc_vertex point; /* Point of intersection */ + struct it_shape *next; /* The next intersection table node */ +} it_node; + +typedef struct st_shape /* Sorted edge table */ +{ + edge_node *edge; /* Pointer to AET edge */ + double xb; /* Scanbeam bottom x coordinate */ + double xt; /* Scanbeam top x coordinate */ + double dx; /* Change in x for a unit y increase */ + struct st_shape *prev; /* Previous edge in sorted list */ +} st_node; + +typedef struct bbox_shape /* Contour axis-aligned bounding box */ +{ + double xmin; /* Minimum x coordinate */ + double ymin; /* Minimum y coordinate */ + double xmax; /* Maximum x coordinate */ + double ymax; /* Maximum y coordinate */ +} bbox; + + +/* +=========================================================================== + Global Data +=========================================================================== +*/ + +/* Horizontal edge state transitions within scanbeam boundary */ +const h_state next_h_state[3][6]= +{ + /* ABOVE BELOW CROSS */ + /* L R L R L R */ + /* NH */ {BH, TH, TH, BH, NH, NH}, + /* BH */ {NH, NH, NH, NH, TH, TH}, + /* TH */ {NH, NH, NH, NH, BH, BH} +}; + + +/* +=========================================================================== + Private Functions +=========================================================================== +*/ + +static void reset_it(it_node **it) +{ + it_node *itn; + + while (*it) + { + itn= (*it)->next; + FREE(*it); + *it= itn; + } +} + + +static void reset_lmt(lmt_node **lmt) +{ + lmt_node *lmtn; + + while (*lmt) + { + lmtn= (*lmt)->next; + FREE(*lmt); + *lmt= lmtn; + } +} + + +static void insert_bound(edge_node **b, edge_node *e) +{ + edge_node *existing_bound; + + if (!*b) + { + /* Link node e to the tail of the list */ + *b= e; + } + else + { + /* Do primary sort on the x field */ + if (e[0].bot.x < (*b)[0].bot.x) + { + /* Insert a new node mid-list */ + existing_bound= *b; + *b= e; + (*b)->next_bound= existing_bound; + } + else + { + if (e[0].bot.x == (*b)[0].bot.x) + { + /* Do secondary sort on the dx field */ + if (e[0].dx < (*b)[0].dx) + { + /* Insert a new node mid-list */ + existing_bound= *b; + *b= e; + (*b)->next_bound= existing_bound; + } + else + { + /* Head further down the list */ + insert_bound(&((*b)->next_bound), e); + } + } + else + { + /* Head further down the list */ + insert_bound(&((*b)->next_bound), e); + } + } + } +} + + +static edge_node **bound_list(lmt_node **lmt, double y) +{ + lmt_node *existing_node; + + if (!*lmt) + { + /* Add node onto the tail end of the LMT */ + MALLOC(*lmt, sizeof(lmt_node), "LMT insertion", lmt_node); + (*lmt)->y= y; + (*lmt)->first_bound= NULL; + (*lmt)->next= NULL; + return &((*lmt)->first_bound); + } + else + if (y < (*lmt)->y) + { + /* Insert a new LMT node before the current node */ + existing_node= *lmt; + MALLOC(*lmt, sizeof(lmt_node), "LMT insertion", lmt_node); + (*lmt)->y= y; + (*lmt)->first_bound= NULL; + (*lmt)->next= existing_node; + return &((*lmt)->first_bound); + } + else + if (y > (*lmt)->y) + /* Head further up the LMT */ + return bound_list(&((*lmt)->next), y); + else + /* Use this existing LMT node */ + return &((*lmt)->first_bound); +} + + +static void add_to_sbtree(int *entries, sb_tree **sbtree, double y) +{ + if (!*sbtree) + { + /* Add a new tree node here */ + MALLOC(*sbtree, sizeof(sb_tree), "scanbeam tree insertion", sb_tree); + (*sbtree)->y= y; + (*sbtree)->less= NULL; + (*sbtree)->more= NULL; + (*entries)++; + } + else + { + if ((*sbtree)->y > y) + { + /* Head into the 'less' sub-tree */ + add_to_sbtree(entries, &((*sbtree)->less), y); + } + else + { + if ((*sbtree)->y < y) + { + /* Head into the 'more' sub-tree */ + add_to_sbtree(entries, &((*sbtree)->more), y); + } + } + } +} + + +static void build_sbt(int *entries, double *sbt, sb_tree *sbtree) +{ + if (sbtree->less) + build_sbt(entries, sbt, sbtree->less); + sbt[*entries]= sbtree->y; + (*entries)++; + if (sbtree->more) + build_sbt(entries, sbt, sbtree->more); +} + + +static void free_sbtree(sb_tree **sbtree) +{ + if (*sbtree) + { + free_sbtree(&((*sbtree)->less)); + free_sbtree(&((*sbtree)->more)); + FREE(*sbtree); + } +} + + +static int count_optimal_vertices(gpc_vertex_list c) +{ + int result= 0, i; + + /* Ignore non-contributing contours */ + if (c.num_vertices > 0) + { + for (i= 0; i < c.num_vertices; i++) + /* Ignore superfluous vertices embedded in horizontal edges */ + if (OPTIMAL(c.vertex, i, c.num_vertices)) + result++; + } + return result; +} + + +static edge_node *build_lmt(lmt_node **lmt, sb_tree **sbtree, + int *sbt_entries, gpc_polygon *p, int type, + gpc_op op) +{ + int c, i, min, max, num_edges, v, num_vertices; + int total_vertices= 0, e_index=0; + edge_node *e, *edge_table; + + for (c= 0; c < p->num_contours; c++) + total_vertices+= count_optimal_vertices(p->contour[c]); + + /* Create the entire input polygon edge table in one go */ + MALLOC(edge_table, total_vertices * sizeof(edge_node), + "edge table creation", edge_node); + + for (c= 0; c < p->num_contours; c++) + { + if (p->contour[c].num_vertices < 0) + { + /* Ignore the non-contributing contour and repair the vertex count */ + p->contour[c].num_vertices= -p->contour[c].num_vertices; + } + else + { + /* Perform contour optimisation */ + num_vertices= 0; + for (i= 0; i < p->contour[c].num_vertices; i++) + if (OPTIMAL(p->contour[c].vertex, i, p->contour[c].num_vertices)) + { + edge_table[num_vertices].vertex.x= p->contour[c].vertex[i].x; + edge_table[num_vertices].vertex.y= p->contour[c].vertex[i].y; + + /* Record vertex in the scanbeam table */ + add_to_sbtree(sbt_entries, sbtree, + edge_table[num_vertices].vertex.y); + + num_vertices++; + } + + /* Do the contour forward pass */ + for (min= 0; min < num_vertices; min++) + { + /* If a forward local minimum... */ + if (FWD_MIN(edge_table, min, num_vertices)) + { + /* Search for the next local maximum... */ + num_edges= 1; + max= NEXT_INDEX(min, num_vertices); + while (NOT_FMAX(edge_table, max, num_vertices)) + { + num_edges++; + max= NEXT_INDEX(max, num_vertices); + } + + /* Build the next edge list */ + e= &edge_table[e_index]; + e_index+= num_edges; + v= min; + e[0].bstate[BELOW]= UNBUNDLED; + e[0].bundle[BELOW][CLIP]= FALSE; + e[0].bundle[BELOW][SUBJ]= FALSE; + for (i= 0; i < num_edges; i++) + { + e[i].xb= edge_table[v].vertex.x; + e[i].bot.x= edge_table[v].vertex.x; + e[i].bot.y= edge_table[v].vertex.y; + + v= NEXT_INDEX(v, num_vertices); + + e[i].top.x= edge_table[v].vertex.x; + e[i].top.y= edge_table[v].vertex.y; + e[i].dx= (edge_table[v].vertex.x - e[i].bot.x) / + (e[i].top.y - e[i].bot.y); + e[i].type= type; + e[i].outp[ABOVE]= NULL; + e[i].outp[BELOW]= NULL; + e[i].next= NULL; + e[i].prev= NULL; + e[i].succ= ((num_edges > 1) && (i < (num_edges - 1))) ? + &(e[i + 1]) : NULL; + e[i].pred= ((num_edges > 1) && (i > 0)) ? &(e[i - 1]) : NULL; + e[i].next_bound= NULL; + e[i].bside[CLIP]= (op == GPC_DIFF) ? RIGHT : LEFT; + e[i].bside[SUBJ]= LEFT; + } + insert_bound(bound_list(lmt, edge_table[min].vertex.y), e); + } + } + + /* Do the contour reverse pass */ + for (min= 0; min < num_vertices; min++) + { + /* If a reverse local minimum... */ + if (REV_MIN(edge_table, min, num_vertices)) + { + /* Search for the previous local maximum... */ + num_edges= 1; + max= PREV_INDEX(min, num_vertices); + while (NOT_RMAX(edge_table, max, num_vertices)) + { + num_edges++; + max= PREV_INDEX(max, num_vertices); + } + + /* Build the previous edge list */ + e= &edge_table[e_index]; + e_index+= num_edges; + v= min; + e[0].bstate[BELOW]= UNBUNDLED; + e[0].bundle[BELOW][CLIP]= FALSE; + e[0].bundle[BELOW][SUBJ]= FALSE; + for (i= 0; i < num_edges; i++) + { + e[i].xb= edge_table[v].vertex.x; + e[i].bot.x= edge_table[v].vertex.x; + e[i].bot.y= edge_table[v].vertex.y; + + v= PREV_INDEX(v, num_vertices); + + e[i].top.x= edge_table[v].vertex.x; + e[i].top.y= edge_table[v].vertex.y; + e[i].dx= (edge_table[v].vertex.x - e[i].bot.x) / + (e[i].top.y - e[i].bot.y); + e[i].type= type; + e[i].outp[ABOVE]= NULL; + e[i].outp[BELOW]= NULL; + e[i].next= NULL; + e[i].prev= NULL; + e[i].succ= ((num_edges > 1) && (i < (num_edges - 1))) ? + &(e[i + 1]) : NULL; + e[i].pred= ((num_edges > 1) && (i > 0)) ? &(e[i - 1]) : NULL; + e[i].next_bound= NULL; + e[i].bside[CLIP]= (op == GPC_DIFF) ? RIGHT : LEFT; + e[i].bside[SUBJ]= LEFT; + } + insert_bound(bound_list(lmt, edge_table[min].vertex.y), e); + } + } + } + } + return edge_table; +} + + +static void add_edge_to_aet(edge_node **aet, edge_node *edge, edge_node *prev) +{ + if (!*aet) + { + /* Append edge onto the tail end of the AET */ + *aet= edge; + edge->prev= prev; + edge->next= NULL; + } + else + { + /* Do primary sort on the xb field */ + if (edge->xb < (*aet)->xb) + { + /* Insert edge here (before the AET edge) */ + edge->prev= prev; + edge->next= *aet; + (*aet)->prev= edge; + *aet= edge; + } + else + { + if (edge->xb == (*aet)->xb) + { + /* Do secondary sort on the dx field */ + if (edge->dx < (*aet)->dx) + { + /* Insert edge here (before the AET edge) */ + edge->prev= prev; + edge->next= *aet; + (*aet)->prev= edge; + *aet= edge; + } + else + { + /* Head further into the AET */ + add_edge_to_aet(&((*aet)->next), edge, *aet); + } + } + else + { + /* Head further into the AET */ + add_edge_to_aet(&((*aet)->next), edge, *aet); + } + } + } +} + + +static void add_intersection(it_node **it, edge_node *edge0, edge_node *edge1, + double x, double y) +{ + it_node *existing_node; + + if (!*it) + { + /* Append a new node to the tail of the list */ + MALLOC(*it, sizeof(it_node), "IT insertion", it_node); + (*it)->ie[0]= edge0; + (*it)->ie[1]= edge1; + (*it)->point.x= x; + (*it)->point.y= y; + (*it)->next= NULL; + } + else + { + if ((*it)->point.y > y) + { + /* Insert a new node mid-list */ + existing_node= *it; + MALLOC(*it, sizeof(it_node), "IT insertion", it_node); + (*it)->ie[0]= edge0; + (*it)->ie[1]= edge1; + (*it)->point.x= x; + (*it)->point.y= y; + (*it)->next= existing_node; + } + else + /* Head further down the list */ + add_intersection(&((*it)->next), edge0, edge1, x, y); + } +} + + +static void add_st_edge(st_node **st, it_node **it, edge_node *edge, + double dy) +{ + st_node *existing_node; + double den, r, x, y; + + if (!*st) + { + /* Append edge onto the tail end of the ST */ + MALLOC(*st, sizeof(st_node), "ST insertion", st_node); + (*st)->edge= edge; + (*st)->xb= edge->xb; + (*st)->xt= edge->xt; + (*st)->dx= edge->dx; + (*st)->prev= NULL; + } + else + { + den= ((*st)->xt - (*st)->xb) - (edge->xt - edge->xb); + + /* If new edge and ST edge don't cross */ + if ((edge->xt >= (*st)->xt) || (edge->dx == (*st)->dx) || + (fabs(den) <= DBL_EPSILON)) + { + /* No intersection - insert edge here (before the ST edge) */ + existing_node= *st; + MALLOC(*st, sizeof(st_node), "ST insertion", st_node); + (*st)->edge= edge; + (*st)->xb= edge->xb; + (*st)->xt= edge->xt; + (*st)->dx= edge->dx; + (*st)->prev= existing_node; + } + else + { + /* Compute intersection between new edge and ST edge */ + r= (edge->xb - (*st)->xb) / den; + x= (*st)->xb + r * ((*st)->xt - (*st)->xb); + y= r * dy; + + /* Insert the edge pointers and the intersection point in the IT */ + add_intersection(it, (*st)->edge, edge, x, y); + + /* Head further into the ST */ + add_st_edge(&((*st)->prev), it, edge, dy); + } + } +} + + +static void build_intersection_table(it_node **it, edge_node *aet, double dy) +{ + st_node *st, *stp; + edge_node *edge; + + /* Build intersection table for the current scanbeam */ + reset_it(it); + st= NULL; + + /* Process each AET edge */ + for (edge= aet; edge; edge= edge->next) + { + if ((edge->bstate[ABOVE] == BUNDLE_HEAD) || + edge->bundle[ABOVE][CLIP] || edge->bundle[ABOVE][SUBJ]) + add_st_edge(&st, it, edge, dy); + } + + /* Free the sorted edge table */ + while (st) + { + stp= st->prev; + FREE(st); + st= stp; + } +} + +static int count_contours(polygon_node *polygon) +{ + int nc, nv; + vertex_node *v, *nextv; + + for (nc= 0; polygon; polygon= polygon->next) + if (polygon->active) + { + /* Count the vertices in the current contour */ + nv= 0; + for (v= polygon->proxy->v[LEFT]; v; v= v->next) + nv++; + + /* Record valid vertex counts in the active field */ + if (nv > 2) + { + polygon->active= nv; + nc++; + } + else + { + /* Invalid contour: just free the heap */ + for (v= polygon->proxy->v[LEFT]; v; v= nextv) + { + nextv= v->next; + FREE(v); + } + polygon->active= 0; + } + } + return nc; +} + + +static void add_left(polygon_node *p, double x, double y) +{ + vertex_node *nv; + + /* Create a new vertex node and set its fields */ + MALLOC(nv, sizeof(vertex_node), "vertex node creation", vertex_node); + nv->x= x; + nv->y= y; + + /* Add vertex nv to the left end of the polygon's vertex list */ + nv->next= p->proxy->v[LEFT]; + + /* Update proxy->[LEFT] to point to nv */ + p->proxy->v[LEFT]= nv; +} + + +static void merge_left(polygon_node *p, polygon_node *q, polygon_node *list) +{ + polygon_node *target; + + /* Label contour as a hole */ + q->proxy->hole= TRUE; + + if (p->proxy != q->proxy) + { + /* Assign p's vertex list to the left end of q's list */ + p->proxy->v[RIGHT]->next= q->proxy->v[LEFT]; + q->proxy->v[LEFT]= p->proxy->v[LEFT]; + + /* Redirect any p->proxy references to q->proxy */ + + for (target= p->proxy; list; list= list->next) + { + if (list->proxy == target) + { + list->active= FALSE; + list->proxy= q->proxy; + } + } + } +} + + +static void add_right(polygon_node *p, double x, double y) +{ + vertex_node *nv; + + /* Create a new vertex node and set its fields */ + MALLOC(nv, sizeof(vertex_node), "vertex node creation", vertex_node); + nv->x= x; + nv->y= y; + nv->next= NULL; + + /* Add vertex nv to the right end of the polygon's vertex list */ + p->proxy->v[RIGHT]->next= nv; + + /* Update proxy->v[RIGHT] to point to nv */ + p->proxy->v[RIGHT]= nv; +} + + +static void merge_right(polygon_node *p, polygon_node *q, polygon_node *list) +{ + polygon_node *target; + + /* Label contour as external */ + q->proxy->hole= FALSE; + + if (p->proxy != q->proxy) + { + /* Assign p's vertex list to the right end of q's list */ + q->proxy->v[RIGHT]->next= p->proxy->v[LEFT]; + q->proxy->v[RIGHT]= p->proxy->v[RIGHT]; + + /* Redirect any p->proxy references to q->proxy */ + for (target= p->proxy; list; list= list->next) + { + if (list->proxy == target) + { + list->active= FALSE; + list->proxy= q->proxy; + } + } + } +} + + +static void add_local_min(polygon_node **p, edge_node *edge, + double x, double y) +{ + polygon_node *existing_min; + vertex_node *nv; + + existing_min= *p; + + MALLOC(*p, sizeof(polygon_node), "polygon node creation", polygon_node); + + /* Create a new vertex node and set its fields */ + MALLOC(nv, sizeof(vertex_node), "vertex node creation", vertex_node); + nv->x= x; + nv->y= y; + nv->next= NULL; + + /* Initialise proxy to point to p itself */ + (*p)->proxy= (*p); + (*p)->active= TRUE; + (*p)->next= existing_min; + + /* Make v[LEFT] and v[RIGHT] point to new vertex nv */ + (*p)->v[LEFT]= nv; + (*p)->v[RIGHT]= nv; + + /* Assign polygon p to the edge */ + edge->outp[ABOVE]= *p; +} + + +static int count_tristrips(polygon_node *tn) +{ + int total; + + for (total= 0; tn; tn= tn->next) + if (tn->active > 2) + total++; + return total; +} + + +static void add_vertex(vertex_node **t, double x, double y) +{ + if (!(*t)) + { + MALLOC(*t, sizeof(vertex_node), "tristrip vertex creation", vertex_node); + (*t)->x= x; + (*t)->y= y; + (*t)->next= NULL; + } + else + /* Head further down the list */ + add_vertex(&((*t)->next), x, y); +} + + +static void new_tristrip(polygon_node **tn, edge_node *edge, + double x, double y) +{ + if (!(*tn)) + { + MALLOC(*tn, sizeof(polygon_node), "tristrip node creation", polygon_node); + (*tn)->next= NULL; + (*tn)->v[LEFT]= NULL; + (*tn)->v[RIGHT]= NULL; + (*tn)->active= 1; + add_vertex(&((*tn)->v[LEFT]), x, y); + edge->outp[ABOVE]= *tn; + } + else + /* Head further down the list */ + new_tristrip(&((*tn)->next), edge, x, y); +} + + +static bbox *create_contour_bboxes(gpc_polygon *p) +{ + bbox *box; + int c, v; + + MALLOC(box, p->num_contours * sizeof(bbox), "Bounding box creation", bbox); + + /* Construct contour bounding boxes */ + for (c= 0; c < p->num_contours; c++) + { + /* Initialise bounding box extent */ + box[c].xmin= DBL_MAX; + box[c].ymin= DBL_MAX; + box[c].xmax= -DBL_MAX; + box[c].ymax= -DBL_MAX; + + for (v= 0; v < p->contour[c].num_vertices; v++) + { + /* Adjust bounding box */ + if (p->contour[c].vertex[v].x < box[c].xmin) + box[c].xmin= p->contour[c].vertex[v].x; + if (p->contour[c].vertex[v].y < box[c].ymin) + box[c].ymin= p->contour[c].vertex[v].y; + if (p->contour[c].vertex[v].x > box[c].xmax) + box[c].xmax= p->contour[c].vertex[v].x; + if (p->contour[c].vertex[v].y > box[c].ymax) + box[c].ymax= p->contour[c].vertex[v].y; + } + } + return box; +} + + +static void minimax_test(gpc_polygon *subj, gpc_polygon *clip, gpc_op op) +{ + bbox *s_bbox, *c_bbox; + int s, c, *o_table, overlap; + + s_bbox= create_contour_bboxes(subj); + c_bbox= create_contour_bboxes(clip); + + MALLOC(o_table, subj->num_contours * clip->num_contours * sizeof(int), + "overlap table creation", int); + + /* Check all subject contour bounding boxes against clip boxes */ + for (s= 0; s < subj->num_contours; s++) + for (c= 0; c < clip->num_contours; c++) + o_table[c * subj->num_contours + s]= + (!((s_bbox[s].xmax < c_bbox[c].xmin) || + (s_bbox[s].xmin > c_bbox[c].xmax))) && + (!((s_bbox[s].ymax < c_bbox[c].ymin) || + (s_bbox[s].ymin > c_bbox[c].ymax))); + + /* For each clip contour, search for any subject contour overlaps */ + for (c= 0; c < clip->num_contours; c++) + { + overlap= 0; + for (s= 0; (!overlap) && (s < subj->num_contours); s++) + overlap= o_table[c * subj->num_contours + s]; + + if (!overlap) + /* Flag non contributing status by negating vertex count */ + clip->contour[c].num_vertices = -clip->contour[c].num_vertices; + } + + if (op == GPC_INT) + { + /* For each subject contour, search for any clip contour overlaps */ + for (s= 0; s < subj->num_contours; s++) + { + overlap= 0; + for (c= 0; (!overlap) && (c < clip->num_contours); c++) + overlap= o_table[c * subj->num_contours + s]; + + if (!overlap) + /* Flag non contributing status by negating vertex count */ + subj->contour[s].num_vertices = -subj->contour[s].num_vertices; + } + } + + FREE(s_bbox); + FREE(c_bbox); + FREE(o_table); +} + + +/* +=========================================================================== + Public Functions +=========================================================================== +*/ + +void gpc_free_polygon(gpc_polygon *p) +{ + int c; + + for (c= 0; c < p->num_contours; c++) + FREE(p->contour[c].vertex); + FREE(p->hole); + FREE(p->contour); + p->num_contours= 0; +} + + +void gpc_read_polygon(FILE *fp, int read_hole_flags, gpc_polygon *p) +{ + int c, v; + + fscanf(fp, "%d", &(p->num_contours)); + MALLOC(p->hole, p->num_contours * sizeof(int), + "hole flag array creation", int); + MALLOC(p->contour, p->num_contours + * sizeof(gpc_vertex_list), "contour creation", gpc_vertex_list); + for (c= 0; c < p->num_contours; c++) + { + fscanf(fp, "%d", &(p->contour[c].num_vertices)); + + if (read_hole_flags) + fscanf(fp, "%d", &(p->hole[c])); + else + p->hole[c]= FALSE; /* Assume all contours to be external */ + + MALLOC(p->contour[c].vertex, p->contour[c].num_vertices + * sizeof(gpc_vertex), "vertex creation", gpc_vertex); + for (v= 0; v < p->contour[c].num_vertices; v++) + fscanf(fp, "%lf %lf", &(p->contour[c].vertex[v].x), + &(p->contour[c].vertex[v].y)); + } +} + + +void gpc_write_polygon(FILE *fp, int write_hole_flags, gpc_polygon *p) +{ + int c, v; + + fprintf(fp, "%d\n", p->num_contours); + for (c= 0; c < p->num_contours; c++) + { + fprintf(fp, "%d\n", p->contour[c].num_vertices); + + if (write_hole_flags) + fprintf(fp, "%d\n", p->hole[c]); + + for (v= 0; v < p->contour[c].num_vertices; v++) + fprintf(fp, "% .*lf % .*lf\n", + DBL_DIG, p->contour[c].vertex[v].x, + DBL_DIG, p->contour[c].vertex[v].y); + } +} + + +void gpc_add_contour(gpc_polygon *p, gpc_vertex_list *new_contour, int hole) +{ + int *extended_hole, c, v; + gpc_vertex_list *extended_contour; + + /* Create an extended hole array */ + MALLOC(extended_hole, (p->num_contours + 1) + * sizeof(int), "contour hole addition", int); + + /* Create an extended contour array */ + MALLOC(extended_contour, (p->num_contours + 1) + * sizeof(gpc_vertex_list), "contour addition", gpc_vertex_list); + + /* Copy the old contour and hole data into the extended arrays */ + for (c= 0; c < p->num_contours; c++) + { + extended_hole[c]= p->hole[c]; + extended_contour[c]= p->contour[c]; + } + + /* Copy the new contour and hole onto the end of the extended arrays */ + c= p->num_contours; + extended_hole[c]= hole; + extended_contour[c].num_vertices= new_contour->num_vertices; + MALLOC(extended_contour[c].vertex, new_contour->num_vertices + * sizeof(gpc_vertex), "contour addition", gpc_vertex); + for (v= 0; v < new_contour->num_vertices; v++) + extended_contour[c].vertex[v]= new_contour->vertex[v]; + + /* Dispose of the old contour */ + FREE(p->contour); + FREE(p->hole); + + /* Update the polygon information */ + p->num_contours++; + p->hole= extended_hole; + p->contour= extended_contour; +} + + +void gpc_polygon_clip(gpc_op op, gpc_polygon *subj, gpc_polygon *clip, + gpc_polygon *result) +{ + sb_tree *sbtree= NULL; + it_node *it= NULL, *intersect; + edge_node *edge, *prev_edge, *next_edge, *succ_edge, *e0, *e1; + edge_node *aet= NULL, *c_heap= NULL, *s_heap= NULL; + lmt_node *lmt= NULL, *local_min; + polygon_node *out_poly= NULL, *p, *q, *poly, *npoly, *cf= NULL; + vertex_node *vtx, *nv; + h_state horiz[2]; + int in[2], exists[2], parity[2]= {LEFT, LEFT}; + int c, v, contributing, search, scanbeam= 0, sbt_entries= 0; + int vclass, bl, br, tl, tr; + double *sbt= NULL, xb, px, yb, yt, dy, ix, iy; + + /* Test for trivial NULL result cases */ + if (((subj->num_contours == 0) && (clip->num_contours == 0)) + || ((subj->num_contours == 0) && ((op == GPC_INT) || (op == GPC_DIFF))) + || ((clip->num_contours == 0) && (op == GPC_INT))) + { + result->num_contours= 0; + result->hole= NULL; + result->contour= NULL; + return; + } + + /* Identify potentialy contributing contours */ + if (((op == GPC_INT) || (op == GPC_DIFF)) + && (subj->num_contours > 0) && (clip->num_contours > 0)) + minimax_test(subj, clip, op); + + /* Build LMT */ + if (subj->num_contours > 0) + s_heap= build_lmt(&lmt, &sbtree, &sbt_entries, subj, SUBJ, op); + if (clip->num_contours > 0) + c_heap= build_lmt(&lmt, &sbtree, &sbt_entries, clip, CLIP, op); + + /* Return a NULL result if no contours contribute */ + if (lmt == NULL) + { + result->num_contours= 0; + result->hole= NULL; + result->contour= NULL; + reset_lmt(&lmt); + FREE(s_heap); + FREE(c_heap); + return; + } + + /* Build scanbeam table from scanbeam tree */ + MALLOC(sbt, sbt_entries * sizeof(double), "sbt creation", double); + build_sbt(&scanbeam, sbt, sbtree); + scanbeam= 0; + free_sbtree(&sbtree); + + /* Allow pointer re-use without causing memory leak */ + if (subj == result) + gpc_free_polygon(subj); + if (clip == result) + gpc_free_polygon(clip); + + /* Invert clip polygon for difference operation */ + if (op == GPC_DIFF) + parity[CLIP]= RIGHT; + + local_min= lmt; + + /* Process each scanbeam */ + while (scanbeam < sbt_entries) + { + /* Set yb and yt to the bottom and top of the scanbeam */ + yb= sbt[scanbeam++]; + if (scanbeam < sbt_entries) + { + yt= sbt[scanbeam]; + dy= yt - yb; + } + + /* === SCANBEAM BOUNDARY PROCESSING ================================ */ + + /* If LMT node corresponding to yb exists */ + if (local_min) + { + if (local_min->y == yb) + { + /* Add edges starting at this local minimum to the AET */ + for (edge= local_min->first_bound; edge; edge= edge->next_bound) + add_edge_to_aet(&aet, edge, NULL); + + local_min= local_min->next; + } + } + + /* Set dummy previous x value */ + px= -DBL_MAX; + + /* Create bundles within AET */ + e0= aet; + e1= aet; + + /* Set up bundle fields of first edge */ + aet->bundle[ABOVE][ aet->type]= (aet->top.y != yb); + aet->bundle[ABOVE][!aet->type]= FALSE; + aet->bstate[ABOVE]= UNBUNDLED; + + for (next_edge= aet->next; next_edge; next_edge= next_edge->next) + { + /* Set up bundle fields of next edge */ + next_edge->bundle[ABOVE][ next_edge->type]= (next_edge->top.y != yb); + next_edge->bundle[ABOVE][!next_edge->type]= FALSE; + next_edge->bstate[ABOVE]= UNBUNDLED; + + /* Bundle edges above the scanbeam boundary if they coincide */ + if (next_edge->bundle[ABOVE][next_edge->type]) + { + if (EQ(e0->xb, next_edge->xb) && EQ(e0->dx, next_edge->dx) + && (e0->top.y != yb)) + { + next_edge->bundle[ABOVE][ next_edge->type]^= + e0->bundle[ABOVE][ next_edge->type]; + next_edge->bundle[ABOVE][!next_edge->type]= + e0->bundle[ABOVE][!next_edge->type]; + next_edge->bstate[ABOVE]= BUNDLE_HEAD; + e0->bundle[ABOVE][CLIP]= FALSE; + e0->bundle[ABOVE][SUBJ]= FALSE; + e0->bstate[ABOVE]= BUNDLE_TAIL; + } + e0= next_edge; + } + } + + horiz[CLIP]= NH; + horiz[SUBJ]= NH; + + /* Process each edge at this scanbeam boundary */ + for (edge= aet; edge; edge= edge->next) + { + exists[CLIP]= edge->bundle[ABOVE][CLIP] + + (edge->bundle[BELOW][CLIP] << 1); + exists[SUBJ]= edge->bundle[ABOVE][SUBJ] + + (edge->bundle[BELOW][SUBJ] << 1); + + if (exists[CLIP] || exists[SUBJ]) + { + /* Set bundle side */ + edge->bside[CLIP]= parity[CLIP]; + edge->bside[SUBJ]= parity[SUBJ]; + + /* Determine contributing status and quadrant occupancies */ + switch (op) + { + case GPC_DIFF: + case GPC_INT: + contributing= (exists[CLIP] && (parity[SUBJ] || horiz[SUBJ])) + || (exists[SUBJ] && (parity[CLIP] || horiz[CLIP])) + || (exists[CLIP] && exists[SUBJ] + && (parity[CLIP] == parity[SUBJ])); + br= (parity[CLIP]) + && (parity[SUBJ]); + bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP]) + && (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]); + tr= (parity[CLIP] ^ (horiz[CLIP]!=NH)) + && (parity[SUBJ] ^ (horiz[SUBJ]!=NH)); + tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP]) + && (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]); + break; + case GPC_XOR: + contributing= exists[CLIP] || exists[SUBJ]; + br= (parity[CLIP]) + ^ (parity[SUBJ]); + bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP]) + ^ (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]); + tr= (parity[CLIP] ^ (horiz[CLIP]!=NH)) + ^ (parity[SUBJ] ^ (horiz[SUBJ]!=NH)); + tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP]) + ^ (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]); + break; + case GPC_UNION: + contributing= (exists[CLIP] && (!parity[SUBJ] || horiz[SUBJ])) + || (exists[SUBJ] && (!parity[CLIP] || horiz[CLIP])) + || (exists[CLIP] && exists[SUBJ] + && (parity[CLIP] == parity[SUBJ])); + br= (parity[CLIP]) + || (parity[SUBJ]); + bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP]) + || (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]); + tr= (parity[CLIP] ^ (horiz[CLIP]!=NH)) + || (parity[SUBJ] ^ (horiz[SUBJ]!=NH)); + tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP]) + || (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]); + break; + } + + /* Update parity */ + parity[CLIP]^= edge->bundle[ABOVE][CLIP]; + parity[SUBJ]^= edge->bundle[ABOVE][SUBJ]; + + /* Update horizontal state */ + if (exists[CLIP]) + horiz[CLIP]= + next_h_state[horiz[CLIP]] + [((exists[CLIP] - 1) << 1) + parity[CLIP]]; + if (exists[SUBJ]) + horiz[SUBJ]= + next_h_state[horiz[SUBJ]] + [((exists[SUBJ] - 1) << 1) + parity[SUBJ]]; + + vclass= tr + (tl << 1) + (br << 2) + (bl << 3); + + if (contributing) + { + xb= edge->xb; + + switch (vclass) + { + case EMN: + case IMN: + add_local_min(&out_poly, edge, xb, yb); + px= xb; + cf= edge->outp[ABOVE]; + break; + case ERI: + if (xb != px) + { + add_right(cf, xb, yb); + px= xb; + } + edge->outp[ABOVE]= cf; + cf= NULL; + break; + case ELI: + add_left(edge->outp[BELOW], xb, yb); + px= xb; + cf= edge->outp[BELOW]; + break; + case EMX: + if (xb != px) + { + add_left(cf, xb, yb); + px= xb; + } + merge_right(cf, edge->outp[BELOW], out_poly); + cf= NULL; + break; + case ILI: + if (xb != px) + { + add_left(cf, xb, yb); + px= xb; + } + edge->outp[ABOVE]= cf; + cf= NULL; + break; + case IRI: + add_right(edge->outp[BELOW], xb, yb); + px= xb; + cf= edge->outp[BELOW]; + edge->outp[BELOW]= NULL; + break; + case IMX: + if (xb != px) + { + add_right(cf, xb, yb); + px= xb; + } + merge_left(cf, edge->outp[BELOW], out_poly); + cf= NULL; + edge->outp[BELOW]= NULL; + break; + case IMM: + if (xb != px) + { + add_right(cf, xb, yb); + px= xb; + } + merge_left(cf, edge->outp[BELOW], out_poly); + edge->outp[BELOW]= NULL; + add_local_min(&out_poly, edge, xb, yb); + cf= edge->outp[ABOVE]; + break; + case EMM: + if (xb != px) + { + add_left(cf, xb, yb); + px= xb; + } + merge_right(cf, edge->outp[BELOW], out_poly); + edge->outp[BELOW]= NULL; + add_local_min(&out_poly, edge, xb, yb); + cf= edge->outp[ABOVE]; + break; + case LED: + if (edge->bot.y == yb) + add_left(edge->outp[BELOW], xb, yb); + edge->outp[ABOVE]= edge->outp[BELOW]; + px= xb; + break; + case RED: + if (edge->bot.y == yb) + add_right(edge->outp[BELOW], xb, yb); + edge->outp[ABOVE]= edge->outp[BELOW]; + px= xb; + break; + default: + break; + } /* End of switch */ + } /* End of contributing conditional */ + } /* End of edge exists conditional */ + } /* End of AET loop */ + + /* Delete terminating edges from the AET, otherwise compute xt */ + for (edge= aet; edge; edge= edge->next) + { + if (edge->top.y == yb) + { + prev_edge= edge->prev; + next_edge= edge->next; + if (prev_edge) + prev_edge->next= next_edge; + else + aet= next_edge; + if (next_edge) + next_edge->prev= prev_edge; + + /* Copy bundle head state to the adjacent tail edge if required */ + if ((edge->bstate[BELOW] == BUNDLE_HEAD) && prev_edge) + { + if (prev_edge->bstate[BELOW] == BUNDLE_TAIL) + { + prev_edge->outp[BELOW]= edge->outp[BELOW]; + prev_edge->bstate[BELOW]= UNBUNDLED; + if (prev_edge->prev) + if (prev_edge->prev->bstate[BELOW] == BUNDLE_TAIL) + prev_edge->bstate[BELOW]= BUNDLE_HEAD; + } + } + } + else + { + if (edge->top.y == yt) + edge->xt= edge->top.x; + else + edge->xt= edge->bot.x + edge->dx * (yt - edge->bot.y); + } + } + + if (scanbeam < sbt_entries) + { + /* === SCANBEAM INTERIOR PROCESSING ============================== */ + + build_intersection_table(&it, aet, dy); + + /* Process each node in the intersection table */ + for (intersect= it; intersect; intersect= intersect->next) + { + e0= intersect->ie[0]; + e1= intersect->ie[1]; + + /* Only generate output for contributing intersections */ + if ((e0->bundle[ABOVE][CLIP] || e0->bundle[ABOVE][SUBJ]) + && (e1->bundle[ABOVE][CLIP] || e1->bundle[ABOVE][SUBJ])) + { + p= e0->outp[ABOVE]; + q= e1->outp[ABOVE]; + ix= intersect->point.x; + iy= intersect->point.y + yb; + + in[CLIP]= ( e0->bundle[ABOVE][CLIP] && !e0->bside[CLIP]) + || ( e1->bundle[ABOVE][CLIP] && e1->bside[CLIP]) + || (!e0->bundle[ABOVE][CLIP] && !e1->bundle[ABOVE][CLIP] + && e0->bside[CLIP] && e1->bside[CLIP]); + in[SUBJ]= ( e0->bundle[ABOVE][SUBJ] && !e0->bside[SUBJ]) + || ( e1->bundle[ABOVE][SUBJ] && e1->bside[SUBJ]) + || (!e0->bundle[ABOVE][SUBJ] && !e1->bundle[ABOVE][SUBJ] + && e0->bside[SUBJ] && e1->bside[SUBJ]); + + /* Determine quadrant occupancies */ + switch (op) + { + case GPC_DIFF: + case GPC_INT: + tr= (in[CLIP]) + && (in[SUBJ]); + tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP]) + && (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]); + br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP]) + && (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP]) + && (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + break; + case GPC_XOR: + tr= (in[CLIP]) + ^ (in[SUBJ]); + tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP]) + ^ (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]); + br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP]) + ^ (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP]) + ^ (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + break; + case GPC_UNION: + tr= (in[CLIP]) + || (in[SUBJ]); + tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP]) + || (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]); + br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP]) + || (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP]) + || (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + break; + } + + vclass= tr + (tl << 1) + (br << 2) + (bl << 3); + + switch (vclass) + { + case EMN: + add_local_min(&out_poly, e0, ix, iy); + e1->outp[ABOVE]= e0->outp[ABOVE]; + break; + case ERI: + if (p) + { + add_right(p, ix, iy); + e1->outp[ABOVE]= p; + e0->outp[ABOVE]= NULL; + } + break; + case ELI: + if (q) + { + add_left(q, ix, iy); + e0->outp[ABOVE]= q; + e1->outp[ABOVE]= NULL; + } + break; + case EMX: + if (p && q) + { + add_left(p, ix, iy); + merge_right(p, q, out_poly); + e0->outp[ABOVE]= NULL; + e1->outp[ABOVE]= NULL; + } + break; + case IMN: + add_local_min(&out_poly, e0, ix, iy); + e1->outp[ABOVE]= e0->outp[ABOVE]; + break; + case ILI: + if (p) + { + add_left(p, ix, iy); + e1->outp[ABOVE]= p; + e0->outp[ABOVE]= NULL; + } + break; + case IRI: + if (q) + { + add_right(q, ix, iy); + e0->outp[ABOVE]= q; + e1->outp[ABOVE]= NULL; + } + break; + case IMX: + if (p && q) + { + add_right(p, ix, iy); + merge_left(p, q, out_poly); + e0->outp[ABOVE]= NULL; + e1->outp[ABOVE]= NULL; + } + break; + case IMM: + if (p && q) + { + add_right(p, ix, iy); + merge_left(p, q, out_poly); + add_local_min(&out_poly, e0, ix, iy); + e1->outp[ABOVE]= e0->outp[ABOVE]; + } + break; + case EMM: + if (p && q) + { + add_left(p, ix, iy); + merge_right(p, q, out_poly); + add_local_min(&out_poly, e0, ix, iy); + e1->outp[ABOVE]= e0->outp[ABOVE]; + } + break; + default: + break; + } /* End of switch */ + } /* End of contributing intersection conditional */ + + /* Swap bundle sides in response to edge crossing */ + if (e0->bundle[ABOVE][CLIP]) + e1->bside[CLIP]= !e1->bside[CLIP]; + if (e1->bundle[ABOVE][CLIP]) + e0->bside[CLIP]= !e0->bside[CLIP]; + if (e0->bundle[ABOVE][SUBJ]) + e1->bside[SUBJ]= !e1->bside[SUBJ]; + if (e1->bundle[ABOVE][SUBJ]) + e0->bside[SUBJ]= !e0->bside[SUBJ]; + + /* Swap e0 and e1 bundles in the AET */ + prev_edge= e0->prev; + next_edge= e1->next; + if (next_edge) + next_edge->prev= e0; + + if (e0->bstate[ABOVE] == BUNDLE_HEAD) + { + search= TRUE; + while (search) + { + prev_edge= prev_edge->prev; + if (prev_edge) + { + if (prev_edge->bstate[ABOVE] != BUNDLE_TAIL) + search= FALSE; + } + else + search= FALSE; + } + } + if (!prev_edge) + { + aet->prev= e1; + e1->next= aet; + aet= e0->next; + } + else + { + prev_edge->next->prev= e1; + e1->next= prev_edge->next; + prev_edge->next= e0->next; + } + e0->next->prev= prev_edge; + e1->next->prev= e1; + e0->next= next_edge; + } /* End of IT loop*/ + + /* Prepare for next scanbeam */ + for (edge= aet; edge; edge= next_edge) + { + next_edge= edge->next; + succ_edge= edge->succ; + + if ((edge->top.y == yt) && succ_edge) + { + /* Replace AET edge by its successor */ + succ_edge->outp[BELOW]= edge->outp[ABOVE]; + succ_edge->bstate[BELOW]= edge->bstate[ABOVE]; + succ_edge->bundle[BELOW][CLIP]= edge->bundle[ABOVE][CLIP]; + succ_edge->bundle[BELOW][SUBJ]= edge->bundle[ABOVE][SUBJ]; + prev_edge= edge->prev; + if (prev_edge) + prev_edge->next= succ_edge; + else + aet= succ_edge; + if (next_edge) + next_edge->prev= succ_edge; + succ_edge->prev= prev_edge; + succ_edge->next= next_edge; + } + else + { + /* Update this edge */ + edge->outp[BELOW]= edge->outp[ABOVE]; + edge->bstate[BELOW]= edge->bstate[ABOVE]; + edge->bundle[BELOW][CLIP]= edge->bundle[ABOVE][CLIP]; + edge->bundle[BELOW][SUBJ]= edge->bundle[ABOVE][SUBJ]; + edge->xb= edge->xt; + } + edge->outp[ABOVE]= NULL; + } + } + } /* === END OF SCANBEAM PROCESSING ================================== */ + + /* Generate result polygon from out_poly */ + result->contour= NULL; + result->hole= NULL; + result->num_contours= count_contours(out_poly); + if (result->num_contours > 0) + { + MALLOC(result->hole, result->num_contours + * sizeof(int), "hole flag table creation", int); + MALLOC(result->contour, result->num_contours + * sizeof(gpc_vertex_list), "contour creation", gpc_vertex_list); + + c= 0; + for (poly= out_poly; poly; poly= npoly) + { + npoly= poly->next; + if (poly->active) + { + result->hole[c]= poly->proxy->hole; + result->contour[c].num_vertices= poly->active; + MALLOC(result->contour[c].vertex, + result->contour[c].num_vertices * sizeof(gpc_vertex), + "vertex creation", gpc_vertex); + + v= result->contour[c].num_vertices - 1; + for (vtx= poly->proxy->v[LEFT]; vtx; vtx= nv) + { + nv= vtx->next; + result->contour[c].vertex[v].x= vtx->x; + result->contour[c].vertex[v].y= vtx->y; + FREE(vtx); + v--; + } + c++; + } + FREE(poly); + } + } + else + { + for (poly= out_poly; poly; poly= npoly) + { + npoly= poly->next; + FREE(poly); + } + } + + /* Tidy up */ + reset_it(&it); + reset_lmt(&lmt); + FREE(c_heap); + FREE(s_heap); + FREE(sbt); +} + + +void gpc_free_tristrip(gpc_tristrip *t) +{ + int s; + + for (s= 0; s < t->num_strips; s++) + FREE(t->strip[s].vertex); + FREE(t->strip); + t->num_strips= 0; +} + + +void gpc_polygon_to_tristrip(gpc_polygon *s, gpc_tristrip *t) +{ + gpc_polygon c; + + c.num_contours= 0; + c.hole= NULL; + c.contour= NULL; + gpc_tristrip_clip(GPC_DIFF, s, &c, t); +} + + +void gpc_tristrip_clip(gpc_op op, gpc_polygon *subj, gpc_polygon *clip, + gpc_tristrip *result) +{ + sb_tree *sbtree= NULL; + it_node *it= NULL, *intersect; + edge_node *edge, *prev_edge, *next_edge, *succ_edge, *e0, *e1; + edge_node *aet= NULL, *c_heap= NULL, *s_heap= NULL, *cf; + lmt_node *lmt= NULL, *local_min; + polygon_node *tlist= NULL, *tn, *tnn, *p, *q; + vertex_node *lt, *ltn, *rt, *rtn; + h_state horiz[2]; + vertex_type cft; + int in[2], exists[2], parity[2]= {LEFT, LEFT}; + int s, v, contributing, search, scanbeam= 0, sbt_entries= 0; + int vclass, bl, br, tl, tr; + double *sbt= NULL, xb, px, nx, yb, yt, dy, ix, iy; + + /* Test for trivial NULL result cases */ + if (((subj->num_contours == 0) && (clip->num_contours == 0)) + || ((subj->num_contours == 0) && ((op == GPC_INT) || (op == GPC_DIFF))) + || ((clip->num_contours == 0) && (op == GPC_INT))) + { + result->num_strips= 0; + result->strip= NULL; + return; + } + + /* Identify potentialy contributing contours */ + if (((op == GPC_INT) || (op == GPC_DIFF)) + && (subj->num_contours > 0) && (clip->num_contours > 0)) + minimax_test(subj, clip, op); + + /* Build LMT */ + if (subj->num_contours > 0) + s_heap= build_lmt(&lmt, &sbtree, &sbt_entries, subj, SUBJ, op); + if (clip->num_contours > 0) + c_heap= build_lmt(&lmt, &sbtree, &sbt_entries, clip, CLIP, op); + + /* Return a NULL result if no contours contribute */ + if (lmt == NULL) + { + result->num_strips= 0; + result->strip= NULL; + reset_lmt(&lmt); + FREE(s_heap); + FREE(c_heap); + return; + } + + /* Build scanbeam table from scanbeam tree */ + MALLOC(sbt, sbt_entries * sizeof(double), "sbt creation", double); + build_sbt(&scanbeam, sbt, sbtree); + scanbeam= 0; + free_sbtree(&sbtree); + + /* Invert clip polygon for difference operation */ + if (op == GPC_DIFF) + parity[CLIP]= RIGHT; + + local_min= lmt; + + /* Process each scanbeam */ + while (scanbeam < sbt_entries) + { + /* Set yb and yt to the bottom and top of the scanbeam */ + yb= sbt[scanbeam++]; + if (scanbeam < sbt_entries) + { + yt= sbt[scanbeam]; + dy= yt - yb; + } + + /* === SCANBEAM BOUNDARY PROCESSING ================================ */ + + /* If LMT node corresponding to yb exists */ + if (local_min) + { + if (local_min->y == yb) + { + /* Add edges starting at this local minimum to the AET */ + for (edge= local_min->first_bound; edge; edge= edge->next_bound) + add_edge_to_aet(&aet, edge, NULL); + + local_min= local_min->next; + } + } + + /* Set dummy previous x value */ + px= -DBL_MAX; + + /* Create bundles within AET */ + e0= aet; + e1= aet; + + /* Set up bundle fields of first edge */ + aet->bundle[ABOVE][ aet->type]= (aet->top.y != yb); + aet->bundle[ABOVE][!aet->type]= FALSE; + aet->bstate[ABOVE]= UNBUNDLED; + + for (next_edge= aet->next; next_edge; next_edge= next_edge->next) + { + /* Set up bundle fields of next edge */ + next_edge->bundle[ABOVE][ next_edge->type]= (next_edge->top.y != yb); + next_edge->bundle[ABOVE][!next_edge->type]= FALSE; + next_edge->bstate[ABOVE]= UNBUNDLED; + + /* Bundle edges above the scanbeam boundary if they coincide */ + if (next_edge->bundle[ABOVE][next_edge->type]) + { + if (EQ(e0->xb, next_edge->xb) && EQ(e0->dx, next_edge->dx) + && (e0->top.y != yb)) + { + next_edge->bundle[ABOVE][ next_edge->type]^= + e0->bundle[ABOVE][ next_edge->type]; + next_edge->bundle[ABOVE][!next_edge->type]= + e0->bundle[ABOVE][!next_edge->type]; + next_edge->bstate[ABOVE]= BUNDLE_HEAD; + e0->bundle[ABOVE][CLIP]= FALSE; + e0->bundle[ABOVE][SUBJ]= FALSE; + e0->bstate[ABOVE]= BUNDLE_TAIL; + } + e0= next_edge; + } + } + + horiz[CLIP]= NH; + horiz[SUBJ]= NH; + + /* Process each edge at this scanbeam boundary */ + for (edge= aet; edge; edge= edge->next) + { + exists[CLIP]= edge->bundle[ABOVE][CLIP] + + (edge->bundle[BELOW][CLIP] << 1); + exists[SUBJ]= edge->bundle[ABOVE][SUBJ] + + (edge->bundle[BELOW][SUBJ] << 1); + + if (exists[CLIP] || exists[SUBJ]) + { + /* Set bundle side */ + edge->bside[CLIP]= parity[CLIP]; + edge->bside[SUBJ]= parity[SUBJ]; + + /* Determine contributing status and quadrant occupancies */ + switch (op) + { + case GPC_DIFF: + case GPC_INT: + contributing= (exists[CLIP] && (parity[SUBJ] || horiz[SUBJ])) + || (exists[SUBJ] && (parity[CLIP] || horiz[CLIP])) + || (exists[CLIP] && exists[SUBJ] + && (parity[CLIP] == parity[SUBJ])); + br= (parity[CLIP]) + && (parity[SUBJ]); + bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP]) + && (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]); + tr= (parity[CLIP] ^ (horiz[CLIP]!=NH)) + && (parity[SUBJ] ^ (horiz[SUBJ]!=NH)); + tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP]) + && (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]); + break; + case GPC_XOR: + contributing= exists[CLIP] || exists[SUBJ]; + br= (parity[CLIP]) + ^ (parity[SUBJ]); + bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP]) + ^ (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]); + tr= (parity[CLIP] ^ (horiz[CLIP]!=NH)) + ^ (parity[SUBJ] ^ (horiz[SUBJ]!=NH)); + tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP]) + ^ (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]); + break; + case GPC_UNION: + contributing= (exists[CLIP] && (!parity[SUBJ] || horiz[SUBJ])) + || (exists[SUBJ] && (!parity[CLIP] || horiz[CLIP])) + || (exists[CLIP] && exists[SUBJ] + && (parity[CLIP] == parity[SUBJ])); + br= (parity[CLIP]) + || (parity[SUBJ]); + bl= (parity[CLIP] ^ edge->bundle[ABOVE][CLIP]) + || (parity[SUBJ] ^ edge->bundle[ABOVE][SUBJ]); + tr= (parity[CLIP] ^ (horiz[CLIP]!=NH)) + || (parity[SUBJ] ^ (horiz[SUBJ]!=NH)); + tl= (parity[CLIP] ^ (horiz[CLIP]!=NH) ^ edge->bundle[BELOW][CLIP]) + || (parity[SUBJ] ^ (horiz[SUBJ]!=NH) ^ edge->bundle[BELOW][SUBJ]); + break; + } + + /* Update parity */ + parity[CLIP]^= edge->bundle[ABOVE][CLIP]; + parity[SUBJ]^= edge->bundle[ABOVE][SUBJ]; + + /* Update horizontal state */ + if (exists[CLIP]) + horiz[CLIP]= + next_h_state[horiz[CLIP]] + [((exists[CLIP] - 1) << 1) + parity[CLIP]]; + if (exists[SUBJ]) + horiz[SUBJ]= + next_h_state[horiz[SUBJ]] + [((exists[SUBJ] - 1) << 1) + parity[SUBJ]]; + + vclass= tr + (tl << 1) + (br << 2) + (bl << 3); + + if (contributing) + { + xb= edge->xb; + + switch (vclass) + { + case EMN: + new_tristrip(&tlist, edge, xb, yb); + cf= edge; + break; + case ERI: + edge->outp[ABOVE]= cf->outp[ABOVE]; + if (xb != cf->xb) + VERTEX(edge, ABOVE, RIGHT, xb, yb); + cf= NULL; + break; + case ELI: + VERTEX(edge, BELOW, LEFT, xb, yb); + edge->outp[ABOVE]= NULL; + cf= edge; + break; + case EMX: + if (xb != cf->xb) + VERTEX(edge, BELOW, RIGHT, xb, yb); + edge->outp[ABOVE]= NULL; + cf= NULL; + break; + case IMN: + if (cft == LED) + { + if (cf->bot.y != yb) + VERTEX(cf, BELOW, LEFT, cf->xb, yb); + new_tristrip(&tlist, cf, cf->xb, yb); + } + edge->outp[ABOVE]= cf->outp[ABOVE]; + VERTEX(edge, ABOVE, RIGHT, xb, yb); + break; + case ILI: + new_tristrip(&tlist, edge, xb, yb); + cf= edge; + cft= ILI; + break; + case IRI: + if (cft == LED) + { + if (cf->bot.y != yb) + VERTEX(cf, BELOW, LEFT, cf->xb, yb); + new_tristrip(&tlist, cf, cf->xb, yb); + } + VERTEX(edge, BELOW, RIGHT, xb, yb); + edge->outp[ABOVE]= NULL; + break; + case IMX: + VERTEX(edge, BELOW, LEFT, xb, yb); + edge->outp[ABOVE]= NULL; + cft= IMX; + break; + case IMM: + VERTEX(edge, BELOW, LEFT, xb, yb); + edge->outp[ABOVE]= cf->outp[ABOVE]; + if (xb != cf->xb) + VERTEX(cf, ABOVE, RIGHT, xb, yb); + cf= edge; + break; + case EMM: + VERTEX(edge, BELOW, RIGHT, xb, yb); + edge->outp[ABOVE]= NULL; + new_tristrip(&tlist, edge, xb, yb); + cf= edge; + break; + case LED: + if (edge->bot.y == yb) + VERTEX(edge, BELOW, LEFT, xb, yb); + edge->outp[ABOVE]= edge->outp[BELOW]; + cf= edge; + cft= LED; + break; + case RED: + edge->outp[ABOVE]= cf->outp[ABOVE]; + if (cft == LED) + { + if (cf->bot.y == yb) + { + VERTEX(edge, BELOW, RIGHT, xb, yb); + } + else + { + if (edge->bot.y == yb) + { + VERTEX(cf, BELOW, LEFT, cf->xb, yb); + VERTEX(edge, BELOW, RIGHT, xb, yb); + } + } + } + else + { + VERTEX(edge, BELOW, RIGHT, xb, yb); + VERTEX(edge, ABOVE, RIGHT, xb, yb); + } + cf= NULL; + break; + default: + break; + } /* End of switch */ + } /* End of contributing conditional */ + } /* End of edge exists conditional */ + } /* End of AET loop */ + + /* Delete terminating edges from the AET, otherwise compute xt */ + for (edge= aet; edge; edge= edge->next) + { + if (edge->top.y == yb) + { + prev_edge= edge->prev; + next_edge= edge->next; + if (prev_edge) + prev_edge->next= next_edge; + else + aet= next_edge; + if (next_edge) + next_edge->prev= prev_edge; + + /* Copy bundle head state to the adjacent tail edge if required */ + if ((edge->bstate[BELOW] == BUNDLE_HEAD) && prev_edge) + { + if (prev_edge->bstate[BELOW] == BUNDLE_TAIL) + { + prev_edge->outp[BELOW]= edge->outp[BELOW]; + prev_edge->bstate[BELOW]= UNBUNDLED; + if (prev_edge->prev) + if (prev_edge->prev->bstate[BELOW] == BUNDLE_TAIL) + prev_edge->bstate[BELOW]= BUNDLE_HEAD; + } + } + } + else + { + if (edge->top.y == yt) + edge->xt= edge->top.x; + else + edge->xt= edge->bot.x + edge->dx * (yt - edge->bot.y); + } + } + + if (scanbeam < sbt_entries) + { + /* === SCANBEAM INTERIOR PROCESSING ============================== */ + + build_intersection_table(&it, aet, dy); + + /* Process each node in the intersection table */ + for (intersect= it; intersect; intersect= intersect->next) + { + e0= intersect->ie[0]; + e1= intersect->ie[1]; + + /* Only generate output for contributing intersections */ + if ((e0->bundle[ABOVE][CLIP] || e0->bundle[ABOVE][SUBJ]) + && (e1->bundle[ABOVE][CLIP] || e1->bundle[ABOVE][SUBJ])) + { + p= e0->outp[ABOVE]; + q= e1->outp[ABOVE]; + ix= intersect->point.x; + iy= intersect->point.y + yb; + + in[CLIP]= ( e0->bundle[ABOVE][CLIP] && !e0->bside[CLIP]) + || ( e1->bundle[ABOVE][CLIP] && e1->bside[CLIP]) + || (!e0->bundle[ABOVE][CLIP] && !e1->bundle[ABOVE][CLIP] + && e0->bside[CLIP] && e1->bside[CLIP]); + in[SUBJ]= ( e0->bundle[ABOVE][SUBJ] && !e0->bside[SUBJ]) + || ( e1->bundle[ABOVE][SUBJ] && e1->bside[SUBJ]) + || (!e0->bundle[ABOVE][SUBJ] && !e1->bundle[ABOVE][SUBJ] + && e0->bside[SUBJ] && e1->bside[SUBJ]); + + /* Determine quadrant occupancies */ + switch (op) + { + case GPC_DIFF: + case GPC_INT: + tr= (in[CLIP]) + && (in[SUBJ]); + tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP]) + && (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]); + br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP]) + && (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP]) + && (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + break; + case GPC_XOR: + tr= (in[CLIP]) + ^ (in[SUBJ]); + tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP]) + ^ (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]); + br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP]) + ^ (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP]) + ^ (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + break; + case GPC_UNION: + tr= (in[CLIP]) + || (in[SUBJ]); + tl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP]) + || (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ]); + br= (in[CLIP] ^ e0->bundle[ABOVE][CLIP]) + || (in[SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + bl= (in[CLIP] ^ e1->bundle[ABOVE][CLIP] ^ e0->bundle[ABOVE][CLIP]) + || (in[SUBJ] ^ e1->bundle[ABOVE][SUBJ] ^ e0->bundle[ABOVE][SUBJ]); + break; + } + + vclass= tr + (tl << 1) + (br << 2) + (bl << 3); + + switch (vclass) + { + case EMN: + new_tristrip(&tlist, e1, ix, iy); + e0->outp[ABOVE]= e1->outp[ABOVE]; + break; + case ERI: + if (p) + { + P_EDGE(prev_edge, e0, ABOVE, px, iy); + VERTEX(prev_edge, ABOVE, LEFT, px, iy); + VERTEX(e0, ABOVE, RIGHT, ix, iy); + e1->outp[ABOVE]= e0->outp[ABOVE]; + e0->outp[ABOVE]= NULL; + } + break; + case ELI: + if (q) + { + N_EDGE(next_edge, e1, ABOVE, nx, iy); + VERTEX(e1, ABOVE, LEFT, ix, iy); + VERTEX(next_edge, ABOVE, RIGHT, nx, iy); + e0->outp[ABOVE]= e1->outp[ABOVE]; + e1->outp[ABOVE]= NULL; + } + break; + case EMX: + if (p && q) + { + VERTEX(e0, ABOVE, LEFT, ix, iy); + e0->outp[ABOVE]= NULL; + e1->outp[ABOVE]= NULL; + } + break; + case IMN: + P_EDGE(prev_edge, e0, ABOVE, px, iy); + VERTEX(prev_edge, ABOVE, LEFT, px, iy); + N_EDGE(next_edge, e1, ABOVE, nx, iy); + VERTEX(next_edge, ABOVE, RIGHT, nx, iy); + new_tristrip(&tlist, prev_edge, px, iy); + e1->outp[ABOVE]= prev_edge->outp[ABOVE]; + VERTEX(e1, ABOVE, RIGHT, ix, iy); + new_tristrip(&tlist, e0, ix, iy); + next_edge->outp[ABOVE]= e0->outp[ABOVE]; + VERTEX(next_edge, ABOVE, RIGHT, nx, iy); + break; + case ILI: + if (p) + { + VERTEX(e0, ABOVE, LEFT, ix, iy); + N_EDGE(next_edge, e1, ABOVE, nx, iy); + VERTEX(next_edge, ABOVE, RIGHT, nx, iy); + e1->outp[ABOVE]= e0->outp[ABOVE]; + e0->outp[ABOVE]= NULL; + } + break; + case IRI: + if (q) + { + VERTEX(e1, ABOVE, RIGHT, ix, iy); + P_EDGE(prev_edge, e0, ABOVE, px, iy); + VERTEX(prev_edge, ABOVE, LEFT, px, iy); + e0->outp[ABOVE]= e1->outp[ABOVE]; + e1->outp[ABOVE]= NULL; + } + break; + case IMX: + if (p && q) + { + VERTEX(e0, ABOVE, RIGHT, ix, iy); + VERTEX(e1, ABOVE, LEFT, ix, iy); + e0->outp[ABOVE]= NULL; + e1->outp[ABOVE]= NULL; + P_EDGE(prev_edge, e0, ABOVE, px, iy); + VERTEX(prev_edge, ABOVE, LEFT, px, iy); + new_tristrip(&tlist, prev_edge, px, iy); + N_EDGE(next_edge, e1, ABOVE, nx, iy); + VERTEX(next_edge, ABOVE, RIGHT, nx, iy); + next_edge->outp[ABOVE]= prev_edge->outp[ABOVE]; + VERTEX(next_edge, ABOVE, RIGHT, nx, iy); + } + break; + case IMM: + if (p && q) + { + VERTEX(e0, ABOVE, RIGHT, ix, iy); + VERTEX(e1, ABOVE, LEFT, ix, iy); + P_EDGE(prev_edge, e0, ABOVE, px, iy); + VERTEX(prev_edge, ABOVE, LEFT, px, iy); + new_tristrip(&tlist, prev_edge, px, iy); + N_EDGE(next_edge, e1, ABOVE, nx, iy); + VERTEX(next_edge, ABOVE, RIGHT, nx, iy); + e1->outp[ABOVE]= prev_edge->outp[ABOVE]; + VERTEX(e1, ABOVE, RIGHT, ix, iy); + new_tristrip(&tlist, e0, ix, iy); + next_edge->outp[ABOVE]= e0->outp[ABOVE]; + VERTEX(next_edge, ABOVE, RIGHT, nx, iy); + } + break; + case EMM: + if (p && q) + { + VERTEX(e0, ABOVE, LEFT, ix, iy); + new_tristrip(&tlist, e1, ix, iy); + e0->outp[ABOVE]= e1->outp[ABOVE]; + } + break; + default: + break; + } /* End of switch */ + } /* End of contributing intersection conditional */ + + /* Swap bundle sides in response to edge crossing */ + if (e0->bundle[ABOVE][CLIP]) + e1->bside[CLIP]= !e1->bside[CLIP]; + if (e1->bundle[ABOVE][CLIP]) + e0->bside[CLIP]= !e0->bside[CLIP]; + if (e0->bundle[ABOVE][SUBJ]) + e1->bside[SUBJ]= !e1->bside[SUBJ]; + if (e1->bundle[ABOVE][SUBJ]) + e0->bside[SUBJ]= !e0->bside[SUBJ]; + + /* Swap e0 and e1 bundles in the AET */ + prev_edge= e0->prev; + next_edge= e1->next; + if (e1->next) + e1->next->prev= e0; + + if (e0->bstate[ABOVE] == BUNDLE_HEAD) + { + search= TRUE; + while (search) + { + prev_edge= prev_edge->prev; + if (prev_edge) + { + if (prev_edge->bundle[ABOVE][CLIP] + || prev_edge->bundle[ABOVE][SUBJ] + || (prev_edge->bstate[ABOVE] == BUNDLE_HEAD)) + search= FALSE; + } + else + search= FALSE; + } + } + if (!prev_edge) + { + e1->next= aet; + aet= e0->next; + } + else + { + e1->next= prev_edge->next; + prev_edge->next= e0->next; + } + e0->next->prev= prev_edge; + e1->next->prev= e1; + e0->next= next_edge; + } /* End of IT loop*/ + + /* Prepare for next scanbeam */ + for (edge= aet; edge; edge= next_edge) + { + next_edge= edge->next; + succ_edge= edge->succ; + + if ((edge->top.y == yt) && succ_edge) + { + /* Replace AET edge by its successor */ + succ_edge->outp[BELOW]= edge->outp[ABOVE]; + succ_edge->bstate[BELOW]= edge->bstate[ABOVE]; + succ_edge->bundle[BELOW][CLIP]= edge->bundle[ABOVE][CLIP]; + succ_edge->bundle[BELOW][SUBJ]= edge->bundle[ABOVE][SUBJ]; + prev_edge= edge->prev; + if (prev_edge) + prev_edge->next= succ_edge; + else + aet= succ_edge; + if (next_edge) + next_edge->prev= succ_edge; + succ_edge->prev= prev_edge; + succ_edge->next= next_edge; + } + else + { + /* Update this edge */ + edge->outp[BELOW]= edge->outp[ABOVE]; + edge->bstate[BELOW]= edge->bstate[ABOVE]; + edge->bundle[BELOW][CLIP]= edge->bundle[ABOVE][CLIP]; + edge->bundle[BELOW][SUBJ]= edge->bundle[ABOVE][SUBJ]; + edge->xb= edge->xt; + } + edge->outp[ABOVE]= NULL; + } + } + } /* === END OF SCANBEAM PROCESSING ================================== */ + + /* Generate result tristrip from tlist */ + result->strip= NULL; + result->num_strips= count_tristrips(tlist); + if (result->num_strips > 0) + { + MALLOC(result->strip, result->num_strips * sizeof(gpc_vertex_list), + "tristrip list creation", gpc_vertex_list); + + s= 0; + for (tn= tlist; tn; tn= tnn) + { + tnn= tn->next; + + if (tn->active > 2) + { + /* Valid tristrip: copy the vertices and free the heap */ + result->strip[s].num_vertices= tn->active; + MALLOC(result->strip[s].vertex, tn->active * sizeof(gpc_vertex), + "tristrip creation", gpc_vertex); + v= 0; + if (INVERT_TRISTRIPS) + { + lt= tn->v[RIGHT]; + rt= tn->v[LEFT]; + } + else + { + lt= tn->v[LEFT]; + rt= tn->v[RIGHT]; + } + while (lt || rt) + { + if (lt) + { + ltn= lt->next; + result->strip[s].vertex[v].x= lt->x; + result->strip[s].vertex[v].y= lt->y; + v++; + FREE(lt); + lt= ltn; + } + if (rt) + { + rtn= rt->next; + result->strip[s].vertex[v].x= rt->x; + result->strip[s].vertex[v].y= rt->y; + v++; + FREE(rt); + rt= rtn; + } + } + s++; + } + else + { + /* Invalid tristrip: just free the heap */ + for (lt= tn->v[LEFT]; lt; lt= ltn) + { + ltn= lt->next; + FREE(lt); + } + for (rt= tn->v[RIGHT]; rt; rt=rtn) + { + rtn= rt->next; + FREE(rt); + } + } + FREE(tn); + } + } + + /* Tidy up */ + reset_it(&it); + reset_lmt(&lmt); + FREE(c_heap); + FREE(s_heap); + FREE(sbt); +} + +/* +=========================================================================== + End of file: gpc.c +=========================================================================== +*/ diff --git a/jni/desmume/src/android/agg/gpc/gpc.h b/jni/desmume/src/android/agg/gpc/gpc.h new file mode 100755 index 0000000..ff00f7b --- /dev/null +++ b/jni/desmume/src/android/agg/gpc/gpc.h @@ -0,0 +1,133 @@ +/* +=========================================================================== + +Project: Generic Polygon Clipper + + A new algorithm for calculating the difference, intersection, + exclusive-or or union of arbitrary polygon sets. + +File: gpc.h +Author: Alan Murta (email: gpc@cs.man.ac.uk) +Version: 2.32 +Date: 17th December 2004 + +Copyright: (C) 1997-2004, Advanced Interfaces Group, + University of Manchester. + + This software is free for non-commercial use. It may be copied, + modified, and redistributed provided that this copyright notice + is preserved on all copies. The intellectual property rights of + the algorithms used reside with the University of Manchester + Advanced Interfaces Group. + + You may not use this software, in whole or in part, in support + of any commercial product without the express consent of the + author. + + There is no warranty or other guarantee of fitness of this + software for any purpose. It is provided solely "as is". + +=========================================================================== +*/ + +#ifndef __gpc_h +#define __gpc_h + +#include <stdio.h> + + +/* +=========================================================================== + Constants +=========================================================================== +*/ + +/* Increase GPC_EPSILON to encourage merging of near coincident edges */ + +#define GPC_EPSILON (DBL_EPSILON) + +#define GPC_VERSION "2.32" + + +/* +=========================================================================== + Public Data Types +=========================================================================== +*/ + +typedef enum /* Set operation type */ +{ + GPC_DIFF, /* Difference */ + GPC_INT, /* Intersection */ + GPC_XOR, /* Exclusive or */ + GPC_UNION /* Union */ +} gpc_op; + +typedef struct /* Polygon vertex structure */ +{ + double x; /* Vertex x component */ + double y; /* vertex y component */ +} gpc_vertex; + +typedef struct /* Vertex list structure */ +{ + int num_vertices; /* Number of vertices in list */ + gpc_vertex *vertex; /* Vertex array pointer */ +} gpc_vertex_list; + +typedef struct /* Polygon set structure */ +{ + int num_contours; /* Number of contours in polygon */ + int *hole; /* Hole / external contour flags */ + gpc_vertex_list *contour; /* Contour array pointer */ +} gpc_polygon; + +typedef struct /* Tristrip set structure */ +{ + int num_strips; /* Number of tristrips */ + gpc_vertex_list *strip; /* Tristrip array pointer */ +} gpc_tristrip; + + +/* +=========================================================================== + Public Function Prototypes +=========================================================================== +*/ + +void gpc_read_polygon (FILE *infile_ptr, + int read_hole_flags, + gpc_polygon *polygon); + +void gpc_write_polygon (FILE *outfile_ptr, + int write_hole_flags, + gpc_polygon *polygon); + +void gpc_add_contour (gpc_polygon *polygon, + gpc_vertex_list *contour, + int hole); + +void gpc_polygon_clip (gpc_op set_operation, + gpc_polygon *subject_polygon, + gpc_polygon *clip_polygon, + gpc_polygon *result_polygon); + +void gpc_tristrip_clip (gpc_op set_operation, + gpc_polygon *subject_polygon, + gpc_polygon *clip_polygon, + gpc_tristrip *result_tristrip); + +void gpc_polygon_to_tristrip (gpc_polygon *polygon, + gpc_tristrip *tristrip); + +void gpc_free_polygon (gpc_polygon *polygon); + +void gpc_free_tristrip (gpc_tristrip *tristrip); + +#endif + +/* +=========================================================================== + End of file: gpc.h +=========================================================================== +*/ diff --git a/jni/desmume/src/android/agg/include/Makefile.am b/jni/desmume/src/android/agg/include/Makefile.am new file mode 100755 index 0000000..9a20600 --- /dev/null +++ b/jni/desmume/src/android/agg/include/Makefile.am @@ -0,0 +1,47 @@ +SUBDIRS = ctrl util platform + +aggincludedir = $(includedir)/agg2 +agginclude_HEADERS = \ + agg_alpha_mask_u8.h agg_glyph_raster_bin.h agg_span_allocator.h \ + agg_arc.h agg_gsv_text.h agg_span_converter.h \ + agg_array.h agg_image_accessors.h agg_span_gouraud.h \ + agg_arrowhead.h agg_image_filters.h agg_span_gouraud_gray.h \ + agg_basics.h agg_line_aa_basics.h agg_span_gouraud_rgba.h \ + agg_bezier_arc.h agg_math.h agg_span_gradient.h \ + agg_bitset_iterator.h agg_blur.h agg_math_stroke.h \ + agg_span_gradient_alpha.h agg_gradient_lut.h \ + agg_bounding_rect.h agg_path_length.h agg_span_image_filter.h \ + agg_bspline.h agg_path_storage.h agg_span_image_filter_gray.h \ + agg_clip_liang_barsky.h agg_path_storage_integer.h agg_span_image_filter_rgb.h \ + agg_color_gray.h agg_pattern_filters_rgba.h agg_span_image_filter_rgba.h \ + agg_color_rgba.h agg_pixfmt_amask_adaptor.h agg_span_interpolator_adaptor.h \ + agg_config.h agg_pixfmt_gray.h agg_span_interpolator_linear.h \ + agg_conv_adaptor_vcgen.h agg_pixfmt_rgb.h agg_span_interpolator_persp.h \ + agg_conv_adaptor_vpgen.h agg_pixfmt_rgb_packed.h agg_span_interpolator_trans.h \ + agg_conv_bspline.h agg_pixfmt_rgba.h agg_pixfmt_transposer.h \ + agg_span_pattern_gray.h \ + agg_conv_clip_polygon.h agg_rasterizer_cells_aa.h agg_span_pattern_rgb.h \ + agg_conv_clip_polyline.h agg_rasterizer_compound_aa.h agg_span_pattern_rgba.h \ + agg_conv_close_polygon.h agg_rasterizer_outline.h agg_span_solid.h \ + agg_conv_concat.h agg_rasterizer_outline_aa.h agg_span_subdiv_adaptor.h \ + agg_conv_contour.h agg_rasterizer_scanline_aa.h agg_trans_affine.h \ + agg_conv_curve.h agg_rasterizer_sl_clip.h agg_trans_bilinear.h \ + agg_conv_dash.h agg_renderer_base.h agg_trans_double_path.h \ + agg_conv_gpc.h agg_renderer_markers.h \ + agg_conv_marker.h agg_renderer_mclip.h agg_trans_perspective.h \ + agg_conv_marker_adaptor.h agg_renderer_outline_aa.h agg_trans_single_path.h \ + agg_conv_segmentator.h agg_renderer_outline_image.h agg_trans_viewport.h \ + agg_conv_shorten_path.h agg_renderer_primitives.h agg_trans_warp_magnifier.h \ + agg_conv_smooth_poly1.h agg_renderer_raster_text.h agg_vcgen_bspline.h \ + agg_conv_stroke.h agg_renderer_scanline.h agg_vcgen_contour.h \ + agg_conv_transform.h agg_rendering_buffer.h agg_vcgen_dash.h \ + agg_conv_unclose_polygon.h agg_rendering_buffer_dynarow.h agg_vcgen_markers_term.h \ + agg_curves.h agg_rounded_rect.h agg_vcgen_smooth_poly1.h \ + agg_scanline_bin.h agg_vcgen_stroke.h \ + agg_dda_line.h agg_scanline_boolean_algebra.h agg_vcgen_vertex_sequence.h \ + agg_ellipse.h agg_scanline_p.h agg_vertex_sequence.h \ + agg_ellipse_bresenham.h agg_scanline_storage_aa.h agg_vpgen_clip_polygon.h \ + agg_embedded_raster_fonts.h agg_scanline_storage_bin.h agg_vpgen_clip_polyline.h \ + agg_font_cache_manager.h agg_scanline_u.h agg_vpgen_segmentator.h \ + agg_gamma_functions.h agg_shorten_path.h \ + agg_gamma_lut.h agg_simul_eq.h diff --git a/jni/desmume/src/android/agg/include/agg_alpha_mask_u8.h b/jni/desmume/src/android/agg/include/agg_alpha_mask_u8.h new file mode 100755 index 0000000..b7ed0ef --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_alpha_mask_u8.h @@ -0,0 +1,505 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_ALPHA_MASK_U8_INCLUDED +#define AGG_ALPHA_MASK_U8_INCLUDED + +#include <string.h> +#include "agg_basics.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + //===================================================one_component_mask_u8 + struct one_component_mask_u8 + { + static unsigned calculate(const int8u* p) { return *p; } + }; + + + //=====================================================rgb_to_gray_mask_u8 + template<unsigned R, unsigned G, unsigned B> + struct rgb_to_gray_mask_u8 + { + static unsigned calculate(const int8u* p) + { + return (p[R]*77 + p[G]*150 + p[B]*29) >> 8; + } + }; + + //==========================================================alpha_mask_u8 + template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8> + class alpha_mask_u8 + { + public: + typedef int8u cover_type; + typedef alpha_mask_u8<Step, Offset, MaskF> self_type; + enum cover_scale_e + { + cover_shift = 8, + cover_none = 0, + cover_full = 255 + }; + + alpha_mask_u8() : m_rbuf(0) {} + explicit alpha_mask_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {} + + void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; } + + MaskF& mask_function() { return m_mask_function; } + const MaskF& mask_function() const { return m_mask_function; } + + + //-------------------------------------------------------------------- + cover_type pixel(int x, int y) const + { + if(x >= 0 && y >= 0 && + x < (int)m_rbuf->width() && + y < (int)m_rbuf->height()) + { + return (cover_type)m_mask_function.calculate( + m_rbuf->row_ptr(y) + x * Step + Offset); + } + return 0; + } + + //-------------------------------------------------------------------- + cover_type combine_pixel(int x, int y, cover_type val) const + { + if(x >= 0 && y >= 0 && + x < (int)m_rbuf->width() && + y < (int)m_rbuf->height()) + { + return (cover_type)((cover_full + val * + m_mask_function.calculate( + m_rbuf->row_ptr(y) + x * Step + Offset)) >> + cover_shift); + } + return 0; + } + + + //-------------------------------------------------------------------- + void fill_hspan(int x, int y, cover_type* dst, int num_pix) const + { + int xmax = m_rbuf->width() - 1; + int ymax = m_rbuf->height() - 1; + + int count = num_pix; + cover_type* covers = dst; + + if(y < 0 || y > ymax) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + + if(x < 0) + { + count += x; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers, 0, -x * sizeof(cover_type)); + covers -= x; + x = 0; + } + + if(x + count > xmax) + { + int rest = x + count - xmax - 1; + count -= rest; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers + count, 0, rest * sizeof(cover_type)); + } + + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; + do + { + *covers++ = (cover_type)m_mask_function.calculate(mask); + mask += Step; + } + while(--count); + } + + + //-------------------------------------------------------------------- + void combine_hspan(int x, int y, cover_type* dst, int num_pix) const + { + int xmax = m_rbuf->width() - 1; + int ymax = m_rbuf->height() - 1; + + int count = num_pix; + cover_type* covers = dst; + + if(y < 0 || y > ymax) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + + if(x < 0) + { + count += x; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers, 0, -x * sizeof(cover_type)); + covers -= x; + x = 0; + } + + if(x + count > xmax) + { + int rest = x + count - xmax - 1; + count -= rest; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers + count, 0, rest * sizeof(cover_type)); + } + + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; + do + { + *covers = (cover_type)((cover_full + (*covers) * + m_mask_function.calculate(mask)) >> + cover_shift); + ++covers; + mask += Step; + } + while(--count); + } + + //-------------------------------------------------------------------- + void fill_vspan(int x, int y, cover_type* dst, int num_pix) const + { + int xmax = m_rbuf->width() - 1; + int ymax = m_rbuf->height() - 1; + + int count = num_pix; + cover_type* covers = dst; + + if(x < 0 || x > xmax) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + + if(y < 0) + { + count += y; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers, 0, -y * sizeof(cover_type)); + covers -= y; + y = 0; + } + + if(y + count > ymax) + { + int rest = y + count - ymax - 1; + count -= rest; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers + count, 0, rest * sizeof(cover_type)); + } + + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; + do + { + *covers++ = (cover_type)m_mask_function.calculate(mask); + mask += m_rbuf->stride(); + } + while(--count); + } + + //-------------------------------------------------------------------- + void combine_vspan(int x, int y, cover_type* dst, int num_pix) const + { + int xmax = m_rbuf->width() - 1; + int ymax = m_rbuf->height() - 1; + + int count = num_pix; + cover_type* covers = dst; + + if(x < 0 || x > xmax) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + + if(y < 0) + { + count += y; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers, 0, -y * sizeof(cover_type)); + covers -= y; + y = 0; + } + + if(y + count > ymax) + { + int rest = y + count - ymax - 1; + count -= rest; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers + count, 0, rest * sizeof(cover_type)); + } + + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; + do + { + *covers = (cover_type)((cover_full + (*covers) * + m_mask_function.calculate(mask)) >> + cover_shift); + ++covers; + mask += m_rbuf->stride(); + } + while(--count); + } + + + private: + alpha_mask_u8(const self_type&); + const self_type& operator = (const self_type&); + + rendering_buffer* m_rbuf; + MaskF m_mask_function; + }; + + + typedef alpha_mask_u8<1, 0> alpha_mask_gray8; //----alpha_mask_gray8 + + typedef alpha_mask_u8<3, 0> alpha_mask_rgb24r; //----alpha_mask_rgb24r + typedef alpha_mask_u8<3, 1> alpha_mask_rgb24g; //----alpha_mask_rgb24g + typedef alpha_mask_u8<3, 2> alpha_mask_rgb24b; //----alpha_mask_rgb24b + + typedef alpha_mask_u8<3, 2> alpha_mask_bgr24r; //----alpha_mask_bgr24r + typedef alpha_mask_u8<3, 1> alpha_mask_bgr24g; //----alpha_mask_bgr24g + typedef alpha_mask_u8<3, 0> alpha_mask_bgr24b; //----alpha_mask_bgr24b + + typedef alpha_mask_u8<4, 0> alpha_mask_rgba32r; //----alpha_mask_rgba32r + typedef alpha_mask_u8<4, 1> alpha_mask_rgba32g; //----alpha_mask_rgba32g + typedef alpha_mask_u8<4, 2> alpha_mask_rgba32b; //----alpha_mask_rgba32b + typedef alpha_mask_u8<4, 3> alpha_mask_rgba32a; //----alpha_mask_rgba32a + + typedef alpha_mask_u8<4, 1> alpha_mask_argb32r; //----alpha_mask_argb32r + typedef alpha_mask_u8<4, 2> alpha_mask_argb32g; //----alpha_mask_argb32g + typedef alpha_mask_u8<4, 3> alpha_mask_argb32b; //----alpha_mask_argb32b + typedef alpha_mask_u8<4, 0> alpha_mask_argb32a; //----alpha_mask_argb32a + + typedef alpha_mask_u8<4, 2> alpha_mask_bgra32r; //----alpha_mask_bgra32r + typedef alpha_mask_u8<4, 1> alpha_mask_bgra32g; //----alpha_mask_bgra32g + typedef alpha_mask_u8<4, 0> alpha_mask_bgra32b; //----alpha_mask_bgra32b + typedef alpha_mask_u8<4, 3> alpha_mask_bgra32a; //----alpha_mask_bgra32a + + typedef alpha_mask_u8<4, 3> alpha_mask_abgr32r; //----alpha_mask_abgr32r + typedef alpha_mask_u8<4, 2> alpha_mask_abgr32g; //----alpha_mask_abgr32g + typedef alpha_mask_u8<4, 1> alpha_mask_abgr32b; //----alpha_mask_abgr32b + typedef alpha_mask_u8<4, 0> alpha_mask_abgr32a; //----alpha_mask_abgr32a + + typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgb24gray; //----alpha_mask_rgb24gray + typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgr24gray; //----alpha_mask_bgr24gray + typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgba32gray; //----alpha_mask_rgba32gray + typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_argb32gray; //----alpha_mask_argb32gray + typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgra32gray; //----alpha_mask_bgra32gray + typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_abgr32gray; //----alpha_mask_abgr32gray + + + + //==========================================================amask_no_clip_u8 + template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8> + class amask_no_clip_u8 + { + public: + typedef int8u cover_type; + typedef amask_no_clip_u8<Step, Offset, MaskF> self_type; + enum cover_scale_e + { + cover_shift = 8, + cover_none = 0, + cover_full = 255 + }; + + amask_no_clip_u8() : m_rbuf(0) {} + explicit amask_no_clip_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {} + + void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; } + + MaskF& mask_function() { return m_mask_function; } + const MaskF& mask_function() const { return m_mask_function; } + + + //-------------------------------------------------------------------- + cover_type pixel(int x, int y) const + { + return (cover_type)m_mask_function.calculate( + m_rbuf->row_ptr(y) + x * Step + Offset); + } + + + //-------------------------------------------------------------------- + cover_type combine_pixel(int x, int y, cover_type val) const + { + return (cover_type)((cover_full + val * + m_mask_function.calculate( + m_rbuf->row_ptr(y) + x * Step + Offset)) >> + cover_shift); + } + + + //-------------------------------------------------------------------- + void fill_hspan(int x, int y, cover_type* dst, int num_pix) const + { + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; + do + { + *dst++ = (cover_type)m_mask_function.calculate(mask); + mask += Step; + } + while(--num_pix); + } + + + + //-------------------------------------------------------------------- + void combine_hspan(int x, int y, cover_type* dst, int num_pix) const + { + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; + do + { + *dst = (cover_type)((cover_full + (*dst) * + m_mask_function.calculate(mask)) >> + cover_shift); + ++dst; + mask += Step; + } + while(--num_pix); + } + + + //-------------------------------------------------------------------- + void fill_vspan(int x, int y, cover_type* dst, int num_pix) const + { + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; + do + { + *dst++ = (cover_type)m_mask_function.calculate(mask); + mask += m_rbuf->stride(); + } + while(--num_pix); + } + + + //-------------------------------------------------------------------- + void combine_vspan(int x, int y, cover_type* dst, int num_pix) const + { + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; + do + { + *dst = (cover_type)((cover_full + (*dst) * + m_mask_function.calculate(mask)) >> + cover_shift); + ++dst; + mask += m_rbuf->stride(); + } + while(--num_pix); + } + + private: + amask_no_clip_u8(const self_type&); + const self_type& operator = (const self_type&); + + rendering_buffer* m_rbuf; + MaskF m_mask_function; + }; + + + typedef amask_no_clip_u8<1, 0> amask_no_clip_gray8; //----amask_no_clip_gray8 + + typedef amask_no_clip_u8<3, 0> amask_no_clip_rgb24r; //----amask_no_clip_rgb24r + typedef amask_no_clip_u8<3, 1> amask_no_clip_rgb24g; //----amask_no_clip_rgb24g + typedef amask_no_clip_u8<3, 2> amask_no_clip_rgb24b; //----amask_no_clip_rgb24b + + typedef amask_no_clip_u8<3, 2> amask_no_clip_bgr24r; //----amask_no_clip_bgr24r + typedef amask_no_clip_u8<3, 1> amask_no_clip_bgr24g; //----amask_no_clip_bgr24g + typedef amask_no_clip_u8<3, 0> amask_no_clip_bgr24b; //----amask_no_clip_bgr24b + + typedef amask_no_clip_u8<4, 0> amask_no_clip_rgba32r; //----amask_no_clip_rgba32r + typedef amask_no_clip_u8<4, 1> amask_no_clip_rgba32g; //----amask_no_clip_rgba32g + typedef amask_no_clip_u8<4, 2> amask_no_clip_rgba32b; //----amask_no_clip_rgba32b + typedef amask_no_clip_u8<4, 3> amask_no_clip_rgba32a; //----amask_no_clip_rgba32a + + typedef amask_no_clip_u8<4, 1> amask_no_clip_argb32r; //----amask_no_clip_argb32r + typedef amask_no_clip_u8<4, 2> amask_no_clip_argb32g; //----amask_no_clip_argb32g + typedef amask_no_clip_u8<4, 3> amask_no_clip_argb32b; //----amask_no_clip_argb32b + typedef amask_no_clip_u8<4, 0> amask_no_clip_argb32a; //----amask_no_clip_argb32a + + typedef amask_no_clip_u8<4, 2> amask_no_clip_bgra32r; //----amask_no_clip_bgra32r + typedef amask_no_clip_u8<4, 1> amask_no_clip_bgra32g; //----amask_no_clip_bgra32g + typedef amask_no_clip_u8<4, 0> amask_no_clip_bgra32b; //----amask_no_clip_bgra32b + typedef amask_no_clip_u8<4, 3> amask_no_clip_bgra32a; //----amask_no_clip_bgra32a + + typedef amask_no_clip_u8<4, 3> amask_no_clip_abgr32r; //----amask_no_clip_abgr32r + typedef amask_no_clip_u8<4, 2> amask_no_clip_abgr32g; //----amask_no_clip_abgr32g + typedef amask_no_clip_u8<4, 1> amask_no_clip_abgr32b; //----amask_no_clip_abgr32b + typedef amask_no_clip_u8<4, 0> amask_no_clip_abgr32a; //----amask_no_clip_abgr32a + + typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgb24gray; //----amask_no_clip_rgb24gray + typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgr24gray; //----amask_no_clip_bgr24gray + typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgba32gray; //----amask_no_clip_rgba32gray + typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_argb32gray; //----amask_no_clip_argb32gray + typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgra32gray; //----amask_no_clip_bgra32gray + typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_abgr32gray; //----amask_no_clip_abgr32gray + + +} + + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_arc.h b/jni/desmume/src/android/agg/include/agg_arc.h new file mode 100755 index 0000000..b885173 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_arc.h @@ -0,0 +1,79 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_ARC_INCLUDED +#define AGG_ARC_INCLUDED + +#include <math.h> +#include "agg_basics.h" + +namespace agg +{ + + //=====================================================================arc + // + // See Implementation agg_arc.cpp + // + class arc + { + public: + arc() : m_scale(1.0), m_initialized(false) {} + arc(double x, double y, + double rx, double ry, + double a1, double a2, + bool ccw=true); + + void init(double x, double y, + double rx, double ry, + double a1, double a2, + bool ccw=true); + + void approximation_scale(double s); + double approximation_scale() const { return m_scale; } + + void rewind(unsigned); + unsigned vertex(double* x, double* y); + + private: + void normalize(double a1, double a2, bool ccw); + + double m_x; + double m_y; + double m_rx; + double m_ry; + double m_angle; + double m_start; + double m_end; + double m_scale; + double m_da; + bool m_ccw; + bool m_initialized; + unsigned m_path_cmd; + }; + + +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_array.h b/jni/desmume/src/android/agg/include/agg_array.h new file mode 100755 index 0000000..5c6d390 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_array.h @@ -0,0 +1,1129 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_ARRAY_INCLUDED +#define AGG_ARRAY_INCLUDED + +#include <stddef.h> +#include <string.h> +#include "agg_basics.h" + +namespace agg +{ + + //-------------------------------------------------------pod_array_adaptor + template<class T> class pod_array_adaptor + { + public: + typedef T value_type; + pod_array_adaptor(T* array, unsigned size) : + m_array(array), m_size(size) {} + + unsigned size() const { return m_size; } + const T& operator [] (unsigned i) const { return m_array[i]; } + T& operator [] (unsigned i) { return m_array[i]; } + const T& at(unsigned i) const { return m_array[i]; } + T& at(unsigned i) { return m_array[i]; } + T value_at(unsigned i) const { return m_array[i]; } + + private: + T* m_array; + unsigned m_size; + }; + + + //---------------------------------------------------------pod_auto_array + template<class T, unsigned Size> class pod_auto_array + { + public: + typedef T value_type; + typedef pod_auto_array<T, Size> self_type; + + pod_auto_array() {} + explicit pod_auto_array(const T* c) + { + memcpy(m_array, c, sizeof(T) * Size); + } + + const self_type& operator = (const T* c) + { + memcpy(m_array, c, sizeof(T) * Size); + return *this; + } + + static unsigned size() { return Size; } + const T& operator [] (unsigned i) const { return m_array[i]; } + T& operator [] (unsigned i) { return m_array[i]; } + const T& at(unsigned i) const { return m_array[i]; } + T& at(unsigned i) { return m_array[i]; } + T value_at(unsigned i) const { return m_array[i]; } + + private: + T m_array[Size]; + }; + + + //--------------------------------------------------------pod_auto_vector + template<class T, unsigned Size> class pod_auto_vector + { + public: + typedef T value_type; + typedef pod_auto_vector<T, Size> self_type; + + pod_auto_vector() : m_size(0) {} + + void remove_all() { m_size = 0; } + void clear() { m_size = 0; } + void add(const T& v) { m_array[m_size++] = v; } + void push_back(const T& v) { m_array[m_size++] = v; } + void inc_size(unsigned size) { m_size += size; } + + unsigned size() const { return m_size; } + const T& operator [] (unsigned i) const { return m_array[i]; } + T& operator [] (unsigned i) { return m_array[i]; } + const T& at(unsigned i) const { return m_array[i]; } + T& at(unsigned i) { return m_array[i]; } + T value_at(unsigned i) const { return m_array[i]; } + + private: + T m_array[Size]; + unsigned m_size; + }; + + + //---------------------------------------------------------------pod_array + template<class T> class pod_array + { + public: + typedef T value_type; + typedef pod_array<T> self_type; + + ~pod_array() { pod_allocator<T>::deallocate(m_array, m_size); } + pod_array() : m_array(0), m_size(0) {} + + pod_array(unsigned size) : + m_array(pod_allocator<T>::allocate(size)), + m_size(size) + {} + + pod_array(const self_type& v) : + m_array(pod_allocator<T>::allocate(v.m_size)), + m_size(v.m_size) + { + memcpy(m_array, v.m_array, sizeof(T) * m_size); + } + + void resize(unsigned size) + { + if(size != m_size) + { + pod_allocator<T>::deallocate(m_array, m_size); + m_array = pod_allocator<T>::allocate(m_size = size); + } + } + const self_type& operator = (const self_type& v) + { + resize(v.size()); + memcpy(m_array, v.m_array, sizeof(T) * m_size); + return *this; + } + + unsigned size() const { return m_size; } + const T& operator [] (unsigned i) const { return m_array[i]; } + T& operator [] (unsigned i) { return m_array[i]; } + const T& at(unsigned i) const { return m_array[i]; } + T& at(unsigned i) { return m_array[i]; } + T value_at(unsigned i) const { return m_array[i]; } + + const T* data() const { return m_array; } + T* data() { return m_array; } + private: + T* m_array; + unsigned m_size; + }; + + + + //--------------------------------------------------------------pod_vector + // A simple class template to store Plain Old Data, a vector + // of a fixed size. The data is continous in memory + //------------------------------------------------------------------------ + template<class T> class pod_vector + { + public: + typedef T value_type; + + ~pod_vector() { pod_allocator<T>::deallocate(m_array, m_capacity); } + pod_vector() : m_size(0), m_capacity(0), m_array(0) {} + pod_vector(unsigned cap, unsigned extra_tail=0); + + // Copying + pod_vector(const pod_vector<T>&); + const pod_vector<T>& operator = (const pod_vector<T>&); + + // Set new capacity. All data is lost, size is set to zero. + void capacity(unsigned cap, unsigned extra_tail=0); + unsigned capacity() const { return m_capacity; } + + // Allocate n elements. All data is lost, + // but elements can be accessed in range 0...size-1. + void allocate(unsigned size, unsigned extra_tail=0); + + // Resize keeping the content. + void resize(unsigned new_size); + + void zero() + { + memset(m_array, 0, sizeof(T) * m_size); + } + + void add(const T& v) { m_array[m_size++] = v; } + void push_back(const T& v) { m_array[m_size++] = v; } + void insert_at(unsigned pos, const T& val); + void inc_size(unsigned size) { m_size += size; } + unsigned size() const { return m_size; } + unsigned byte_size() const { return m_size * sizeof(T); } + void serialize(int8u* ptr) const; + void deserialize(const int8u* data, unsigned byte_size); + const T& operator [] (unsigned i) const { return m_array[i]; } + T& operator [] (unsigned i) { return m_array[i]; } + const T& at(unsigned i) const { return m_array[i]; } + T& at(unsigned i) { return m_array[i]; } + T value_at(unsigned i) const { return m_array[i]; } + + const T* data() const { return m_array; } + T* data() { return m_array; } + + void remove_all() { m_size = 0; } + void clear() { m_size = 0; } + void cut_at(unsigned num) { if(num < m_size) m_size = num; } + + private: + unsigned m_size; + unsigned m_capacity; + T* m_array; + }; + + //------------------------------------------------------------------------ + template<class T> + void pod_vector<T>::capacity(unsigned cap, unsigned extra_tail) + { + m_size = 0; + if(cap > m_capacity) + { + pod_allocator<T>::deallocate(m_array, m_capacity); + m_capacity = cap + extra_tail; + m_array = m_capacity ? pod_allocator<T>::allocate(m_capacity) : 0; + } + } + + //------------------------------------------------------------------------ + template<class T> + void pod_vector<T>::allocate(unsigned size, unsigned extra_tail) + { + capacity(size, extra_tail); + m_size = size; + } + + + //------------------------------------------------------------------------ + template<class T> + void pod_vector<T>::resize(unsigned new_size) + { + if(new_size > m_size) + { + if(new_size > m_capacity) + { + T* data = pod_allocator<T>::allocate(new_size); + memcpy(data, m_array, m_size * sizeof(T)); + pod_allocator<T>::deallocate(m_array, m_capacity); + m_array = data; + } + } + else + { + m_size = new_size; + } + } + + //------------------------------------------------------------------------ + template<class T> pod_vector<T>::pod_vector(unsigned cap, unsigned extra_tail) : + m_size(0), + m_capacity(cap + extra_tail), + m_array(pod_allocator<T>::allocate(m_capacity)) {} + + //------------------------------------------------------------------------ + template<class T> pod_vector<T>::pod_vector(const pod_vector<T>& v) : + m_size(v.m_size), + m_capacity(v.m_capacity), + m_array(v.m_capacity ? pod_allocator<T>::allocate(v.m_capacity) : 0) + { + memcpy(m_array, v.m_array, sizeof(T) * v.m_size); + } + + //------------------------------------------------------------------------ + template<class T> const pod_vector<T>& + pod_vector<T>::operator = (const pod_vector<T>&v) + { + allocate(v.m_size); + if(v.m_size) memcpy(m_array, v.m_array, sizeof(T) * v.m_size); + return *this; + } + + //------------------------------------------------------------------------ + template<class T> void pod_vector<T>::serialize(int8u* ptr) const + { + if(m_size) memcpy(ptr, m_array, m_size * sizeof(T)); + } + + //------------------------------------------------------------------------ + template<class T> + void pod_vector<T>::deserialize(const int8u* data, unsigned byte_size) + { + byte_size /= sizeof(T); + allocate(byte_size); + if(byte_size) memcpy(m_array, data, byte_size * sizeof(T)); + } + + //------------------------------------------------------------------------ + template<class T> + void pod_vector<T>::insert_at(unsigned pos, const T& val) + { + if(pos >= m_size) + { + m_array[m_size] = val; + } + else + { + memmove(m_array + pos + 1, m_array + pos, (m_size - pos) * sizeof(T)); + m_array[pos] = val; + } + ++m_size; + } + + //---------------------------------------------------------------pod_bvector + // A simple class template to store Plain Old Data, similar to std::deque + // It doesn't reallocate memory but instead, uses blocks of data of size + // of (1 << S), that is, power of two. The data is NOT contiguous in memory, + // so the only valid access method is operator [] or curr(), prev(), next() + // + // There reallocs occure only when the pool of pointers to blocks needs + // to be extended (it happens very rarely). You can control the value + // of increment to reallocate the pointer buffer. See the second constructor. + // By default, the incremeent value equals (1 << S), i.e., the block size. + //------------------------------------------------------------------------ + template<class T, unsigned S=6> class pod_bvector + { + public: + enum block_scale_e + { + block_shift = S, + block_size = 1 << block_shift, + block_mask = block_size - 1 + }; + + typedef T value_type; + + ~pod_bvector(); + pod_bvector(); + pod_bvector(unsigned block_ptr_inc); + + // Copying + pod_bvector(const pod_bvector<T, S>& v); + const pod_bvector<T, S>& operator = (const pod_bvector<T, S>& v); + + void remove_all() { m_size = 0; } + void clear() { m_size = 0; } + void free_all() { free_tail(0); } + void free_tail(unsigned size); + void add(const T& val); + void push_back(const T& val) { add(val); } + void modify_last(const T& val); + void remove_last(); + + int allocate_continuous_block(unsigned num_elements); + + void add_array(const T* ptr, unsigned num_elem) + { + while(num_elem--) + { + add(*ptr++); + } + } + + template<class DataAccessor> void add_data(DataAccessor& data) + { + while(data.size()) + { + add(*data); + ++data; + } + } + + void cut_at(unsigned size) + { + if(size < m_size) m_size = size; + } + + unsigned size() const { return m_size; } + + const T& operator [] (unsigned i) const + { + return m_blocks[i >> block_shift][i & block_mask]; + } + + T& operator [] (unsigned i) + { + return m_blocks[i >> block_shift][i & block_mask]; + } + + const T& at(unsigned i) const + { + return m_blocks[i >> block_shift][i & block_mask]; + } + + T& at(unsigned i) + { + return m_blocks[i >> block_shift][i & block_mask]; + } + + T value_at(unsigned i) const + { + return m_blocks[i >> block_shift][i & block_mask]; + } + + const T& curr(unsigned idx) const + { + return (*this)[idx]; + } + + T& curr(unsigned idx) + { + return (*this)[idx]; + } + + const T& prev(unsigned idx) const + { + return (*this)[(idx + m_size - 1) % m_size]; + } + + T& prev(unsigned idx) + { + return (*this)[(idx + m_size - 1) % m_size]; + } + + const T& next(unsigned idx) const + { + return (*this)[(idx + 1) % m_size]; + } + + T& next(unsigned idx) + { + return (*this)[(idx + 1) % m_size]; + } + + const T& last() const + { + return (*this)[m_size - 1]; + } + + T& last() + { + return (*this)[m_size - 1]; + } + + unsigned byte_size() const; + void serialize(int8u* ptr) const; + void deserialize(const int8u* data, unsigned byte_size); + void deserialize(unsigned start, const T& empty_val, + const int8u* data, unsigned byte_size); + + template<class ByteAccessor> + void deserialize(ByteAccessor data) + { + remove_all(); + unsigned elem_size = data.size() / sizeof(T); + + for(unsigned i = 0; i < elem_size; ++i) + { + int8u* ptr = (int8u*)data_ptr(); + for(unsigned j = 0; j < sizeof(T); ++j) + { + *ptr++ = *data; + ++data; + } + ++m_size; + } + } + + template<class ByteAccessor> + void deserialize(unsigned start, const T& empty_val, ByteAccessor data) + { + while(m_size < start) + { + add(empty_val); + } + + unsigned elem_size = data.size() / sizeof(T); + for(unsigned i = 0; i < elem_size; ++i) + { + int8u* ptr; + if(start + i < m_size) + { + ptr = (int8u*)(&((*this)[start + i])); + } + else + { + ptr = (int8u*)data_ptr(); + ++m_size; + } + for(unsigned j = 0; j < sizeof(T); ++j) + { + *ptr++ = *data; + ++data; + } + } + } + + const T* block(unsigned nb) const { return m_blocks[nb]; } + + private: + void allocate_block(unsigned nb); + T* data_ptr(); + + unsigned m_size; + unsigned m_num_blocks; + unsigned m_max_blocks; + T** m_blocks; + unsigned m_block_ptr_inc; + }; + + + //------------------------------------------------------------------------ + template<class T, unsigned S> pod_bvector<T, S>::~pod_bvector() + { + if(m_num_blocks) + { + T** blk = m_blocks + m_num_blocks - 1; + while(m_num_blocks--) + { + pod_allocator<T>::deallocate(*blk, block_size); + --blk; + } + } + pod_allocator<T*>::deallocate(m_blocks, m_max_blocks); + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + void pod_bvector<T, S>::free_tail(unsigned size) + { + if(size < m_size) + { + unsigned nb = (size + block_mask) >> block_shift; + while(m_num_blocks > nb) + { + pod_allocator<T>::deallocate(m_blocks[--m_num_blocks], block_size); + } + if(m_num_blocks == 0) + { + pod_allocator<T*>::deallocate(m_blocks, m_max_blocks); + m_blocks = 0; + m_max_blocks = 0; + } + m_size = size; + } + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> pod_bvector<T, S>::pod_bvector() : + m_size(0), + m_num_blocks(0), + m_max_blocks(0), + m_blocks(0), + m_block_ptr_inc(block_size) + { + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + pod_bvector<T, S>::pod_bvector(unsigned block_ptr_inc) : + m_size(0), + m_num_blocks(0), + m_max_blocks(0), + m_blocks(0), + m_block_ptr_inc(block_ptr_inc) + { + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + pod_bvector<T, S>::pod_bvector(const pod_bvector<T, S>& v) : + m_size(v.m_size), + m_num_blocks(v.m_num_blocks), + m_max_blocks(v.m_max_blocks), + m_blocks(v.m_max_blocks ? + pod_allocator<T*>::allocate(v.m_max_blocks) : + 0), + m_block_ptr_inc(v.m_block_ptr_inc) + { + unsigned i; + for(i = 0; i < v.m_num_blocks; ++i) + { + m_blocks[i] = pod_allocator<T>::allocate(block_size); + memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T)); + } + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + const pod_bvector<T, S>& + pod_bvector<T, S>::operator = (const pod_bvector<T, S>& v) + { + unsigned i; + for(i = m_num_blocks; i < v.m_num_blocks; ++i) + { + allocate_block(i); + } + for(i = 0; i < v.m_num_blocks; ++i) + { + memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T)); + } + m_size = v.m_size; + return *this; + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + void pod_bvector<T, S>::allocate_block(unsigned nb) + { + if(nb >= m_max_blocks) + { + T** new_blocks = pod_allocator<T*>::allocate(m_max_blocks + m_block_ptr_inc); + + if(m_blocks) + { + memcpy(new_blocks, + m_blocks, + m_num_blocks * sizeof(T*)); + + pod_allocator<T*>::deallocate(m_blocks, m_max_blocks); + } + m_blocks = new_blocks; + m_max_blocks += m_block_ptr_inc; + } + m_blocks[nb] = pod_allocator<T>::allocate(block_size); + m_num_blocks++; + } + + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + inline T* pod_bvector<T, S>::data_ptr() + { + unsigned nb = m_size >> block_shift; + if(nb >= m_num_blocks) + { + allocate_block(nb); + } + return m_blocks[nb] + (m_size & block_mask); + } + + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + inline void pod_bvector<T, S>::add(const T& val) + { + *data_ptr() = val; + ++m_size; + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + inline void pod_bvector<T, S>::remove_last() + { + if(m_size) --m_size; + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + void pod_bvector<T, S>::modify_last(const T& val) + { + remove_last(); + add(val); + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + int pod_bvector<T, S>::allocate_continuous_block(unsigned num_elements) + { + if(num_elements < block_size) + { + data_ptr(); // Allocate initial block if necessary + unsigned rest = block_size - (m_size & block_mask); + unsigned index; + if(num_elements <= rest) + { + // The rest of the block is good, we can use it + //----------------- + index = m_size; + m_size += num_elements; + return index; + } + + // New block + //--------------- + m_size += rest; + data_ptr(); + index = m_size; + m_size += num_elements; + return index; + } + return -1; // Impossible to allocate + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + unsigned pod_bvector<T, S>::byte_size() const + { + return m_size * sizeof(T); + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + void pod_bvector<T, S>::serialize(int8u* ptr) const + { + unsigned i; + for(i = 0; i < m_size; i++) + { + memcpy(ptr, &(*this)[i], sizeof(T)); + ptr += sizeof(T); + } + } + + //------------------------------------------------------------------------ + template<class T, unsigned S> + void pod_bvector<T, S>::deserialize(const int8u* data, unsigned byte_size) + { + remove_all(); + byte_size /= sizeof(T); + for(unsigned i = 0; i < byte_size; ++i) + { + T* ptr = data_ptr(); + memcpy(ptr, data, sizeof(T)); + ++m_size; + data += sizeof(T); + } + } + + + // Replace or add a number of elements starting from "start" position + //------------------------------------------------------------------------ + template<class T, unsigned S> + void pod_bvector<T, S>::deserialize(unsigned start, const T& empty_val, + const int8u* data, unsigned byte_size) + { + while(m_size < start) + { + add(empty_val); + } + + byte_size /= sizeof(T); + for(unsigned i = 0; i < byte_size; ++i) + { + if(start + i < m_size) + { + memcpy(&((*this)[start + i]), data, sizeof(T)); + } + else + { + T* ptr = data_ptr(); + memcpy(ptr, data, sizeof(T)); + ++m_size; + } + data += sizeof(T); + } + } + + + //---------------------------------------------------------block_allocator + // Allocator for arbitrary POD data. Most usable in different cache + // systems for efficient memory allocations. + // Memory is allocated with blocks of fixed size ("block_size" in + // the constructor). If required size exceeds the block size the allocator + // creates a new block of the required size. However, the most efficient + // use is when the average reqired size is much less than the block size. + //------------------------------------------------------------------------ + class block_allocator + { + struct block_type + { + int8u* data; + unsigned size; + }; + + public: + void remove_all() + { + if(m_num_blocks) + { + block_type* blk = m_blocks + m_num_blocks - 1; + while(m_num_blocks--) + { + pod_allocator<int8u>::deallocate(blk->data, blk->size); + --blk; + } + pod_allocator<block_type>::deallocate(m_blocks, m_max_blocks); + } + m_num_blocks = 0; + m_max_blocks = 0; + m_blocks = 0; + m_buf_ptr = 0; + m_rest = 0; + } + + ~block_allocator() + { + remove_all(); + } + + block_allocator(unsigned block_size, unsigned block_ptr_inc=256-8) : + m_block_size(block_size), + m_block_ptr_inc(block_ptr_inc), + m_num_blocks(0), + m_max_blocks(0), + m_blocks(0), + m_buf_ptr(0), + m_rest(0) + { + } + + + int8u* allocate(unsigned size, unsigned alignment=1) + { + if(size == 0) return 0; + if(size <= m_rest) + { + int8u* ptr = m_buf_ptr; + if(alignment > 1) + { + unsigned align = + (alignment - unsigned((size_t)ptr) % alignment) % alignment; + + size += align; + ptr += align; + if(size <= m_rest) + { + m_rest -= size; + m_buf_ptr += size; + return ptr; + } + allocate_block(size); + return allocate(size - align, alignment); + } + m_rest -= size; + m_buf_ptr += size; + return ptr; + } + allocate_block(size + alignment - 1); + return allocate(size, alignment); + } + + + private: + void allocate_block(unsigned size) + { + if(size < m_block_size) size = m_block_size; + if(m_num_blocks >= m_max_blocks) + { + block_type* new_blocks = + pod_allocator<block_type>::allocate(m_max_blocks + m_block_ptr_inc); + + if(m_blocks) + { + memcpy(new_blocks, + m_blocks, + m_num_blocks * sizeof(block_type)); + pod_allocator<block_type>::deallocate(m_blocks, m_max_blocks); + } + m_blocks = new_blocks; + m_max_blocks += m_block_ptr_inc; + } + + m_blocks[m_num_blocks].size = size; + m_blocks[m_num_blocks].data = + m_buf_ptr = + pod_allocator<int8u>::allocate(size); + + m_num_blocks++; + m_rest = size; + } + + unsigned m_block_size; + unsigned m_block_ptr_inc; + unsigned m_num_blocks; + unsigned m_max_blocks; + block_type* m_blocks; + int8u* m_buf_ptr; + unsigned m_rest; + }; + + + + + + + + + //------------------------------------------------------------------------ + enum quick_sort_threshold_e + { + quick_sort_threshold = 9 + }; + + + //-----------------------------------------------------------swap_elements + template<class T> inline void swap_elements(T& a, T& b) + { + T temp = a; + a = b; + b = temp; + } + + + //--------------------------------------------------------------quick_sort + template<class Array, class Less> + void quick_sort(Array& arr, Less less) + { + if(arr.size() < 2) return; + + typename Array::value_type* e1; + typename Array::value_type* e2; + + int stack[80]; + int* top = stack; + int limit = arr.size(); + int base = 0; + + for(;;) + { + int len = limit - base; + + int i; + int j; + int pivot; + + if(len > quick_sort_threshold) + { + // we use base + len/2 as the pivot + pivot = base + len / 2; + swap_elements(arr[base], arr[pivot]); + + i = base + 1; + j = limit - 1; + + // now ensure that *i <= *base <= *j + e1 = &(arr[j]); + e2 = &(arr[i]); + if(less(*e1, *e2)) swap_elements(*e1, *e2); + + e1 = &(arr[base]); + e2 = &(arr[i]); + if(less(*e1, *e2)) swap_elements(*e1, *e2); + + e1 = &(arr[j]); + e2 = &(arr[base]); + if(less(*e1, *e2)) swap_elements(*e1, *e2); + + for(;;) + { + do i++; while( less(arr[i], arr[base]) ); + do j--; while( less(arr[base], arr[j]) ); + + if( i > j ) + { + break; + } + + swap_elements(arr[i], arr[j]); + } + + swap_elements(arr[base], arr[j]); + + // now, push the largest sub-array + if(j - base > limit - i) + { + top[0] = base; + top[1] = j; + base = i; + } + else + { + top[0] = i; + top[1] = limit; + limit = j; + } + top += 2; + } + else + { + // the sub-array is small, perform insertion sort + j = base; + i = j + 1; + + for(; i < limit; j = i, i++) + { + for(; less(*(e1 = &(arr[j + 1])), *(e2 = &(arr[j]))); j--) + { + swap_elements(*e1, *e2); + if(j == base) + { + break; + } + } + } + if(top > stack) + { + top -= 2; + base = top[0]; + limit = top[1]; + } + else + { + break; + } + } + } + } + + + + + //------------------------------------------------------remove_duplicates + // Remove duplicates from a sorted array. It doesn't cut the + // tail of the array, it just returns the number of remaining elements. + //----------------------------------------------------------------------- + template<class Array, class Equal> + unsigned remove_duplicates(Array& arr, Equal equal) + { + if(arr.size() < 2) return arr.size(); + + unsigned i, j; + for(i = 1, j = 1; i < arr.size(); i++) + { + typename Array::value_type& e = arr[i]; + if(!equal(e, arr[i - 1])) + { + arr[j++] = e; + } + } + return j; + } + + //--------------------------------------------------------invert_container + template<class Array> void invert_container(Array& arr) + { + int i = 0; + int j = arr.size() - 1; + while(i < j) + { + swap_elements(arr[i++], arr[j--]); + } + } + + //------------------------------------------------------binary_search_pos + template<class Array, class Value, class Less> + unsigned binary_search_pos(const Array& arr, const Value& val, Less less) + { + if(arr.size() == 0) return 0; + + unsigned beg = 0; + unsigned end = arr.size() - 1; + + if(less(val, arr[0])) return 0; + if(less(arr[end], val)) return end + 1; + + while(end - beg > 1) + { + unsigned mid = (end + beg) >> 1; + if(less(val, arr[mid])) end = mid; + else beg = mid; + } + + //if(beg <= 0 && less(val, arr[0])) return 0; + //if(end >= arr.size() - 1 && less(arr[end], val)) ++end; + + return end; + } + + //----------------------------------------------------------range_adaptor + template<class Array> class range_adaptor + { + public: + typedef typename Array::value_type value_type; + + range_adaptor(Array& array, unsigned start, unsigned size) : + m_array(array), m_start(start), m_size(size) + {} + + unsigned size() const { return m_size; } + const value_type& operator [] (unsigned i) const { return m_array[m_start + i]; } + value_type& operator [] (unsigned i) { return m_array[m_start + i]; } + const value_type& at(unsigned i) const { return m_array[m_start + i]; } + value_type& at(unsigned i) { return m_array[m_start + i]; } + value_type value_at(unsigned i) const { return m_array[m_start + i]; } + + private: + Array& m_array; + unsigned m_start; + unsigned m_size; + }; + + //---------------------------------------------------------------int_less + inline bool int_less(int a, int b) { return a < b; } + + //------------------------------------------------------------int_greater + inline bool int_greater(int a, int b) { return a > b; } + + //----------------------------------------------------------unsigned_less + inline bool unsigned_less(unsigned a, unsigned b) { return a < b; } + + //-------------------------------------------------------unsigned_greater + inline bool unsigned_greater(unsigned a, unsigned b) { return a > b; } +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_arrowhead.h b/jni/desmume/src/android/agg/include/agg_arrowhead.h new file mode 100755 index 0000000..893ebaa --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_arrowhead.h @@ -0,0 +1,88 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_ARROWHEAD_INCLUDED +#define AGG_ARROWHEAD_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //===============================================================arrowhead + // + // See implementation agg_arrowhead.cpp + // + class arrowhead + { + public: + arrowhead(); + + void head(double d1, double d2, double d3, double d4) + { + m_head_d1 = d1; + m_head_d2 = d2; + m_head_d3 = d3; + m_head_d4 = d4; + m_head_flag = true; + } + + void head() { m_head_flag = true; } + void no_head() { m_head_flag = false; } + + void tail(double d1, double d2, double d3, double d4) + { + m_tail_d1 = d1; + m_tail_d2 = d2; + m_tail_d3 = d3; + m_tail_d4 = d4; + m_tail_flag = true; + } + + void tail() { m_tail_flag = true; } + void no_tail() { m_tail_flag = false; } + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + double m_head_d1; + double m_head_d2; + double m_head_d3; + double m_head_d4; + double m_tail_d1; + double m_tail_d2; + double m_tail_d3; + double m_tail_d4; + bool m_head_flag; + bool m_tail_flag; + double m_coord[16]; + unsigned m_cmd[8]; + unsigned m_curr_id; + unsigned m_curr_coord; + }; + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_basics.h b/jni/desmume/src/android/agg/include/agg_basics.h new file mode 100755 index 0000000..4a1b481 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_basics.h @@ -0,0 +1,539 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_BASICS_INCLUDED +#define AGG_BASICS_INCLUDED + +#include <math.h> +#include "agg_config.h" + +//---------------------------------------------------------AGG_CUSTOM_ALLOCATOR +#ifdef AGG_CUSTOM_ALLOCATOR +#include "agg_allocator.h" +#else +namespace agg +{ + // The policy of all AGG containers and memory allocation strategy + // in general is that no allocated data requires explicit construction. + // It means that the allocator can be really simple; you can even + // replace new/delete to malloc/free. The constructors and destructors + // won't be called in this case, however everything will remain working. + // The second argument of deallocate() is the size of the allocated + // block. You can use this information if you wish. + //------------------------------------------------------------pod_allocator + template<class T> struct pod_allocator + { + static T* allocate(unsigned num) { return new T [num]; } + static void deallocate(T* ptr, unsigned) { delete [] ptr; } + }; + + // Single object allocator. It's also can be replaced with your custom + // allocator. The difference is that it can only allocate a single + // object and the constructor and destructor must be called. + // In AGG there is no need to allocate an array of objects with + // calling their constructors (only single ones). So that, if you + // replace these new/delete to malloc/free make sure that the in-place + // new is called and take care of calling the destructor too. + //------------------------------------------------------------obj_allocator + template<class T> struct obj_allocator + { + static T* allocate() { return new T; } + static void deallocate(T* ptr) { delete ptr; } + }; +} +#endif + + +//-------------------------------------------------------- Default basic types +// +// If the compiler has different capacity of the basic types you can redefine +// them via the compiler command line or by generating agg_config.h that is +// empty by default. +// +#ifndef AGG_INT8 +#define AGG_INT8 signed char +#endif + +#ifndef AGG_INT8U +#define AGG_INT8U unsigned char +#endif + +#ifndef AGG_INT16 +#define AGG_INT16 short +#endif + +#ifndef AGG_INT16U +#define AGG_INT16U unsigned short +#endif + +#ifndef AGG_INT32 +#define AGG_INT32 int +#endif + +#ifndef AGG_INT32U +#define AGG_INT32U unsigned +#endif + +#ifndef AGG_INT64 +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define AGG_INT64 signed __int64 +#else +#define AGG_INT64 signed long long +#endif +#endif + +#ifndef AGG_INT64U +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define AGG_INT64U unsigned __int64 +#else +#define AGG_INT64U unsigned long long +#endif +#endif + +//------------------------------------------------ Some fixes for MS Visual C++ +#if defined(_MSC_VER) +#pragma warning(disable:4786) // Identifier was truncated... +#endif + +#if defined(_MSC_VER) +#define AGG_INLINE __forceinline +#else +#define AGG_INLINE inline +#endif + +namespace agg +{ + //------------------------------------------------------------------------- + typedef AGG_INT8 int8; //----int8 + typedef AGG_INT8U int8u; //----int8u + typedef AGG_INT16 int16; //----int16 + typedef AGG_INT16U int16u; //----int16u + typedef AGG_INT32 int32; //----int32 + typedef AGG_INT32U int32u; //----int32u + typedef AGG_INT64 int64; //----int64 + typedef AGG_INT64U int64u; //----int64u + +#if defined(AGG_FISTP) +#pragma warning(push) +#pragma warning(disable : 4035) //Disable warning "no return value" + AGG_INLINE int iround(double v) //-------iround + { + int t; + __asm fld qword ptr [v] + __asm fistp dword ptr [t] + __asm mov eax, dword ptr [t] + } + AGG_INLINE unsigned uround(double v) //-------uround + { + unsigned t; + __asm fld qword ptr [v] + __asm fistp dword ptr [t] + __asm mov eax, dword ptr [t] + } +#pragma warning(pop) + AGG_INLINE unsigned ufloor(double v) //-------ufloor + { + return unsigned(floor(v)); + } + AGG_INLINE unsigned uceil(double v) //--------uceil + { + return unsigned(ceil(v)); + } +#elif defined(AGG_QIFIST) + AGG_INLINE int iround(double v) + { + return int(v); + } + AGG_INLINE int uround(double v) + { + return unsigned(v); + } + AGG_INLINE unsigned ufloor(double v) + { + return unsigned(floor(v)); + } + AGG_INLINE unsigned uceil(double v) + { + return unsigned(ceil(v)); + } +#else + AGG_INLINE int iround(double v) + { + return int((v < 0.0) ? v - 0.5 : v + 0.5); + } + AGG_INLINE int uround(double v) + { + return unsigned(v + 0.5); + } + AGG_INLINE unsigned ufloor(double v) + { + return unsigned(v); + } + AGG_INLINE unsigned uceil(double v) + { + return unsigned(ceil(v)); + } +#endif + + //---------------------------------------------------------------saturation + template<int Limit> struct saturation + { + AGG_INLINE static int iround(double v) + { + if(v < double(-Limit)) return -Limit; + if(v > double( Limit)) return Limit; + return agg::iround(v); + } + }; + + //------------------------------------------------------------------mul_one + template<unsigned Shift> struct mul_one + { + AGG_INLINE static unsigned mul(unsigned a, unsigned b) + { + register unsigned q = a * b + (1 << (Shift-1)); + return (q + (q >> Shift)) >> Shift; + } + }; + + //------------------------------------------------------------------------- + typedef unsigned char cover_type; //----cover_type + enum cover_scale_e + { + cover_shift = 8, //----cover_shift + cover_size = 1 << cover_shift, //----cover_size + cover_mask = cover_size - 1, //----cover_mask + cover_none = 0, //----cover_none + cover_full = cover_mask //----cover_full + }; + + //----------------------------------------------------poly_subpixel_scale_e + // These constants determine the subpixel accuracy, to be more precise, + // the number of bits of the fractional part of the coordinates. + // The possible coordinate capacity in bits can be calculated by formula: + // sizeof(int) * 8 - poly_subpixel_shift, i.e, for 32-bit integers and + // 8-bits fractional part the capacity is 24 bits. + enum poly_subpixel_scale_e + { + poly_subpixel_shift = 8, //----poly_subpixel_shift + poly_subpixel_scale = 1<<poly_subpixel_shift, //----poly_subpixel_scale + poly_subpixel_mask = poly_subpixel_scale-1, //----poly_subpixel_mask + }; + + //----------------------------------------------------------filling_rule_e + enum filling_rule_e + { + fill_non_zero, + fill_even_odd + }; + + //-----------------------------------------------------------------------pi + const double pi = 3.14159265358979323846; + + //------------------------------------------------------------------deg2rad + inline double deg2rad(double deg) + { + return deg * pi / 180.0; + } + + //------------------------------------------------------------------rad2deg + inline double rad2deg(double rad) + { + return rad * 180.0 / pi; + } + + //----------------------------------------------------------------rect_base + template<class T> struct rect_base + { + typedef T value_type; + typedef rect_base<T> self_type; + T x1, y1, x2, y2; + + rect_base() {} + rect_base(T x1_, T y1_, T x2_, T y2_) : + x1(x1_), y1(y1_), x2(x2_), y2(y2_) {} + + void init(T x1_, T y1_, T x2_, T y2_) + { + x1 = x1_; y1 = y1_; x2 = x2_; y2 = y2_; + } + + const self_type& normalize() + { + T t; + if(x1 > x2) { t = x1; x1 = x2; x2 = t; } + if(y1 > y2) { t = y1; y1 = y2; y2 = t; } + return *this; + } + + bool clip(const self_type& r) + { + if(x2 > r.x2) x2 = r.x2; + if(y2 > r.y2) y2 = r.y2; + if(x1 < r.x1) x1 = r.x1; + if(y1 < r.y1) y1 = r.y1; + return x1 <= x2 && y1 <= y2; + } + + bool is_valid() const + { + return x1 <= x2 && y1 <= y2; + } + + bool hit_test(T x, T y) const + { + return (x >= x1 && x <= x2 && y >= y1 && y <= y2); + } + }; + + //-----------------------------------------------------intersect_rectangles + template<class Rect> + inline Rect intersect_rectangles(const Rect& r1, const Rect& r2) + { + Rect r = r1; + + // First process x2,y2 because the other order + // results in Internal Compiler Error under + // Microsoft Visual C++ .NET 2003 69462-335-0000007-18038 in + // case of "Maximize Speed" optimization option. + //----------------- + if(r.x2 > r2.x2) r.x2 = r2.x2; + if(r.y2 > r2.y2) r.y2 = r2.y2; + if(r.x1 < r2.x1) r.x1 = r2.x1; + if(r.y1 < r2.y1) r.y1 = r2.y1; + return r; + } + + + //---------------------------------------------------------unite_rectangles + template<class Rect> + inline Rect unite_rectangles(const Rect& r1, const Rect& r2) + { + Rect r = r1; + if(r.x2 < r2.x2) r.x2 = r2.x2; + if(r.y2 < r2.y2) r.y2 = r2.y2; + if(r.x1 > r2.x1) r.x1 = r2.x1; + if(r.y1 > r2.y1) r.y1 = r2.y1; + return r; + } + + typedef rect_base<int> rect_i; //----rect_i + typedef rect_base<float> rect_f; //----rect_f + typedef rect_base<double> rect_d; //----rect_d + + //---------------------------------------------------------path_commands_e + enum path_commands_e + { + path_cmd_stop = 0, //----path_cmd_stop + path_cmd_move_to = 1, //----path_cmd_move_to + path_cmd_line_to = 2, //----path_cmd_line_to + path_cmd_curve3 = 3, //----path_cmd_curve3 + path_cmd_curve4 = 4, //----path_cmd_curve4 + path_cmd_curveN = 5, //----path_cmd_curveN + path_cmd_catrom = 6, //----path_cmd_catrom + path_cmd_ubspline = 7, //----path_cmd_ubspline + path_cmd_end_poly = 0x0F, //----path_cmd_end_poly + path_cmd_mask = 0x0F //----path_cmd_mask + }; + + //------------------------------------------------------------path_flags_e + enum path_flags_e + { + path_flags_none = 0, //----path_flags_none + path_flags_ccw = 0x10, //----path_flags_ccw + path_flags_cw = 0x20, //----path_flags_cw + path_flags_close = 0x40, //----path_flags_close + path_flags_mask = 0xF0 //----path_flags_mask + }; + + //---------------------------------------------------------------is_vertex + inline bool is_vertex(unsigned c) + { + return c >= path_cmd_move_to && c < path_cmd_end_poly; + } + + //--------------------------------------------------------------is_drawing + inline bool is_drawing(unsigned c) + { + return c >= path_cmd_line_to && c < path_cmd_end_poly; + } + + //-----------------------------------------------------------------is_stop + inline bool is_stop(unsigned c) + { + return c == path_cmd_stop; + } + + //--------------------------------------------------------------is_move_to + inline bool is_move_to(unsigned c) + { + return c == path_cmd_move_to; + } + + //--------------------------------------------------------------is_line_to + inline bool is_line_to(unsigned c) + { + return c == path_cmd_line_to; + } + + //----------------------------------------------------------------is_curve + inline bool is_curve(unsigned c) + { + return c == path_cmd_curve3 || c == path_cmd_curve4; + } + + //---------------------------------------------------------------is_curve3 + inline bool is_curve3(unsigned c) + { + return c == path_cmd_curve3; + } + + //---------------------------------------------------------------is_curve4 + inline bool is_curve4(unsigned c) + { + return c == path_cmd_curve4; + } + + //-------------------------------------------------------------is_end_poly + inline bool is_end_poly(unsigned c) + { + return (c & path_cmd_mask) == path_cmd_end_poly; + } + + //----------------------------------------------------------------is_close + inline bool is_close(unsigned c) + { + return (c & ~(path_flags_cw | path_flags_ccw)) == + (path_cmd_end_poly | path_flags_close); + } + + //------------------------------------------------------------is_next_poly + inline bool is_next_poly(unsigned c) + { + return is_stop(c) || is_move_to(c) || is_end_poly(c); + } + + //-------------------------------------------------------------------is_cw + inline bool is_cw(unsigned c) + { + return (c & path_flags_cw) != 0; + } + + //------------------------------------------------------------------is_ccw + inline bool is_ccw(unsigned c) + { + return (c & path_flags_ccw) != 0; + } + + //-------------------------------------------------------------is_oriented + inline bool is_oriented(unsigned c) + { + return (c & (path_flags_cw | path_flags_ccw)) != 0; + } + + //---------------------------------------------------------------is_closed + inline bool is_closed(unsigned c) + { + return (c & path_flags_close) != 0; + } + + //----------------------------------------------------------get_close_flag + inline unsigned get_close_flag(unsigned c) + { + return c & path_flags_close; + } + + //-------------------------------------------------------clear_orientation + inline unsigned clear_orientation(unsigned c) + { + return c & ~(path_flags_cw | path_flags_ccw); + } + + //---------------------------------------------------------get_orientation + inline unsigned get_orientation(unsigned c) + { + return c & (path_flags_cw | path_flags_ccw); + } + + //---------------------------------------------------------set_orientation + inline unsigned set_orientation(unsigned c, unsigned o) + { + return clear_orientation(c) | o; + } + + //--------------------------------------------------------------point_base + template<class T> struct point_base + { + typedef T value_type; + T x,y; + point_base() {} + point_base(T x_, T y_) : x(x_), y(y_) {} + }; + typedef point_base<int> point_i; //-----point_i + typedef point_base<float> point_f; //-----point_f + typedef point_base<double> point_d; //-----point_d + + //-------------------------------------------------------------vertex_base + template<class T> struct vertex_base + { + typedef T value_type; + T x,y; + unsigned cmd; + vertex_base() {} + vertex_base(T x_, T y_, unsigned cmd_) : x(x_), y(y_), cmd(cmd_) {} + }; + typedef vertex_base<int> vertex_i; //-----vertex_i + typedef vertex_base<float> vertex_f; //-----vertex_f + typedef vertex_base<double> vertex_d; //-----vertex_d + + //----------------------------------------------------------------row_info + template<class T> struct row_info + { + int x1, x2; + T* ptr; + row_info() {} + row_info(int x1_, int x2_, T* ptr_) : x1(x1_), x2(x2_), ptr(ptr_) {} + }; + + //----------------------------------------------------------const_row_info + template<class T> struct const_row_info + { + int x1, x2; + const T* ptr; + const_row_info() {} + const_row_info(int x1_, int x2_, const T* ptr_) : + x1(x1_), x2(x2_), ptr(ptr_) {} + }; + + //------------------------------------------------------------is_equal_eps + template<class T> inline bool is_equal_eps(T v1, T v2, T epsilon) + { + return fabs(v1 - v2) <= double(epsilon); + } + +} + + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_bezier_arc.h b/jni/desmume/src/android/agg/include/agg_bezier_arc.h new file mode 100755 index 0000000..a6f2b22 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_bezier_arc.h @@ -0,0 +1,163 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_BEZIER_ARC_INCLUDED +#define AGG_BEZIER_ARC_INCLUDED + +#include "agg_conv_transform.h" + +namespace agg +{ + + //----------------------------------------------------------------------- + void arc_to_bezier(double cx, double cy, double rx, double ry, + double start_angle, double sweep_angle, + double* curve); + + + //==============================================================bezier_arc + // + // See implemantaion agg_bezier_arc.cpp + // + class bezier_arc + { + public: + //-------------------------------------------------------------------- + bezier_arc() : m_vertex(26), m_num_vertices(0), m_cmd(path_cmd_line_to) {} + bezier_arc(double x, double y, + double rx, double ry, + double start_angle, + double sweep_angle) + { + init(x, y, rx, ry, start_angle, sweep_angle); + } + + //-------------------------------------------------------------------- + void init(double x, double y, + double rx, double ry, + double start_angle, + double sweep_angle); + + //-------------------------------------------------------------------- + void rewind(unsigned) + { + m_vertex = 0; + } + + //-------------------------------------------------------------------- + unsigned vertex(double* x, double* y) + { + if(m_vertex >= m_num_vertices) return path_cmd_stop; + *x = m_vertices[m_vertex]; + *y = m_vertices[m_vertex + 1]; + m_vertex += 2; + return (m_vertex == 2) ? path_cmd_move_to : m_cmd; + } + + // Supplemantary functions. num_vertices() actually returns doubled + // number of vertices. That is, for 1 vertex it returns 2. + //-------------------------------------------------------------------- + unsigned num_vertices() const { return m_num_vertices; } + const double* vertices() const { return m_vertices; } + double* vertices() { return m_vertices; } + + private: + unsigned m_vertex; + unsigned m_num_vertices; + double m_vertices[26]; + unsigned m_cmd; + }; + + + + //==========================================================bezier_arc_svg + // Compute an SVG-style bezier arc. + // + // Computes an elliptical arc from (x1, y1) to (x2, y2). The size and + // orientation of the ellipse are defined by two radii (rx, ry) + // and an x-axis-rotation, which indicates how the ellipse as a whole + // is rotated relative to the current coordinate system. The center + // (cx, cy) of the ellipse is calculated automatically to satisfy the + // constraints imposed by the other parameters. + // large-arc-flag and sweep-flag contribute to the automatic calculations + // and help determine how the arc is drawn. + class bezier_arc_svg + { + public: + //-------------------------------------------------------------------- + bezier_arc_svg() : m_arc(), m_radii_ok(false) {} + + bezier_arc_svg(double x1, double y1, + double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double x2, double y2) : + m_arc(), m_radii_ok(false) + { + init(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2); + } + + //-------------------------------------------------------------------- + void init(double x1, double y1, + double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double x2, double y2); + + //-------------------------------------------------------------------- + bool radii_ok() const { return m_radii_ok; } + + //-------------------------------------------------------------------- + void rewind(unsigned) + { + m_arc.rewind(0); + } + + //-------------------------------------------------------------------- + unsigned vertex(double* x, double* y) + { + return m_arc.vertex(x, y); + } + + // Supplemantary functions. num_vertices() actually returns doubled + // number of vertices. That is, for 1 vertex it returns 2. + //-------------------------------------------------------------------- + unsigned num_vertices() const { return m_arc.num_vertices(); } + const double* vertices() const { return m_arc.vertices(); } + double* vertices() { return m_arc.vertices(); } + + private: + bezier_arc m_arc; + bool m_radii_ok; + }; + + + + +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_bitset_iterator.h b/jni/desmume/src/android/agg/include/agg_bitset_iterator.h new file mode 100755 index 0000000..7d59092 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_bitset_iterator.h @@ -0,0 +1,63 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_BITSET_ITERATOR_INCLUDED +#define AGG_BITSET_ITERATOR_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + class bitset_iterator + { + public: + bitset_iterator(const int8u* bits, unsigned offset = 0) : + m_bits(bits + (offset >> 3)), + m_mask(0x80 >> (offset & 7)) + {} + + void operator ++ () + { + m_mask >>= 1; + if(m_mask == 0) + { + ++m_bits; + m_mask = 0x80; + } + } + + unsigned bit() const + { + return (*m_bits) & m_mask; + } + + private: + const int8u* m_bits; + int8u m_mask; + }; + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_blur.h b/jni/desmume/src/android/agg/include/agg_blur.h new file mode 100755 index 0000000..3efd54f --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_blur.h @@ -0,0 +1,1303 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// The Stack Blur Algorithm was invented by Mario Klingemann, +// mario@quasimondo.com and described here: +// http://incubator.quasimondo.com/processing/fast_blur_deluxe.php +// (search phrase "Stackblur: Fast But Goodlooking"). +// The major improvement is that there's no more division table +// that was very expensive to create for large blur radii. Insted, +// for 8-bit per channel and radius not exceeding 254 the division is +// replaced by multiplication and shift. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_BLUR_INCLUDED +#define AGG_BLUR_INCLUDED + +#include "agg_array.h" +#include "agg_pixfmt_transposer.h" + +namespace agg +{ + + template<class T> struct stack_blur_tables + { + static int16u const g_stack_blur8_mul[255]; + static int8u const g_stack_blur8_shr[255]; + }; + + //------------------------------------------------------------------------ + template<class T> + int16u const stack_blur_tables<T>::g_stack_blur8_mul[255] = + { + 512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512, + 454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512, + 482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456, + 437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512, + 497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328, + 320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456, + 446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335, + 329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512, + 505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405, + 399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328, + 324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271, + 268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456, + 451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388, + 385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335, + 332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292, + 289,287,285,282,280,278,275,273,271,269,267,265,263,261,259 + }; + + //------------------------------------------------------------------------ + template<class T> + int8u const stack_blur_tables<T>::g_stack_blur8_shr[255] = + { + 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, + 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 + }; + + + + //==============================================================stack_blur + template<class ColorT, class CalculatorT> class stack_blur + { + public: + typedef ColorT color_type; + typedef CalculatorT calculator_type; + + //-------------------------------------------------------------------- + template<class Img> void blur_x(Img& img, unsigned radius) + { + if(radius < 1) return; + + unsigned x, y, xp, i; + unsigned stack_ptr; + unsigned stack_start; + + color_type pix; + color_type* stack_pix; + calculator_type sum; + calculator_type sum_in; + calculator_type sum_out; + + unsigned w = img.width(); + unsigned h = img.height(); + unsigned wm = w - 1; + unsigned div = radius * 2 + 1; + + unsigned div_sum = (radius + 1) * (radius + 1); + unsigned mul_sum = 0; + unsigned shr_sum = 0; + unsigned max_val = color_type::base_mask; + + if(max_val <= 255 && radius < 255) + { + mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[radius]; + shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[radius]; + } + + m_buf.allocate(w, 128); + m_stack.allocate(div, 32); + + for(y = 0; y < h; y++) + { + sum.clear(); + sum_in.clear(); + sum_out.clear(); + + pix = img.pixel(0, y); + for(i = 0; i <= radius; i++) + { + m_stack[i] = pix; + sum.add(pix, i + 1); + sum_out.add(pix); + } + for(i = 1; i <= radius; i++) + { + pix = img.pixel((i > wm) ? wm : i, y); + m_stack[i + radius] = pix; + sum.add(pix, radius + 1 - i); + sum_in.add(pix); + } + + stack_ptr = radius; + for(x = 0; x < w; x++) + { + if(mul_sum) sum.calc_pix(m_buf[x], mul_sum, shr_sum); + else sum.calc_pix(m_buf[x], div_sum); + + sum.sub(sum_out); + + stack_start = stack_ptr + div - radius; + if(stack_start >= div) stack_start -= div; + stack_pix = &m_stack[stack_start]; + + sum_out.sub(*stack_pix); + + xp = x + radius + 1; + if(xp > wm) xp = wm; + pix = img.pixel(xp, y); + + *stack_pix = pix; + + sum_in.add(pix); + sum.add(sum_in); + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix = &m_stack[stack_ptr]; + + sum_out.add(*stack_pix); + sum_in.sub(*stack_pix); + } + img.copy_color_hspan(0, y, w, &m_buf[0]); + } + } + + //-------------------------------------------------------------------- + template<class Img> void blur_y(Img& img, unsigned radius) + { + pixfmt_transposer<Img> img2(img); + blur_x(img2, radius); + } + + //-------------------------------------------------------------------- + template<class Img> void blur(Img& img, unsigned radius) + { + blur_x(img, radius); + pixfmt_transposer<Img> img2(img); + blur_x(img2, radius); + } + + private: + pod_vector<color_type> m_buf; + pod_vector<color_type> m_stack; + }; + + //====================================================stack_blur_calc_rgba + template<class T=unsigned> struct stack_blur_calc_rgba + { + typedef T value_type; + value_type r,g,b,a; + + AGG_INLINE void clear() + { + r = g = b = a = 0; + } + + template<class ArgT> AGG_INLINE void add(const ArgT& v) + { + r += v.r; + g += v.g; + b += v.b; + a += v.a; + } + + template<class ArgT> AGG_INLINE void add(const ArgT& v, unsigned k) + { + r += v.r * k; + g += v.g * k; + b += v.b * k; + a += v.a * k; + } + + template<class ArgT> AGG_INLINE void sub(const ArgT& v) + { + r -= v.r; + g -= v.g; + b -= v.b; + a -= v.a; + } + + template<class ArgT> AGG_INLINE void calc_pix(ArgT& v, unsigned div) + { + typedef typename ArgT::value_type value_type; + v.r = value_type(r / div); + v.g = value_type(g / div); + v.b = value_type(b / div); + v.a = value_type(a / div); + } + + template<class ArgT> + AGG_INLINE void calc_pix(ArgT& v, unsigned mul, unsigned shr) + { + typedef typename ArgT::value_type value_type; + v.r = value_type((r * mul) >> shr); + v.g = value_type((g * mul) >> shr); + v.b = value_type((b * mul) >> shr); + v.a = value_type((a * mul) >> shr); + } + }; + + + //=====================================================stack_blur_calc_rgb + template<class T=unsigned> struct stack_blur_calc_rgb + { + typedef T value_type; + value_type r,g,b; + + AGG_INLINE void clear() + { + r = g = b = 0; + } + + template<class ArgT> AGG_INLINE void add(const ArgT& v) + { + r += v.r; + g += v.g; + b += v.b; + } + + template<class ArgT> AGG_INLINE void add(const ArgT& v, unsigned k) + { + r += v.r * k; + g += v.g * k; + b += v.b * k; + } + + template<class ArgT> AGG_INLINE void sub(const ArgT& v) + { + r -= v.r; + g -= v.g; + b -= v.b; + } + + template<class ArgT> AGG_INLINE void calc_pix(ArgT& v, unsigned div) + { + typedef typename ArgT::value_type value_type; + v.r = value_type(r / div); + v.g = value_type(g / div); + v.b = value_type(b / div); + } + + template<class ArgT> + AGG_INLINE void calc_pix(ArgT& v, unsigned mul, unsigned shr) + { + typedef typename ArgT::value_type value_type; + v.r = value_type((r * mul) >> shr); + v.g = value_type((g * mul) >> shr); + v.b = value_type((b * mul) >> shr); + } + }; + + + //====================================================stack_blur_calc_gray + template<class T=unsigned> struct stack_blur_calc_gray + { + typedef T value_type; + value_type v; + + AGG_INLINE void clear() + { + v = 0; + } + + template<class ArgT> AGG_INLINE void add(const ArgT& a) + { + v += a.v; + } + + template<class ArgT> AGG_INLINE void add(const ArgT& a, unsigned k) + { + v += a.v * k; + } + + template<class ArgT> AGG_INLINE void sub(const ArgT& a) + { + v -= a.v; + } + + template<class ArgT> AGG_INLINE void calc_pix(ArgT& a, unsigned div) + { + typedef typename ArgT::value_type value_type; + a.v = value_type(v / div); + } + + template<class ArgT> + AGG_INLINE void calc_pix(ArgT& a, unsigned mul, unsigned shr) + { + typedef typename ArgT::value_type value_type; + a.v = value_type((v * mul) >> shr); + } + }; + + + + //========================================================stack_blur_gray8 + template<class Img> + void stack_blur_gray8(Img& img, unsigned rx, unsigned ry) + { + unsigned x, y, xp, yp, i; + unsigned stack_ptr; + unsigned stack_start; + + const int8u* src_pix_ptr; + int8u* dst_pix_ptr; + unsigned pix; + unsigned stack_pix; + unsigned sum; + unsigned sum_in; + unsigned sum_out; + + unsigned w = img.width(); + unsigned h = img.height(); + unsigned wm = w - 1; + unsigned hm = h - 1; + + unsigned div; + unsigned mul_sum; + unsigned shr_sum; + + pod_vector<int8u> stack; + + if(rx > 0) + { + if(rx > 254) rx = 254; + div = rx * 2 + 1; + mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[rx]; + shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[rx]; + stack.allocate(div); + + for(y = 0; y < h; y++) + { + sum = sum_in = sum_out = 0; + + src_pix_ptr = img.pix_ptr(0, y); + pix = *src_pix_ptr; + for(i = 0; i <= rx; i++) + { + stack[i] = pix; + sum += pix * (i + 1); + sum_out += pix; + } + for(i = 1; i <= rx; i++) + { + if(i <= wm) src_pix_ptr += Img::pix_step; + pix = *src_pix_ptr; + stack[i + rx] = pix; + sum += pix * (rx + 1 - i); + sum_in += pix; + } + + stack_ptr = rx; + xp = rx; + if(xp > wm) xp = wm; + src_pix_ptr = img.pix_ptr(xp, y); + dst_pix_ptr = img.pix_ptr(0, y); + for(x = 0; x < w; x++) + { + *dst_pix_ptr = (sum * mul_sum) >> shr_sum; + dst_pix_ptr += Img::pix_step; + + sum -= sum_out; + + stack_start = stack_ptr + div - rx; + if(stack_start >= div) stack_start -= div; + sum_out -= stack[stack_start]; + + if(xp < wm) + { + src_pix_ptr += Img::pix_step; + pix = *src_pix_ptr; + ++xp; + } + + stack[stack_start] = pix; + + sum_in += pix; + sum += sum_in; + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix = stack[stack_ptr]; + + sum_out += stack_pix; + sum_in -= stack_pix; + } + } + } + + if(ry > 0) + { + if(ry > 254) ry = 254; + div = ry * 2 + 1; + mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[ry]; + shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[ry]; + stack.allocate(div); + + int stride = img.stride(); + for(x = 0; x < w; x++) + { + sum = sum_in = sum_out = 0; + + src_pix_ptr = img.pix_ptr(x, 0); + pix = *src_pix_ptr; + for(i = 0; i <= ry; i++) + { + stack[i] = pix; + sum += pix * (i + 1); + sum_out += pix; + } + for(i = 1; i <= ry; i++) + { + if(i <= hm) src_pix_ptr += stride; + pix = *src_pix_ptr; + stack[i + ry] = pix; + sum += pix * (ry + 1 - i); + sum_in += pix; + } + + stack_ptr = ry; + yp = ry; + if(yp > hm) yp = hm; + src_pix_ptr = img.pix_ptr(x, yp); + dst_pix_ptr = img.pix_ptr(x, 0); + for(y = 0; y < h; y++) + { + *dst_pix_ptr = (sum * mul_sum) >> shr_sum; + dst_pix_ptr += stride; + + sum -= sum_out; + + stack_start = stack_ptr + div - ry; + if(stack_start >= div) stack_start -= div; + sum_out -= stack[stack_start]; + + if(yp < hm) + { + src_pix_ptr += stride; + pix = *src_pix_ptr; + ++yp; + } + + stack[stack_start] = pix; + + sum_in += pix; + sum += sum_in; + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix = stack[stack_ptr]; + + sum_out += stack_pix; + sum_in -= stack_pix; + } + } + } + } + + + + //========================================================stack_blur_rgb24 + template<class Img> + void stack_blur_rgb24(Img& img, unsigned rx, unsigned ry) + { + typedef typename Img::color_type color_type; + typedef typename Img::order_type order_type; + enum order_e + { + R = order_type::R, + G = order_type::G, + B = order_type::B + }; + + unsigned x, y, xp, yp, i; + unsigned stack_ptr; + unsigned stack_start; + + const int8u* src_pix_ptr; + int8u* dst_pix_ptr; + color_type* stack_pix_ptr; + + unsigned sum_r; + unsigned sum_g; + unsigned sum_b; + unsigned sum_in_r; + unsigned sum_in_g; + unsigned sum_in_b; + unsigned sum_out_r; + unsigned sum_out_g; + unsigned sum_out_b; + + unsigned w = img.width(); + unsigned h = img.height(); + unsigned wm = w - 1; + unsigned hm = h - 1; + + unsigned div; + unsigned mul_sum; + unsigned shr_sum; + + pod_vector<color_type> stack; + + if(rx > 0) + { + if(rx > 254) rx = 254; + div = rx * 2 + 1; + mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[rx]; + shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[rx]; + stack.allocate(div); + + for(y = 0; y < h; y++) + { + sum_r = + sum_g = + sum_b = + sum_in_r = + sum_in_g = + sum_in_b = + sum_out_r = + sum_out_g = + sum_out_b = 0; + + src_pix_ptr = img.pix_ptr(0, y); + for(i = 0; i <= rx; i++) + { + stack_pix_ptr = &stack[i]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + sum_r += src_pix_ptr[R] * (i + 1); + sum_g += src_pix_ptr[G] * (i + 1); + sum_b += src_pix_ptr[B] * (i + 1); + sum_out_r += src_pix_ptr[R]; + sum_out_g += src_pix_ptr[G]; + sum_out_b += src_pix_ptr[B]; + } + for(i = 1; i <= rx; i++) + { + if(i <= wm) src_pix_ptr += Img::pix_width; + stack_pix_ptr = &stack[i + rx]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + sum_r += src_pix_ptr[R] * (rx + 1 - i); + sum_g += src_pix_ptr[G] * (rx + 1 - i); + sum_b += src_pix_ptr[B] * (rx + 1 - i); + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + } + + stack_ptr = rx; + xp = rx; + if(xp > wm) xp = wm; + src_pix_ptr = img.pix_ptr(xp, y); + dst_pix_ptr = img.pix_ptr(0, y); + for(x = 0; x < w; x++) + { + dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; + dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; + dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; + dst_pix_ptr += Img::pix_width; + + sum_r -= sum_out_r; + sum_g -= sum_out_g; + sum_b -= sum_out_b; + + stack_start = stack_ptr + div - rx; + if(stack_start >= div) stack_start -= div; + stack_pix_ptr = &stack[stack_start]; + + sum_out_r -= stack_pix_ptr->r; + sum_out_g -= stack_pix_ptr->g; + sum_out_b -= stack_pix_ptr->b; + + if(xp < wm) + { + src_pix_ptr += Img::pix_width; + ++xp; + } + + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + sum_r += sum_in_r; + sum_g += sum_in_g; + sum_b += sum_in_b; + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix_ptr = &stack[stack_ptr]; + + sum_out_r += stack_pix_ptr->r; + sum_out_g += stack_pix_ptr->g; + sum_out_b += stack_pix_ptr->b; + sum_in_r -= stack_pix_ptr->r; + sum_in_g -= stack_pix_ptr->g; + sum_in_b -= stack_pix_ptr->b; + } + } + } + + if(ry > 0) + { + if(ry > 254) ry = 254; + div = ry * 2 + 1; + mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[ry]; + shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[ry]; + stack.allocate(div); + + int stride = img.stride(); + for(x = 0; x < w; x++) + { + sum_r = + sum_g = + sum_b = + sum_in_r = + sum_in_g = + sum_in_b = + sum_out_r = + sum_out_g = + sum_out_b = 0; + + src_pix_ptr = img.pix_ptr(x, 0); + for(i = 0; i <= ry; i++) + { + stack_pix_ptr = &stack[i]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + sum_r += src_pix_ptr[R] * (i + 1); + sum_g += src_pix_ptr[G] * (i + 1); + sum_b += src_pix_ptr[B] * (i + 1); + sum_out_r += src_pix_ptr[R]; + sum_out_g += src_pix_ptr[G]; + sum_out_b += src_pix_ptr[B]; + } + for(i = 1; i <= ry; i++) + { + if(i <= hm) src_pix_ptr += stride; + stack_pix_ptr = &stack[i + ry]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + sum_r += src_pix_ptr[R] * (ry + 1 - i); + sum_g += src_pix_ptr[G] * (ry + 1 - i); + sum_b += src_pix_ptr[B] * (ry + 1 - i); + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + } + + stack_ptr = ry; + yp = ry; + if(yp > hm) yp = hm; + src_pix_ptr = img.pix_ptr(x, yp); + dst_pix_ptr = img.pix_ptr(x, 0); + for(y = 0; y < h; y++) + { + dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; + dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; + dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; + dst_pix_ptr += stride; + + sum_r -= sum_out_r; + sum_g -= sum_out_g; + sum_b -= sum_out_b; + + stack_start = stack_ptr + div - ry; + if(stack_start >= div) stack_start -= div; + + stack_pix_ptr = &stack[stack_start]; + sum_out_r -= stack_pix_ptr->r; + sum_out_g -= stack_pix_ptr->g; + sum_out_b -= stack_pix_ptr->b; + + if(yp < hm) + { + src_pix_ptr += stride; + ++yp; + } + + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + sum_r += sum_in_r; + sum_g += sum_in_g; + sum_b += sum_in_b; + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix_ptr = &stack[stack_ptr]; + + sum_out_r += stack_pix_ptr->r; + sum_out_g += stack_pix_ptr->g; + sum_out_b += stack_pix_ptr->b; + sum_in_r -= stack_pix_ptr->r; + sum_in_g -= stack_pix_ptr->g; + sum_in_b -= stack_pix_ptr->b; + } + } + } + } + + + + //=======================================================stack_blur_rgba32 + template<class Img> + void stack_blur_rgba32(Img& img, unsigned rx, unsigned ry) + { + typedef typename Img::color_type color_type; + typedef typename Img::order_type order_type; + enum order_e + { + R = order_type::R, + G = order_type::G, + B = order_type::B, + A = order_type::A + }; + + unsigned x, y, xp, yp, i; + unsigned stack_ptr; + unsigned stack_start; + + const int8u* src_pix_ptr; + int8u* dst_pix_ptr; + color_type* stack_pix_ptr; + + unsigned sum_r; + unsigned sum_g; + unsigned sum_b; + unsigned sum_a; + unsigned sum_in_r; + unsigned sum_in_g; + unsigned sum_in_b; + unsigned sum_in_a; + unsigned sum_out_r; + unsigned sum_out_g; + unsigned sum_out_b; + unsigned sum_out_a; + + unsigned w = img.width(); + unsigned h = img.height(); + unsigned wm = w - 1; + unsigned hm = h - 1; + + unsigned div; + unsigned mul_sum; + unsigned shr_sum; + + pod_vector<color_type> stack; + + if(rx > 0) + { + if(rx > 254) rx = 254; + div = rx * 2 + 1; + mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[rx]; + shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[rx]; + stack.allocate(div); + + for(y = 0; y < h; y++) + { + sum_r = + sum_g = + sum_b = + sum_a = + sum_in_r = + sum_in_g = + sum_in_b = + sum_in_a = + sum_out_r = + sum_out_g = + sum_out_b = + sum_out_a = 0; + + src_pix_ptr = img.pix_ptr(0, y); + for(i = 0; i <= rx; i++) + { + stack_pix_ptr = &stack[i]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + stack_pix_ptr->a = src_pix_ptr[A]; + sum_r += src_pix_ptr[R] * (i + 1); + sum_g += src_pix_ptr[G] * (i + 1); + sum_b += src_pix_ptr[B] * (i + 1); + sum_a += src_pix_ptr[A] * (i + 1); + sum_out_r += src_pix_ptr[R]; + sum_out_g += src_pix_ptr[G]; + sum_out_b += src_pix_ptr[B]; + sum_out_a += src_pix_ptr[A]; + } + for(i = 1; i <= rx; i++) + { + if(i <= wm) src_pix_ptr += Img::pix_width; + stack_pix_ptr = &stack[i + rx]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + stack_pix_ptr->a = src_pix_ptr[A]; + sum_r += src_pix_ptr[R] * (rx + 1 - i); + sum_g += src_pix_ptr[G] * (rx + 1 - i); + sum_b += src_pix_ptr[B] * (rx + 1 - i); + sum_a += src_pix_ptr[A] * (rx + 1 - i); + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + sum_in_a += src_pix_ptr[A]; + } + + stack_ptr = rx; + xp = rx; + if(xp > wm) xp = wm; + src_pix_ptr = img.pix_ptr(xp, y); + dst_pix_ptr = img.pix_ptr(0, y); + for(x = 0; x < w; x++) + { + dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; + dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; + dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; + dst_pix_ptr[A] = (sum_a * mul_sum) >> shr_sum; + dst_pix_ptr += Img::pix_width; + + sum_r -= sum_out_r; + sum_g -= sum_out_g; + sum_b -= sum_out_b; + sum_a -= sum_out_a; + + stack_start = stack_ptr + div - rx; + if(stack_start >= div) stack_start -= div; + stack_pix_ptr = &stack[stack_start]; + + sum_out_r -= stack_pix_ptr->r; + sum_out_g -= stack_pix_ptr->g; + sum_out_b -= stack_pix_ptr->b; + sum_out_a -= stack_pix_ptr->a; + + if(xp < wm) + { + src_pix_ptr += Img::pix_width; + ++xp; + } + + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + stack_pix_ptr->a = src_pix_ptr[A]; + + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + sum_in_a += src_pix_ptr[A]; + sum_r += sum_in_r; + sum_g += sum_in_g; + sum_b += sum_in_b; + sum_a += sum_in_a; + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix_ptr = &stack[stack_ptr]; + + sum_out_r += stack_pix_ptr->r; + sum_out_g += stack_pix_ptr->g; + sum_out_b += stack_pix_ptr->b; + sum_out_a += stack_pix_ptr->a; + sum_in_r -= stack_pix_ptr->r; + sum_in_g -= stack_pix_ptr->g; + sum_in_b -= stack_pix_ptr->b; + sum_in_a -= stack_pix_ptr->a; + } + } + } + + if(ry > 0) + { + if(ry > 254) ry = 254; + div = ry * 2 + 1; + mul_sum = stack_blur_tables<int>::g_stack_blur8_mul[ry]; + shr_sum = stack_blur_tables<int>::g_stack_blur8_shr[ry]; + stack.allocate(div); + + int stride = img.stride(); + for(x = 0; x < w; x++) + { + sum_r = + sum_g = + sum_b = + sum_a = + sum_in_r = + sum_in_g = + sum_in_b = + sum_in_a = + sum_out_r = + sum_out_g = + sum_out_b = + sum_out_a = 0; + + src_pix_ptr = img.pix_ptr(x, 0); + for(i = 0; i <= ry; i++) + { + stack_pix_ptr = &stack[i]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + stack_pix_ptr->a = src_pix_ptr[A]; + sum_r += src_pix_ptr[R] * (i + 1); + sum_g += src_pix_ptr[G] * (i + 1); + sum_b += src_pix_ptr[B] * (i + 1); + sum_a += src_pix_ptr[A] * (i + 1); + sum_out_r += src_pix_ptr[R]; + sum_out_g += src_pix_ptr[G]; + sum_out_b += src_pix_ptr[B]; + sum_out_a += src_pix_ptr[A]; + } + for(i = 1; i <= ry; i++) + { + if(i <= hm) src_pix_ptr += stride; + stack_pix_ptr = &stack[i + ry]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + stack_pix_ptr->a = src_pix_ptr[A]; + sum_r += src_pix_ptr[R] * (ry + 1 - i); + sum_g += src_pix_ptr[G] * (ry + 1 - i); + sum_b += src_pix_ptr[B] * (ry + 1 - i); + sum_a += src_pix_ptr[A] * (ry + 1 - i); + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + sum_in_a += src_pix_ptr[A]; + } + + stack_ptr = ry; + yp = ry; + if(yp > hm) yp = hm; + src_pix_ptr = img.pix_ptr(x, yp); + dst_pix_ptr = img.pix_ptr(x, 0); + for(y = 0; y < h; y++) + { + dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; + dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; + dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; + dst_pix_ptr[A] = (sum_a * mul_sum) >> shr_sum; + dst_pix_ptr += stride; + + sum_r -= sum_out_r; + sum_g -= sum_out_g; + sum_b -= sum_out_b; + sum_a -= sum_out_a; + + stack_start = stack_ptr + div - ry; + if(stack_start >= div) stack_start -= div; + + stack_pix_ptr = &stack[stack_start]; + sum_out_r -= stack_pix_ptr->r; + sum_out_g -= stack_pix_ptr->g; + sum_out_b -= stack_pix_ptr->b; + sum_out_a -= stack_pix_ptr->a; + + if(yp < hm) + { + src_pix_ptr += stride; + ++yp; + } + + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + stack_pix_ptr->a = src_pix_ptr[A]; + + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + sum_in_a += src_pix_ptr[A]; + sum_r += sum_in_r; + sum_g += sum_in_g; + sum_b += sum_in_b; + sum_a += sum_in_a; + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix_ptr = &stack[stack_ptr]; + + sum_out_r += stack_pix_ptr->r; + sum_out_g += stack_pix_ptr->g; + sum_out_b += stack_pix_ptr->b; + sum_out_a += stack_pix_ptr->a; + sum_in_r -= stack_pix_ptr->r; + sum_in_g -= stack_pix_ptr->g; + sum_in_b -= stack_pix_ptr->b; + sum_in_a -= stack_pix_ptr->a; + } + } + } + } + + + + //===========================================================recursive_blur + template<class ColorT, class CalculatorT> class recursive_blur + { + public: + typedef ColorT color_type; + typedef CalculatorT calculator_type; + typedef typename color_type::value_type value_type; + typedef typename calculator_type::value_type calc_type; + + //-------------------------------------------------------------------- + template<class Img> void blur_x(Img& img, double radius) + { + if(radius < 0.62) return; + if(img.width() < 3) return; + + calc_type s = calc_type(radius * 0.5); + calc_type q = calc_type((s < 2.5) ? + 3.97156 - 4.14554 * sqrt(1 - 0.26891 * s) : + 0.98711 * s - 0.96330); + + calc_type q2 = calc_type(q * q); + calc_type q3 = calc_type(q2 * q); + + calc_type b0 = calc_type(1.0 / (1.578250 + + 2.444130 * q + + 1.428100 * q2 + + 0.422205 * q3)); + + calc_type b1 = calc_type( 2.44413 * q + + 2.85619 * q2 + + 1.26661 * q3); + + calc_type b2 = calc_type(-1.42810 * q2 + + -1.26661 * q3); + + calc_type b3 = calc_type(0.422205 * q3); + + calc_type b = calc_type(1 - (b1 + b2 + b3) * b0); + + b1 *= b0; + b2 *= b0; + b3 *= b0; + + int w = img.width(); + int h = img.height(); + int wm = w-1; + int x, y; + + m_sum1.allocate(w); + m_sum2.allocate(w); + m_buf.allocate(w); + + for(y = 0; y < h; y++) + { + calculator_type c; + c.from_pix(img.pixel(0, y)); + m_sum1[0].calc(b, b1, b2, b3, c, c, c, c); + c.from_pix(img.pixel(1, y)); + m_sum1[1].calc(b, b1, b2, b3, c, m_sum1[0], m_sum1[0], m_sum1[0]); + c.from_pix(img.pixel(2, y)); + m_sum1[2].calc(b, b1, b2, b3, c, m_sum1[1], m_sum1[0], m_sum1[0]); + + for(x = 3; x < w; ++x) + { + c.from_pix(img.pixel(x, y)); + m_sum1[x].calc(b, b1, b2, b3, c, m_sum1[x-1], m_sum1[x-2], m_sum1[x-3]); + } + + m_sum2[wm ].calc(b, b1, b2, b3, m_sum1[wm ], m_sum1[wm ], m_sum1[wm], m_sum1[wm]); + m_sum2[wm-1].calc(b, b1, b2, b3, m_sum1[wm-1], m_sum2[wm ], m_sum2[wm], m_sum2[wm]); + m_sum2[wm-2].calc(b, b1, b2, b3, m_sum1[wm-2], m_sum2[wm-1], m_sum2[wm], m_sum2[wm]); + m_sum2[wm ].to_pix(m_buf[wm ]); + m_sum2[wm-1].to_pix(m_buf[wm-1]); + m_sum2[wm-2].to_pix(m_buf[wm-2]); + + for(x = wm-3; x >= 0; --x) + { + m_sum2[x].calc(b, b1, b2, b3, m_sum1[x], m_sum2[x+1], m_sum2[x+2], m_sum2[x+3]); + m_sum2[x].to_pix(m_buf[x]); + } + img.copy_color_hspan(0, y, w, &m_buf[0]); + } + } + + //-------------------------------------------------------------------- + template<class Img> void blur_y(Img& img, double radius) + { + pixfmt_transposer<Img> img2(img); + blur_x(img2, radius); + } + + //-------------------------------------------------------------------- + template<class Img> void blur(Img& img, double radius) + { + blur_x(img, radius); + pixfmt_transposer<Img> img2(img); + blur_x(img2, radius); + } + + private: + agg::pod_vector<calculator_type> m_sum1; + agg::pod_vector<calculator_type> m_sum2; + agg::pod_vector<color_type> m_buf; + }; + + + //=================================================recursive_blur_calc_rgba + template<class T=double> struct recursive_blur_calc_rgba + { + typedef T value_type; + typedef recursive_blur_calc_rgba<T> self_type; + + value_type r,g,b,a; + + template<class ColorT> + AGG_INLINE void from_pix(const ColorT& c) + { + r = c.r; + g = c.g; + b = c.b; + a = c.a; + } + + AGG_INLINE void calc(value_type b1, + value_type b2, + value_type b3, + value_type b4, + const self_type& c1, + const self_type& c2, + const self_type& c3, + const self_type& c4) + { + r = b1*c1.r + b2*c2.r + b3*c3.r + b4*c4.r; + g = b1*c1.g + b2*c2.g + b3*c3.g + b4*c4.g; + b = b1*c1.b + b2*c2.b + b3*c3.b + b4*c4.b; + a = b1*c1.a + b2*c2.a + b3*c3.a + b4*c4.a; + } + + template<class ColorT> + AGG_INLINE void to_pix(ColorT& c) const + { + typedef typename ColorT::value_type cv_type; + c.r = (cv_type)uround(r); + c.g = (cv_type)uround(g); + c.b = (cv_type)uround(b); + c.a = (cv_type)uround(a); + } + }; + + + //=================================================recursive_blur_calc_rgb + template<class T=double> struct recursive_blur_calc_rgb + { + typedef T value_type; + typedef recursive_blur_calc_rgb<T> self_type; + + value_type r,g,b; + + template<class ColorT> + AGG_INLINE void from_pix(const ColorT& c) + { + r = c.r; + g = c.g; + b = c.b; + } + + AGG_INLINE void calc(value_type b1, + value_type b2, + value_type b3, + value_type b4, + const self_type& c1, + const self_type& c2, + const self_type& c3, + const self_type& c4) + { + r = b1*c1.r + b2*c2.r + b3*c3.r + b4*c4.r; + g = b1*c1.g + b2*c2.g + b3*c3.g + b4*c4.g; + b = b1*c1.b + b2*c2.b + b3*c3.b + b4*c4.b; + } + + template<class ColorT> + AGG_INLINE void to_pix(ColorT& c) const + { + typedef typename ColorT::value_type cv_type; + c.r = (cv_type)uround(r); + c.g = (cv_type)uround(g); + c.b = (cv_type)uround(b); + } + }; + + + //================================================recursive_blur_calc_gray + template<class T=double> struct recursive_blur_calc_gray + { + typedef T value_type; + typedef recursive_blur_calc_gray<T> self_type; + + value_type v; + + template<class ColorT> + AGG_INLINE void from_pix(const ColorT& c) + { + v = c.v; + } + + AGG_INLINE void calc(value_type b1, + value_type b2, + value_type b3, + value_type b4, + const self_type& c1, + const self_type& c2, + const self_type& c3, + const self_type& c4) + { + v = b1*c1.v + b2*c2.v + b3*c3.v + b4*c4.v; + } + + template<class ColorT> + AGG_INLINE void to_pix(ColorT& c) const + { + typedef typename ColorT::value_type cv_type; + c.v = (cv_type)uround(v); + } + }; + +} + + + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_bounding_rect.h b/jni/desmume/src/android/agg/include/agg_bounding_rect.h new file mode 100755 index 0000000..e82c181 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_bounding_rect.h @@ -0,0 +1,122 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_BOUNDING_RECT_INCLUDED +#define AGG_BOUNDING_RECT_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //-----------------------------------------------------------bounding_rect + template<class VertexSource, class GetId, class CoordT> + bool bounding_rect(VertexSource& vs, GetId& gi, + unsigned start, unsigned num, + CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2) + { + unsigned i; + double x; + double y; + bool first = true; + + *x1 = CoordT(1); + *y1 = CoordT(1); + *x2 = CoordT(0); + *y2 = CoordT(0); + + for(i = 0; i < num; i++) + { + vs.rewind(gi[start + i]); + unsigned cmd; + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + if(is_vertex(cmd)) + { + if(first) + { + *x1 = CoordT(x); + *y1 = CoordT(y); + *x2 = CoordT(x); + *y2 = CoordT(y); + first = false; + } + else + { + if(CoordT(x) < *x1) *x1 = CoordT(x); + if(CoordT(y) < *y1) *y1 = CoordT(y); + if(CoordT(x) > *x2) *x2 = CoordT(x); + if(CoordT(y) > *y2) *y2 = CoordT(y); + } + } + } + } + return *x1 <= *x2 && *y1 <= *y2; + } + + + //-----------------------------------------------------bounding_rect_single + template<class VertexSource, class CoordT> + bool bounding_rect_single(VertexSource& vs, unsigned path_id, + CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2) + { + double x; + double y; + bool first = true; + + *x1 = CoordT(1); + *y1 = CoordT(1); + *x2 = CoordT(0); + *y2 = CoordT(0); + + vs.rewind(path_id); + unsigned cmd; + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + if(is_vertex(cmd)) + { + if(first) + { + *x1 = CoordT(x); + *y1 = CoordT(y); + *x2 = CoordT(x); + *y2 = CoordT(y); + first = false; + } + else + { + if(CoordT(x) < *x1) *x1 = CoordT(x); + if(CoordT(y) < *y1) *y1 = CoordT(y); + if(CoordT(x) > *x2) *x2 = CoordT(x); + if(CoordT(y) > *y2) *y2 = CoordT(y); + } + } + } + return *x1 <= *x2 && *y1 <= *y2; + } + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_bspline.h b/jni/desmume/src/android/agg/include/agg_bspline.h new file mode 100755 index 0000000..46ad429 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_bspline.h @@ -0,0 +1,81 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_BSPLINE_INCLUDED +#define AGG_BSPLINE_INCLUDED + +#include "agg_array.h" + +namespace agg +{ + //----------------------------------------------------------------bspline + // A very simple class of Bi-cubic Spline interpolation. + // First call init(num, x[], y[]) where num - number of source points, + // x, y - arrays of X and Y values respectively. Here Y must be a function + // of X. It means that all the X-coordinates must be arranged in the ascending + // order. + // Then call get(x) that calculates a value Y for the respective X. + // The class supports extrapolation, i.e. you can call get(x) where x is + // outside the given with init() X-range. Extrapolation is a simple linear + // function. + // + // See Implementation agg_bspline.cpp + //------------------------------------------------------------------------ + class bspline + { + public: + bspline(); + bspline(int num); + bspline(int num, const double* x, const double* y); + + void init(int num); + void add_point(double x, double y); + void prepare(); + + void init(int num, const double* x, const double* y); + + double get(double x) const; + double get_stateful(double x) const; + + private: + bspline(const bspline&); + const bspline& operator = (const bspline&); + + static void bsearch(int n, const double *x, double x0, int *i); + double extrapolation_left(double x) const; + double extrapolation_right(double x) const; + double interpolation(double x, int i) const; + + int m_max; + int m_num; + double* m_x; + double* m_y; + pod_array<double> m_am; + mutable int m_last_idx; + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_clip_liang_barsky.h b/jni/desmume/src/android/agg/include/agg_clip_liang_barsky.h new file mode 100755 index 0000000..e897560 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_clip_liang_barsky.h @@ -0,0 +1,339 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_CLIP_LIANG_BARSKY_INCLUDED +#define AGG_CLIP_LIANG_BARSKY_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + enum clipping_flags_e + { + clipping_flags_x1_clipped = 4, + clipping_flags_x2_clipped = 1, + clipping_flags_y1_clipped = 8, + clipping_flags_y2_clipped = 2, + clipping_flags_x_clipped = clipping_flags_x1_clipped | clipping_flags_x2_clipped, + clipping_flags_y_clipped = clipping_flags_y1_clipped | clipping_flags_y2_clipped + }; + + //----------------------------------------------------------clipping_flags + // Determine the clipping code of the vertex according to the + // Cyrus-Beck line clipping algorithm + // + // | | + // 0110 | 0010 | 0011 + // | | + // -------+--------+-------- clip_box.y2 + // | | + // 0100 | 0000 | 0001 + // | | + // -------+--------+-------- clip_box.y1 + // | | + // 1100 | 1000 | 1001 + // | | + // clip_box.x1 clip_box.x2 + // + // + template<class T> + inline unsigned clipping_flags(T x, T y, const rect_base<T>& clip_box) + { + return (x > clip_box.x2) | + ((y > clip_box.y2) << 1) | + ((x < clip_box.x1) << 2) | + ((y < clip_box.y1) << 3); + } + + //--------------------------------------------------------clipping_flags_x + template<class T> + inline unsigned clipping_flags_x(T x, const rect_base<T>& clip_box) + { + return (x > clip_box.x2) | ((x < clip_box.x1) << 2); + } + + + //--------------------------------------------------------clipping_flags_y + template<class T> + inline unsigned clipping_flags_y(T y, const rect_base<T>& clip_box) + { + return ((y > clip_box.y2) << 1) | ((y < clip_box.y1) << 3); + } + + + //-------------------------------------------------------clip_liang_barsky + template<class T> + inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2, + const rect_base<T>& clip_box, + T* x, T* y) + { + const double nearzero = 1e-30; + + double deltax = x2 - x1; + double deltay = y2 - y1; + double xin; + double xout; + double yin; + double yout; + double tinx; + double tiny; + double toutx; + double touty; + double tin1; + double tin2; + double tout1; + unsigned np = 0; + + if(deltax == 0.0) + { + // bump off of the vertical + deltax = (x1 > clip_box.x1) ? -nearzero : nearzero; + } + + if(deltay == 0.0) + { + // bump off of the horizontal + deltay = (y1 > clip_box.y1) ? -nearzero : nearzero; + } + + if(deltax > 0.0) + { + // points to right + xin = clip_box.x1; + xout = clip_box.x2; + } + else + { + xin = clip_box.x2; + xout = clip_box.x1; + } + + if(deltay > 0.0) + { + // points up + yin = clip_box.y1; + yout = clip_box.y2; + } + else + { + yin = clip_box.y2; + yout = clip_box.y1; + } + + tinx = (xin - x1) / deltax; + tiny = (yin - y1) / deltay; + + if (tinx < tiny) + { + // hits x first + tin1 = tinx; + tin2 = tiny; + } + else + { + // hits y first + tin1 = tiny; + tin2 = tinx; + } + + if(tin1 <= 1.0) + { + if(0.0 < tin1) + { + *x++ = (T)xin; + *y++ = (T)yin; + ++np; + } + + if(tin2 <= 1.0) + { + toutx = (xout - x1) / deltax; + touty = (yout - y1) / deltay; + + tout1 = (toutx < touty) ? toutx : touty; + + if(tin2 > 0.0 || tout1 > 0.0) + { + if(tin2 <= tout1) + { + if(tin2 > 0.0) + { + if(tinx > tiny) + { + *x++ = (T)xin; + *y++ = (T)(y1 + tinx * deltay); + } + else + { + *x++ = (T)(x1 + tiny * deltax); + *y++ = (T)yin; + } + ++np; + } + + if(tout1 < 1.0) + { + if(toutx < touty) + { + *x++ = (T)xout; + *y++ = (T)(y1 + toutx * deltay); + } + else + { + *x++ = (T)(x1 + touty * deltax); + *y++ = (T)yout; + } + } + else + { + *x++ = x2; + *y++ = y2; + } + ++np; + } + else + { + if(tinx > tiny) + { + *x++ = (T)xin; + *y++ = (T)yout; + } + else + { + *x++ = (T)xout; + *y++ = (T)yin; + } + ++np; + } + } + } + } + return np; + } + + + //---------------------------------------------------------------------------- + template<class T> + bool clip_move_point(T x1, T y1, T x2, T y2, + const rect_base<T>& clip_box, + T* x, T* y, unsigned flags) + { + T bound; + + if(flags & clipping_flags_x_clipped) + { + if(x1 == x2) + { + return false; + } + bound = (flags & clipping_flags_x1_clipped) ? clip_box.x1 : clip_box.x2; + *y = (T)(double(bound - x1) * (y2 - y1) / (x2 - x1) + y1); + *x = bound; + } + + flags = clipping_flags_y(*y, clip_box); + if(flags & clipping_flags_y_clipped) + { + if(y1 == y2) + { + return false; + } + bound = (flags & clipping_flags_y1_clipped) ? clip_box.y1 : clip_box.y2; + *x = (T)(double(bound - y1) * (x2 - x1) / (y2 - y1) + x1); + *y = bound; + } + return true; + } + + //-------------------------------------------------------clip_line_segment + // Returns: ret >= 4 - Fully clipped + // (ret & 1) != 0 - First point has been moved + // (ret & 2) != 0 - Second point has been moved + // + template<class T> + unsigned clip_line_segment(T* x1, T* y1, T* x2, T* y2, + const rect_base<T>& clip_box) + { + unsigned f1 = clipping_flags(*x1, *y1, clip_box); + unsigned f2 = clipping_flags(*x2, *y2, clip_box); + unsigned ret = 0; + + if((f2 | f1) == 0) + { + // Fully visible + return 0; + } + + if((f1 & clipping_flags_x_clipped) != 0 && + (f1 & clipping_flags_x_clipped) == (f2 & clipping_flags_x_clipped)) + { + // Fully clipped + return 4; + } + + if((f1 & clipping_flags_y_clipped) != 0 && + (f1 & clipping_flags_y_clipped) == (f2 & clipping_flags_y_clipped)) + { + // Fully clipped + return 4; + } + + T tx1 = *x1; + T ty1 = *y1; + T tx2 = *x2; + T ty2 = *y2; + if(f1) + { + if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x1, y1, f1)) + { + return 4; + } + if(*x1 == *x2 && *y1 == *y2) + { + return 4; + } + ret |= 1; + } + if(f2) + { + if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x2, y2, f2)) + { + return 4; + } + if(*x1 == *x2 && *y1 == *y2) + { + return 4; + } + ret |= 2; + } + return ret; + } + + +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_color_gray.h b/jni/desmume/src/android/agg/include/agg_color_gray.h new file mode 100755 index 0000000..a4d50e8 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_color_gray.h @@ -0,0 +1,423 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- +// +// color types gray8, gray16 +// +//---------------------------------------------------------------------------- + +#ifndef AGG_COLOR_GRAY_INCLUDED +#define AGG_COLOR_GRAY_INCLUDED + +#include "agg_basics.h" +#include "agg_color_rgba.h" + +namespace agg +{ + + //===================================================================gray8 + struct gray8 + { + typedef int8u value_type; + typedef int32u calc_type; + typedef int32 long_type; + enum base_scale_e + { + base_shift = 8, + base_scale = 1 << base_shift, + base_mask = base_scale - 1 + }; + typedef gray8 self_type; + + value_type v; + value_type a; + + //-------------------------------------------------------------------- + gray8() {} + + //-------------------------------------------------------------------- + gray8(unsigned v_, unsigned a_=base_mask) : + v(int8u(v_)), a(int8u(a_)) {} + + //-------------------------------------------------------------------- + gray8(const self_type& c, unsigned a_) : + v(c.v), a(value_type(a_)) {} + + //-------------------------------------------------------------------- + gray8(const rgba& c) : + v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))), + a((value_type)uround(c.a * double(base_mask))) {} + + //-------------------------------------------------------------------- + gray8(const rgba& c, double a_) : + v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))), + a((value_type)uround(a_ * double(base_mask))) {} + + //-------------------------------------------------------------------- + gray8(const rgba8& c) : + v((c.r*77 + c.g*150 + c.b*29) >> 8), + a(c.a) {} + + //-------------------------------------------------------------------- + gray8(const rgba8& c, unsigned a_) : + v((c.r*77 + c.g*150 + c.b*29) >> 8), + a(a_) {} + + //-------------------------------------------------------------------- + void clear() + { + v = a = 0; + } + + //-------------------------------------------------------------------- + const self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + void opacity(double a_) + { + if(a_ < 0.0) a_ = 0.0; + if(a_ > 1.0) a_ = 1.0; + a = (value_type)uround(a_ * double(base_mask)); + } + + //-------------------------------------------------------------------- + double opacity() const + { + return double(a) / double(base_mask); + } + + + //-------------------------------------------------------------------- + const self_type& premultiply() + { + if(a == base_mask) return *this; + if(a == 0) + { + v = 0; + return *this; + } + v = value_type((calc_type(v) * a) >> base_shift); + return *this; + } + + //-------------------------------------------------------------------- + const self_type& premultiply(unsigned a_) + { + if(a == base_mask && a_ >= base_mask) return *this; + if(a == 0 || a_ == 0) + { + v = a = 0; + return *this; + } + calc_type v_ = (calc_type(v) * a_) / a; + v = value_type((v_ > a_) ? a_ : v_); + a = value_type(a_); + return *this; + } + + //-------------------------------------------------------------------- + const self_type& demultiply() + { + if(a == base_mask) return *this; + if(a == 0) + { + v = 0; + return *this; + } + calc_type v_ = (calc_type(v) * base_mask) / a; + v = value_type((v_ > base_mask) ? (value_type)base_mask : v_); + return *this; + } + + //-------------------------------------------------------------------- + self_type gradient(self_type c, double k) const + { + self_type ret; + calc_type ik = uround(k * base_scale); + ret.v = value_type(calc_type(v) + (((calc_type(c.v) - v) * ik) >> base_shift)); + ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); + return ret; + } + + //-------------------------------------------------------------------- + AGG_INLINE void add(const self_type& c, unsigned cover) + { + calc_type cv, ca; + if(cover == cover_mask) + { + if(c.a == base_mask) + { + *this = c; + } + else + { + cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; + ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; + } + } + else + { + cv = v + ((c.v * cover + cover_mask/2) >> cover_shift); + ca = a + ((c.a * cover + cover_mask/2) >> cover_shift); + v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; + a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; + } + } + + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0); } + }; + + + //-------------------------------------------------------------gray8_pre + inline gray8 gray8_pre(unsigned v, unsigned a = gray8::base_mask) + { + return gray8(v,a).premultiply(); + } + inline gray8 gray8_pre(const gray8& c, unsigned a) + { + return gray8(c,a).premultiply(); + } + inline gray8 gray8_pre(const rgba& c) + { + return gray8(c).premultiply(); + } + inline gray8 gray8_pre(const rgba& c, double a) + { + return gray8(c,a).premultiply(); + } + inline gray8 gray8_pre(const rgba8& c) + { + return gray8(c).premultiply(); + } + inline gray8 gray8_pre(const rgba8& c, unsigned a) + { + return gray8(c,a).premultiply(); + } + + + + + //==================================================================gray16 + struct gray16 + { + typedef int16u value_type; + typedef int32u calc_type; + typedef int64 long_type; + enum base_scale_e + { + base_shift = 16, + base_scale = 1 << base_shift, + base_mask = base_scale - 1 + }; + typedef gray16 self_type; + + value_type v; + value_type a; + + //-------------------------------------------------------------------- + gray16() {} + + //-------------------------------------------------------------------- + gray16(unsigned v_, unsigned a_=base_mask) : + v(int16u(v_)), a(int16u(a_)) {} + + //-------------------------------------------------------------------- + gray16(const self_type& c, unsigned a_) : + v(c.v), a(value_type(a_)) {} + + //-------------------------------------------------------------------- + gray16(const rgba& c) : + v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))), + a((value_type)uround(c.a * double(base_mask))) {} + + //-------------------------------------------------------------------- + gray16(const rgba& c, double a_) : + v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))), + a((value_type)uround(a_ * double(base_mask))) {} + + //-------------------------------------------------------------------- + gray16(const rgba8& c) : + v(c.r*77 + c.g*150 + c.b*29), + a((value_type(c.a) << 8) | c.a) {} + + //-------------------------------------------------------------------- + gray16(const rgba8& c, unsigned a_) : + v(c.r*77 + c.g*150 + c.b*29), + a((value_type(a_) << 8) | c.a) {} + + //-------------------------------------------------------------------- + void clear() + { + v = a = 0; + } + + //-------------------------------------------------------------------- + const self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + void opacity(double a_) + { + if(a_ < 0.0) a_ = 0.0; + if(a_ > 1.0) a_ = 1.0; + a = (value_type)uround(a_ * double(base_mask)); + } + + //-------------------------------------------------------------------- + double opacity() const + { + return double(a) / double(base_mask); + } + + + //-------------------------------------------------------------------- + const self_type& premultiply() + { + if(a == base_mask) return *this; + if(a == 0) + { + v = 0; + return *this; + } + v = value_type((calc_type(v) * a) >> base_shift); + return *this; + } + + //-------------------------------------------------------------------- + const self_type& premultiply(unsigned a_) + { + if(a == base_mask && a_ >= base_mask) return *this; + if(a == 0 || a_ == 0) + { + v = a = 0; + return *this; + } + calc_type v_ = (calc_type(v) * a_) / a; + v = value_type((v_ > a_) ? a_ : v_); + a = value_type(a_); + return *this; + } + + //-------------------------------------------------------------------- + const self_type& demultiply() + { + if(a == base_mask) return *this; + if(a == 0) + { + v = 0; + return *this; + } + calc_type v_ = (calc_type(v) * base_mask) / a; + v = value_type((v_ > base_mask) ? base_mask : v_); + return *this; + } + + //-------------------------------------------------------------------- + self_type gradient(self_type c, double k) const + { + self_type ret; + calc_type ik = uround(k * base_scale); + ret.v = value_type(calc_type(v) + (((calc_type(c.v) - v) * ik) >> base_shift)); + ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); + return ret; + } + + //-------------------------------------------------------------------- + AGG_INLINE void add(const self_type& c, unsigned cover) + { + calc_type cv, ca; + if(cover == cover_mask) + { + if(c.a == base_mask) + { + *this = c; + } + else + { + cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; + ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; + } + } + else + { + cv = v + ((c.v * cover + cover_mask/2) >> cover_shift); + ca = a + ((c.a * cover + cover_mask/2) >> cover_shift); + v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; + a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; + } + } + + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0); } + }; + + + //------------------------------------------------------------gray16_pre + inline gray16 gray16_pre(unsigned v, unsigned a = gray16::base_mask) + { + return gray16(v,a).premultiply(); + } + inline gray16 gray16_pre(const gray16& c, unsigned a) + { + return gray16(c,a).premultiply(); + } + inline gray16 gray16_pre(const rgba& c) + { + return gray16(c).premultiply(); + } + inline gray16 gray16_pre(const rgba& c, double a) + { + return gray16(c,a).premultiply(); + } + inline gray16 gray16_pre(const rgba8& c) + { + return gray16(c).premultiply(); + } + inline gray16 gray16_pre(const rgba8& c, unsigned a) + { + return gray16(c,a).premultiply(); + } + + +} + + + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_color_rgba.h b/jni/desmume/src/android/agg/include/agg_color_rgba.h new file mode 100755 index 0000000..77efac8 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_color_rgba.h @@ -0,0 +1,756 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_COLOR_RGBA_INCLUDED +#define AGG_COLOR_RGBA_INCLUDED + +#include <math.h> +#include "agg_basics.h" + +namespace agg +{ + // Supported byte orders for RGB and RGBA pixel formats + //======================================================================= + struct order_rgb { enum rgb_e { R=0, G=1, B=2, rgb_tag }; }; //----order_rgb + struct order_bgr { enum bgr_e { B=0, G=1, R=2, rgb_tag }; }; //----order_bgr + struct order_rgba { enum rgba_e { R=0, G=1, B=2, A=3, rgba_tag }; }; //----order_rgba + struct order_argb { enum argb_e { A=0, R=1, G=2, B=3, rgba_tag }; }; //----order_argb + struct order_abgr { enum abgr_e { A=0, B=1, G=2, R=3, rgba_tag }; }; //----order_abgr + struct order_bgra { enum bgra_e { B=0, G=1, R=2, A=3, rgba_tag }; }; //----order_bgra + + //====================================================================rgba + struct rgba + { + typedef double value_type; + + double r; + double g; + double b; + double a; + + //-------------------------------------------------------------------- + rgba() {} + + //-------------------------------------------------------------------- + rgba(double r_, double g_, double b_, double a_=1.0) : + r(r_), g(g_), b(b_), a(a_) {} + + //-------------------------------------------------------------------- + rgba(const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_) {} + + //-------------------------------------------------------------------- + void clear() + { + r = g = b = a = 0; + } + + //-------------------------------------------------------------------- + const rgba& transparent() + { + a = 0.0; + return *this; + } + + //-------------------------------------------------------------------- + const rgba& opacity(double a_) + { + if(a_ < 0.0) a_ = 0.0; + if(a_ > 1.0) a_ = 1.0; + a = a_; + return *this; + } + + //-------------------------------------------------------------------- + double opacity() const + { + return a; + } + + //-------------------------------------------------------------------- + const rgba& premultiply() + { + r *= a; + g *= a; + b *= a; + return *this; + } + + //-------------------------------------------------------------------- + const rgba& premultiply(double a_) + { + if(a <= 0.0 || a_ <= 0.0) + { + r = g = b = a = 0.0; + return *this; + } + a_ /= a; + r *= a_; + g *= a_; + b *= a_; + a = a_; + return *this; + } + + //-------------------------------------------------------------------- + const rgba& demultiply() + { + if(a == 0) + { + r = g = b = 0; + return *this; + } + double a_ = 1.0 / a; + r *= a_; + g *= a_; + b *= a_; + return *this; + } + + + //-------------------------------------------------------------------- + rgba gradient(rgba c, double k) const + { + rgba ret; + ret.r = r + (c.r - r) * k; + ret.g = g + (c.g - g) * k; + ret.b = b + (c.b - b) * k; + ret.a = a + (c.a - a) * k; + return ret; + } + + //-------------------------------------------------------------------- + static rgba no_color() { return rgba(0,0,0,0); } + + //-------------------------------------------------------------------- + static rgba from_wavelength(double wl, double gamma = 1.0); + + //-------------------------------------------------------------------- + explicit rgba(double wavelen, double gamma=1.0) + { + *this = from_wavelength(wavelen, gamma); + } + + }; + + //----------------------------------------------------------------rgba_pre + inline rgba rgba_pre(double r, double g, double b, double a=1.0) + { + return rgba(r, g, b, a).premultiply(); + } + inline rgba rgba_pre(const rgba& c) + { + return rgba(c).premultiply(); + } + inline rgba rgba_pre(const rgba& c, double a) + { + return rgba(c, a).premultiply(); + } + + //------------------------------------------------------------------------ + inline rgba rgba::from_wavelength(double wl, double gamma) + { + rgba t(0.0, 0.0, 0.0); + + if(wl >= 380.0 && wl <= 440.0) + { + t.r = -1.0 * (wl - 440.0) / (440.0 - 380.0); + t.b = 1.0; + } + else + if(wl >= 440.0 && wl <= 490.0) + { + t.g = (wl - 440.0) / (490.0 - 440.0); + t.b = 1.0; + } + else + if(wl >= 490.0 && wl <= 510.0) + { + t.g = 1.0; + t.b = -1.0 * (wl - 510.0) / (510.0 - 490.0); + } + else + if(wl >= 510.0 && wl <= 580.0) + { + t.r = (wl - 510.0) / (580.0 - 510.0); + t.g = 1.0; + } + else + if(wl >= 580.0 && wl <= 645.0) + { + t.r = 1.0; + t.g = -1.0 * (wl - 645.0) / (645.0 - 580.0); + } + else + if(wl >= 645.0 && wl <= 780.0) + { + t.r = 1.0; + } + + double s = 1.0; + if(wl > 700.0) s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0); + else if(wl < 420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0); + + t.r = pow(t.r * s, gamma); + t.g = pow(t.g * s, gamma); + t.b = pow(t.b * s, gamma); + return t; + } + + + + + //===================================================================rgba8 + struct rgba8 + { + typedef int8u value_type; + typedef int32u calc_type; + typedef int32 long_type; + enum base_scale_e + { + base_shift = 8, + base_scale = 1 << base_shift, + base_mask = base_scale - 1 + }; + typedef rgba8 self_type; + + + value_type r; + value_type g; + value_type b; + value_type a; + + //-------------------------------------------------------------------- + rgba8() {} + + //-------------------------------------------------------------------- + rgba8(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) : + r(value_type(r_)), + g(value_type(g_)), + b(value_type(b_)), + a(value_type(a_)) {} + + //-------------------------------------------------------------------- + rgba8(const rgba& c, double a_) : + r((value_type)uround(c.r * double(base_mask))), + g((value_type)uround(c.g * double(base_mask))), + b((value_type)uround(c.b * double(base_mask))), + a((value_type)uround(a_ * double(base_mask))) {} + + //-------------------------------------------------------------------- + rgba8(const self_type& c, unsigned a_) : + r(c.r), g(c.g), b(c.b), a(value_type(a_)) {} + + //-------------------------------------------------------------------- + rgba8(const rgba& c) : + r((value_type)uround(c.r * double(base_mask))), + g((value_type)uround(c.g * double(base_mask))), + b((value_type)uround(c.b * double(base_mask))), + a((value_type)uround(c.a * double(base_mask))) {} + + //-------------------------------------------------------------------- + void clear() + { + r = g = b = a = 0; + } + + //-------------------------------------------------------------------- + const self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + const self_type& opacity(double a_) + { + if(a_ < 0.0) a_ = 0.0; + if(a_ > 1.0) a_ = 1.0; + a = (value_type)uround(a_ * double(base_mask)); + return *this; + } + + //-------------------------------------------------------------------- + double opacity() const + { + return double(a) / double(base_mask); + } + + //-------------------------------------------------------------------- + AGG_INLINE const self_type& premultiply() + { + if(a == base_mask) return *this; + if(a == 0) + { + r = g = b = 0; + return *this; + } + r = value_type((calc_type(r) * a) >> base_shift); + g = value_type((calc_type(g) * a) >> base_shift); + b = value_type((calc_type(b) * a) >> base_shift); + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE const self_type& premultiply(unsigned a_) + { + if(a == base_mask && a_ >= base_mask) return *this; + if(a == 0 || a_ == 0) + { + r = g = b = a = 0; + return *this; + } + calc_type r_ = (calc_type(r) * a_) / a; + calc_type g_ = (calc_type(g) * a_) / a; + calc_type b_ = (calc_type(b) * a_) / a; + r = value_type((r_ > a_) ? a_ : r_); + g = value_type((g_ > a_) ? a_ : g_); + b = value_type((b_ > a_) ? a_ : b_); + a = value_type(a_); + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE const self_type& demultiply() + { + if(a == base_mask) return *this; + if(a == 0) + { + r = g = b = 0; + return *this; + } + calc_type r_ = (calc_type(r) * base_mask) / a; + calc_type g_ = (calc_type(g) * base_mask) / a; + calc_type b_ = (calc_type(b) * base_mask) / a; + r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_); + g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_); + b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_); + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type gradient(const self_type& c, double k) const + { + self_type ret; + calc_type ik = uround(k * base_scale); + ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift)); + ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift)); + ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift)); + ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); + return ret; + } + + //-------------------------------------------------------------------- + AGG_INLINE void add(const self_type& c, unsigned cover) + { + calc_type cr, cg, cb, ca; + if(cover == cover_mask) + { + if(c.a == base_mask) + { + *this = c; + } + else + { + cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr; + cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg; + cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb; + ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; + } + } + else + { + cr = r + ((c.r * cover + cover_mask/2) >> cover_shift); + cg = g + ((c.g * cover + cover_mask/2) >> cover_shift); + cb = b + ((c.b * cover + cover_mask/2) >> cover_shift); + ca = a + ((c.a * cover + cover_mask/2) >> cover_shift); + r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr; + g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg; + b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb; + a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; + } + } + + //-------------------------------------------------------------------- + template<class GammaLUT> + AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma) + { + r = gamma.dir(r); + g = gamma.dir(g); + b = gamma.dir(b); + } + + //-------------------------------------------------------------------- + template<class GammaLUT> + AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma) + { + r = gamma.inv(r); + g = gamma.inv(g); + b = gamma.inv(b); + } + + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0,0,0); } + + //-------------------------------------------------------------------- + static self_type from_wavelength(double wl, double gamma = 1.0) + { + return self_type(rgba::from_wavelength(wl, gamma)); + } + }; + + + //-------------------------------------------------------------rgba8_pre + inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b, + unsigned a = rgba8::base_mask) + { + return rgba8(r,g,b,a).premultiply(); + } + inline rgba8 rgba8_pre(const rgba8& c) + { + return rgba8(c).premultiply(); + } + inline rgba8 rgba8_pre(const rgba8& c, unsigned a) + { + return rgba8(c,a).premultiply(); + } + inline rgba8 rgba8_pre(const rgba& c) + { + return rgba8(c).premultiply(); + } + inline rgba8 rgba8_pre(const rgba& c, double a) + { + return rgba8(c,a).premultiply(); + } + + + //-------------------------------------------------------------rgb8_packed + inline rgba8 rgb8_packed(unsigned v) + { + return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF); + } + + //-------------------------------------------------------------bgr8_packed + inline rgba8 bgr8_packed(unsigned v) + { + return rgba8(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF); + } + + //------------------------------------------------------------argb8_packed + inline rgba8 argb8_packed(unsigned v) + { + return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, v >> 24); + } + + //---------------------------------------------------------rgba8_gamma_dir + template<class GammaLUT> + rgba8 rgba8_gamma_dir(rgba8 c, const GammaLUT& gamma) + { + return rgba8(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a); + } + + //---------------------------------------------------------rgba8_gamma_inv + template<class GammaLUT> + rgba8 rgba8_gamma_inv(rgba8 c, const GammaLUT& gamma) + { + return rgba8(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a); + } + + + + + + //==================================================================rgba16 + struct rgba16 + { + typedef int16u value_type; + typedef int32u calc_type; + typedef int64 long_type; + enum base_scale_e + { + base_shift = 16, + base_scale = 1 << base_shift, + base_mask = base_scale - 1 + }; + typedef rgba16 self_type; + + value_type r; + value_type g; + value_type b; + value_type a; + + //-------------------------------------------------------------------- + rgba16() {} + + //-------------------------------------------------------------------- + rgba16(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) : + r(value_type(r_)), + g(value_type(g_)), + b(value_type(b_)), + a(value_type(a_)) {} + + //-------------------------------------------------------------------- + rgba16(const self_type& c, unsigned a_) : + r(c.r), g(c.g), b(c.b), a(value_type(a_)) {} + + //-------------------------------------------------------------------- + rgba16(const rgba& c) : + r((value_type)uround(c.r * double(base_mask))), + g((value_type)uround(c.g * double(base_mask))), + b((value_type)uround(c.b * double(base_mask))), + a((value_type)uround(c.a * double(base_mask))) {} + + //-------------------------------------------------------------------- + rgba16(const rgba& c, double a_) : + r((value_type)uround(c.r * double(base_mask))), + g((value_type)uround(c.g * double(base_mask))), + b((value_type)uround(c.b * double(base_mask))), + a((value_type)uround(a_ * double(base_mask))) {} + + //-------------------------------------------------------------------- + rgba16(const rgba8& c) : + r(value_type((value_type(c.r) << 8) | c.r)), + g(value_type((value_type(c.g) << 8) | c.g)), + b(value_type((value_type(c.b) << 8) | c.b)), + a(value_type((value_type(c.a) << 8) | c.a)) {} + + //-------------------------------------------------------------------- + rgba16(const rgba8& c, unsigned a_) : + r(value_type((value_type(c.r) << 8) | c.r)), + g(value_type((value_type(c.g) << 8) | c.g)), + b(value_type((value_type(c.b) << 8) | c.b)), + a(value_type(( a_ << 8) | c.a)) {} + + //-------------------------------------------------------------------- + void clear() + { + r = g = b = a = 0; + } + + //-------------------------------------------------------------------- + const self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE const self_type& opacity(double a_) + { + if(a_ < 0.0) a_ = 0.0; + if(a_ > 1.0) a_ = 1.0; + a = (value_type)uround(a_ * double(base_mask)); + return *this; + } + + //-------------------------------------------------------------------- + double opacity() const + { + return double(a) / double(base_mask); + } + + //-------------------------------------------------------------------- + AGG_INLINE const self_type& premultiply() + { + if(a == base_mask) return *this; + if(a == 0) + { + r = g = b = 0; + return *this; + } + r = value_type((calc_type(r) * a) >> base_shift); + g = value_type((calc_type(g) * a) >> base_shift); + b = value_type((calc_type(b) * a) >> base_shift); + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE const self_type& premultiply(unsigned a_) + { + if(a == base_mask && a_ >= base_mask) return *this; + if(a == 0 || a_ == 0) + { + r = g = b = a = 0; + return *this; + } + calc_type r_ = (calc_type(r) * a_) / a; + calc_type g_ = (calc_type(g) * a_) / a; + calc_type b_ = (calc_type(b) * a_) / a; + r = value_type((r_ > a_) ? a_ : r_); + g = value_type((g_ > a_) ? a_ : g_); + b = value_type((b_ > a_) ? a_ : b_); + a = value_type(a_); + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE const self_type& demultiply() + { + if(a == base_mask) return *this; + if(a == 0) + { + r = g = b = 0; + return *this; + } + calc_type r_ = (calc_type(r) * base_mask) / a; + calc_type g_ = (calc_type(g) * base_mask) / a; + calc_type b_ = (calc_type(b) * base_mask) / a; + r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_); + g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_); + b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_); + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type gradient(const self_type& c, double k) const + { + self_type ret; + calc_type ik = uround(k * base_scale); + ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift)); + ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift)); + ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift)); + ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); + return ret; + } + + //-------------------------------------------------------------------- + AGG_INLINE void add(const self_type& c, unsigned cover) + { + calc_type cr, cg, cb, ca; + if(cover == cover_mask) + { + if(c.a == base_mask) + { + *this = c; + } + else + { + cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr; + cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg; + cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb; + ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; + } + } + else + { + cr = r + ((c.r * cover + cover_mask) >> cover_shift); + cg = g + ((c.g * cover + cover_mask) >> cover_shift); + cb = b + ((c.b * cover + cover_mask) >> cover_shift); + ca = a + ((c.a * cover + cover_mask) >> cover_shift); + r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr; + g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg; + b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb; + a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; + } + } + + //-------------------------------------------------------------------- + template<class GammaLUT> + AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma) + { + r = gamma.dir(r); + g = gamma.dir(g); + b = gamma.dir(b); + } + + //-------------------------------------------------------------------- + template<class GammaLUT> + AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma) + { + r = gamma.inv(r); + g = gamma.inv(g); + b = gamma.inv(b); + } + + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0,0,0); } + + //-------------------------------------------------------------------- + static self_type from_wavelength(double wl, double gamma = 1.0) + { + return self_type(rgba::from_wavelength(wl, gamma)); + } + }; + + + + //--------------------------------------------------------------rgba16_pre + inline rgba16 rgba16_pre(unsigned r, unsigned g, unsigned b, + unsigned a = rgba16::base_mask) + { + return rgba16(r,g,b,a).premultiply(); + } + inline rgba16 rgba16_pre(const rgba16& c, unsigned a) + { + return rgba16(c,a).premultiply(); + } + inline rgba16 rgba16_pre(const rgba& c) + { + return rgba16(c).premultiply(); + } + inline rgba16 rgba16_pre(const rgba& c, double a) + { + return rgba16(c,a).premultiply(); + } + inline rgba16 rgba16_pre(const rgba8& c) + { + return rgba16(c).premultiply(); + } + inline rgba16 rgba16_pre(const rgba8& c, unsigned a) + { + return rgba16(c,a).premultiply(); + } + + + //------------------------------------------------------rgba16_gamma_dir + template<class GammaLUT> + rgba16 rgba16_gamma_dir(rgba16 c, const GammaLUT& gamma) + { + return rgba16(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a); + } + + //------------------------------------------------------rgba16_gamma_inv + template<class GammaLUT> + rgba16 rgba16_gamma_inv(rgba16 c, const GammaLUT& gamma) + { + return rgba16(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a); + } + + +} + + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_config.h b/jni/desmume/src/android/agg/include/agg_config.h new file mode 100755 index 0000000..81c75f1 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_config.h @@ -0,0 +1,44 @@ +#ifndef AGG_CONFIG_INCLUDED +#define AGG_CONFIG_INCLUDED + +// This file can be used to redefine certain data types. + +//--------------------------------------- +// 1. Default basic types such as: +// +// AGG_INT8 +// AGG_INT8U +// AGG_INT16 +// AGG_INT16U +// AGG_INT32 +// AGG_INT32U +// AGG_INT64 +// AGG_INT64U +// +// Just replace this file with new defines if necessary. +// For example, if your compiler doesn't have a 64 bit integer type +// you can still use AGG if you define the follows: +// +// #define AGG_INT64 int +// #define AGG_INT64U unsigned +// +// It will result in overflow in 16 bit-per-component image/pattern resampling +// but it won't result any crash and the rest of the library will remain +// fully functional. + + +//--------------------------------------- +// 2. Default rendering_buffer type. Can be: +// +// Provides faster access for massive pixel operations, +// such as blur, image filtering: +// #define AGG_RENDERING_BUFFER row_ptr_cache<int8u> +// +// Provides cheaper creation and destruction (no mem allocs): +// #define AGG_RENDERING_BUFFER row_accessor<int8u> +// +// You can still use both of them simultaneouslyin your applications +// This #define is used only for default rendering_buffer type, +// in short hand typedefs like pixfmt_rgba32. + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_conv_adaptor_vcgen.h b/jni/desmume/src/android/agg/include/agg_conv_adaptor_vcgen.h new file mode 100755 index 0000000..7bd9b07 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_conv_adaptor_vcgen.h @@ -0,0 +1,166 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_ADAPTOR_VCGEN_INCLUDED +#define AGG_CONV_ADAPTOR_VCGEN_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //------------------------------------------------------------null_markers + struct null_markers + { + void remove_all() {} + void add_vertex(double, double, unsigned) {} + void prepare_src() {} + + void rewind(unsigned) {} + unsigned vertex(double*, double*) { return path_cmd_stop; } + }; + + + //------------------------------------------------------conv_adaptor_vcgen + template<class VertexSource, + class Generator, + class Markers=null_markers> class conv_adaptor_vcgen + { + enum status + { + initial, + accumulate, + generate + }; + + public: + explicit conv_adaptor_vcgen(VertexSource& source) : + m_source(&source), + m_status(initial) + {} + void attach(VertexSource& source) { m_source = &source; } + + Generator& generator() { return m_generator; } + const Generator& generator() const { return m_generator; } + + Markers& markers() { return m_markers; } + const Markers& markers() const { return m_markers; } + + void rewind(unsigned path_id) + { + m_source->rewind(path_id); + m_status = initial; + } + + unsigned vertex(double* x, double* y); + + private: + // Prohibit copying + conv_adaptor_vcgen(const conv_adaptor_vcgen<VertexSource, Generator, Markers>&); + const conv_adaptor_vcgen<VertexSource, Generator, Markers>& + operator = (const conv_adaptor_vcgen<VertexSource, Generator, Markers>&); + + VertexSource* m_source; + Generator m_generator; + Markers m_markers; + status m_status; + unsigned m_last_cmd; + double m_start_x; + double m_start_y; + }; + + + + + + //------------------------------------------------------------------------ + template<class VertexSource, class Generator, class Markers> + unsigned conv_adaptor_vcgen<VertexSource, Generator, Markers>::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + bool done = false; + while(!done) + { + switch(m_status) + { + case initial: + m_markers.remove_all(); + m_last_cmd = m_source->vertex(&m_start_x, &m_start_y); + m_status = accumulate; + + case accumulate: + if(is_stop(m_last_cmd)) return path_cmd_stop; + + m_generator.remove_all(); + m_generator.add_vertex(m_start_x, m_start_y, path_cmd_move_to); + m_markers.add_vertex(m_start_x, m_start_y, path_cmd_move_to); + + for(;;) + { + cmd = m_source->vertex(x, y); + if(is_vertex(cmd)) + { + m_last_cmd = cmd; + if(is_move_to(cmd)) + { + m_start_x = *x; + m_start_y = *y; + break; + } + m_generator.add_vertex(*x, *y, cmd); + m_markers.add_vertex(*x, *y, path_cmd_line_to); + } + else + { + if(is_stop(cmd)) + { + m_last_cmd = path_cmd_stop; + break; + } + if(is_end_poly(cmd)) + { + m_generator.add_vertex(*x, *y, cmd); + break; + } + } + } + m_generator.rewind(0); + m_status = generate; + + case generate: + cmd = m_generator.vertex(x, y); + if(is_stop(cmd)) + { + m_status = accumulate; + break; + } + done = true; + break; + } + } + return cmd; + } + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_conv_adaptor_vpgen.h b/jni/desmume/src/android/agg/include/agg_conv_adaptor_vpgen.h new file mode 100755 index 0000000..dca9415 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_conv_adaptor_vpgen.h @@ -0,0 +1,168 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_ADAPTOR_VPGEN_INCLUDED +#define AGG_CONV_ADAPTOR_VPGEN_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //======================================================conv_adaptor_vpgen + template<class VertexSource, class VPGen> class conv_adaptor_vpgen + { + public: + explicit conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {} + void attach(VertexSource& source) { m_source = &source; } + + VPGen& vpgen() { return m_vpgen; } + const VPGen& vpgen() const { return m_vpgen; } + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + conv_adaptor_vpgen(const conv_adaptor_vpgen<VertexSource, VPGen>&); + const conv_adaptor_vpgen<VertexSource, VPGen>& + operator = (const conv_adaptor_vpgen<VertexSource, VPGen>&); + + VertexSource* m_source; + VPGen m_vpgen; + double m_start_x; + double m_start_y; + unsigned m_poly_flags; + int m_vertices; + }; + + + + //------------------------------------------------------------------------ + template<class VertexSource, class VPGen> + void conv_adaptor_vpgen<VertexSource, VPGen>::rewind(unsigned path_id) + { + m_source->rewind(path_id); + m_vpgen.reset(); + m_start_x = 0; + m_start_y = 0; + m_poly_flags = 0; + m_vertices = 0; + } + + + //------------------------------------------------------------------------ + template<class VertexSource, class VPGen> + unsigned conv_adaptor_vpgen<VertexSource, VPGen>::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + for(;;) + { + cmd = m_vpgen.vertex(x, y); + if(!is_stop(cmd)) break; + + if(m_poly_flags && !m_vpgen.auto_unclose()) + { + *x = 0.0; + *y = 0.0; + cmd = m_poly_flags; + m_poly_flags = 0; + break; + } + + if(m_vertices < 0) + { + if(m_vertices < -1) + { + m_vertices = 0; + return path_cmd_stop; + } + m_vpgen.move_to(m_start_x, m_start_y); + m_vertices = 1; + continue; + } + + double tx, ty; + cmd = m_source->vertex(&tx, &ty); + if(is_vertex(cmd)) + { + if(is_move_to(cmd)) + { + if(m_vpgen.auto_close() && m_vertices > 2) + { + m_vpgen.line_to(m_start_x, m_start_y); + m_poly_flags = path_cmd_end_poly | path_flags_close; + m_start_x = tx; + m_start_y = ty; + m_vertices = -1; + continue; + } + m_vpgen.move_to(tx, ty); + m_start_x = tx; + m_start_y = ty; + m_vertices = 1; + } + else + { + m_vpgen.line_to(tx, ty); + ++m_vertices; + } + } + else + { + if(is_end_poly(cmd)) + { + m_poly_flags = cmd; + if(is_closed(cmd) || m_vpgen.auto_close()) + { + if(m_vpgen.auto_close()) m_poly_flags |= path_flags_close; + if(m_vertices > 2) + { + m_vpgen.line_to(m_start_x, m_start_y); + } + m_vertices = 0; + } + } + else + { + // path_cmd_stop + if(m_vpgen.auto_close() && m_vertices > 2) + { + m_vpgen.line_to(m_start_x, m_start_y); + m_poly_flags = path_cmd_end_poly | path_flags_close; + m_vertices = -2; + continue; + } + break; + } + } + } + return cmd; + } + + +} + + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_conv_bspline.h b/jni/desmume/src/android/agg/include/agg_conv_bspline.h new file mode 100755 index 0000000..9bdcb67 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_conv_bspline.h @@ -0,0 +1,58 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_BSPLINE_INCLUDED +#define AGG_CONV_BSPLINE_INCLUDED + +#include "agg_basics.h" +#include "agg_vcgen_bspline.h" +#include "agg_conv_adaptor_vcgen.h" + + +namespace agg +{ + + //---------------------------------------------------------conv_bspline + template<class VertexSource> + struct conv_bspline : public conv_adaptor_vcgen<VertexSource, vcgen_bspline> + { + typedef conv_adaptor_vcgen<VertexSource, vcgen_bspline> base_type; + + conv_bspline(VertexSource& vs) : + conv_adaptor_vcgen<VertexSource, vcgen_bspline>(vs) {} + + void interpolation_step(double v) { base_type::generator().interpolation_step(v); } + double interpolation_step() const { return base_type::generator().interpolation_step(); } + + private: + conv_bspline(const conv_bspline<VertexSource>&); + const conv_bspline<VertexSource>& + operator = (const conv_bspline<VertexSource>&); + }; + +} + + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_conv_clip_polygon.h b/jni/desmume/src/android/agg/include/agg_conv_clip_polygon.h new file mode 100755 index 0000000..3c34590 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_conv_clip_polygon.h @@ -0,0 +1,72 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Polygon clipping converter +// There an optimized Liang-Basky algorithm is used. +// The algorithm doesn't optimize the degenerate edges, i.e. it will never +// break a closed polygon into two or more ones, instead, there will be +// degenerate edges coinciding with the respective clipping boundaries. +// This is a sub-optimal solution, because that optimization would require +// extra, rather expensive math while the rasterizer tolerates it quite well, +// without any considerable overhead. +// +//---------------------------------------------------------------------------- +#ifndef AGG_CONV_CLIP_POLYGON_INCLUDED +#define AGG_CONV_CLIP_POLYGON_INCLUDED + +#include "agg_basics.h" +#include "agg_conv_adaptor_vpgen.h" +#include "agg_vpgen_clip_polygon.h" + +namespace agg +{ + + //=======================================================conv_clip_polygon + template<class VertexSource> + struct conv_clip_polygon : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon> + { + typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon> base_type; + + conv_clip_polygon(VertexSource& vs) : + conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>(vs) {} + + void clip_box(double x1, double y1, double x2, double y2) + { + base_type::vpgen().clip_box(x1, y1, x2, y2); + } + + double x1() const { return base_type::vpgen().x1(); } + double y1() const { return base_type::vpgen().y1(); } + double x2() const { return base_type::vpgen().x2(); } + double y2() const { return base_type::vpgen().y2(); } + + private: + conv_clip_polygon(const conv_clip_polygon<VertexSource>&); + const conv_clip_polygon<VertexSource>& + operator = (const conv_clip_polygon<VertexSource>&); + }; + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_conv_clip_polyline.h b/jni/desmume/src/android/agg/include/agg_conv_clip_polyline.h new file mode 100755 index 0000000..d45067f --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_conv_clip_polyline.h @@ -0,0 +1,72 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// polyline clipping converter +// There an optimized Liang-Basky algorithm is used. +// The algorithm doesn't optimize the degenerate edges, i.e. it will never +// break a closed polyline into two or more ones, instead, there will be +// degenerate edges coinciding with the respective clipping boundaries. +// This is a sub-optimal solution, because that optimization would require +// extra, rather expensive math while the rasterizer tolerates it quite well, +// without any considerable overhead. +// +//---------------------------------------------------------------------------- +#ifndef AGG_CONV_CLIP_polyline_INCLUDED +#define AGG_CONV_CLIP_polyline_INCLUDED + +#include "agg_basics.h" +#include "agg_conv_adaptor_vpgen.h" +#include "agg_vpgen_clip_polyline.h" + +namespace agg +{ + + //=======================================================conv_clip_polyline + template<class VertexSource> + struct conv_clip_polyline : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline> + { + typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline> base_type; + + conv_clip_polyline(VertexSource& vs) : + conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>(vs) {} + + void clip_box(double x1, double y1, double x2, double y2) + { + base_type::vpgen().clip_box(x1, y1, x2, y2); + } + + double x1() const { return base_type::vpgen().x1(); } + double y1() const { return base_type::vpgen().y1(); } + double x2() const { return base_type::vpgen().x2(); } + double y2() const { return base_type::vpgen().y2(); } + + private: + conv_clip_polyline(const conv_clip_polyline<VertexSource>&); + const conv_clip_polyline<VertexSource>& + operator = (const conv_clip_polyline<VertexSource>&); + }; + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_conv_close_polygon.h b/jni/desmume/src/android/agg/include/agg_conv_close_polygon.h new file mode 100755 index 0000000..85e5e28 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_conv_close_polygon.h @@ -0,0 +1,134 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_CLOSE_POLYGON_INCLUDED +#define AGG_CONV_CLOSE_POLYGON_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //======================================================conv_close_polygon + template<class VertexSource> class conv_close_polygon + { + public: + explicit conv_close_polygon(VertexSource& vs) : m_source(&vs) {} + void attach(VertexSource& source) { m_source = &source; } + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + conv_close_polygon(const conv_close_polygon<VertexSource>&); + const conv_close_polygon<VertexSource>& + operator = (const conv_close_polygon<VertexSource>&); + + VertexSource* m_source; + unsigned m_cmd[2]; + double m_x[2]; + double m_y[2]; + unsigned m_vertex; + bool m_line_to; + }; + + + + //------------------------------------------------------------------------ + template<class VertexSource> + void conv_close_polygon<VertexSource>::rewind(unsigned path_id) + { + m_source->rewind(path_id); + m_vertex = 2; + m_line_to = false; + } + + + + //------------------------------------------------------------------------ + template<class VertexSource> + unsigned conv_close_polygon<VertexSource>::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + for(;;) + { + if(m_vertex < 2) + { + *x = m_x[m_vertex]; + *y = m_y[m_vertex]; + cmd = m_cmd[m_vertex]; + ++m_vertex; + break; + } + + cmd = m_source->vertex(x, y); + + if(is_end_poly(cmd)) + { + cmd |= path_flags_close; + break; + } + + if(is_stop(cmd)) + { + if(m_line_to) + { + m_cmd[0] = path_cmd_end_poly | path_flags_close; + m_cmd[1] = path_cmd_stop; + m_vertex = 0; + m_line_to = false; + continue; + } + break; + } + + if(is_move_to(cmd)) + { + if(m_line_to) + { + m_x[0] = 0.0; + m_y[0] = 0.0; + m_cmd[0] = path_cmd_end_poly | path_flags_close; + m_x[1] = *x; + m_y[1] = *y; + m_cmd[1] = cmd; + m_vertex = 0; + m_line_to = false; + continue; + } + break; + } + + if(is_vertex(cmd)) + { + m_line_to = true; + break; + } + } + return cmd; + } + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_conv_concat.h b/jni/desmume/src/android/agg/include/agg_conv_concat.h new file mode 100755 index 0000000..60b23e8 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_conv_concat.h @@ -0,0 +1,82 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_CONCAT_INCLUDED +#define AGG_CONV_CONCAT_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //=============================================================conv_concat + // Concatenation of two paths. Usually used to combine lines or curves + // with markers such as arrowheads + template<class VS1, class VS2> class conv_concat + { + public: + conv_concat(VS1& source1, VS2& source2) : + m_source1(&source1), m_source2(&source2), m_status(2) {} + void attach1(VS1& source) { m_source1 = &source; } + void attach2(VS2& source) { m_source2 = &source; } + + + void rewind(unsigned path_id) + { + m_source1->rewind(path_id); + m_source2->rewind(0); + m_status = 0; + } + + unsigned vertex(double* x, double* y) + { + unsigned cmd; + if(m_status == 0) + { + cmd = m_source1->vertex(x, y); + if(!is_stop(cmd)) return cmd; + m_status = 1; + } + if(m_status == 1) + { + cmd = m_source2->vertex(x, y); + if(!is_stop(cmd)) return cmd; + m_status = 2; + } + return path_cmd_stop; + } + + private: + conv_concat(const conv_concat<VS1, VS2>&); + const conv_concat<VS1, VS2>& + operator = (const conv_concat<VS1, VS2>&); + + VS1* m_source1; + VS2* m_source2; + int m_status; + + }; +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_conv_contour.h b/jni/desmume/src/android/agg/include/agg_conv_contour.h new file mode 100755 index 0000000..dd29861 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_conv_contour.h @@ -0,0 +1,71 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_CONTOUR_INCLUDED +#define AGG_CONV_CONTOUR_INCLUDED + +#include "agg_basics.h" +#include "agg_vcgen_contour.h" +#include "agg_conv_adaptor_vcgen.h" + +namespace agg +{ + + //-----------------------------------------------------------conv_contour + template<class VertexSource> + struct conv_contour : public conv_adaptor_vcgen<VertexSource, vcgen_contour> + { + typedef conv_adaptor_vcgen<VertexSource, vcgen_contour> base_type; + + conv_contour(VertexSource& vs) : + conv_adaptor_vcgen<VertexSource, vcgen_contour>(vs) + { + } + + void line_join(line_join_e lj) { base_type::generator().line_join(lj); } + void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); } + void width(double w) { base_type::generator().width(w); } + void miter_limit(double ml) { base_type::generator().miter_limit(ml); } + void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); } + void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); } + void approximation_scale(double as) { base_type::generator().approximation_scale(as); } + void auto_detect_orientation(bool v) { base_type::generator().auto_detect_orientation(v); } + + line_join_e line_join() const { return base_type::generator().line_join(); } + inner_join_e inner_join() const { return base_type::generator().inner_join(); } + double width() const { return base_type::generator().width(); } + double miter_limit() const { return base_type::generator().miter_limit(); } + double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); } + double approximation_scale() const { return base_type::generator().approximation_scale(); } + bool auto_detect_orientation() const { return base_type::generator().auto_detect_orientation(); } + + private: + conv_contour(const conv_contour<VertexSource>&); + const conv_contour<VertexSource>& + operator = (const conv_contour<VertexSource>&); + }; + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_conv_curve.h b/jni/desmume/src/android/agg/include/agg_conv_curve.h new file mode 100755 index 0000000..1280903 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_conv_curve.h @@ -0,0 +1,206 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_CURVE_INCLUDED +#define AGG_CONV_CURVE_INCLUDED + +#include "agg_basics.h" +#include "agg_curves.h" + +namespace agg +{ + + + //---------------------------------------------------------------conv_curve + // Curve converter class. Any path storage can have Bezier curves defined + // by their control points. There're two types of curves supported: curve3 + // and curve4. Curve3 is a conic Bezier curve with 2 endpoints and 1 control + // point. Curve4 has 2 control points (4 points in total) and can be used + // to interpolate more complicated curves. Curve4, unlike curve3 can be used + // to approximate arcs, both circular and elliptical. Curves are approximated + // with straight lines and one of the approaches is just to store the whole + // sequence of vertices that approximate our curve. It takes additional + // memory, and at the same time the consecutive vertices can be calculated + // on demand. + // + // Initially, path storages are not suppose to keep all the vertices of the + // curves (although, nothing prevents us from doing so). Instead, path_storage + // keeps only vertices, needed to calculate a curve on demand. Those vertices + // are marked with special commands. So, if the path_storage contains curves + // (which are not real curves yet), and we render this storage directly, + // all we will see is only 2 or 3 straight line segments (for curve3 and + // curve4 respectively). If we need to see real curves drawn we need to + // include this class into the conversion pipeline. + // + // Class conv_curve recognizes commands path_cmd_curve3 and path_cmd_curve4 + // and converts these vertices into a move_to/line_to sequence. + //----------------------------------------------------------------------- + template<class VertexSource, + class Curve3=curve3, + class Curve4=curve4> class conv_curve + { + public: + typedef Curve3 curve3_type; + typedef Curve4 curve4_type; + typedef conv_curve<VertexSource, Curve3, Curve4> self_type; + + explicit conv_curve(VertexSource& source) : + m_source(&source), m_last_x(0.0), m_last_y(0.0) {} + void attach(VertexSource& source) { m_source = &source; } + + void approximation_method(curve_approximation_method_e v) + { + m_curve3.approximation_method(v); + m_curve4.approximation_method(v); + } + + curve_approximation_method_e approximation_method() const + { + return m_curve4.approximation_method(); + } + + void approximation_scale(double s) + { + m_curve3.approximation_scale(s); + m_curve4.approximation_scale(s); + } + + double approximation_scale() const + { + return m_curve4.approximation_scale(); + } + + void angle_tolerance(double v) + { + m_curve3.angle_tolerance(v); + m_curve4.angle_tolerance(v); + } + + double angle_tolerance() const + { + return m_curve4.angle_tolerance(); + } + + void cusp_limit(double v) + { + m_curve3.cusp_limit(v); + m_curve4.cusp_limit(v); + } + + double cusp_limit() const + { + return m_curve4.cusp_limit(); + } + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + conv_curve(const self_type&); + const self_type& operator = (const self_type&); + + VertexSource* m_source; + double m_last_x; + double m_last_y; + curve3_type m_curve3; + curve4_type m_curve4; + }; + + + + //------------------------------------------------------------------------ + template<class VertexSource, class Curve3, class Curve4> + void conv_curve<VertexSource, Curve3, Curve4>::rewind(unsigned path_id) + { + m_source->rewind(path_id); + m_last_x = 0.0; + m_last_y = 0.0; + m_curve3.reset(); + m_curve4.reset(); + } + + + //------------------------------------------------------------------------ + template<class VertexSource, class Curve3, class Curve4> + unsigned conv_curve<VertexSource, Curve3, Curve4>::vertex(double* x, double* y) + { + if(!is_stop(m_curve3.vertex(x, y))) + { + m_last_x = *x; + m_last_y = *y; + return path_cmd_line_to; + } + + if(!is_stop(m_curve4.vertex(x, y))) + { + m_last_x = *x; + m_last_y = *y; + return path_cmd_line_to; + } + + double ct2_x; + double ct2_y; + double end_x; + double end_y; + + unsigned cmd = m_source->vertex(x, y); + switch(cmd) + { + case path_cmd_curve3: + m_source->vertex(&end_x, &end_y); + + m_curve3.init(m_last_x, m_last_y, + *x, *y, + end_x, end_y); + + m_curve3.vertex(x, y); // First call returns path_cmd_move_to + m_curve3.vertex(x, y); // This is the first vertex of the curve + cmd = path_cmd_line_to; + break; + + case path_cmd_curve4: + m_source->vertex(&ct2_x, &ct2_y); + m_source->vertex(&end_x, &end_y); + + m_curve4.init(m_last_x, m_last_y, + *x, *y, + ct2_x, ct2_y, + end_x, end_y); + + m_curve4.vertex(x, y); // First call returns path_cmd_move_to + m_curve4.vertex(x, y); // This is the first vertex of the curve + cmd = path_cmd_line_to; + break; + } + m_last_x = *x; + m_last_y = *y; + return cmd; + } + + +} + + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_conv_dash.h b/jni/desmume/src/android/agg/include/agg_conv_dash.h new file mode 100755 index 0000000..4c57444 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_conv_dash.h @@ -0,0 +1,74 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_DASH_INCLUDED +#define AGG_CONV_DASH_INCLUDED + +#include "agg_basics.h" +#include "agg_vcgen_dash.h" +#include "agg_conv_adaptor_vcgen.h" + +namespace agg +{ + + //---------------------------------------------------------------conv_dash + template<class VertexSource, class Markers=null_markers> + struct conv_dash : public conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers> + { + typedef Markers marker_type; + typedef conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers> base_type; + + conv_dash(VertexSource& vs) : + conv_adaptor_vcgen<VertexSource, vcgen_dash, Markers>(vs) + { + } + + void remove_all_dashes() + { + base_type::generator().remove_all_dashes(); + } + + void add_dash(double dash_len, double gap_len) + { + base_type::generator().add_dash(dash_len, gap_len); + } + + void dash_start(double ds) + { + base_type::generator().dash_start(ds); + } + + void shorten(double s) { base_type::generator().shorten(s); } + double shorten() const { return base_type::generator().shorten(); } + + private: + conv_dash(const conv_dash<VertexSource, Markers>&); + const conv_dash<VertexSource, Markers>& + operator = (const conv_dash<VertexSource, Markers>&); + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_conv_gpc.h b/jni/desmume/src/android/agg/include/agg_conv_gpc.h new file mode 100755 index 0000000..2d5913c --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_conv_gpc.h @@ -0,0 +1,441 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// General Polygon Clipper based on the GPC library by Alan Murta +// Union, Intersection, XOR, A-B, B-A +// Contact the author if you intend to use it in commercial applications! +// http://www.cs.man.ac.uk/aig/staff/alan/software/ +// Alan Murta (email: gpc@cs.man.ac.uk) +// +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_GPC_INCLUDED +#define AGG_CONV_GPC_INCLUDED + +#include <math.h> +#include "agg_basics.h" +#include "agg_array.h" + +extern "C" +{ +#include "gpc.h" +} + +namespace agg +{ + enum gpc_op_e + { + gpc_or, + gpc_and, + gpc_xor, + gpc_a_minus_b, + gpc_b_minus_a + }; + + + //================================================================conv_gpc + template<class VSA, class VSB> class conv_gpc + { + enum status + { + status_move_to, + status_line_to, + status_stop + }; + + struct contour_header_type + { + int num_vertices; + int hole_flag; + gpc_vertex* vertices; + }; + + typedef pod_bvector<gpc_vertex, 8> vertex_array_type; + typedef pod_bvector<contour_header_type, 6> contour_header_array_type; + + + public: + typedef VSA source_a_type; + typedef VSB source_b_type; + typedef conv_gpc<source_a_type, source_b_type> self_type; + + ~conv_gpc() + { + free_gpc_data(); + } + + conv_gpc(source_a_type& a, source_b_type& b, gpc_op_e op = gpc_or) : + m_src_a(&a), + m_src_b(&b), + m_status(status_move_to), + m_vertex(-1), + m_contour(-1), + m_operation(op) + { + memset(&m_poly_a, 0, sizeof(m_poly_a)); + memset(&m_poly_b, 0, sizeof(m_poly_b)); + memset(&m_result, 0, sizeof(m_result)); + } + + void attach1(VSA& source) { m_src_a = &source; } + void attach2(VSB& source) { m_src_b = &source; } + + void operation(gpc_op_e v) { m_operation = v; } + + // Vertex Source Interface + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + conv_gpc(const conv_gpc<VSA, VSB>&); + const conv_gpc<VSA, VSB>& operator = (const conv_gpc<VSA, VSB>&); + + //-------------------------------------------------------------------- + void free_polygon(gpc_polygon& p); + void free_result(); + void free_gpc_data(); + void start_contour(); + void add_vertex(double x, double y); + void end_contour(unsigned orientation); + void make_polygon(gpc_polygon& p); + void start_extracting(); + bool next_contour(); + bool next_vertex(double* x, double* y); + + + //-------------------------------------------------------------------- + template<class VS> void add(VS& src, gpc_polygon& p) + { + unsigned cmd; + double x, y; + double start_x = 0.0; + double start_y = 0.0; + bool line_to = false; + unsigned orientation = 0; + + m_contour_accumulator.remove_all(); + + while(!is_stop(cmd = src.vertex(&x, &y))) + { + if(is_vertex(cmd)) + { + if(is_move_to(cmd)) + { + if(line_to) + { + end_contour(orientation); + orientation = 0; + } + start_contour(); + start_x = x; + start_y = y; + } + add_vertex(x, y); + line_to = true; + } + else + { + if(is_end_poly(cmd)) + { + orientation = get_orientation(cmd); + if(line_to && is_closed(cmd)) + { + add_vertex(start_x, start_y); + } + } + } + } + if(line_to) + { + end_contour(orientation); + } + make_polygon(p); + } + + + private: + //-------------------------------------------------------------------- + source_a_type* m_src_a; + source_b_type* m_src_b; + status m_status; + int m_vertex; + int m_contour; + gpc_op_e m_operation; + vertex_array_type m_vertex_accumulator; + contour_header_array_type m_contour_accumulator; + gpc_polygon m_poly_a; + gpc_polygon m_poly_b; + gpc_polygon m_result; + }; + + + + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + void conv_gpc<VSA, VSB>::free_polygon(gpc_polygon& p) + { + int i; + for(i = 0; i < p.num_contours; i++) + { + pod_allocator<gpc_vertex>::deallocate(p.contour[i].vertex, + p.contour[i].num_vertices); + } + pod_allocator<gpc_vertex_list>::deallocate(p.contour, p.num_contours); + memset(&p, 0, sizeof(gpc_polygon)); + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + void conv_gpc<VSA, VSB>::free_result() + { + if(m_result.contour) + { + gpc_free_polygon(&m_result); + } + memset(&m_result, 0, sizeof(m_result)); + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + void conv_gpc<VSA, VSB>::free_gpc_data() + { + free_polygon(m_poly_a); + free_polygon(m_poly_b); + free_result(); + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + void conv_gpc<VSA, VSB>::start_contour() + { + contour_header_type h; + memset(&h, 0, sizeof(h)); + m_contour_accumulator.add(h); + m_vertex_accumulator.remove_all(); + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + inline void conv_gpc<VSA, VSB>::add_vertex(double x, double y) + { + gpc_vertex v; + v.x = x; + v.y = y; + m_vertex_accumulator.add(v); + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + void conv_gpc<VSA, VSB>::end_contour(unsigned orientation) + { + if(m_contour_accumulator.size()) + { + if(m_vertex_accumulator.size() > 2) + { + contour_header_type& h = + m_contour_accumulator[m_contour_accumulator.size() - 1]; + + h.num_vertices = m_vertex_accumulator.size(); + h.hole_flag = 0; + + // TO DO: Clarify the "holes" + //if(is_cw(orientation)) h.hole_flag = 1; + + h.vertices = pod_allocator<gpc_vertex>::allocate(h.num_vertices); + gpc_vertex* d = h.vertices; + int i; + for(i = 0; i < h.num_vertices; i++) + { + const gpc_vertex& s = m_vertex_accumulator[i]; + d->x = s.x; + d->y = s.y; + ++d; + } + } + else + { + m_vertex_accumulator.remove_last(); + } + } + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + void conv_gpc<VSA, VSB>::make_polygon(gpc_polygon& p) + { + free_polygon(p); + if(m_contour_accumulator.size()) + { + p.num_contours = m_contour_accumulator.size(); + + p.hole = 0; + p.contour = pod_allocator<gpc_vertex_list>::allocate(p.num_contours); + + int i; + gpc_vertex_list* pv = p.contour; + for(i = 0; i < p.num_contours; i++) + { + const contour_header_type& h = m_contour_accumulator[i]; + pv->num_vertices = h.num_vertices; + pv->vertex = h.vertices; + ++pv; + } + } + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + void conv_gpc<VSA, VSB>::start_extracting() + { + m_status = status_move_to; + m_contour = -1; + m_vertex = -1; + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + bool conv_gpc<VSA, VSB>::next_contour() + { + if(++m_contour < m_result.num_contours) + { + m_vertex = -1; + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + inline bool conv_gpc<VSA, VSB>::next_vertex(double* x, double* y) + { + const gpc_vertex_list& vlist = m_result.contour[m_contour]; + if(++m_vertex < vlist.num_vertices) + { + const gpc_vertex& v = vlist.vertex[m_vertex]; + *x = v.x; + *y = v.y; + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + void conv_gpc<VSA, VSB>::rewind(unsigned path_id) + { + free_result(); + m_src_a->rewind(path_id); + m_src_b->rewind(path_id); + add(*m_src_a, m_poly_a); + add(*m_src_b, m_poly_b); + switch(m_operation) + { + case gpc_or: + gpc_polygon_clip(GPC_UNION, + &m_poly_a, + &m_poly_b, + &m_result); + break; + + case gpc_and: + gpc_polygon_clip(GPC_INT, + &m_poly_a, + &m_poly_b, + &m_result); + break; + + case gpc_xor: + gpc_polygon_clip(GPC_XOR, + &m_poly_a, + &m_poly_b, + &m_result); + break; + + case gpc_a_minus_b: + gpc_polygon_clip(GPC_DIFF, + &m_poly_a, + &m_poly_b, + &m_result); + break; + + case gpc_b_minus_a: + gpc_polygon_clip(GPC_DIFF, + &m_poly_b, + &m_poly_a, + &m_result); + break; + } + start_extracting(); + } + + + //------------------------------------------------------------------------ + template<class VSA, class VSB> + unsigned conv_gpc<VSA, VSB>::vertex(double* x, double* y) + { + if(m_status == status_move_to) + { + if(next_contour()) + { + if(next_vertex(x, y)) + { + m_status = status_line_to; + return path_cmd_move_to; + } + m_status = status_stop; + return path_cmd_end_poly | path_flags_close; + } + } + else + { + if(next_vertex(x, y)) + { + return path_cmd_line_to; + } + else + { + m_status = status_move_to; + } + return path_cmd_end_poly | path_flags_close; + } + return path_cmd_stop; + } + + +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_conv_marker.h b/jni/desmume/src/android/agg/include/agg_conv_marker.h new file mode 100755 index 0000000..3f261d3 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_conv_marker.h @@ -0,0 +1,154 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_MARKER_INCLUDED +#define AGG_CONV_MARKER_INCLUDED + +#include "agg_basics.h" +#include "agg_trans_affine.h" + +namespace agg +{ + //-------------------------------------------------------------conv_marker + template<class MarkerLocator, class MarkerShapes> + class conv_marker + { + public: + conv_marker(MarkerLocator& ml, MarkerShapes& ms); + + trans_affine& transform() { return m_transform; } + const trans_affine& transform() const { return m_transform; } + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + conv_marker(const conv_marker<MarkerLocator, MarkerShapes>&); + const conv_marker<MarkerLocator, MarkerShapes>& + operator = (const conv_marker<MarkerLocator, MarkerShapes>&); + + enum status_e + { + initial, + markers, + polygon, + stop + }; + + MarkerLocator* m_marker_locator; + MarkerShapes* m_marker_shapes; + trans_affine m_transform; + trans_affine m_mtx; + status_e m_status; + unsigned m_marker; + unsigned m_num_markers; + }; + + + //------------------------------------------------------------------------ + template<class MarkerLocator, class MarkerShapes> + conv_marker<MarkerLocator, MarkerShapes>::conv_marker(MarkerLocator& ml, MarkerShapes& ms) : + m_marker_locator(&ml), + m_marker_shapes(&ms), + m_status(initial), + m_marker(0), + m_num_markers(1) + { + } + + + //------------------------------------------------------------------------ + template<class MarkerLocator, class MarkerShapes> + void conv_marker<MarkerLocator, MarkerShapes>::rewind(unsigned) + { + m_status = initial; + m_marker = 0; + m_num_markers = 1; + } + + + //------------------------------------------------------------------------ + template<class MarkerLocator, class MarkerShapes> + unsigned conv_marker<MarkerLocator, MarkerShapes>::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_move_to; + double x1, y1, x2, y2; + + while(!is_stop(cmd)) + { + switch(m_status) + { + case initial: + if(m_num_markers == 0) + { + cmd = path_cmd_stop; + break; + } + m_marker_locator->rewind(m_marker); + ++m_marker; + m_num_markers = 0; + m_status = markers; + + case markers: + if(is_stop(m_marker_locator->vertex(&x1, &y1))) + { + m_status = initial; + break; + } + if(is_stop(m_marker_locator->vertex(&x2, &y2))) + { + m_status = initial; + break; + } + ++m_num_markers; + m_mtx = m_transform; + m_mtx *= trans_affine_rotation(atan2(y2 - y1, x2 - x1)); + m_mtx *= trans_affine_translation(x1, y1); + m_marker_shapes->rewind(m_marker - 1); + m_status = polygon; + + case polygon: + cmd = m_marker_shapes->vertex(x, y); + if(is_stop(cmd)) + { + cmd = path_cmd_move_to; + m_status = markers; + break; + } + m_mtx.transform(x, y); + return cmd; + + case stop: + cmd = path_cmd_stop; + break; + } + } + return cmd; + } + +} + + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_conv_marker_adaptor.h b/jni/desmume/src/android/agg/include/agg_conv_marker_adaptor.h new file mode 100755 index 0000000..54694ba --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_conv_marker_adaptor.h @@ -0,0 +1,60 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_MARKER_ADAPTOR_INCLUDED +#define AGG_CONV_MARKER_ADAPTOR_INCLUDED + +#include "agg_basics.h" +#include "agg_conv_adaptor_vcgen.h" +#include "agg_vcgen_vertex_sequence.h" + +namespace agg +{ + + //=====================================================conv_marker_adaptor + template<class VertexSource, class Markers=null_markers> + struct conv_marker_adaptor : + public conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers> + { + typedef Markers marker_type; + typedef conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers> base_type; + + conv_marker_adaptor(VertexSource& vs) : + conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence, Markers>(vs) + { + } + + void shorten(double s) { base_type::generator().shorten(s); } + double shorten() const { return base_type::generator().shorten(); } + + private: + conv_marker_adaptor(const conv_marker_adaptor<VertexSource, Markers>&); + const conv_marker_adaptor<VertexSource, Markers>& + operator = (const conv_marker_adaptor<VertexSource, Markers>&); + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_conv_segmentator.h b/jni/desmume/src/android/agg/include/agg_conv_segmentator.h new file mode 100755 index 0000000..04466c8 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_conv_segmentator.h @@ -0,0 +1,57 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_SEGMENTATOR_INCLUDED +#define AGG_CONV_SEGMENTATOR_INCLUDED + +#include "agg_basics.h" +#include "agg_conv_adaptor_vpgen.h" +#include "agg_vpgen_segmentator.h" + +namespace agg +{ + + //========================================================conv_segmentator + template<class VertexSource> + struct conv_segmentator : public conv_adaptor_vpgen<VertexSource, vpgen_segmentator> + { + typedef conv_adaptor_vpgen<VertexSource, vpgen_segmentator> base_type; + + conv_segmentator(VertexSource& vs) : + conv_adaptor_vpgen<VertexSource, vpgen_segmentator>(vs) {} + + void approximation_scale(double s) { base_type::vpgen().approximation_scale(s); } + double approximation_scale() const { return base_type::vpgen().approximation_scale(); } + + private: + conv_segmentator(const conv_segmentator<VertexSource>&); + const conv_segmentator<VertexSource>& + operator = (const conv_segmentator<VertexSource>&); + }; + + +} + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_conv_shorten_path.h b/jni/desmume/src/android/agg/include/agg_conv_shorten_path.h new file mode 100755 index 0000000..96b7387 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_conv_shorten_path.h @@ -0,0 +1,59 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_SHORTEN_PATH_INCLUDED +#define AGG_CONV_SHORTEN_PATH_INCLUDED + +#include "agg_basics.h" +#include "agg_conv_adaptor_vcgen.h" +#include "agg_vcgen_vertex_sequence.h" + +namespace agg +{ + + //=======================================================conv_shorten_path + template<class VertexSource> class conv_shorten_path : + public conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence> + { + public: + typedef conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence> base_type; + + conv_shorten_path(VertexSource& vs) : + conv_adaptor_vcgen<VertexSource, vcgen_vertex_sequence>(vs) + { + } + + void shorten(double s) { base_type::generator().shorten(s); } + double shorten() const { return base_type::generator().shorten(); } + + private: + conv_shorten_path(const conv_shorten_path<VertexSource>&); + const conv_shorten_path<VertexSource>& + operator = (const conv_shorten_path<VertexSource>&); + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_conv_smooth_poly1.h b/jni/desmume/src/android/agg/include/agg_conv_smooth_poly1.h new file mode 100755 index 0000000..15f7f8d --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_conv_smooth_poly1.h @@ -0,0 +1,86 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_SMOOTH_POLY1_INCLUDED +#define AGG_CONV_SMOOTH_POLY1_INCLUDED + +#include "agg_basics.h" +#include "agg_vcgen_smooth_poly1.h" +#include "agg_conv_adaptor_vcgen.h" +#include "agg_conv_curve.h" + + +namespace agg +{ + + //-------------------------------------------------------conv_smooth_poly1 + template<class VertexSource> + struct conv_smooth_poly1 : + public conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1> + { + typedef conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1> base_type; + + conv_smooth_poly1(VertexSource& vs) : + conv_adaptor_vcgen<VertexSource, vcgen_smooth_poly1>(vs) + { + } + + void smooth_value(double v) { base_type::generator().smooth_value(v); } + double smooth_value() const { return base_type::generator().smooth_value(); } + + private: + conv_smooth_poly1(const conv_smooth_poly1<VertexSource>&); + const conv_smooth_poly1<VertexSource>& + operator = (const conv_smooth_poly1<VertexSource>&); + }; + + + + //-------------------------------------------------conv_smooth_poly1_curve + template<class VertexSource> + struct conv_smooth_poly1_curve : + public conv_curve<conv_smooth_poly1<VertexSource> > + { + conv_smooth_poly1_curve(VertexSource& vs) : + conv_curve<conv_smooth_poly1<VertexSource> >(m_smooth), + m_smooth(vs) + { + } + + void smooth_value(double v) { m_smooth.generator().smooth_value(v); } + double smooth_value() const { return m_smooth.generator().smooth_value(); } + + private: + conv_smooth_poly1_curve(const conv_smooth_poly1_curve<VertexSource>&); + const conv_smooth_poly1_curve<VertexSource>& + operator = (const conv_smooth_poly1_curve<VertexSource>&); + + conv_smooth_poly1<VertexSource> m_smooth; + }; + +} + + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_conv_stroke.h b/jni/desmume/src/android/agg/include/agg_conv_stroke.h new file mode 100755 index 0000000..2713100 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_conv_stroke.h @@ -0,0 +1,79 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_STROKE_INCLUDED +#define AGG_CONV_STROKE_INCLUDED + +#include "agg_basics.h" +#include "agg_vcgen_stroke.h" +#include "agg_conv_adaptor_vcgen.h" + +namespace agg +{ + + //-------------------------------------------------------------conv_stroke + template<class VertexSource, class Markers=null_markers> + struct conv_stroke : + public conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers> + { + typedef Markers marker_type; + typedef conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers> base_type; + + conv_stroke(VertexSource& vs) : + conv_adaptor_vcgen<VertexSource, vcgen_stroke, Markers>(vs) + { + } + + void line_cap(line_cap_e lc) { base_type::generator().line_cap(lc); } + void line_join(line_join_e lj) { base_type::generator().line_join(lj); } + void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); } + + line_cap_e line_cap() const { return base_type::generator().line_cap(); } + line_join_e line_join() const { return base_type::generator().line_join(); } + inner_join_e inner_join() const { return base_type::generator().inner_join(); } + + void width(double w) { base_type::generator().width(w); } + void miter_limit(double ml) { base_type::generator().miter_limit(ml); } + void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); } + void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); } + void approximation_scale(double as) { base_type::generator().approximation_scale(as); } + + double width() const { return base_type::generator().width(); } + double miter_limit() const { return base_type::generator().miter_limit(); } + double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); } + double approximation_scale() const { return base_type::generator().approximation_scale(); } + + void shorten(double s) { base_type::generator().shorten(s); } + double shorten() const { return base_type::generator().shorten(); } + + private: + conv_stroke(const conv_stroke<VertexSource, Markers>&); + const conv_stroke<VertexSource, Markers>& + operator = (const conv_stroke<VertexSource, Markers>&); + + }; + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_conv_transform.h b/jni/desmume/src/android/agg/include/agg_conv_transform.h new file mode 100755 index 0000000..33c19b6 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_conv_transform.h @@ -0,0 +1,74 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_TRANSFORM_INCLUDED +#define AGG_CONV_TRANSFORM_INCLUDED + +#include "agg_basics.h" +#include "agg_trans_affine.h" + +namespace agg +{ + + //----------------------------------------------------------conv_transform + template<class VertexSource, class Transformer=trans_affine> class conv_transform + { + public: + conv_transform(VertexSource& source, const Transformer& tr) : + m_source(&source), m_trans(&tr) {} + void attach(VertexSource& source) { m_source = &source; } + + void rewind(unsigned path_id) + { + m_source->rewind(path_id); + } + + unsigned vertex(double* x, double* y) + { + unsigned cmd = m_source->vertex(x, y); + if(is_vertex(cmd)) + { + m_trans->transform(x, y); + } + return cmd; + } + + void transformer(const Transformer& tr) + { + m_trans = &tr; + } + + private: + conv_transform(const conv_transform<VertexSource>&); + const conv_transform<VertexSource>& + operator = (const conv_transform<VertexSource>&); + + VertexSource* m_source; + const Transformer* m_trans; + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_conv_unclose_polygon.h b/jni/desmume/src/android/agg/include/agg_conv_unclose_polygon.h new file mode 100755 index 0000000..9375705 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_conv_unclose_polygon.h @@ -0,0 +1,61 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_UNCLOSE_POLYGON_INCLUDED +#define AGG_CONV_UNCLOSE_POLYGON_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //====================================================conv_unclose_polygon + template<class VertexSource> class conv_unclose_polygon + { + public: + explicit conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {} + void attach(VertexSource& source) { m_source = &source; } + + void rewind(unsigned path_id) + { + m_source->rewind(path_id); + } + + unsigned vertex(double* x, double* y) + { + unsigned cmd = m_source->vertex(x, y); + if(is_end_poly(cmd)) cmd &= ~path_flags_close; + return cmd; + } + + private: + conv_unclose_polygon(const conv_unclose_polygon<VertexSource>&); + const conv_unclose_polygon<VertexSource>& + operator = (const conv_unclose_polygon<VertexSource>&); + + VertexSource* m_source; + }; + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_curves.h b/jni/desmume/src/android/agg/include/agg_curves.h new file mode 100755 index 0000000..25845ca --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_curves.h @@ -0,0 +1,701 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_CURVES_INCLUDED +#define AGG_CURVES_INCLUDED + +#include "agg_array.h" + +namespace agg +{ + + // See Implementation agg_curves.cpp + + //--------------------------------------------curve_approximation_method_e + enum curve_approximation_method_e + { + curve_inc, + curve_div + }; + + //--------------------------------------------------------------curve3_inc + class curve3_inc + { + public: + curve3_inc() : + m_num_steps(0), m_step(0), m_scale(1.0) { } + + curve3_inc(double x1, double y1, + double x2, double y2, + double x3, double y3) : + m_num_steps(0), m_step(0), m_scale(1.0) + { + init(x1, y1, x2, y2, x3, y3); + } + + void reset() { m_num_steps = 0; m_step = -1; } + void init(double x1, double y1, + double x2, double y2, + double x3, double y3); + + void approximation_method(curve_approximation_method_e) {} + curve_approximation_method_e approximation_method() const { return curve_inc; } + + void approximation_scale(double s); + double approximation_scale() const; + + void angle_tolerance(double) {} + double angle_tolerance() const { return 0.0; } + + void cusp_limit(double) {} + double cusp_limit() const { return 0.0; } + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + int m_num_steps; + int m_step; + double m_scale; + double m_start_x; + double m_start_y; + double m_end_x; + double m_end_y; + double m_fx; + double m_fy; + double m_dfx; + double m_dfy; + double m_ddfx; + double m_ddfy; + double m_saved_fx; + double m_saved_fy; + double m_saved_dfx; + double m_saved_dfy; + }; + + + + + + //-------------------------------------------------------------curve3_div + class curve3_div + { + public: + curve3_div() : + m_approximation_scale(1.0), + m_angle_tolerance(0.0), + m_count(0) + {} + + curve3_div(double x1, double y1, + double x2, double y2, + double x3, double y3) : + m_approximation_scale(1.0), + m_angle_tolerance(0.0), + m_count(0) + { + init(x1, y1, x2, y2, x3, y3); + } + + void reset() { m_points.remove_all(); m_count = 0; } + void init(double x1, double y1, + double x2, double y2, + double x3, double y3); + + void approximation_method(curve_approximation_method_e) {} + curve_approximation_method_e approximation_method() const { return curve_div; } + + void approximation_scale(double s) { m_approximation_scale = s; } + double approximation_scale() const { return m_approximation_scale; } + + void angle_tolerance(double a) { m_angle_tolerance = a; } + double angle_tolerance() const { return m_angle_tolerance; } + + void cusp_limit(double) {} + double cusp_limit() const { return 0.0; } + + void rewind(unsigned) + { + m_count = 0; + } + + unsigned vertex(double* x, double* y) + { + if(m_count >= m_points.size()) return path_cmd_stop; + const point_d& p = m_points[m_count++]; + *x = p.x; + *y = p.y; + return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to; + } + + private: + void bezier(double x1, double y1, + double x2, double y2, + double x3, double y3); + void recursive_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + unsigned level); + + double m_approximation_scale; + double m_distance_tolerance_square; + double m_angle_tolerance; + unsigned m_count; + pod_bvector<point_d> m_points; + }; + + + + + + + + //-------------------------------------------------------------curve4_points + struct curve4_points + { + double cp[8]; + curve4_points() {} + curve4_points(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2; + cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4; + } + void init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2; + cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4; + } + double operator [] (unsigned i) const { return cp[i]; } + double& operator [] (unsigned i) { return cp[i]; } + }; + + + + //-------------------------------------------------------------curve4_inc + class curve4_inc + { + public: + curve4_inc() : + m_num_steps(0), m_step(0), m_scale(1.0) { } + + curve4_inc(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) : + m_num_steps(0), m_step(0), m_scale(1.0) + { + init(x1, y1, x2, y2, x3, y3, x4, y4); + } + + curve4_inc(const curve4_points& cp) : + m_num_steps(0), m_step(0), m_scale(1.0) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void reset() { m_num_steps = 0; m_step = -1; } + void init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4); + + void init(const curve4_points& cp) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void approximation_method(curve_approximation_method_e) {} + curve_approximation_method_e approximation_method() const { return curve_inc; } + + void approximation_scale(double s); + double approximation_scale() const; + + void angle_tolerance(double) {} + double angle_tolerance() const { return 0.0; } + + void cusp_limit(double) {} + double cusp_limit() const { return 0.0; } + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + int m_num_steps; + int m_step; + double m_scale; + double m_start_x; + double m_start_y; + double m_end_x; + double m_end_y; + double m_fx; + double m_fy; + double m_dfx; + double m_dfy; + double m_ddfx; + double m_ddfy; + double m_dddfx; + double m_dddfy; + double m_saved_fx; + double m_saved_fy; + double m_saved_dfx; + double m_saved_dfy; + double m_saved_ddfx; + double m_saved_ddfy; + }; + + + + //-------------------------------------------------------catrom_to_bezier + inline curve4_points catrom_to_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + // Trans. matrix Catmull-Rom to Bezier + // + // 0 1 0 0 + // -1/6 1 1/6 0 + // 0 1/6 1 -1/6 + // 0 0 1 0 + // + return curve4_points( + x2, + y2, + (-x1 + 6*x2 + x3) / 6, + (-y1 + 6*y2 + y3) / 6, + ( x2 + 6*x3 - x4) / 6, + ( y2 + 6*y3 - y4) / 6, + x3, + y3); + } + + + //----------------------------------------------------------------------- + inline curve4_points + catrom_to_bezier(const curve4_points& cp) + { + return catrom_to_bezier(cp[0], cp[1], cp[2], cp[3], + cp[4], cp[5], cp[6], cp[7]); + } + + + + //-----------------------------------------------------ubspline_to_bezier + inline curve4_points ubspline_to_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + // Trans. matrix Uniform BSpline to Bezier + // + // 1/6 4/6 1/6 0 + // 0 4/6 2/6 0 + // 0 2/6 4/6 0 + // 0 1/6 4/6 1/6 + // + return curve4_points( + (x1 + 4*x2 + x3) / 6, + (y1 + 4*y2 + y3) / 6, + (4*x2 + 2*x3) / 6, + (4*y2 + 2*y3) / 6, + (2*x2 + 4*x3) / 6, + (2*y2 + 4*y3) / 6, + (x2 + 4*x3 + x4) / 6, + (y2 + 4*y3 + y4) / 6); + } + + + //----------------------------------------------------------------------- + inline curve4_points + ubspline_to_bezier(const curve4_points& cp) + { + return ubspline_to_bezier(cp[0], cp[1], cp[2], cp[3], + cp[4], cp[5], cp[6], cp[7]); + } + + + + + //------------------------------------------------------hermite_to_bezier + inline curve4_points hermite_to_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + // Trans. matrix Hermite to Bezier + // + // 1 0 0 0 + // 1 0 1/3 0 + // 0 1 0 -1/3 + // 0 1 0 0 + // + return curve4_points( + x1, + y1, + (3*x1 + x3) / 3, + (3*y1 + y3) / 3, + (3*x2 - x4) / 3, + (3*y2 - y4) / 3, + x2, + y2); + } + + + + //----------------------------------------------------------------------- + inline curve4_points + hermite_to_bezier(const curve4_points& cp) + { + return hermite_to_bezier(cp[0], cp[1], cp[2], cp[3], + cp[4], cp[5], cp[6], cp[7]); + } + + + //-------------------------------------------------------------curve4_div + class curve4_div + { + public: + curve4_div() : + m_approximation_scale(1.0), + m_angle_tolerance(0.0), + m_cusp_limit(0.0), + m_count(0) + {} + + curve4_div(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) : + m_approximation_scale(1.0), + m_angle_tolerance(0.0), + m_cusp_limit(0.0), + m_count(0) + { + init(x1, y1, x2, y2, x3, y3, x4, y4); + } + + curve4_div(const curve4_points& cp) : + m_approximation_scale(1.0), + m_angle_tolerance(0.0), + m_count(0) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void reset() { m_points.remove_all(); m_count = 0; } + void init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4); + + void init(const curve4_points& cp) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void approximation_method(curve_approximation_method_e) {} + + curve_approximation_method_e approximation_method() const + { + return curve_div; + } + + void approximation_scale(double s) { m_approximation_scale = s; } + double approximation_scale() const { return m_approximation_scale; } + + void angle_tolerance(double a) { m_angle_tolerance = a; } + double angle_tolerance() const { return m_angle_tolerance; } + + void cusp_limit(double v) + { + m_cusp_limit = (v == 0.0) ? 0.0 : pi - v; + } + + double cusp_limit() const + { + return (m_cusp_limit == 0.0) ? 0.0 : pi - m_cusp_limit; + } + + void rewind(unsigned) + { + m_count = 0; + } + + unsigned vertex(double* x, double* y) + { + if(m_count >= m_points.size()) return path_cmd_stop; + const point_d& p = m_points[m_count++]; + *x = p.x; + *y = p.y; + return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to; + } + + private: + void bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4); + + void recursive_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4, + unsigned level); + + double m_approximation_scale; + double m_distance_tolerance_square; + double m_angle_tolerance; + double m_cusp_limit; + unsigned m_count; + pod_bvector<point_d> m_points; + }; + + + //-----------------------------------------------------------------curve3 + class curve3 + { + public: + curve3() : m_approximation_method(curve_div) {} + curve3(double x1, double y1, + double x2, double y2, + double x3, double y3) : + m_approximation_method(curve_div) + { + init(x1, y1, x2, y2, x3, y3); + } + + void reset() + { + m_curve_inc.reset(); + m_curve_div.reset(); + } + + void init(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + if(m_approximation_method == curve_inc) + { + m_curve_inc.init(x1, y1, x2, y2, x3, y3); + } + else + { + m_curve_div.init(x1, y1, x2, y2, x3, y3); + } + } + + void approximation_method(curve_approximation_method_e v) + { + m_approximation_method = v; + } + + curve_approximation_method_e approximation_method() const + { + return m_approximation_method; + } + + void approximation_scale(double s) + { + m_curve_inc.approximation_scale(s); + m_curve_div.approximation_scale(s); + } + + double approximation_scale() const + { + return m_curve_inc.approximation_scale(); + } + + void angle_tolerance(double a) + { + m_curve_div.angle_tolerance(a); + } + + double angle_tolerance() const + { + return m_curve_div.angle_tolerance(); + } + + void cusp_limit(double v) + { + m_curve_div.cusp_limit(v); + } + + double cusp_limit() const + { + return m_curve_div.cusp_limit(); + } + + void rewind(unsigned path_id) + { + if(m_approximation_method == curve_inc) + { + m_curve_inc.rewind(path_id); + } + else + { + m_curve_div.rewind(path_id); + } + } + + unsigned vertex(double* x, double* y) + { + if(m_approximation_method == curve_inc) + { + return m_curve_inc.vertex(x, y); + } + return m_curve_div.vertex(x, y); + } + + private: + curve3_inc m_curve_inc; + curve3_div m_curve_div; + curve_approximation_method_e m_approximation_method; + }; + + + + + + //-----------------------------------------------------------------curve4 + class curve4 + { + public: + curve4() : m_approximation_method(curve_div) {} + curve4(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) : + m_approximation_method(curve_div) + { + init(x1, y1, x2, y2, x3, y3, x4, y4); + } + + curve4(const curve4_points& cp) : + m_approximation_method(curve_div) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void reset() + { + m_curve_inc.reset(); + m_curve_div.reset(); + } + + void init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + if(m_approximation_method == curve_inc) + { + m_curve_inc.init(x1, y1, x2, y2, x3, y3, x4, y4); + } + else + { + m_curve_div.init(x1, y1, x2, y2, x3, y3, x4, y4); + } + } + + void init(const curve4_points& cp) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void approximation_method(curve_approximation_method_e v) + { + m_approximation_method = v; + } + + curve_approximation_method_e approximation_method() const + { + return m_approximation_method; + } + + void approximation_scale(double s) + { + m_curve_inc.approximation_scale(s); + m_curve_div.approximation_scale(s); + } + double approximation_scale() const { return m_curve_inc.approximation_scale(); } + + void angle_tolerance(double v) + { + m_curve_div.angle_tolerance(v); + } + + double angle_tolerance() const + { + return m_curve_div.angle_tolerance(); + } + + void cusp_limit(double v) + { + m_curve_div.cusp_limit(v); + } + + double cusp_limit() const + { + return m_curve_div.cusp_limit(); + } + + void rewind(unsigned path_id) + { + if(m_approximation_method == curve_inc) + { + m_curve_inc.rewind(path_id); + } + else + { + m_curve_div.rewind(path_id); + } + } + + unsigned vertex(double* x, double* y) + { + if(m_approximation_method == curve_inc) + { + return m_curve_inc.vertex(x, y); + } + return m_curve_div.vertex(x, y); + } + + private: + curve4_inc m_curve_inc; + curve4_div m_curve_div; + curve_approximation_method_e m_approximation_method; + }; + + + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_dda_line.h b/jni/desmume/src/android/agg/include/agg_dda_line.h new file mode 100755 index 0000000..1b86ed9 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_dda_line.h @@ -0,0 +1,295 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_DDA_LINE_INCLUDED +#define AGG_DDA_LINE_INCLUDED + +#include <stdlib.h> +#include "agg_basics.h" + +namespace agg +{ + + //===================================================dda_line_interpolator + template<int FractionShift, int YShift=0> class dda_line_interpolator + { + public: + //-------------------------------------------------------------------- + dda_line_interpolator() {} + + //-------------------------------------------------------------------- + dda_line_interpolator(int y1, int y2, unsigned count) : + m_y(y1), + m_inc(((y2 - y1) << FractionShift) / int(count)), + m_dy(0) + { + } + + //-------------------------------------------------------------------- + void operator ++ () + { + m_dy += m_inc; + } + + //-------------------------------------------------------------------- + void operator -- () + { + m_dy -= m_inc; + } + + //-------------------------------------------------------------------- + void operator += (unsigned n) + { + m_dy += m_inc * n; + } + + //-------------------------------------------------------------------- + void operator -= (unsigned n) + { + m_dy -= m_inc * n; + } + + + //-------------------------------------------------------------------- + int y() const { return m_y + (m_dy >> (FractionShift-YShift)); } + int dy() const { return m_dy; } + + + private: + int m_y; + int m_inc; + int m_dy; + }; + + + + + + //=================================================dda2_line_interpolator + class dda2_line_interpolator + { + public: + typedef int save_data_type; + enum save_size_e { save_size = 2 }; + + //-------------------------------------------------------------------- + dda2_line_interpolator() {} + + //-------------------------------------------- Forward-adjusted line + dda2_line_interpolator(int y1, int y2, int count) : + m_cnt(count <= 0 ? 1 : count), + m_lft((y2 - y1) / m_cnt), + m_rem((y2 - y1) % m_cnt), + m_mod(m_rem), + m_y(y1) + { + if(m_mod <= 0) + { + m_mod += count; + m_rem += count; + m_lft--; + } + m_mod -= count; + } + + //-------------------------------------------- Backward-adjusted line + dda2_line_interpolator(int y1, int y2, int count, int) : + m_cnt(count <= 0 ? 1 : count), + m_lft((y2 - y1) / m_cnt), + m_rem((y2 - y1) % m_cnt), + m_mod(m_rem), + m_y(y1) + { + if(m_mod <= 0) + { + m_mod += count; + m_rem += count; + m_lft--; + } + } + + //-------------------------------------------- Backward-adjusted line + dda2_line_interpolator(int y, int count) : + m_cnt(count <= 0 ? 1 : count), + m_lft(y / m_cnt), + m_rem(y % m_cnt), + m_mod(m_rem), + m_y(0) + { + if(m_mod <= 0) + { + m_mod += count; + m_rem += count; + m_lft--; + } + } + + + //-------------------------------------------------------------------- + void save(save_data_type* data) const + { + data[0] = m_mod; + data[1] = m_y; + } + + //-------------------------------------------------------------------- + void load(const save_data_type* data) + { + m_mod = data[0]; + m_y = data[1]; + } + + //-------------------------------------------------------------------- + void operator++() + { + m_mod += m_rem; + m_y += m_lft; + if(m_mod > 0) + { + m_mod -= m_cnt; + m_y++; + } + } + + //-------------------------------------------------------------------- + void operator--() + { + if(m_mod <= m_rem) + { + m_mod += m_cnt; + m_y--; + } + m_mod -= m_rem; + m_y -= m_lft; + } + + //-------------------------------------------------------------------- + void adjust_forward() + { + m_mod -= m_cnt; + } + + //-------------------------------------------------------------------- + void adjust_backward() + { + m_mod += m_cnt; + } + + //-------------------------------------------------------------------- + int mod() const { return m_mod; } + int rem() const { return m_rem; } + int lft() const { return m_lft; } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + + private: + int m_cnt; + int m_lft; + int m_rem; + int m_mod; + int m_y; + }; + + + + + + + + //---------------------------------------------line_bresenham_interpolator + class line_bresenham_interpolator + { + public: + enum subpixel_scale_e + { + subpixel_shift = 8, + subpixel_scale = 1 << subpixel_shift, + subpixel_mask = subpixel_scale - 1 + }; + + //-------------------------------------------------------------------- + static int line_lr(int v) { return v >> subpixel_shift; } + + //-------------------------------------------------------------------- + line_bresenham_interpolator(int x1, int y1, int x2, int y2) : + m_x1_lr(line_lr(x1)), + m_y1_lr(line_lr(y1)), + m_x2_lr(line_lr(x2)), + m_y2_lr(line_lr(y2)), + m_ver(abs(m_x2_lr - m_x1_lr) < abs(m_y2_lr - m_y1_lr)), + m_len(m_ver ? abs(m_y2_lr - m_y1_lr) : + abs(m_x2_lr - m_x1_lr)), + m_inc(m_ver ? ((y2 > y1) ? 1 : -1) : ((x2 > x1) ? 1 : -1)), + m_interpolator(m_ver ? x1 : y1, + m_ver ? x2 : y2, + m_len) + { + } + + //-------------------------------------------------------------------- + bool is_ver() const { return m_ver; } + unsigned len() const { return m_len; } + int inc() const { return m_inc; } + + //-------------------------------------------------------------------- + void hstep() + { + ++m_interpolator; + m_x1_lr += m_inc; + } + + //-------------------------------------------------------------------- + void vstep() + { + ++m_interpolator; + m_y1_lr += m_inc; + } + + //-------------------------------------------------------------------- + int x1() const { return m_x1_lr; } + int y1() const { return m_y1_lr; } + int x2() const { return line_lr(m_interpolator.y()); } + int y2() const { return line_lr(m_interpolator.y()); } + int x2_hr() const { return m_interpolator.y(); } + int y2_hr() const { return m_interpolator.y(); } + + private: + int m_x1_lr; + int m_y1_lr; + int m_x2_lr; + int m_y2_lr; + bool m_ver; + unsigned m_len; + int m_inc; + dda2_line_interpolator m_interpolator; + + }; + + +} + + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_ellipse.h b/jni/desmume/src/android/agg/include/agg_ellipse.h new file mode 100755 index 0000000..c2eb0c8 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_ellipse.h @@ -0,0 +1,128 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_ELLIPSE_INCLUDED +#define AGG_ELLIPSE_INCLUDED + +#include "agg_basics.h" +#include <math.h> + +namespace agg +{ + + //----------------------------------------------------------------ellipse + class ellipse + { + public: + ellipse() : + m_x(0.0), m_y(0.0), m_rx(1.0), m_ry(1.0), m_scale(1.0), + m_num(4), m_step(0), m_cw(false) {} + + ellipse(double x, double y, double rx, double ry, + unsigned num_steps=0, bool cw=false) : + m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_scale(1.0), + m_num(num_steps), m_step(0), m_cw(cw) + { + if(m_num == 0) calc_num_steps(); + } + + void init(double x, double y, double rx, double ry, + unsigned num_steps=0, bool cw=false); + + void approximation_scale(double scale); + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + void calc_num_steps(); + + double m_x; + double m_y; + double m_rx; + double m_ry; + double m_scale; + unsigned m_num; + unsigned m_step; + bool m_cw; + }; + + //------------------------------------------------------------------------ + inline void ellipse::init(double x, double y, double rx, double ry, + unsigned num_steps, bool cw) + { + m_x = x; + m_y = y; + m_rx = rx; + m_ry = ry; + m_num = num_steps; + m_step = 0; + m_cw = cw; + if(m_num == 0) calc_num_steps(); + } + + //------------------------------------------------------------------------ + inline void ellipse::approximation_scale(double scale) + { + m_scale = scale; + calc_num_steps(); + } + + //------------------------------------------------------------------------ + inline void ellipse::calc_num_steps() + { + double ra = (fabs(m_rx) + fabs(m_ry)) / 2; + double da = acos(ra / (ra + 0.125 / m_scale)) * 2; + m_num = uround(2*pi / da); + } + + //------------------------------------------------------------------------ + inline void ellipse::rewind(unsigned) + { + m_step = 0; + } + + //------------------------------------------------------------------------ + inline unsigned ellipse::vertex(double* x, double* y) + { + if(m_step == m_num) + { + ++m_step; + return path_cmd_end_poly | path_flags_close | path_flags_ccw; + } + if(m_step > m_num) return path_cmd_stop; + double angle = double(m_step) / double(m_num) * 2.0 * pi; + if(m_cw) angle = 2.0 * pi - angle; + *x = m_x + cos(angle) * m_rx; + *y = m_y + sin(angle) * m_ry; + m_step++; + return ((m_step == 1) ? path_cmd_move_to : path_cmd_line_to); + } + +} + + + +#endif + + diff --git a/jni/desmume/src/android/agg/include/agg_ellipse_bresenham.h b/jni/desmume/src/android/agg/include/agg_ellipse_bresenham.h new file mode 100755 index 0000000..af9a13c --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_ellipse_bresenham.h @@ -0,0 +1,118 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_ELLIPSE_BRESENHAM_INCLUDED +#define AGG_ELLIPSE_BRESENHAM_INCLUDED + + +#include "agg_basics.h" + + +namespace agg +{ + + //------------------------------------------ellipse_bresenham_interpolator + class ellipse_bresenham_interpolator + { + public: + ellipse_bresenham_interpolator(int rx, int ry) : + m_rx2(rx * rx), + m_ry2(ry * ry), + m_two_rx2(m_rx2 << 1), + m_two_ry2(m_ry2 << 1), + m_dx(0), + m_dy(0), + m_inc_x(0), + m_inc_y(-ry * m_two_rx2), + m_cur_f(0) + {} + + int dx() const { return m_dx; } + int dy() const { return m_dy; } + + void operator++ () + { + int mx, my, mxy, min_m; + int fx, fy, fxy; + + mx = fx = m_cur_f + m_inc_x + m_ry2; + if(mx < 0) mx = -mx; + + my = fy = m_cur_f + m_inc_y + m_rx2; + if(my < 0) my = -my; + + mxy = fxy = m_cur_f + m_inc_x + m_ry2 + m_inc_y + m_rx2; + if(mxy < 0) mxy = -mxy; + + min_m = mx; + bool flag = true; + + if(min_m > my) + { + min_m = my; + flag = false; + } + + m_dx = m_dy = 0; + + if(min_m > mxy) + { + m_inc_x += m_two_ry2; + m_inc_y += m_two_rx2; + m_cur_f = fxy; + m_dx = 1; + m_dy = 1; + return; + } + + if(flag) + { + m_inc_x += m_two_ry2; + m_cur_f = fx; + m_dx = 1; + return; + } + + m_inc_y += m_two_rx2; + m_cur_f = fy; + m_dy = 1; + } + + private: + int m_rx2; + int m_ry2; + int m_two_rx2; + int m_two_ry2; + int m_dx; + int m_dy; + int m_inc_x; + int m_inc_y; + int m_cur_f; + + }; + +} + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_embedded_raster_fonts.h b/jni/desmume/src/android/agg/include/agg_embedded_raster_fonts.h new file mode 100755 index 0000000..5c58aa8 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_embedded_raster_fonts.h @@ -0,0 +1,68 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_EMBEDDED_RASTER_FONTS_INCLUDED +#define AGG_EMBEDDED_RASTER_FONTS_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + extern const int8u gse4x6[]; + extern const int8u gse4x8[]; + extern const int8u gse5x7[]; + extern const int8u gse5x9[]; + extern const int8u gse6x12[]; + extern const int8u gse6x9[]; + extern const int8u gse7x11[]; + extern const int8u gse7x11_bold[]; + extern const int8u gse7x15[]; + extern const int8u gse7x15_bold[]; + extern const int8u gse8x16[]; + extern const int8u gse8x16_bold[]; + extern const int8u mcs11_prop[]; + extern const int8u mcs11_prop_condensed[]; + extern const int8u mcs12_prop[]; + extern const int8u mcs13_prop[]; + extern const int8u mcs5x10_mono[]; + extern const int8u mcs5x11_mono[]; + extern const int8u mcs6x10_mono[]; + extern const int8u mcs6x11_mono[]; + extern const int8u mcs7x12_mono_high[]; + extern const int8u mcs7x12_mono_low[]; + extern const int8u verdana12[]; + extern const int8u verdana12_bold[]; + extern const int8u verdana13[]; + extern const int8u verdana13_bold[]; + extern const int8u verdana14[]; + extern const int8u verdana14_bold[]; + extern const int8u verdana16[]; + extern const int8u verdana16_bold[]; + extern const int8u verdana17[]; + extern const int8u verdana17_bold[]; + extern const int8u verdana18[]; + extern const int8u verdana18_bold[]; +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_font_cache_manager.h b/jni/desmume/src/android/agg/include/agg_font_cache_manager.h new file mode 100755 index 0000000..8e35206 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_font_cache_manager.h @@ -0,0 +1,418 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_FONT_CACHE_MANAGER_INCLUDED +#define AGG_FONT_CACHE_MANAGER_INCLUDED + +#include <string.h> +#include "agg_array.h" + +namespace agg +{ + + //---------------------------------------------------------glyph_data_type + enum glyph_data_type + { + glyph_data_invalid = 0, + glyph_data_mono = 1, + glyph_data_gray8 = 2, + glyph_data_outline = 3 + }; + + + //-------------------------------------------------------------glyph_cache + struct glyph_cache + { + unsigned glyph_index; + int8u* data; + unsigned data_size; + glyph_data_type data_type; + rect_i bounds; + double advance_x; + double advance_y; + }; + + + //--------------------------------------------------------------font_cache + class font_cache + { + public: + enum block_size_e { block_size = 16384-16 }; + + //-------------------------------------------------------------------- + font_cache() : + m_allocator(block_size), + m_font_signature(0) + {} + + //-------------------------------------------------------------------- + void signature(const char* font_signature) + { + m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1); + strcpy(m_font_signature, font_signature); + memset(m_glyphs, 0, sizeof(m_glyphs)); + } + + //-------------------------------------------------------------------- + bool font_is(const char* font_signature) const + { + return strcmp(font_signature, m_font_signature) == 0; + } + + //-------------------------------------------------------------------- + const glyph_cache* find_glyph(unsigned glyph_code) const + { + unsigned msb = (glyph_code >> 8) & 0xFF; + if(m_glyphs[msb]) + { + return m_glyphs[msb][glyph_code & 0xFF]; + } + return 0; + } + + //-------------------------------------------------------------------- + glyph_cache* cache_glyph(unsigned glyph_code, + unsigned glyph_index, + unsigned data_size, + glyph_data_type data_type, + const rect_i& bounds, + double advance_x, + double advance_y) + { + unsigned msb = (glyph_code >> 8) & 0xFF; + if(m_glyphs[msb] == 0) + { + m_glyphs[msb] = + (glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256, + sizeof(glyph_cache*)); + memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256); + } + + unsigned lsb = glyph_code & 0xFF; + if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite + + glyph_cache* glyph = + (glyph_cache*)m_allocator.allocate(sizeof(glyph_cache), + sizeof(double)); + + glyph->glyph_index = glyph_index; + glyph->data = m_allocator.allocate(data_size); + glyph->data_size = data_size; + glyph->data_type = data_type; + glyph->bounds = bounds; + glyph->advance_x = advance_x; + glyph->advance_y = advance_y; + return m_glyphs[msb][lsb] = glyph; + } + + private: + block_allocator m_allocator; + glyph_cache** m_glyphs[256]; + char* m_font_signature; + }; + + + + + + + + //---------------------------------------------------------font_cache_pool + class font_cache_pool + { + public: + //-------------------------------------------------------------------- + ~font_cache_pool() + { + unsigned i; + for(i = 0; i < m_num_fonts; ++i) + { + obj_allocator<font_cache>::deallocate(m_fonts[i]); + } + pod_allocator<font_cache*>::deallocate(m_fonts, m_max_fonts); + } + + //-------------------------------------------------------------------- + font_cache_pool(unsigned max_fonts=32) : + m_fonts(pod_allocator<font_cache*>::allocate(max_fonts)), + m_max_fonts(max_fonts), + m_num_fonts(0), + m_cur_font(0) + {} + + + //-------------------------------------------------------------------- + void font(const char* font_signature, bool reset_cache = false) + { + int idx = find_font(font_signature); + if(idx >= 0) + { + if(reset_cache) + { + obj_allocator<font_cache>::deallocate(m_fonts[idx]); + m_fonts[idx] = obj_allocator<font_cache>::allocate(); + m_fonts[idx]->signature(font_signature); + } + m_cur_font = m_fonts[idx]; + } + else + { + if(m_num_fonts >= m_max_fonts) + { + obj_allocator<font_cache>::deallocate(m_fonts[0]); + memcpy(m_fonts, + m_fonts + 1, + (m_max_fonts - 1) * sizeof(font_cache*)); + m_num_fonts = m_max_fonts - 1; + } + m_fonts[m_num_fonts] = obj_allocator<font_cache>::allocate(); + m_fonts[m_num_fonts]->signature(font_signature); + m_cur_font = m_fonts[m_num_fonts]; + ++m_num_fonts; + } + } + + //-------------------------------------------------------------------- + const font_cache* font() const + { + return m_cur_font; + } + + //-------------------------------------------------------------------- + const glyph_cache* find_glyph(unsigned glyph_code) const + { + if(m_cur_font) return m_cur_font->find_glyph(glyph_code); + return 0; + } + + //-------------------------------------------------------------------- + glyph_cache* cache_glyph(unsigned glyph_code, + unsigned glyph_index, + unsigned data_size, + glyph_data_type data_type, + const rect_i& bounds, + double advance_x, + double advance_y) + { + if(m_cur_font) + { + return m_cur_font->cache_glyph(glyph_code, + glyph_index, + data_size, + data_type, + bounds, + advance_x, + advance_y); + } + return 0; + } + + + //-------------------------------------------------------------------- + int find_font(const char* font_signature) + { + unsigned i; + for(i = 0; i < m_num_fonts; i++) + { + if(m_fonts[i]->font_is(font_signature)) return int(i); + } + return -1; + } + + private: + font_cache** m_fonts; + unsigned m_max_fonts; + unsigned m_num_fonts; + font_cache* m_cur_font; + }; + + + + + //------------------------------------------------------------------------ + enum glyph_rendering + { + glyph_ren_native_mono, + glyph_ren_native_gray8, + glyph_ren_outline, + glyph_ren_agg_mono, + glyph_ren_agg_gray8 + }; + + + + + //------------------------------------------------------font_cache_manager + template<class FontEngine> class font_cache_manager + { + public: + typedef FontEngine font_engine_type; + typedef font_cache_manager<FontEngine> self_type; + typedef typename font_engine_type::path_adaptor_type path_adaptor_type; + typedef typename font_engine_type::gray8_adaptor_type gray8_adaptor_type; + typedef typename gray8_adaptor_type::embedded_scanline gray8_scanline_type; + typedef typename font_engine_type::mono_adaptor_type mono_adaptor_type; + typedef typename mono_adaptor_type::embedded_scanline mono_scanline_type; + + //-------------------------------------------------------------------- + font_cache_manager(font_engine_type& engine, unsigned max_fonts=32) : + m_fonts(max_fonts), + m_engine(engine), + m_change_stamp(-1), + m_prev_glyph(0), + m_last_glyph(0) + {} + + //-------------------------------------------------------------------- + void reset_last_glyph() + { + m_prev_glyph = m_last_glyph = 0; + } + + //-------------------------------------------------------------------- + const glyph_cache* glyph(unsigned glyph_code) + { + synchronize(); + const glyph_cache* gl = m_fonts.find_glyph(glyph_code); + if(gl) + { + m_prev_glyph = m_last_glyph; + return m_last_glyph = gl; + } + else + { + if(m_engine.prepare_glyph(glyph_code)) + { + m_prev_glyph = m_last_glyph; + m_last_glyph = m_fonts.cache_glyph(glyph_code, + m_engine.glyph_index(), + m_engine.data_size(), + m_engine.data_type(), + m_engine.bounds(), + m_engine.advance_x(), + m_engine.advance_y()); + m_engine.write_glyph_to(m_last_glyph->data); + return m_last_glyph; + } + } + return 0; + } + + //-------------------------------------------------------------------- + void init_embedded_adaptors(const glyph_cache* gl, + double x, double y, + double scale=1.0) + { + if(gl) + { + switch(gl->data_type) + { + default: return; + case glyph_data_mono: + m_mono_adaptor.init(gl->data, gl->data_size, x, y); + break; + + case glyph_data_gray8: + m_gray8_adaptor.init(gl->data, gl->data_size, x, y); + break; + + case glyph_data_outline: + m_path_adaptor.init(gl->data, gl->data_size, x, y, scale); + break; + } + } + } + + + //-------------------------------------------------------------------- + path_adaptor_type& path_adaptor() { return m_path_adaptor; } + gray8_adaptor_type& gray8_adaptor() { return m_gray8_adaptor; } + gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; } + mono_adaptor_type& mono_adaptor() { return m_mono_adaptor; } + mono_scanline_type& mono_scanline() { return m_mono_scanline; } + + //-------------------------------------------------------------------- + const glyph_cache* perv_glyph() const { return m_prev_glyph; } + const glyph_cache* last_glyph() const { return m_last_glyph; } + + //-------------------------------------------------------------------- + bool add_kerning(double* x, double* y) + { + if(m_prev_glyph && m_last_glyph) + { + return m_engine.add_kerning(m_prev_glyph->glyph_index, + m_last_glyph->glyph_index, + x, y); + } + return false; + } + + //-------------------------------------------------------------------- + void precache(unsigned from, unsigned to) + { + for(; from <= to; ++from) glyph(from); + } + + //-------------------------------------------------------------------- + void reset_cache() + { + m_fonts.font(m_engine.font_signature(), true); + m_change_stamp = m_engine.change_stamp(); + m_prev_glyph = m_last_glyph = 0; + } + + private: + //-------------------------------------------------------------------- + font_cache_manager(const self_type&); + const self_type& operator = (const self_type&); + + //-------------------------------------------------------------------- + void synchronize() + { + if(m_change_stamp != m_engine.change_stamp()) + { + m_fonts.font(m_engine.font_signature()); + m_change_stamp = m_engine.change_stamp(); + m_prev_glyph = m_last_glyph = 0; + } + } + + font_cache_pool m_fonts; + font_engine_type& m_engine; + int m_change_stamp; + double m_dx; + double m_dy; + const glyph_cache* m_prev_glyph; + const glyph_cache* m_last_glyph; + path_adaptor_type m_path_adaptor; + gray8_adaptor_type m_gray8_adaptor; + gray8_scanline_type m_gray8_scanline; + mono_adaptor_type m_mono_adaptor; + mono_scanline_type m_mono_scanline; + }; + +} + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_gamma_functions.h b/jni/desmume/src/android/agg/include/agg_gamma_functions.h new file mode 100755 index 0000000..fa38a45 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_gamma_functions.h @@ -0,0 +1,132 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_GAMMA_FUNCTIONS_INCLUDED +#define AGG_GAMMA_FUNCTIONS_INCLUDED + +#include <math.h> +#include "agg_basics.h" + +namespace agg +{ + //===============================================================gamma_none + struct gamma_none + { + double operator()(double x) const { return x; } + }; + + + //==============================================================gamma_power + class gamma_power + { + public: + gamma_power() : m_gamma(1.0) {} + gamma_power(double g) : m_gamma(g) {} + + void gamma(double g) { m_gamma = g; } + double gamma() const { return m_gamma; } + + double operator() (double x) const + { + return pow(x, m_gamma); + } + + private: + double m_gamma; + }; + + + //==========================================================gamma_threshold + class gamma_threshold + { + public: + gamma_threshold() : m_threshold(0.5) {} + gamma_threshold(double t) : m_threshold(t) {} + + void threshold(double t) { m_threshold = t; } + double threshold() const { return m_threshold; } + + double operator() (double x) const + { + return (x < m_threshold) ? 0.0 : 1.0; + } + + private: + double m_threshold; + }; + + + //============================================================gamma_linear + class gamma_linear + { + public: + gamma_linear() : m_start(0.0), m_end(1.0) {} + gamma_linear(double s, double e) : m_start(s), m_end(e) {} + + void set(double s, double e) { m_start = s; m_end = e; } + void start(double s) { m_start = s; } + void end(double e) { m_end = e; } + double start() const { return m_start; } + double end() const { return m_end; } + + double operator() (double x) const + { + if(x < m_start) return 0.0; + if(x > m_end) return 1.0; + return (x - m_start) / (m_end - m_start); + } + + private: + double m_start; + double m_end; + }; + + + //==========================================================gamma_multiply + class gamma_multiply + { + public: + gamma_multiply() : m_mul(1.0) {} + gamma_multiply(double v) : m_mul(v) {} + + void value(double v) { m_mul = v; } + double value() const { return m_mul; } + + double operator() (double x) const + { + double y = x * m_mul; + if(y > 1.0) y = 1.0; + return y; + } + + private: + double m_mul; + }; + +} + +#endif + + + diff --git a/jni/desmume/src/android/agg/include/agg_gamma_lut.h b/jni/desmume/src/android/agg/include/agg_gamma_lut.h new file mode 100755 index 0000000..5240da7 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_gamma_lut.h @@ -0,0 +1,130 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_GAMMA_LUT_INCLUDED +#define AGG_GAMMA_LUT_INCLUDED + +#include <math.h> +#include "agg_basics.h" + +namespace agg +{ + template<class LoResT=int8u, + class HiResT=int8u, + unsigned GammaShift=8, + unsigned HiResShift=8> class gamma_lut + { + public: + typedef gamma_lut<LoResT, HiResT, GammaShift, HiResShift> self_type; + + enum gamma_scale_e + { + gamma_shift = GammaShift, + gamma_size = 1 << gamma_shift, + gamma_mask = gamma_size - 1 + }; + + enum hi_res_scale_e + { + hi_res_shift = HiResShift, + hi_res_size = 1 << hi_res_shift, + hi_res_mask = hi_res_size - 1 + }; + + ~gamma_lut() + { + pod_allocator<LoResT>::deallocate(m_inv_gamma, hi_res_size); + pod_allocator<HiResT>::deallocate(m_dir_gamma, gamma_size); + } + + gamma_lut() : + m_gamma(1.0), + m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)), + m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size)) + { + unsigned i; + for(i = 0; i < gamma_size; i++) + { + m_dir_gamma[i] = HiResT(i << (hi_res_shift - gamma_shift)); + } + + for(i = 0; i < hi_res_size; i++) + { + m_inv_gamma[i] = LoResT(i >> (hi_res_shift - gamma_shift)); + } + } + + gamma_lut(double g) : + m_gamma(1.0), + m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)), + m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size)) + { + gamma(g); + } + + void gamma(double g) + { + m_gamma = g; + + unsigned i; + for(i = 0; i < gamma_size; i++) + { + m_dir_gamma[i] = (HiResT) + uround(pow(i / double(gamma_mask), m_gamma) * double(hi_res_mask)); + } + + double inv_g = 1.0 / g; + for(i = 0; i < hi_res_size; i++) + { + m_inv_gamma[i] = (LoResT) + uround(pow(i / double(hi_res_mask), inv_g) * double(gamma_mask)); + } + } + + double gamma() const + { + return m_gamma; + } + + HiResT dir(LoResT v) const + { + return m_dir_gamma[unsigned(v)]; + } + + LoResT inv(HiResT v) const + { + return m_inv_gamma[unsigned(v)]; + } + + private: + gamma_lut(const self_type&); + const self_type& operator = (const self_type&); + + double m_gamma; + HiResT* m_dir_gamma; + LoResT* m_inv_gamma; + }; +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_glyph_raster_bin.h b/jni/desmume/src/android/agg/include/agg_glyph_raster_bin.h new file mode 100755 index 0000000..604ebf0 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_glyph_raster_bin.h @@ -0,0 +1,164 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_GLYPH_RASTER_BIN_INCLUDED +#define AGG_GLYPH_RASTER_BIN_INCLUDED + +#include <string.h> +#include "agg_basics.h" + +namespace agg +{ + + //========================================================glyph_raster_bin + template<class ColorT> class glyph_raster_bin + { + public: + typedef ColorT color_type; + + //-------------------------------------------------------------------- + struct glyph_rect + { + int x1,y1,x2,y2; + double dx, dy; + }; + + //-------------------------------------------------------------------- + glyph_raster_bin(const int8u* font) : + m_font(font), + m_big_endian(false) + { + int t = 1; + if(*(char*)&t == 0) m_big_endian = true; + memset(m_span, 0, sizeof(m_span)); + } + + //-------------------------------------------------------------------- + const int8u* font() const { return m_font; } + void font(const int8u* f) { m_font = f; } + + //-------------------------------------------------------------------- + double height() const { return m_font[0]; } + double base_line() const { return m_font[1]; } + + //-------------------------------------------------------------------- + template<class CharT> + double width(const CharT* str) const + { + unsigned start_char = m_font[2]; + unsigned num_chars = m_font[3]; + + unsigned w = 0; + while(*str) + { + unsigned glyph = *str; + const int8u* bits = m_font + 4 + num_chars * 2 + + value(m_font + 4 + (glyph - start_char) * 2); + w += *bits; + ++str; + } + return w; + } + + //-------------------------------------------------------------------- + void prepare(glyph_rect* r, double x, double y, unsigned glyph, bool flip) + { + unsigned start_char = m_font[2]; + unsigned num_chars = m_font[3]; + + m_bits = m_font + 4 + num_chars * 2 + + value(m_font + 4 + (glyph - start_char) * 2); + + m_glyph_width = *m_bits++; + m_glyph_byte_width = (m_glyph_width + 7) >> 3; + + r->x1 = int(x); + r->x2 = r->x1 + m_glyph_width - 1; + if(flip) + { + r->y1 = int(y) - m_font[0] + m_font[1]; + r->y2 = r->y1 + m_font[0] - 1; + } + else + { + r->y1 = int(y) - m_font[1] + 1; + r->y2 = r->y1 + m_font[0] - 1; + } + r->dx = m_glyph_width; + r->dy = 0; + } + + //-------------------------------------------------------------------- + const cover_type* span(unsigned i) + { + i = m_font[0] - i - 1; + const int8u* bits = m_bits + i * m_glyph_byte_width; + unsigned j; + unsigned val = *bits; + unsigned nb = 0; + for(j = 0; j < m_glyph_width; ++j) + { + m_span[j] = (cover_type)((val & 0x80) ? cover_full : cover_none); + val <<= 1; + if(++nb >= 8) + { + val = *++bits; + nb = 0; + } + } + return m_span; + } + + private: + //-------------------------------------------------------------------- + int16u value(const int8u* p) const + { + int16u v; + if(m_big_endian) + { + *(int8u*)&v = p[1]; + *((int8u*)&v + 1) = p[0]; + } + else + { + *(int8u*)&v = p[0]; + *((int8u*)&v + 1) = p[1]; + } + return v; + } + + + //-------------------------------------------------------------------- + const int8u* m_font; + bool m_big_endian; + cover_type m_span[32]; + const int8u* m_bits; + unsigned m_glyph_width; + unsigned m_glyph_byte_width; + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_gradient_lut.h b/jni/desmume/src/android/agg/include/agg_gradient_lut.h new file mode 100755 index 0000000..9a13b2d --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_gradient_lut.h @@ -0,0 +1,253 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_GRADIENT_LUT_INCLUDED +#define AGG_GRADIENT_LUT_INCLUDED + +#include "agg_array.h" +#include "agg_dda_line.h" +#include "agg_color_rgba.h" +#include "agg_color_gray.h" + +namespace agg +{ + + //======================================================color_interpolator + template<class ColorT> struct color_interpolator + { + public: + typedef ColorT color_type; + + color_interpolator(const color_type& c1, + const color_type& c2, + unsigned len) : + m_c1(c1), + m_c2(c2), + m_len(len), + m_count(0) + {} + + void operator ++ () + { + ++m_count; + } + + color_type color() const + { + return m_c1.gradient(m_c2, double(m_count) / m_len); + } + + private: + color_type m_c1; + color_type m_c2; + unsigned m_len; + unsigned m_count; + }; + + //======================================================================== + // Fast specialization for rgba8 + template<> struct color_interpolator<rgba8> + { + public: + typedef rgba8 color_type; + + color_interpolator(const color_type& c1, + const color_type& c2, + unsigned len) : + r(c1.r, c2.r, len), + g(c1.g, c2.g, len), + b(c1.b, c2.b, len), + a(c1.a, c2.a, len) + {} + + void operator ++ () + { + ++r; ++g; ++b; ++a; + } + + color_type color() const + { + return color_type(r.y(), g.y(), b.y(), a.y()); + } + + private: + agg::dda_line_interpolator<14> r, g, b, a; + }; + + //======================================================================== + // Fast specialization for gray8 + template<> struct color_interpolator<gray8> + { + public: + typedef gray8 color_type; + + color_interpolator(const color_type& c1, + const color_type& c2, + unsigned len) : + v(c1.v, c2.v, len), + a(c1.a, c2.a, len) + {} + + void operator ++ () + { + ++v; ++a; + } + + color_type color() const + { + return color_type(v.y(), a.y()); + } + + private: + agg::dda_line_interpolator<14> v,a; + }; + + //============================================================gradient_lut + template<class ColorInterpolator, + unsigned ColorLutSize=256> class gradient_lut + { + public: + typedef ColorInterpolator interpolator_type; + typedef typename interpolator_type::color_type color_type; + enum { color_lut_size = ColorLutSize }; + + //-------------------------------------------------------------------- + gradient_lut() : m_color_lut(color_lut_size) {} + + // Build Gradient Lut + // First, call remove_all(), then add_color() at least twice, + // then build_lut(). Argument "offset" in add_color must be + // in range [0...1] and defines a color stop as it is described + // in SVG specification, section Gradients and Patterns. + // The simplest linear gradient is: + // gradient_lut.add_color(0.0, start_color); + // gradient_lut.add_color(1.0, end_color); + //-------------------------------------------------------------------- + void remove_all(); + void add_color(double offset, const color_type& color); + void build_lut(); + + // Size-index Interface. This class can be used directly as the + // ColorF in span_gradient. All it needs is two access methods + // size() and operator []. + //-------------------------------------------------------------------- + static unsigned size() + { + return color_lut_size; + } + const color_type& operator [] (unsigned i) const + { + return m_color_lut[i]; + } + + private: + //-------------------------------------------------------------------- + struct color_point + { + double offset; + color_type color; + + color_point() {} + color_point(double off, const color_type& c) : + offset(off), color(c) + { + if(offset < 0.0) offset = 0.0; + if(offset > 1.0) offset = 1.0; + } + }; + typedef agg::pod_bvector<color_point, 4> color_profile_type; + typedef agg::pod_array<color_type> color_lut_type; + + static bool offset_less(const color_point& a, const color_point& b) + { + return a.offset < b.offset; + } + static bool offset_equal(const color_point& a, const color_point& b) + { + return a.offset == b.offset; + } + + //-------------------------------------------------------------------- + color_profile_type m_color_profile; + color_lut_type m_color_lut; + }; + + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + void gradient_lut<T,S>::remove_all() + { + m_color_profile.remove_all(); + } + + //------------------------------------------------------------------------ + template<class T, unsigned S> + void gradient_lut<T,S>::add_color(double offset, const color_type& color) + { + m_color_profile.add(color_point(offset, color)); + } + + //------------------------------------------------------------------------ + template<class T, unsigned S> + void gradient_lut<T,S>::build_lut() + { + quick_sort(m_color_profile, offset_less); + m_color_profile.cut_at(remove_duplicates(m_color_profile, offset_equal)); + if(m_color_profile.size() >= 2) + { + unsigned i; + unsigned start = uround(m_color_profile[0].offset * color_lut_size); + unsigned end; + color_type c = m_color_profile[0].color; + for(i = 0; i < start; i++) + { + m_color_lut[i] = c; + } + for(i = 1; i < m_color_profile.size(); i++) + { + end = uround(m_color_profile[i].offset * color_lut_size); + interpolator_type ci(m_color_profile[i-1].color, + m_color_profile[i ].color, + end - start + 1); + while(start < end) + { + m_color_lut[start] = ci.color(); + ++ci; + ++start; + } + } + c = m_color_profile.last().color; + for(; end < m_color_lut.size(); end++) + { + m_color_lut[end] = c; + } + } + } +} + + + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_gsv_text.h b/jni/desmume/src/android/agg/include/agg_gsv_text.h new file mode 100755 index 0000000..f96c3bf --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_gsv_text.h @@ -0,0 +1,158 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_GSV_TEXT_INCLUDED +#define AGG_GSV_TEXT_INCLUDED + +#include "agg_array.h" +#include "agg_conv_stroke.h" +#include "agg_conv_transform.h" + +namespace agg +{ + + + //---------------------------------------------------------------gsv_text + // + // See Implementation agg_gsv_text.cpp + // + class gsv_text + { + enum status + { + initial, + next_char, + start_glyph, + glyph + }; + + public: + gsv_text(); + + void font(const void* font); + void flip(bool flip_y) { m_flip = flip_y; } + void load_font(const char* file); + void size(double height, double width=0.0); + void space(double space); + void line_space(double line_space); + void start_point(double x, double y); + void text(const char* text); + + double text_width(); + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + // not supposed to be copied + gsv_text(const gsv_text&); + const gsv_text& operator = (const gsv_text&); + + int16u value(const int8u* p) const + { + int16u v; + if(m_big_endian) + { + *(int8u*)&v = p[1]; + *((int8u*)&v + 1) = p[0]; + } + else + { + *(int8u*)&v = p[0]; + *((int8u*)&v + 1) = p[1]; + } + return v; + } + + private: + double m_x; + double m_y; + double m_start_x; + double m_width; + double m_height; + double m_space; + double m_line_space; + char m_chr[2]; + char* m_text; + pod_array<char> m_text_buf; + char* m_cur_chr; + const void* m_font; + pod_array<char> m_loaded_font; + status m_status; + bool m_big_endian; + bool m_flip; + int8u* m_indices; + int8* m_glyphs; + int8* m_bglyph; + int8* m_eglyph; + double m_w; + double m_h; + }; + + + + + //--------------------------------------------------------gsv_text_outline + template<class Transformer = trans_affine> class gsv_text_outline + { + public: + gsv_text_outline(gsv_text& text, const Transformer& trans) : + m_polyline(text), + m_trans(m_polyline, trans) + { + } + + void width(double w) + { + m_polyline.width(w); + } + + void transformer(const Transformer* trans) + { + m_trans->transformer(trans); + } + + void rewind(unsigned path_id) + { + m_trans.rewind(path_id); + m_polyline.line_join(round_join); + m_polyline.line_cap(round_cap); + } + + unsigned vertex(double* x, double* y) + { + return m_trans.vertex(x, y); + } + + private: + conv_stroke<gsv_text> m_polyline; + conv_transform<conv_stroke<gsv_text>, Transformer> m_trans; + }; + + + +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_image_accessors.h b/jni/desmume/src/android/agg/include/agg_image_accessors.h new file mode 100755 index 0000000..c0d1173 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_image_accessors.h @@ -0,0 +1,490 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_IMAGE_ACCESSORS_INCLUDED +#define AGG_IMAGE_ACCESSORS_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //-----------------------------------------------------image_accessor_clip + template<class PixFmt> class image_accessor_clip + { + public: + typedef PixFmt pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::order_type order_type; + typedef typename pixfmt_type::value_type value_type; + enum pix_width_e { pix_width = pixfmt_type::pix_width }; + + image_accessor_clip() {} + explicit image_accessor_clip(const pixfmt_type& pixf, + const color_type& bk) : + m_pixf(&pixf) + { + pixfmt_type::make_pix(m_bk_buf, bk); + } + + void attach(const pixfmt_type& pixf) + { + m_pixf = &pixf; + } + + void background_color(const color_type& bk) + { + pixfmt_type::make_pix(m_bk_buf, bk); + } + + private: + AGG_INLINE const int8u* pixel() const + { + if(m_y >= 0 && m_y < (int)m_pixf->height() && + m_x >= 0 && m_x < (int)m_pixf->width()) + { + return m_pixf->pix_ptr(m_x, m_y); + } + return m_bk_buf; + } + + public: + AGG_INLINE const int8u* span(int x, int y, unsigned len) + { + m_x = m_x0 = x; + m_y = y; + if(y >= 0 && y < (int)m_pixf->height() && + x >= 0 && x+(int)len <= (int)m_pixf->width()) + { + return m_pix_ptr = m_pixf->pix_ptr(x, y); + } + m_pix_ptr = 0; + return pixel(); + } + + AGG_INLINE const int8u* next_x() + { + if(m_pix_ptr) return m_pix_ptr += pix_width; + ++m_x; + return pixel(); + } + + AGG_INLINE const int8u* next_y() + { + ++m_y; + m_x = m_x0; + if(m_pix_ptr && + m_y >= 0 && m_y < (int)m_pixf->height()) + { + return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y); + } + m_pix_ptr = 0; + return pixel(); + } + + private: + const pixfmt_type* m_pixf; + int8u m_bk_buf[4]; + int m_x, m_x0, m_y; + const int8u* m_pix_ptr; + }; + + + + + //--------------------------------------------------image_accessor_no_clip + template<class PixFmt> class image_accessor_no_clip + { + public: + typedef PixFmt pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::order_type order_type; + typedef typename pixfmt_type::value_type value_type; + enum pix_width_e { pix_width = pixfmt_type::pix_width }; + + image_accessor_no_clip() {} + explicit image_accessor_no_clip(const pixfmt_type& pixf) : + m_pixf(&pixf) + {} + + void attach(const pixfmt_type& pixf) + { + m_pixf = &pixf; + } + + AGG_INLINE const int8u* span(int x, int y, unsigned) + { + m_x = x; + m_y = y; + return m_pix_ptr = m_pixf->pix_ptr(x, y); + } + + AGG_INLINE const int8u* next_x() + { + return m_pix_ptr += pix_width; + } + + AGG_INLINE const int8u* next_y() + { + ++m_y; + return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y); + } + + private: + const pixfmt_type* m_pixf; + int m_x, m_y; + const int8u* m_pix_ptr; + }; + + + + + //----------------------------------------------------image_accessor_clone + template<class PixFmt> class image_accessor_clone + { + public: + typedef PixFmt pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::order_type order_type; + typedef typename pixfmt_type::value_type value_type; + enum pix_width_e { pix_width = pixfmt_type::pix_width }; + + image_accessor_clone() {} + explicit image_accessor_clone(const pixfmt_type& pixf) : + m_pixf(&pixf) + {} + + void attach(const pixfmt_type& pixf) + { + m_pixf = &pixf; + } + + private: + AGG_INLINE const int8u* pixel() const + { + register int x = m_x; + register int y = m_y; + if(x < 0) x = 0; + if(y < 0) y = 0; + if(x >= (int)m_pixf->width()) x = m_pixf->width() - 1; + if(y >= (int)m_pixf->height()) y = m_pixf->height() - 1; + return m_pixf->pix_ptr(x, y); + } + + public: + AGG_INLINE const int8u* span(int x, int y, unsigned len) + { + m_x = m_x0 = x; + m_y = y; + if(y >= 0 && y < (int)m_pixf->height() && + x >= 0 && x+len <= (int)m_pixf->width()) + { + return m_pix_ptr = m_pixf->pix_ptr(x, y); + } + m_pix_ptr = 0; + return pixel(); + } + + AGG_INLINE const int8u* next_x() + { + if(m_pix_ptr) return m_pix_ptr += pix_width; + ++m_x; + return pixel(); + } + + AGG_INLINE const int8u* next_y() + { + ++m_y; + m_x = m_x0; + if(m_pix_ptr && + m_y >= 0 && m_y < (int)m_pixf->height()) + { + return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y); + } + m_pix_ptr = 0; + return pixel(); + } + + private: + const pixfmt_type* m_pixf; + int m_x, m_x0, m_y; + const int8u* m_pix_ptr; + }; + + + + + + //-----------------------------------------------------image_accessor_wrap + template<class PixFmt, class WrapX, class WrapY> class image_accessor_wrap + { + public: + typedef PixFmt pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::order_type order_type; + typedef typename pixfmt_type::value_type value_type; + enum pix_width_e { pix_width = pixfmt_type::pix_width }; + + image_accessor_wrap() {} + explicit image_accessor_wrap(const pixfmt_type& pixf) : + m_pixf(&pixf), + m_wrap_x(pixf.width()), + m_wrap_y(pixf.height()) + {} + + void attach(const pixfmt_type& pixf) + { + m_pixf = &pixf; + } + + AGG_INLINE const int8u* span(int x, int y, unsigned) + { + m_x = x; + m_row_ptr = m_pixf->row_ptr(m_wrap_y(y)); + return m_row_ptr + m_wrap_x(x) * pix_width; + } + + AGG_INLINE const int8u* next_x() + { + int x = ++m_wrap_x; + return m_row_ptr + x * pix_width; + } + + AGG_INLINE const int8u* next_y() + { + m_row_ptr = m_pixf->row_ptr(++m_wrap_y); + return m_row_ptr + m_wrap_x(m_x) * pix_width; + } + + private: + const pixfmt_type* m_pixf; + const int8u* m_row_ptr; + int m_x; + WrapX m_wrap_x; + WrapY m_wrap_y; + }; + + + + + //--------------------------------------------------------wrap_mode_repeat + class wrap_mode_repeat + { + public: + wrap_mode_repeat() {} + wrap_mode_repeat(unsigned size) : + m_size(size), + m_add(size * (0x3FFFFFFF / size)), + m_value(0) + {} + + AGG_INLINE unsigned operator() (int v) + { + return m_value = (unsigned(v) + m_add) % m_size; + } + + AGG_INLINE unsigned operator++ () + { + ++m_value; + if(m_value >= m_size) m_value = 0; + return m_value; + } + private: + unsigned m_size; + unsigned m_add; + unsigned m_value; + }; + + + //---------------------------------------------------wrap_mode_repeat_pow2 + class wrap_mode_repeat_pow2 + { + public: + wrap_mode_repeat_pow2() {} + wrap_mode_repeat_pow2(unsigned size) : m_value(0) + { + m_mask = 1; + while(m_mask < size) m_mask = (m_mask << 1) | 1; + m_mask >>= 1; + } + AGG_INLINE unsigned operator() (int v) + { + return m_value = unsigned(v) & m_mask; + } + AGG_INLINE unsigned operator++ () + { + ++m_value; + if(m_value > m_mask) m_value = 0; + return m_value; + } + private: + unsigned m_mask; + unsigned m_value; + }; + + + //----------------------------------------------wrap_mode_repeat_auto_pow2 + class wrap_mode_repeat_auto_pow2 + { + public: + wrap_mode_repeat_auto_pow2() {} + wrap_mode_repeat_auto_pow2(unsigned size) : + m_size(size), + m_add(size * (0x3FFFFFFF / size)), + m_mask((m_size & (m_size-1)) ? 0 : m_size-1), + m_value(0) + {} + + AGG_INLINE unsigned operator() (int v) + { + if(m_mask) return m_value = unsigned(v) & m_mask; + return m_value = (unsigned(v) + m_add) % m_size; + } + AGG_INLINE unsigned operator++ () + { + ++m_value; + if(m_value >= m_size) m_value = 0; + return m_value; + } + + private: + unsigned m_size; + unsigned m_add; + unsigned m_mask; + unsigned m_value; + }; + + + //-------------------------------------------------------wrap_mode_reflect + class wrap_mode_reflect + { + public: + wrap_mode_reflect() {} + wrap_mode_reflect(unsigned size) : + m_size(size), + m_size2(size * 2), + m_add(m_size2 * (0x3FFFFFFF / m_size2)), + m_value(0) + {} + + AGG_INLINE unsigned operator() (int v) + { + m_value = (unsigned(v) + m_add) % m_size2; + if(m_value >= m_size) return m_size2 - m_value - 1; + return m_value; + } + + AGG_INLINE unsigned operator++ () + { + ++m_value; + if(m_value >= m_size2) m_value = 0; + if(m_value >= m_size) return m_size2 - m_value - 1; + return m_value; + } + private: + unsigned m_size; + unsigned m_size2; + unsigned m_add; + unsigned m_value; + }; + + + + //--------------------------------------------------wrap_mode_reflect_pow2 + class wrap_mode_reflect_pow2 + { + public: + wrap_mode_reflect_pow2() {} + wrap_mode_reflect_pow2(unsigned size) : m_value(0) + { + m_mask = 1; + m_size = 1; + while(m_mask < size) + { + m_mask = (m_mask << 1) | 1; + m_size <<= 1; + } + } + AGG_INLINE unsigned operator() (int v) + { + m_value = unsigned(v) & m_mask; + if(m_value >= m_size) return m_mask - m_value; + return m_value; + } + AGG_INLINE unsigned operator++ () + { + ++m_value; + m_value &= m_mask; + if(m_value >= m_size) return m_mask - m_value; + return m_value; + } + private: + unsigned m_size; + unsigned m_mask; + unsigned m_value; + }; + + + + //---------------------------------------------wrap_mode_reflect_auto_pow2 + class wrap_mode_reflect_auto_pow2 + { + public: + wrap_mode_reflect_auto_pow2() {} + wrap_mode_reflect_auto_pow2(unsigned size) : + m_size(size), + m_size2(size * 2), + m_add(m_size2 * (0x3FFFFFFF / m_size2)), + m_mask((m_size2 & (m_size2-1)) ? 0 : m_size2-1), + m_value(0) + {} + + AGG_INLINE unsigned operator() (int v) + { + m_value = m_mask ? unsigned(v) & m_mask : + (unsigned(v) + m_add) % m_size2; + if(m_value >= m_size) return m_size2 - m_value - 1; + return m_value; + } + AGG_INLINE unsigned operator++ () + { + ++m_value; + if(m_value >= m_size2) m_value = 0; + if(m_value >= m_size) return m_size2 - m_value - 1; + return m_value; + } + + private: + unsigned m_size; + unsigned m_size2; + unsigned m_add; + unsigned m_mask; + unsigned m_value; + }; + + +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_image_filters.h b/jni/desmume/src/android/agg/include/agg_image_filters.h new file mode 100755 index 0000000..3505025 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_image_filters.h @@ -0,0 +1,453 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_IMAGE_FILTERS_INCLUDED +#define AGG_IMAGE_FILTERS_INCLUDED + +#include "agg_array.h" +#include "agg_math.h" + +namespace agg +{ + + // See Implementation agg_image_filters.cpp + + enum image_filter_scale_e + { + image_filter_shift = 14, //----image_filter_shift + image_filter_scale = 1 << image_filter_shift, //----image_filter_scale + image_filter_mask = image_filter_scale - 1 //----image_filter_mask + }; + + enum image_subpixel_scale_e + { + image_subpixel_shift = 8, //----image_subpixel_shift + image_subpixel_scale = 1 << image_subpixel_shift, //----image_subpixel_scale + image_subpixel_mask = image_subpixel_scale - 1 //----image_subpixel_mask + }; + + + //-----------------------------------------------------image_filter_lut + class image_filter_lut + { + public: + template<class FilterF> void calculate(const FilterF& filter, + bool normalization=true) + { + double r = filter.radius(); + realloc_lut(r); + unsigned i; + unsigned pivot = diameter() << (image_subpixel_shift - 1); + for(i = 0; i < pivot; i++) + { + double x = double(i) / double(image_subpixel_scale); + double y = filter.calc_weight(x); + m_weight_array[pivot + i] = + m_weight_array[pivot - i] = (int16)iround(y * image_filter_scale); + } + unsigned end = (diameter() << image_subpixel_shift) - 1; + m_weight_array[0] = m_weight_array[end]; + if(normalization) + { + normalize(); + } + } + + image_filter_lut() : m_radius(0), m_diameter(0), m_start(0) {} + + template<class FilterF> image_filter_lut(const FilterF& filter, + bool normalization=true) + { + calculate(filter, normalization); + } + + double radius() const { return m_radius; } + unsigned diameter() const { return m_diameter; } + int start() const { return m_start; } + const int16* weight_array() const { return &m_weight_array[0]; } + void normalize(); + + private: + void realloc_lut(double radius); + image_filter_lut(const image_filter_lut&); + const image_filter_lut& operator = (const image_filter_lut&); + + double m_radius; + unsigned m_diameter; + int m_start; + pod_array<int16> m_weight_array; + }; + + + + //--------------------------------------------------------image_filter + template<class FilterF> class image_filter : public image_filter_lut + { + public: + image_filter() + { + calculate(m_filter_function); + } + private: + FilterF m_filter_function; + }; + + + //-----------------------------------------------image_filter_bilinear + struct image_filter_bilinear + { + static double radius() { return 1.0; } + static double calc_weight(double x) + { + return 1.0 - x; + } + }; + + + //-----------------------------------------------image_filter_hanning + struct image_filter_hanning + { + static double radius() { return 1.0; } + static double calc_weight(double x) + { + return 0.5 + 0.5 * cos(pi * x); + } + }; + + + //-----------------------------------------------image_filter_hamming + struct image_filter_hamming + { + static double radius() { return 1.0; } + static double calc_weight(double x) + { + return 0.54 + 0.46 * cos(pi * x); + } + }; + + //-----------------------------------------------image_filter_hermite + struct image_filter_hermite + { + static double radius() { return 1.0; } + static double calc_weight(double x) + { + return (2.0 * x - 3.0) * x * x + 1.0; + } + }; + + //------------------------------------------------image_filter_quadric + struct image_filter_quadric + { + static double radius() { return 1.5; } + static double calc_weight(double x) + { + double t; + if(x < 0.5) return 0.75 - x * x; + if(x < 1.5) {t = x - 1.5; return 0.5 * t * t;} + return 0.0; + } + }; + + //------------------------------------------------image_filter_bicubic + class image_filter_bicubic + { + static double pow3(double x) + { + return (x <= 0.0) ? 0.0 : x * x * x; + } + + public: + static double radius() { return 2.0; } + static double calc_weight(double x) + { + return + (1.0/6.0) * + (pow3(x + 2) - 4 * pow3(x + 1) + 6 * pow3(x) - 4 * pow3(x - 1)); + } + }; + + //-------------------------------------------------image_filter_kaiser + class image_filter_kaiser + { + double a; + double i0a; + double epsilon; + + public: + image_filter_kaiser(double b = 6.33) : + a(b), epsilon(1e-12) + { + i0a = 1.0 / bessel_i0(b); + } + + static double radius() { return 1.0; } + double calc_weight(double x) const + { + return bessel_i0(a * sqrt(1. - x * x)) * i0a; + } + + private: + double bessel_i0(double x) const + { + int i; + double sum, y, t; + + sum = 1.; + y = x * x / 4.; + t = y; + + for(i = 2; t > epsilon; i++) + { + sum += t; + t *= (double)y / (i * i); + } + return sum; + } + }; + + //----------------------------------------------image_filter_catrom + struct image_filter_catrom + { + static double radius() { return 2.0; } + static double calc_weight(double x) + { + if(x < 1.0) return 0.5 * (2.0 + x * x * (-5.0 + x * 3.0)); + if(x < 2.0) return 0.5 * (4.0 + x * (-8.0 + x * (5.0 - x))); + return 0.; + } + }; + + //---------------------------------------------image_filter_mitchell + class image_filter_mitchell + { + double p0, p2, p3; + double q0, q1, q2, q3; + + public: + image_filter_mitchell(double b = 1.0/3.0, double c = 1.0/3.0) : + p0((6.0 - 2.0 * b) / 6.0), + p2((-18.0 + 12.0 * b + 6.0 * c) / 6.0), + p3((12.0 - 9.0 * b - 6.0 * c) / 6.0), + q0((8.0 * b + 24.0 * c) / 6.0), + q1((-12.0 * b - 48.0 * c) / 6.0), + q2((6.0 * b + 30.0 * c) / 6.0), + q3((-b - 6.0 * c) / 6.0) + {} + + static double radius() { return 2.0; } + double calc_weight(double x) const + { + if(x < 1.0) return p0 + x * x * (p2 + x * p3); + if(x < 2.0) return q0 + x * (q1 + x * (q2 + x * q3)); + return 0.0; + } + }; + + + //----------------------------------------------image_filter_spline16 + struct image_filter_spline16 + { + static double radius() { return 2.0; } + static double calc_weight(double x) + { + if(x < 1.0) + { + return ((x - 9.0/5.0 ) * x - 1.0/5.0 ) * x + 1.0; + } + return ((-1.0/3.0 * (x-1) + 4.0/5.0) * (x-1) - 7.0/15.0 ) * (x-1); + } + }; + + + //---------------------------------------------image_filter_spline36 + struct image_filter_spline36 + { + static double radius() { return 3.0; } + static double calc_weight(double x) + { + if(x < 1.0) + { + return ((13.0/11.0 * x - 453.0/209.0) * x - 3.0/209.0) * x + 1.0; + } + if(x < 2.0) + { + return ((-6.0/11.0 * (x-1) + 270.0/209.0) * (x-1) - 156.0/ 209.0) * (x-1); + } + return ((1.0/11.0 * (x-2) - 45.0/209.0) * (x-2) + 26.0/209.0) * (x-2); + } + }; + + + //----------------------------------------------image_filter_gaussian + struct image_filter_gaussian + { + static double radius() { return 2.0; } + static double calc_weight(double x) + { + return exp(-2.0 * x * x) * sqrt(2.0 / pi); + } + }; + + + //------------------------------------------------image_filter_bessel + struct image_filter_bessel + { + static double radius() { return 3.2383; } + static double calc_weight(double x) + { + return (x == 0.0) ? pi / 4.0 : besj(pi * x, 1) / (2.0 * x); + } + }; + + + //-------------------------------------------------image_filter_sinc + class image_filter_sinc + { + public: + image_filter_sinc(double r) : m_radius(r < 2.0 ? 2.0 : r) {} + double radius() const { return m_radius; } + double calc_weight(double x) const + { + if(x == 0.0) return 1.0; + x *= pi; + return sin(x) / x; + } + private: + double m_radius; + }; + + + //-----------------------------------------------image_filter_lanczos + class image_filter_lanczos + { + public: + image_filter_lanczos(double r) : m_radius(r < 2.0 ? 2.0 : r) {} + double radius() const { return m_radius; } + double calc_weight(double x) const + { + if(x == 0.0) return 1.0; + if(x > m_radius) return 0.0; + x *= pi; + double xr = x / m_radius; + return (sin(x) / x) * (sin(xr) / xr); + } + private: + double m_radius; + }; + + + //----------------------------------------------image_filter_blackman + class image_filter_blackman + { + public: + image_filter_blackman(double r) : m_radius(r < 2.0 ? 2.0 : r) {} + double radius() const { return m_radius; } + double calc_weight(double x) const + { + if(x == 0.0) return 1.0; + if(x > m_radius) return 0.0; + x *= pi; + double xr = x / m_radius; + return (sin(x) / x) * (0.42 + 0.5*cos(xr) + 0.08*cos(2*xr)); + } + private: + double m_radius; + }; + + //------------------------------------------------image_filter_sinc36 + class image_filter_sinc36 : public image_filter_sinc + { public: image_filter_sinc36() : image_filter_sinc(3.0){} }; + + //------------------------------------------------image_filter_sinc64 + class image_filter_sinc64 : public image_filter_sinc + { public: image_filter_sinc64() : image_filter_sinc(4.0){} }; + + //-----------------------------------------------image_filter_sinc100 + class image_filter_sinc100 : public image_filter_sinc + { public: image_filter_sinc100() : image_filter_sinc(5.0){} }; + + //-----------------------------------------------image_filter_sinc144 + class image_filter_sinc144 : public image_filter_sinc + { public: image_filter_sinc144() : image_filter_sinc(6.0){} }; + + //-----------------------------------------------image_filter_sinc196 + class image_filter_sinc196 : public image_filter_sinc + { public: image_filter_sinc196() : image_filter_sinc(7.0){} }; + + //-----------------------------------------------image_filter_sinc256 + class image_filter_sinc256 : public image_filter_sinc + { public: image_filter_sinc256() : image_filter_sinc(8.0){} }; + + //---------------------------------------------image_filter_lanczos36 + class image_filter_lanczos36 : public image_filter_lanczos + { public: image_filter_lanczos36() : image_filter_lanczos(3.0){} }; + + //---------------------------------------------image_filter_lanczos64 + class image_filter_lanczos64 : public image_filter_lanczos + { public: image_filter_lanczos64() : image_filter_lanczos(4.0){} }; + + //--------------------------------------------image_filter_lanczos100 + class image_filter_lanczos100 : public image_filter_lanczos + { public: image_filter_lanczos100() : image_filter_lanczos(5.0){} }; + + //--------------------------------------------image_filter_lanczos144 + class image_filter_lanczos144 : public image_filter_lanczos + { public: image_filter_lanczos144() : image_filter_lanczos(6.0){} }; + + //--------------------------------------------image_filter_lanczos196 + class image_filter_lanczos196 : public image_filter_lanczos + { public: image_filter_lanczos196() : image_filter_lanczos(7.0){} }; + + //--------------------------------------------image_filter_lanczos256 + class image_filter_lanczos256 : public image_filter_lanczos + { public: image_filter_lanczos256() : image_filter_lanczos(8.0){} }; + + //--------------------------------------------image_filter_blackman36 + class image_filter_blackman36 : public image_filter_blackman + { public: image_filter_blackman36() : image_filter_blackman(3.0){} }; + + //--------------------------------------------image_filter_blackman64 + class image_filter_blackman64 : public image_filter_blackman + { public: image_filter_blackman64() : image_filter_blackman(4.0){} }; + + //-------------------------------------------image_filter_blackman100 + class image_filter_blackman100 : public image_filter_blackman + { public: image_filter_blackman100() : image_filter_blackman(5.0){} }; + + //-------------------------------------------image_filter_blackman144 + class image_filter_blackman144 : public image_filter_blackman + { public: image_filter_blackman144() : image_filter_blackman(6.0){} }; + + //-------------------------------------------image_filter_blackman196 + class image_filter_blackman196 : public image_filter_blackman + { public: image_filter_blackman196() : image_filter_blackman(7.0){} }; + + //-------------------------------------------image_filter_blackman256 + class image_filter_blackman256 : public image_filter_blackman + { public: image_filter_blackman256() : image_filter_blackman(8.0){} }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_line_aa_basics.h b/jni/desmume/src/android/agg/include/agg_line_aa_basics.h new file mode 100755 index 0000000..69aed5c --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_line_aa_basics.h @@ -0,0 +1,199 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_LINE_AA_BASICS_INCLUDED +#define AGG_LINE_AA_BASICS_INCLUDED + +#include <stdlib.h> +#include "agg_basics.h" + +namespace agg +{ + + // See Implementation agg_line_aa_basics.cpp + + //------------------------------------------------------------------------- + enum line_subpixel_scale_e + { + line_subpixel_shift = 8, //----line_subpixel_shift + line_subpixel_scale = 1 << line_subpixel_shift, //----line_subpixel_scale + line_subpixel_mask = line_subpixel_scale - 1, //----line_subpixel_mask + line_max_coord = (1 << 28) - 1, //----line_max_coord + line_max_length = 1 << (line_subpixel_shift + 10) //----line_max_length + }; + + //------------------------------------------------------------------------- + enum line_mr_subpixel_scale_e + { + line_mr_subpixel_shift = 4, //----line_mr_subpixel_shift + line_mr_subpixel_scale = 1 << line_mr_subpixel_shift, //----line_mr_subpixel_scale + line_mr_subpixel_mask = line_mr_subpixel_scale - 1 //----line_mr_subpixel_mask + }; + + //------------------------------------------------------------------line_mr + AGG_INLINE int line_mr(int x) + { + return x >> (line_subpixel_shift - line_mr_subpixel_shift); + } + + //-------------------------------------------------------------------line_hr + AGG_INLINE int line_hr(int x) + { + return x << (line_subpixel_shift - line_mr_subpixel_shift); + } + + //---------------------------------------------------------------line_dbl_hr + AGG_INLINE int line_dbl_hr(int x) + { + return x << line_subpixel_shift; + } + + //---------------------------------------------------------------line_coord + struct line_coord + { + AGG_INLINE static int conv(double x) + { + return iround(x * line_subpixel_scale); + } + }; + + //-----------------------------------------------------------line_coord_sat + struct line_coord_sat + { + AGG_INLINE static int conv(double x) + { + return saturation<line_max_coord>::iround(x * line_subpixel_scale); + } + }; + + //==========================================================line_parameters + struct line_parameters + { + //--------------------------------------------------------------------- + line_parameters() {} + line_parameters(int x1_, int y1_, int x2_, int y2_, int len_) : + x1(x1_), y1(y1_), x2(x2_), y2(y2_), + dx(abs(x2_ - x1_)), + dy(abs(y2_ - y1_)), + sx((x2_ > x1_) ? 1 : -1), + sy((y2_ > y1_) ? 1 : -1), + vertical(dy >= dx), + inc(vertical ? sy : sx), + len(len_), + octant((sy & 4) | (sx & 2) | int(vertical)) + { + } + + //--------------------------------------------------------------------- + unsigned orthogonal_quadrant() const { return s_orthogonal_quadrant[octant]; } + unsigned diagonal_quadrant() const { return s_diagonal_quadrant[octant]; } + + //--------------------------------------------------------------------- + bool same_orthogonal_quadrant(const line_parameters& lp) const + { + return s_orthogonal_quadrant[octant] == s_orthogonal_quadrant[lp.octant]; + } + + //--------------------------------------------------------------------- + bool same_diagonal_quadrant(const line_parameters& lp) const + { + return s_diagonal_quadrant[octant] == s_diagonal_quadrant[lp.octant]; + } + + //--------------------------------------------------------------------- + void divide(line_parameters& lp1, line_parameters& lp2) const + { + int xmid = (x1 + x2) >> 1; + int ymid = (y1 + y2) >> 1; + int len2 = len >> 1; + + lp1 = *this; + lp2 = *this; + + lp1.x2 = xmid; + lp1.y2 = ymid; + lp1.len = len2; + lp1.dx = abs(lp1.x2 - lp1.x1); + lp1.dy = abs(lp1.y2 - lp1.y1); + + lp2.x1 = xmid; + lp2.y1 = ymid; + lp2.len = len2; + lp2.dx = abs(lp2.x2 - lp2.x1); + lp2.dy = abs(lp2.y2 - lp2.y1); + } + + //--------------------------------------------------------------------- + int x1, y1, x2, y2, dx, dy, sx, sy; + bool vertical; + int inc; + int len; + int octant; + + //--------------------------------------------------------------------- + static const int8u s_orthogonal_quadrant[8]; + static const int8u s_diagonal_quadrant[8]; + }; + + + + // See Implementation agg_line_aa_basics.cpp + + //----------------------------------------------------------------bisectrix + void bisectrix(const line_parameters& l1, + const line_parameters& l2, + int* x, int* y); + + + //-------------------------------------------fix_degenerate_bisectrix_start + void inline fix_degenerate_bisectrix_start(const line_parameters& lp, + int* x, int* y) + { + int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) - + double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len); + if(d < line_subpixel_scale/2) + { + *x = lp.x1 + (lp.y2 - lp.y1); + *y = lp.y1 - (lp.x2 - lp.x1); + } + } + + + //---------------------------------------------fix_degenerate_bisectrix_end + void inline fix_degenerate_bisectrix_end(const line_parameters& lp, + int* x, int* y) + { + int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) - + double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len); + if(d < line_subpixel_scale/2) + { + *x = lp.x2 + (lp.y2 - lp.y1); + *y = lp.y2 - (lp.x2 - lp.x1); + } + } + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_math.h b/jni/desmume/src/android/agg/include/agg_math.h new file mode 100755 index 0000000..4e512fa --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_math.h @@ -0,0 +1,446 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// Bessel function (besj) was adapted for use in AGG library by Andy Wilk +// Contact: castor.vulgaris@gmail.com +//---------------------------------------------------------------------------- + +#ifndef AGG_MATH_INCLUDED +#define AGG_MATH_INCLUDED + +#include <math.h> +#include "agg_basics.h" + +namespace agg +{ + + //------------------------------------------------------vertex_dist_epsilon + // Coinciding points maximal distance (Epsilon) + const double vertex_dist_epsilon = 1e-14; + + //-----------------------------------------------------intersection_epsilon + // See calc_intersection + const double intersection_epsilon = 1.0e-30; + + //------------------------------------------------------------cross_product + AGG_INLINE double cross_product(double x1, double y1, + double x2, double y2, + double x, double y) + { + return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1); + } + + //--------------------------------------------------------point_in_triangle + AGG_INLINE bool point_in_triangle(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x, double y) + { + bool cp1 = cross_product(x1, y1, x2, y2, x, y) < 0.0; + bool cp2 = cross_product(x2, y2, x3, y3, x, y) < 0.0; + bool cp3 = cross_product(x3, y3, x1, y1, x, y) < 0.0; + return cp1 == cp2 && cp2 == cp3 && cp3 == cp1; + } + + //-----------------------------------------------------------calc_distance + AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2) + { + double dx = x2-x1; + double dy = y2-y1; + return sqrt(dx * dx + dy * dy); + } + + //--------------------------------------------------------calc_sq_distance + AGG_INLINE double calc_sq_distance(double x1, double y1, double x2, double y2) + { + double dx = x2-x1; + double dy = y2-y1; + return dx * dx + dy * dy; + } + + //------------------------------------------------calc_line_point_distance + AGG_INLINE double calc_line_point_distance(double x1, double y1, + double x2, double y2, + double x, double y) + { + double dx = x2-x1; + double dy = y2-y1; + double d = sqrt(dx * dx + dy * dy); + if(d < vertex_dist_epsilon) + { + return calc_distance(x1, y1, x, y); + } + return ((x - x2) * dy - (y - y2) * dx) / d; + } + + //-------------------------------------------------------calc_line_point_u + AGG_INLINE double calc_segment_point_u(double x1, double y1, + double x2, double y2, + double x, double y) + { + double dx = x2 - x1; + double dy = y2 - y1; + + if(dx == 0 && dy == 0) + { + return 0; + } + + double pdx = x - x1; + double pdy = y - y1; + + return (pdx * dx + pdy * dy) / (dx * dx + dy * dy); + } + + //---------------------------------------------calc_line_point_sq_distance + AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1, + double x2, double y2, + double x, double y, + double u) + { + if(u <= 0) + { + return calc_sq_distance(x, y, x1, y1); + } + else + if(u >= 1) + { + return calc_sq_distance(x, y, x2, y2); + } + return calc_sq_distance(x, y, x1 + u * (x2 - x1), y1 + u * (y2 - y1)); + } + + //---------------------------------------------calc_line_point_sq_distance + AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1, + double x2, double y2, + double x, double y) + { + return + calc_segment_point_sq_distance( + x1, y1, x2, y2, x, y, + calc_segment_point_u(x1, y1, x2, y2, x, y)); + } + + //-------------------------------------------------------calc_intersection + AGG_INLINE bool calc_intersection(double ax, double ay, double bx, double by, + double cx, double cy, double dx, double dy, + double* x, double* y) + { + double num = (ay-cy) * (dx-cx) - (ax-cx) * (dy-cy); + double den = (bx-ax) * (dy-cy) - (by-ay) * (dx-cx); + if(fabs(den) < intersection_epsilon) return false; + double r = num / den; + *x = ax + r * (bx-ax); + *y = ay + r * (by-ay); + return true; + } + + //-----------------------------------------------------intersection_exists + AGG_INLINE bool intersection_exists(double x1, double y1, double x2, double y2, + double x3, double y3, double x4, double y4) + { + // It's less expensive but you can't control the + // boundary conditions: Less or LessEqual + double dx1 = x2 - x1; + double dy1 = y2 - y1; + double dx2 = x4 - x3; + double dy2 = y4 - y3; + return ((x3 - x2) * dy1 - (y3 - y2) * dx1 < 0.0) != + ((x4 - x2) * dy1 - (y4 - y2) * dx1 < 0.0) && + ((x1 - x4) * dy2 - (y1 - y4) * dx2 < 0.0) != + ((x2 - x4) * dy2 - (y2 - y4) * dx2 < 0.0); + + // It's is more expensive but more flexible + // in terms of boundary conditions. + //-------------------- + //double den = (x2-x1) * (y4-y3) - (y2-y1) * (x4-x3); + //if(fabs(den) < intersection_epsilon) return false; + //double nom1 = (x4-x3) * (y1-y3) - (y4-y3) * (x1-x3); + //double nom2 = (x2-x1) * (y1-y3) - (y2-y1) * (x1-x3); + //double ua = nom1 / den; + //double ub = nom2 / den; + //return ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0; + } + + //--------------------------------------------------------calc_orthogonal + AGG_INLINE void calc_orthogonal(double thickness, + double x1, double y1, + double x2, double y2, + double* x, double* y) + { + double dx = x2 - x1; + double dy = y2 - y1; + double d = sqrt(dx*dx + dy*dy); + *x = thickness * dy / d; + *y = -thickness * dx / d; + } + + //--------------------------------------------------------dilate_triangle + AGG_INLINE void dilate_triangle(double x1, double y1, + double x2, double y2, + double x3, double y3, + double *x, double* y, + double d) + { + double dx1=0.0; + double dy1=0.0; + double dx2=0.0; + double dy2=0.0; + double dx3=0.0; + double dy3=0.0; + double loc = cross_product(x1, y1, x2, y2, x3, y3); + if(fabs(loc) > intersection_epsilon) + { + if(cross_product(x1, y1, x2, y2, x3, y3) > 0.0) + { + d = -d; + } + calc_orthogonal(d, x1, y1, x2, y2, &dx1, &dy1); + calc_orthogonal(d, x2, y2, x3, y3, &dx2, &dy2); + calc_orthogonal(d, x3, y3, x1, y1, &dx3, &dy3); + } + *x++ = x1 + dx1; *y++ = y1 + dy1; + *x++ = x2 + dx1; *y++ = y2 + dy1; + *x++ = x2 + dx2; *y++ = y2 + dy2; + *x++ = x3 + dx2; *y++ = y3 + dy2; + *x++ = x3 + dx3; *y++ = y3 + dy3; + *x++ = x1 + dx3; *y++ = y1 + dy3; + } + + //------------------------------------------------------calc_triangle_area + AGG_INLINE double calc_triangle_area(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + return (x1*y2 - x2*y1 + x2*y3 - x3*y2 + x3*y1 - x1*y3) * 0.5; + } + + //-------------------------------------------------------calc_polygon_area + template<class Storage> double calc_polygon_area(const Storage& st) + { + unsigned i; + double sum = 0.0; + double x = st[0].x; + double y = st[0].y; + double xs = x; + double ys = y; + + for(i = 1; i < st.size(); i++) + { + const typename Storage::value_type& v = st[i]; + sum += x * v.y - y * v.x; + x = v.x; + y = v.y; + } + return (sum + x * ys - y * xs) * 0.5; + } + + //------------------------------------------------------------------------ + // Tables for fast sqrt + extern int16u g_sqrt_table[1024]; + extern int8 g_elder_bit_table[256]; + + + //---------------------------------------------------------------fast_sqrt + //Fast integer Sqrt - really fast: no cycles, divisions or multiplications + #if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable : 4035) //Disable warning "no return value" + #endif + AGG_INLINE unsigned fast_sqrt(unsigned val) + { + #if defined(_M_IX86) && defined(_MSC_VER) && !defined(AGG_NO_ASM) + //For Ix86 family processors this assembler code is used. + //The key command here is bsr - determination the number of the most + //significant bit of the value. For other processors + //(and maybe compilers) the pure C "#else" section is used. + __asm + { + mov ebx, val + mov edx, 11 + bsr ecx, ebx + sub ecx, 9 + jle less_than_9_bits + shr ecx, 1 + adc ecx, 0 + sub edx, ecx + shl ecx, 1 + shr ebx, cl + less_than_9_bits: + xor eax, eax + mov ax, g_sqrt_table[ebx*2] + mov ecx, edx + shr eax, cl + } + #else + + //This code is actually pure C and portable to most + //arcitectures including 64bit ones. + unsigned t = val; + int bit=0; + unsigned shift = 11; + + //The following piece of code is just an emulation of the + //Ix86 assembler command "bsr" (see above). However on old + //Intels (like Intel MMX 233MHz) this code is about twice + //faster (sic!) then just one "bsr". On PIII and PIV the + //bsr is optimized quite well. + bit = t >> 24; + if(bit) + { + bit = g_elder_bit_table[bit] + 24; + } + else + { + bit = (t >> 16) & 0xFF; + if(bit) + { + bit = g_elder_bit_table[bit] + 16; + } + else + { + bit = (t >> 8) & 0xFF; + if(bit) + { + bit = g_elder_bit_table[bit] + 8; + } + else + { + bit = g_elder_bit_table[t]; + } + } + } + + //This code calculates the sqrt. + bit -= 9; + if(bit > 0) + { + bit = (bit >> 1) + (bit & 1); + shift -= bit; + val >>= (bit << 1); + } + return g_sqrt_table[val] >> shift; + #endif + } + #if defined(_MSC_VER) + #pragma warning(pop) + #endif + + + + + //--------------------------------------------------------------------besj + // Function BESJ calculates Bessel function of first kind of order n + // Arguments: + // n - an integer (>=0), the order + // x - value at which the Bessel function is required + //-------------------- + // C++ Mathematical Library + // Convereted from equivalent FORTRAN library + // Converetd by Gareth Walker for use by course 392 computational project + // All functions tested and yield the same results as the corresponding + // FORTRAN versions. + // + // If you have any problems using these functions please report them to + // M.Muldoon@UMIST.ac.uk + // + // Documentation available on the web + // http://www.ma.umist.ac.uk/mrm/Teaching/392/libs/392.html + // Version 1.0 8/98 + // 29 October, 1999 + //-------------------- + // Adapted for use in AGG library by Andy Wilk (castor.vulgaris@gmail.com) + //------------------------------------------------------------------------ + inline double besj(double x, int n) + { + if(n < 0) + { + return 0; + } + double d = 1E-6; + double b = 0; + if(fabs(x) <= d) + { + if(n != 0) return 0; + return 1; + } + double b1 = 0; // b1 is the value from the previous iteration + // Set up a starting order for recurrence + int m1 = (int)fabs(x) + 6; + if(fabs(x) > 5) + { + m1 = (int)(fabs(1.4 * x + 60 / x)); + } + int m2 = (int)(n + 2 + fabs(x) / 4); + if (m1 > m2) + { + m2 = m1; + } + + // Apply recurrence down from curent max order + for(;;) + { + double c3 = 0; + double c2 = 1E-30; + double c4 = 0; + int m8 = 1; + if (m2 / 2 * 2 == m2) + { + m8 = -1; + } + int imax = m2 - 2; + for (int i = 1; i <= imax; i++) + { + double c6 = 2 * (m2 - i) * c2 / x - c3; + c3 = c2; + c2 = c6; + if(m2 - i - 1 == n) + { + b = c6; + } + m8 = -1 * m8; + if (m8 > 0) + { + c4 = c4 + 2 * c6; + } + } + double c6 = 2 * c2 / x - c3; + if(n == 0) + { + b = c6; + } + c4 += c6; + b /= c4; + if(fabs(b - b1) < d) + { + return b; + } + b1 = b; + m2 += 3; + } + } + +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_math_stroke.h b/jni/desmume/src/android/agg/include/agg_math_stroke.h new file mode 100755 index 0000000..ad09af2 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_math_stroke.h @@ -0,0 +1,531 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_STROKE_MATH_INCLUDED +#define AGG_STROKE_MATH_INCLUDED + +#include "agg_math.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + //-------------------------------------------------------------line_cap_e + enum line_cap_e + { + butt_cap, + square_cap, + round_cap + }; + + //------------------------------------------------------------line_join_e + enum line_join_e + { + miter_join = 0, + miter_join_revert = 1, + round_join = 2, + bevel_join = 3, + miter_join_round = 4 + }; + + + //-----------------------------------------------------------inner_join_e + enum inner_join_e + { + inner_bevel, + inner_miter, + inner_jag, + inner_round + }; + + //------------------------------------------------------------math_stroke + template<class VertexConsumer> class math_stroke + { + public: + typedef typename VertexConsumer::value_type coord_type; + + math_stroke(); + + void line_cap(line_cap_e lc) { m_line_cap = lc; } + void line_join(line_join_e lj) { m_line_join = lj; } + void inner_join(inner_join_e ij) { m_inner_join = ij; } + + line_cap_e line_cap() const { return m_line_cap; } + line_join_e line_join() const { return m_line_join; } + inner_join_e inner_join() const { return m_inner_join; } + + void width(double w); + void miter_limit(double ml) { m_miter_limit = ml; } + void miter_limit_theta(double t); + void inner_miter_limit(double ml) { m_inner_miter_limit = ml; } + void approximation_scale(double as) { m_approx_scale = as; } + + double width() const { return m_width * 2.0; } + double miter_limit() const { return m_miter_limit; } + double inner_miter_limit() const { return m_inner_miter_limit; } + double approximation_scale() const { return m_approx_scale; } + + void calc_cap(VertexConsumer& vc, + const vertex_dist& v0, + const vertex_dist& v1, + double len); + + void calc_join(VertexConsumer& vc, + const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + double len1, + double len2); + + private: + AGG_INLINE void add_vertex(VertexConsumer& vc, double x, double y) + { + vc.add(coord_type(x, y)); + } + + void calc_arc(VertexConsumer& vc, + double x, double y, + double dx1, double dy1, + double dx2, double dy2); + + void calc_miter(VertexConsumer& vc, + const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + double dx1, double dy1, + double dx2, double dy2, + line_join_e lj, + double mlimit, + double dbevel); + + double m_width; + double m_width_abs; + double m_width_eps; + int m_width_sign; + double m_miter_limit; + double m_inner_miter_limit; + double m_approx_scale; + line_cap_e m_line_cap; + line_join_e m_line_join; + inner_join_e m_inner_join; + }; + + //----------------------------------------------------------------------- + template<class VC> math_stroke<VC>::math_stroke() : + m_width(0.5), + m_width_abs(0.5), + m_width_eps(0.5/1024.0), + m_width_sign(1), + m_miter_limit(4.0), + m_inner_miter_limit(1.01), + m_approx_scale(1.0), + m_line_cap(butt_cap), + m_line_join(miter_join), + m_inner_join(inner_miter) + { + } + + //----------------------------------------------------------------------- + template<class VC> void math_stroke<VC>::width(double w) + { + m_width = w * 0.5; + if(m_width < 0) + { + m_width_abs = -m_width; + m_width_sign = -1; + } + else + { + m_width_abs = m_width; + m_width_sign = 1; + } + m_width_eps = m_width / 1024.0; + } + + //----------------------------------------------------------------------- + template<class VC> void math_stroke<VC>::miter_limit_theta(double t) + { + m_miter_limit = 1.0 / sin(t * 0.5) ; + } + + //----------------------------------------------------------------------- + template<class VC> + void math_stroke<VC>::calc_arc(VC& vc, + double x, double y, + double dx1, double dy1, + double dx2, double dy2) + { + double a1 = atan2(dy1 * m_width_sign, dx1 * m_width_sign); + double a2 = atan2(dy2 * m_width_sign, dx2 * m_width_sign); + double da = a1 - a2; + int i, n; + + da = acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2; + + add_vertex(vc, x + dx1, y + dy1); + if(m_width_sign > 0) + { + if(a1 > a2) a2 += 2 * pi; + n = int((a2 - a1) / da); + da = (a2 - a1) / (n + 1); + a1 += da; + for(i = 0; i < n; i++) + { + add_vertex(vc, x + cos(a1) * m_width, y + sin(a1) * m_width); + a1 += da; + } + } + else + { + if(a1 < a2) a2 -= 2 * pi; + n = int((a1 - a2) / da); + da = (a1 - a2) / (n + 1); + a1 -= da; + for(i = 0; i < n; i++) + { + add_vertex(vc, x + cos(a1) * m_width, y + sin(a1) * m_width); + a1 -= da; + } + } + add_vertex(vc, x + dx2, y + dy2); + } + + //----------------------------------------------------------------------- + template<class VC> + void math_stroke<VC>::calc_miter(VC& vc, + const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + double dx1, double dy1, + double dx2, double dy2, + line_join_e lj, + double mlimit, + double dbevel) + { + double xi = v1.x; + double yi = v1.y; + double di = 1; + double lim = m_width_abs * mlimit; + bool miter_limit_exceeded = true; // Assume the worst + bool intersection_failed = true; // Assume the worst + + if(calc_intersection(v0.x + dx1, v0.y - dy1, + v1.x + dx1, v1.y - dy1, + v1.x + dx2, v1.y - dy2, + v2.x + dx2, v2.y - dy2, + &xi, &yi)) + { + // Calculation of the intersection succeeded + //--------------------- + di = calc_distance(v1.x, v1.y, xi, yi); + if(di <= lim) + { + // Inside the miter limit + //--------------------- + add_vertex(vc, xi, yi); + miter_limit_exceeded = false; + } + intersection_failed = false; + } + else + { + // Calculation of the intersection failed, most probably + // the three points lie one straight line. + // First check if v0 and v2 lie on the opposite sides of vector: + // (v1.x, v1.y) -> (v1.x+dx1, v1.y-dy1), that is, the perpendicular + // to the line determined by vertices v0 and v1. + // This condition determines whether the next line segments continues + // the previous one or goes back. + //---------------- + double x2 = v1.x + dx1; + double y2 = v1.y - dy1; + if((cross_product(v0.x, v0.y, v1.x, v1.y, x2, y2) < 0.0) == + (cross_product(v1.x, v1.y, v2.x, v2.y, x2, y2) < 0.0)) + { + // This case means that the next segment continues + // the previous one (straight line) + //----------------- + add_vertex(vc, v1.x + dx1, v1.y - dy1); + miter_limit_exceeded = false; + } + } + + if(miter_limit_exceeded) + { + // Miter limit exceeded + //------------------------ + switch(lj) + { + case miter_join_revert: + // For the compatibility with SVG, PDF, etc, + // we use a simple bevel join instead of + // "smart" bevel + //------------------- + add_vertex(vc, v1.x + dx1, v1.y - dy1); + add_vertex(vc, v1.x + dx2, v1.y - dy2); + break; + + case miter_join_round: + calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2); + break; + + default: + // If no miter-revert, calculate new dx1, dy1, dx2, dy2 + //---------------- + if(intersection_failed) + { + mlimit *= m_width_sign; + add_vertex(vc, v1.x + dx1 + dy1 * mlimit, + v1.y - dy1 + dx1 * mlimit); + add_vertex(vc, v1.x + dx2 - dy2 * mlimit, + v1.y - dy2 - dx2 * mlimit); + } + else + { + double x1 = v1.x + dx1; + double y1 = v1.y - dy1; + double x2 = v1.x + dx2; + double y2 = v1.y - dy2; + di = (lim - dbevel) / (di - dbevel); + add_vertex(vc, x1 + (xi - x1) * di, + y1 + (yi - y1) * di); + add_vertex(vc, x2 + (xi - x2) * di, + y2 + (yi - y2) * di); + } + break; + } + } + } + + //--------------------------------------------------------stroke_calc_cap + template<class VC> + void math_stroke<VC>::calc_cap(VC& vc, + const vertex_dist& v0, + const vertex_dist& v1, + double len) + { + vc.remove_all(); + + double dx1 = (v1.y - v0.y) / len; + double dy1 = (v1.x - v0.x) / len; + double dx2 = 0; + double dy2 = 0; + + dx1 *= m_width; + dy1 *= m_width; + + if(m_line_cap != round_cap) + { + if(m_line_cap == square_cap) + { + dx2 = dy1 * m_width_sign; + dy2 = dx1 * m_width_sign; + } + add_vertex(vc, v0.x - dx1 - dx2, v0.y + dy1 - dy2); + add_vertex(vc, v0.x + dx1 - dx2, v0.y - dy1 - dy2); + } + else + { + double da = acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2; + double a1; + int i; + int n = int(pi / da); + + da = pi / (n + 1); + add_vertex(vc, v0.x - dx1, v0.y + dy1); + if(m_width_sign > 0) + { + a1 = atan2(dy1, -dx1); + a1 += da; + for(i = 0; i < n; i++) + { + add_vertex(vc, v0.x + cos(a1) * m_width, + v0.y + sin(a1) * m_width); + a1 += da; + } + } + else + { + a1 = atan2(-dy1, dx1); + a1 -= da; + for(i = 0; i < n; i++) + { + add_vertex(vc, v0.x + cos(a1) * m_width, + v0.y + sin(a1) * m_width); + a1 -= da; + } + } + add_vertex(vc, v0.x + dx1, v0.y - dy1); + } + } + + //----------------------------------------------------------------------- + template<class VC> + void math_stroke<VC>::calc_join(VC& vc, + const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + double len1, + double len2) + { + double dx1 = m_width * (v1.y - v0.y) / len1; + double dy1 = m_width * (v1.x - v0.x) / len1; + double dx2 = m_width * (v2.y - v1.y) / len2; + double dy2 = m_width * (v2.x - v1.x) / len2; + + vc.remove_all(); + + double cp = cross_product(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y); + if(cp != 0 && (cp > 0) == (m_width > 0)) + { + // Inner join + //--------------- + double limit = ((len1 < len2) ? len1 : len2) / m_width_abs; + if(limit < m_inner_miter_limit) + { + limit = m_inner_miter_limit; + } + + switch(m_inner_join) + { + default: // inner_bevel + add_vertex(vc, v1.x + dx1, v1.y - dy1); + add_vertex(vc, v1.x + dx2, v1.y - dy2); + break; + + case inner_miter: + calc_miter(vc, + v0, v1, v2, dx1, dy1, dx2, dy2, + miter_join_revert, + limit, 0); + break; + + case inner_jag: + case inner_round: + cp = (dx1-dx2) * (dx1-dx2) + (dy1-dy2) * (dy1-dy2); + if(cp < len1 * len1 && cp < len2 * len2) + { + calc_miter(vc, + v0, v1, v2, dx1, dy1, dx2, dy2, + miter_join_revert, + limit, 0); + } + else + { + if(m_inner_join == inner_jag) + { + add_vertex(vc, v1.x + dx1, v1.y - dy1); + add_vertex(vc, v1.x, v1.y ); + add_vertex(vc, v1.x + dx2, v1.y - dy2); + } + else + { + add_vertex(vc, v1.x + dx1, v1.y - dy1); + add_vertex(vc, v1.x, v1.y ); + calc_arc(vc, v1.x, v1.y, dx2, -dy2, dx1, -dy1); + add_vertex(vc, v1.x, v1.y ); + add_vertex(vc, v1.x + dx2, v1.y - dy2); + } + } + break; + } + } + else + { + // Outer join + //--------------- + + // Calculate the distance between v1 and + // the central point of the bevel line segment + //--------------- + double dx = (dx1 + dx2) / 2; + double dy = (dy1 + dy2) / 2; + double dbevel = sqrt(dx * dx + dy * dy); + + if(m_line_join == round_join || m_line_join == bevel_join) + { + // This is an optimization that reduces the number of points + // in cases of almost collinear segments. If there's no + // visible difference between bevel and miter joins we'd rather + // use miter join because it adds only one point instead of two. + // + // Here we calculate the middle point between the bevel points + // and then, the distance between v1 and this middle point. + // At outer joins this distance always less than stroke width, + // because it's actually the height of an isosceles triangle of + // v1 and its two bevel points. If the difference between this + // width and this value is small (no visible bevel) we can + // add just one point. + // + // The constant in the expression makes the result approximately + // the same as in round joins and caps. You can safely comment + // out this entire "if". + //------------------- + if(m_approx_scale * (m_width_abs - dbevel) < m_width_eps) + { + if(calc_intersection(v0.x + dx1, v0.y - dy1, + v1.x + dx1, v1.y - dy1, + v1.x + dx2, v1.y - dy2, + v2.x + dx2, v2.y - dy2, + &dx, &dy)) + { + add_vertex(vc, dx, dy); + } + else + { + add_vertex(vc, v1.x + dx1, v1.y - dy1); + } + return; + } + } + + switch(m_line_join) + { + case miter_join: + case miter_join_revert: + case miter_join_round: + calc_miter(vc, + v0, v1, v2, dx1, dy1, dx2, dy2, + m_line_join, + m_miter_limit, + dbevel); + break; + + case round_join: + calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2); + break; + + default: // Bevel join + add_vertex(vc, v1.x + dx1, v1.y - dy1); + add_vertex(vc, v1.x + dx2, v1.y - dy2); + break; + } + } + } + + + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_path_length.h b/jni/desmume/src/android/agg/include/agg_path_length.h new file mode 100755 index 0000000..084a04b --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_path_length.h @@ -0,0 +1,75 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_PATH_LENGTH_INCLUDED +#define AGG_PATH_LENGTH_INCLUDED + +#include "agg_math.h" + +namespace agg +{ + template<class VertexSource> + double path_length(VertexSource& vs, unsigned path_id = 0) + { + double len = 0.0; + double start_x = 0.0; + double start_y = 0.0; + double x1 = 0.0; + double y1 = 0.0; + double x2 = 0.0; + double y2 = 0.0; + bool first = true; + + unsigned cmd; + vs.rewind(path_id); + while(!is_stop(cmd = vs.vertex(&x2, &y2))) + { + if(is_vertex(cmd)) + { + if(first || is_move_to(cmd)) + { + start_x = x2; + start_y = y2; + } + else + { + len += calc_distance(x1, y1, x2, y2); + } + x1 = x2; + y1 = y2; + first = false; + } + else + { + if(is_close(cmd) && !first) + { + len += calc_distance(x1, y1, start_x, start_y); + } + } + } + return len; + } +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_path_storage.h b/jni/desmume/src/android/agg/include/agg_path_storage.h new file mode 100755 index 0000000..7be7393 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_path_storage.h @@ -0,0 +1,1554 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_PATH_STORAGE_INCLUDED +#define AGG_PATH_STORAGE_INCLUDED + +#include <string.h> +#include <math.h> +#include "agg_math.h" +#include "agg_array.h" +#include "agg_bezier_arc.h" + +namespace agg +{ + + + //----------------------------------------------------vertex_block_storage + template<class T, unsigned BlockShift=8, unsigned BlockPool=256> + class vertex_block_storage + { + public: + // Allocation parameters + enum block_scale_e + { + block_shift = BlockShift, + block_size = 1 << block_shift, + block_mask = block_size - 1, + block_pool = BlockPool + }; + + typedef T value_type; + typedef vertex_block_storage<T, BlockShift, BlockPool> self_type; + + ~vertex_block_storage(); + vertex_block_storage(); + vertex_block_storage(const self_type& v); + const self_type& operator = (const self_type& ps); + + void remove_all(); + void free_all(); + + void add_vertex(double x, double y, unsigned cmd); + void modify_vertex(unsigned idx, double x, double y); + void modify_vertex(unsigned idx, double x, double y, unsigned cmd); + void modify_command(unsigned idx, unsigned cmd); + void swap_vertices(unsigned v1, unsigned v2); + + unsigned last_command() const; + unsigned last_vertex(double* x, double* y) const; + unsigned prev_vertex(double* x, double* y) const; + + double last_x() const; + double last_y() const; + + unsigned total_vertices() const; + unsigned vertex(unsigned idx, double* x, double* y) const; + unsigned command(unsigned idx) const; + + private: + void allocate_block(unsigned nb); + int8u* storage_ptrs(T** xy_ptr); + + private: + unsigned m_total_vertices; + unsigned m_total_blocks; + unsigned m_max_blocks; + T** m_coord_blocks; + int8u** m_cmd_blocks; + }; + + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + void vertex_block_storage<T,S,P>::free_all() + { + if(m_total_blocks) + { + T** coord_blk = m_coord_blocks + m_total_blocks - 1; + while(m_total_blocks--) + { + pod_allocator<T>::deallocate( + *coord_blk, + block_size * 2 + + block_size / (sizeof(T) / sizeof(unsigned char))); + --coord_blk; + } + pod_allocator<T*>::deallocate(m_coord_blocks, m_max_blocks * 2); + m_total_blocks = 0; + m_max_blocks = 0; + m_coord_blocks = 0; + m_cmd_blocks = 0; + m_total_vertices = 0; + } + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + vertex_block_storage<T,S,P>::~vertex_block_storage() + { + free_all(); + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + vertex_block_storage<T,S,P>::vertex_block_storage() : + m_total_vertices(0), + m_total_blocks(0), + m_max_blocks(0), + m_coord_blocks(0), + m_cmd_blocks(0) + { + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + vertex_block_storage<T,S,P>::vertex_block_storage(const vertex_block_storage<T,S,P>& v) : + m_total_vertices(0), + m_total_blocks(0), + m_max_blocks(0), + m_coord_blocks(0), + m_cmd_blocks(0) + { + *this = v; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + const vertex_block_storage<T,S,P>& + vertex_block_storage<T,S,P>::operator = (const vertex_block_storage<T,S,P>& v) + { + remove_all(); + unsigned i; + for(i = 0; i < v.total_vertices(); i++) + { + double x, y; + unsigned cmd = v.vertex(i, &x, &y); + add_vertex(x, y, cmd); + } + return *this; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline void vertex_block_storage<T,S,P>::remove_all() + { + m_total_vertices = 0; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline void vertex_block_storage<T,S,P>::add_vertex(double x, double y, + unsigned cmd) + { + T* coord_ptr = 0; + *storage_ptrs(&coord_ptr) = (int8u)cmd; + coord_ptr[0] = T(x); + coord_ptr[1] = T(y); + m_total_vertices++; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline void vertex_block_storage<T,S,P>::modify_vertex(unsigned idx, + double x, double y) + { + T* pv = m_coord_blocks[idx >> block_shift] + ((idx & block_mask) << 1); + pv[0] = T(x); + pv[1] = T(y); + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline void vertex_block_storage<T,S,P>::modify_vertex(unsigned idx, + double x, double y, + unsigned cmd) + { + unsigned block = idx >> block_shift; + unsigned offset = idx & block_mask; + T* pv = m_coord_blocks[block] + (offset << 1); + pv[0] = T(x); + pv[1] = T(y); + m_cmd_blocks[block][offset] = (int8u)cmd; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline void vertex_block_storage<T,S,P>::modify_command(unsigned idx, + unsigned cmd) + { + m_cmd_blocks[idx >> block_shift][idx & block_mask] = (int8u)cmd; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline void vertex_block_storage<T,S,P>::swap_vertices(unsigned v1, unsigned v2) + { + unsigned b1 = v1 >> block_shift; + unsigned b2 = v2 >> block_shift; + unsigned o1 = v1 & block_mask; + unsigned o2 = v2 & block_mask; + T* pv1 = m_coord_blocks[b1] + (o1 << 1); + T* pv2 = m_coord_blocks[b2] + (o2 << 1); + T val; + val = pv1[0]; pv1[0] = pv2[0]; pv2[0] = val; + val = pv1[1]; pv1[1] = pv2[1]; pv2[1] = val; + int8u cmd = m_cmd_blocks[b1][o1]; + m_cmd_blocks[b1][o1] = m_cmd_blocks[b2][o2]; + m_cmd_blocks[b2][o2] = cmd; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline unsigned vertex_block_storage<T,S,P>::last_command() const + { + if(m_total_vertices) return command(m_total_vertices - 1); + return path_cmd_stop; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline unsigned vertex_block_storage<T,S,P>::last_vertex(double* x, double* y) const + { + if(m_total_vertices) return vertex(m_total_vertices - 1, x, y); + return path_cmd_stop; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline unsigned vertex_block_storage<T,S,P>::prev_vertex(double* x, double* y) const + { + if(m_total_vertices > 1) return vertex(m_total_vertices - 2, x, y); + return path_cmd_stop; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline double vertex_block_storage<T,S,P>::last_x() const + { + if(m_total_vertices) + { + unsigned idx = m_total_vertices - 1; + return m_coord_blocks[idx >> block_shift][(idx & block_mask) << 1]; + } + return 0.0; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline double vertex_block_storage<T,S,P>::last_y() const + { + if(m_total_vertices) + { + unsigned idx = m_total_vertices - 1; + return m_coord_blocks[idx >> block_shift][((idx & block_mask) << 1) + 1]; + } + return 0.0; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline unsigned vertex_block_storage<T,S,P>::total_vertices() const + { + return m_total_vertices; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline unsigned vertex_block_storage<T,S,P>::vertex(unsigned idx, + double* x, double* y) const + { + unsigned nb = idx >> block_shift; + const T* pv = m_coord_blocks[nb] + ((idx & block_mask) << 1); + *x = pv[0]; + *y = pv[1]; + return m_cmd_blocks[nb][idx & block_mask]; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + inline unsigned vertex_block_storage<T,S,P>::command(unsigned idx) const + { + return m_cmd_blocks[idx >> block_shift][idx & block_mask]; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + void vertex_block_storage<T,S,P>::allocate_block(unsigned nb) + { + if(nb >= m_max_blocks) + { + T** new_coords = + pod_allocator<T*>::allocate((m_max_blocks + block_pool) * 2); + + unsigned char** new_cmds = + (unsigned char**)(new_coords + m_max_blocks + block_pool); + + if(m_coord_blocks) + { + memcpy(new_coords, + m_coord_blocks, + m_max_blocks * sizeof(T*)); + + memcpy(new_cmds, + m_cmd_blocks, + m_max_blocks * sizeof(unsigned char*)); + + pod_allocator<T*>::deallocate(m_coord_blocks, m_max_blocks * 2); + } + m_coord_blocks = new_coords; + m_cmd_blocks = new_cmds; + m_max_blocks += block_pool; + } + m_coord_blocks[nb] = + pod_allocator<T>::allocate(block_size * 2 + + block_size / (sizeof(T) / sizeof(unsigned char))); + + m_cmd_blocks[nb] = + (unsigned char*)(m_coord_blocks[nb] + block_size * 2); + + m_total_blocks++; + } + + //------------------------------------------------------------------------ + template<class T, unsigned S, unsigned P> + int8u* vertex_block_storage<T,S,P>::storage_ptrs(T** xy_ptr) + { + unsigned nb = m_total_vertices >> block_shift; + if(nb >= m_total_blocks) + { + allocate_block(nb); + } + *xy_ptr = m_coord_blocks[nb] + ((m_total_vertices & block_mask) << 1); + return m_cmd_blocks[nb] + (m_total_vertices & block_mask); + } + + + + + //-----------------------------------------------------poly_plain_adaptor + template<class T> class poly_plain_adaptor + { + public: + typedef T value_type; + + poly_plain_adaptor() : + m_data(0), + m_ptr(0), + m_end(0), + m_closed(false), + m_stop(false) + {} + + poly_plain_adaptor(const T* data, unsigned num_points, bool closed) : + m_data(data), + m_ptr(data), + m_end(data + num_points * 2), + m_closed(closed), + m_stop(false) + {} + + void init(const T* data, unsigned num_points, bool closed) + { + m_data = data; + m_ptr = data; + m_end = data + num_points * 2; + m_closed = closed; + m_stop = false; + } + + void rewind(unsigned) + { + m_ptr = m_data; + m_stop = false; + } + + unsigned vertex(double* x, double* y) + { + if(m_ptr < m_end) + { + bool first = m_ptr == m_data; + *x = *m_ptr++; + *y = *m_ptr++; + return first ? path_cmd_move_to : path_cmd_line_to; + } + *x = *y = 0.0; + if(m_closed && !m_stop) + { + m_stop = true; + return path_cmd_end_poly | path_flags_close; + } + return path_cmd_stop; + } + + private: + const T* m_data; + const T* m_ptr; + const T* m_end; + bool m_closed; + bool m_stop; + }; + + + + + + //-------------------------------------------------poly_container_adaptor + template<class Container> class poly_container_adaptor + { + public: + typedef typename Container::value_type vertex_type; + + poly_container_adaptor() : + m_container(0), + m_index(0), + m_closed(false), + m_stop(false) + {} + + poly_container_adaptor(const Container& data, bool closed) : + m_container(&data), + m_index(0), + m_closed(closed), + m_stop(false) + {} + + void init(const Container& data, bool closed) + { + m_container = &data; + m_index = 0; + m_closed = closed; + m_stop = false; + } + + void rewind(unsigned) + { + m_index = 0; + m_stop = false; + } + + unsigned vertex(double* x, double* y) + { + if(m_index < m_container->size()) + { + bool first = m_index == 0; + const vertex_type& v = (*m_container)[m_index++]; + *x = v.x; + *y = v.y; + return first ? path_cmd_move_to : path_cmd_line_to; + } + *x = *y = 0.0; + if(m_closed && !m_stop) + { + m_stop = true; + return path_cmd_end_poly | path_flags_close; + } + return path_cmd_stop; + } + + private: + const Container* m_container; + unsigned m_index; + bool m_closed; + bool m_stop; + }; + + + + //-----------------------------------------poly_container_reverse_adaptor + template<class Container> class poly_container_reverse_adaptor + { + public: + typedef typename Container::value_type vertex_type; + + poly_container_reverse_adaptor() : + m_container(0), + m_index(-1), + m_closed(false), + m_stop(false) + {} + + poly_container_reverse_adaptor(const Container& data, bool closed) : + m_container(&data), + m_index(-1), + m_closed(closed), + m_stop(false) + {} + + void init(const Container& data, bool closed) + { + m_container = &data; + m_index = m_container->size() - 1; + m_closed = closed; + m_stop = false; + } + + void rewind(unsigned) + { + m_index = m_container->size() - 1; + m_stop = false; + } + + unsigned vertex(double* x, double* y) + { + if(m_index >= 0) + { + bool first = m_index == int(m_container->size() - 1); + const vertex_type& v = (*m_container)[m_index--]; + *x = v.x; + *y = v.y; + return first ? path_cmd_move_to : path_cmd_line_to; + } + *x = *y = 0.0; + if(m_closed && !m_stop) + { + m_stop = true; + return path_cmd_end_poly | path_flags_close; + } + return path_cmd_stop; + } + + private: + const Container* m_container; + int m_index; + bool m_closed; + bool m_stop; + }; + + + + + + //--------------------------------------------------------line_adaptor + class line_adaptor + { + public: + typedef double value_type; + + line_adaptor() : m_line(m_coord, 2, false) {} + line_adaptor(double x1, double y1, double x2, double y2) : + m_line(m_coord, 2, false) + { + m_coord[0] = x1; + m_coord[1] = y1; + m_coord[2] = x2; + m_coord[3] = y2; + } + + void init(double x1, double y1, double x2, double y2) + { + m_coord[0] = x1; + m_coord[1] = y1; + m_coord[2] = x2; + m_coord[3] = y2; + m_line.rewind(0); + } + + void rewind(unsigned) + { + m_line.rewind(0); + } + + unsigned vertex(double* x, double* y) + { + return m_line.vertex(x, y); + } + + private: + double m_coord[4]; + poly_plain_adaptor<double> m_line; + }; + + + + + + + + + + + + + + //---------------------------------------------------------------path_base + // A container to store vertices with their flags. + // A path consists of a number of contours separated with "move_to" + // commands. The path storage can keep and maintain more than one + // path. + // To navigate to the beginning of a particular path, use rewind(path_id); + // Where path_id is what start_new_path() returns. So, when you call + // start_new_path() you need to store its return value somewhere else + // to navigate to the path afterwards. + // + // See also: vertex_source concept + //------------------------------------------------------------------------ + template<class VertexContainer> class path_base + { + public: + typedef VertexContainer container_type; + typedef path_base<VertexContainer> self_type; + + //-------------------------------------------------------------------- + path_base() : m_vertices(), m_iterator(0) {} + void remove_all() { m_vertices.remove_all(); m_iterator = 0; } + void free_all() { m_vertices.free_all(); m_iterator = 0; } + + // Make path functions + //-------------------------------------------------------------------- + unsigned start_new_path(); + + void move_to(double x, double y); + void move_rel(double dx, double dy); + + void line_to(double x, double y); + void line_rel(double dx, double dy); + + void hline_to(double x); + void hline_rel(double dx); + + void vline_to(double y); + void vline_rel(double dy); + + void arc_to(double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double x, double y); + + void arc_rel(double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double dx, double dy); + + void curve3(double x_ctrl, double y_ctrl, + double x_to, double y_to); + + void curve3_rel(double dx_ctrl, double dy_ctrl, + double dx_to, double dy_to); + + void curve3(double x_to, double y_to); + + void curve3_rel(double dx_to, double dy_to); + + void curve4(double x_ctrl1, double y_ctrl1, + double x_ctrl2, double y_ctrl2, + double x_to, double y_to); + + void curve4_rel(double dx_ctrl1, double dy_ctrl1, + double dx_ctrl2, double dy_ctrl2, + double dx_to, double dy_to); + + void curve4(double x_ctrl2, double y_ctrl2, + double x_to, double y_to); + + void curve4_rel(double x_ctrl2, double y_ctrl2, + double x_to, double y_to); + + + void end_poly(unsigned flags = path_flags_close); + void close_polygon(unsigned flags = path_flags_none); + + // Accessors + //-------------------------------------------------------------------- + const container_type& vertices() const { return m_vertices; } + container_type& vertices() { return m_vertices; } + + unsigned total_vertices() const; + + void rel_to_abs(double* x, double* y) const; + + unsigned last_vertex(double* x, double* y) const; + unsigned prev_vertex(double* x, double* y) const; + + double last_x() const; + double last_y() const; + + unsigned vertex(unsigned idx, double* x, double* y) const; + unsigned command(unsigned idx) const; + + void modify_vertex(unsigned idx, double x, double y); + void modify_vertex(unsigned idx, double x, double y, unsigned cmd); + void modify_command(unsigned idx, unsigned cmd); + + // VertexSource interface + //-------------------------------------------------------------------- + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + // Arrange the orientation of a polygon, all polygons in a path, + // or in all paths. After calling arrange_orientations() or + // arrange_orientations_all_paths(), all the polygons will have + // the same orientation, i.e. path_flags_cw or path_flags_ccw + //-------------------------------------------------------------------- + unsigned arrange_polygon_orientation(unsigned start, path_flags_e orientation); + unsigned arrange_orientations(unsigned path_id, path_flags_e orientation); + void arrange_orientations_all_paths(path_flags_e orientation); + void invert_polygon(unsigned start); + + // Flip all vertices horizontally or vertically, + // between x1 and x2, or between y1 and y2 respectively + //-------------------------------------------------------------------- + void flip_x(double x1, double x2); + void flip_y(double y1, double y2); + + // Concatenate path. The path is added as is. + //-------------------------------------------------------------------- + template<class VertexSource> + void concat_path(VertexSource& vs, unsigned path_id = 0) + { + double x, y; + unsigned cmd; + vs.rewind(path_id); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + m_vertices.add_vertex(x, y, cmd); + } + } + + //-------------------------------------------------------------------- + // Join path. The path is joined with the existing one, that is, + // it behaves as if the pen of a plotter was always down (drawing) + template<class VertexSource> + void join_path(VertexSource& vs, unsigned path_id = 0) + { + double x, y; + unsigned cmd; + vs.rewind(path_id); + cmd = vs.vertex(&x, &y); + if(!is_stop(cmd)) + { + if(is_vertex(cmd)) + { + double x0, y0; + unsigned cmd0 = last_vertex(&x0, &y0); + if(is_vertex(cmd0)) + { + if(calc_distance(x, y, x0, y0) > vertex_dist_epsilon) + { + if(is_move_to(cmd)) cmd = path_cmd_line_to; + m_vertices.add_vertex(x, y, cmd); + } + } + else + { + if(is_stop(cmd0)) + { + cmd = path_cmd_move_to; + } + else + { + if(is_move_to(cmd)) cmd = path_cmd_line_to; + } + m_vertices.add_vertex(x, y, cmd); + } + } + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + m_vertices.add_vertex(x, y, is_move_to(cmd) ? + unsigned(path_cmd_line_to) : + cmd); + } + } + } + + // Concatenate polygon/polyline. + //-------------------------------------------------------------------- + template<class T> void concat_poly(const T* data, + unsigned num_points, + bool closed) + { + poly_plain_adaptor<T> poly(data, num_points, closed); + concat_path(poly); + } + + // Join polygon/polyline continuously. + //-------------------------------------------------------------------- + template<class T> void join_poly(const T* data, + unsigned num_points, + bool closed) + { + poly_plain_adaptor<T> poly(data, num_points, closed); + join_path(poly); + } + + //-------------------------------------------------------------------- + void translate(double dx, double dy, unsigned path_id=0); + void translate_all_paths(double dx, double dy); + + //-------------------------------------------------------------------- + template<class Trans> + void transform(const Trans& trans, unsigned path_id=0) + { + unsigned num_ver = m_vertices.total_vertices(); + for(; path_id < num_ver; path_id++) + { + double x, y; + unsigned cmd = m_vertices.vertex(path_id, &x, &y); + if(is_stop(cmd)) break; + if(is_vertex(cmd)) + { + trans.transform(&x, &y); + m_vertices.modify_vertex(path_id, x, y); + } + } + } + + //-------------------------------------------------------------------- + template<class Trans> + void transform_all_paths(const Trans& trans) + { + unsigned idx; + unsigned num_ver = m_vertices.total_vertices(); + for(idx = 0; idx < num_ver; idx++) + { + double x, y; + if(is_vertex(m_vertices.vertex(idx, &x, &y))) + { + trans.transform(&x, &y); + m_vertices.modify_vertex(idx, x, y); + } + } + } + + + + private: + unsigned perceive_polygon_orientation(unsigned start, unsigned end); + void invert_polygon(unsigned start, unsigned end); + + VertexContainer m_vertices; + unsigned m_iterator; + }; + + //------------------------------------------------------------------------ + template<class VC> + unsigned path_base<VC>::start_new_path() + { + if(!is_stop(m_vertices.last_command())) + { + m_vertices.add_vertex(0.0, 0.0, path_cmd_stop); + } + return m_vertices.total_vertices(); + } + + + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::rel_to_abs(double* x, double* y) const + { + if(m_vertices.total_vertices()) + { + double x2; + double y2; + if(is_vertex(m_vertices.last_vertex(&x2, &y2))) + { + *x += x2; + *y += y2; + } + } + } + + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::move_to(double x, double y) + { + m_vertices.add_vertex(x, y, path_cmd_move_to); + } + + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::move_rel(double dx, double dy) + { + rel_to_abs(&dx, &dy); + m_vertices.add_vertex(dx, dy, path_cmd_move_to); + } + + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::line_to(double x, double y) + { + m_vertices.add_vertex(x, y, path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::line_rel(double dx, double dy) + { + rel_to_abs(&dx, &dy); + m_vertices.add_vertex(dx, dy, path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::hline_to(double x) + { + m_vertices.add_vertex(x, last_y(), path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::hline_rel(double dx) + { + double dy = 0; + rel_to_abs(&dx, &dy); + m_vertices.add_vertex(dx, dy, path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::vline_to(double y) + { + m_vertices.add_vertex(last_x(), y, path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::vline_rel(double dy) + { + double dx = 0; + rel_to_abs(&dx, &dy); + m_vertices.add_vertex(dx, dy, path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::arc_to(double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double x, double y) + { + if(m_vertices.total_vertices() && is_vertex(m_vertices.last_command())) + { + const double epsilon = 1e-30; + double x0 = 0.0; + double y0 = 0.0; + m_vertices.last_vertex(&x0, &y0); + + rx = fabs(rx); + ry = fabs(ry); + + // Ensure radii are valid + //------------------------- + if(rx < epsilon || ry < epsilon) + { + line_to(x, y); + return; + } + + if(calc_distance(x0, y0, x, y) < epsilon) + { + // If the endpoints (x, y) and (x0, y0) are identical, then this + // is equivalent to omitting the elliptical arc segment entirely. + return; + } + bezier_arc_svg a(x0, y0, rx, ry, angle, large_arc_flag, sweep_flag, x, y); + if(a.radii_ok()) + { + join_path(a); + } + else + { + line_to(x, y); + } + } + else + { + move_to(x, y); + } + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::arc_rel(double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double dx, double dy) + { + rel_to_abs(&dx, &dy); + arc_to(rx, ry, angle, large_arc_flag, sweep_flag, dx, dy); + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::curve3(double x_ctrl, double y_ctrl, + double x_to, double y_to) + { + m_vertices.add_vertex(x_ctrl, y_ctrl, path_cmd_curve3); + m_vertices.add_vertex(x_to, y_to, path_cmd_curve3); + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::curve3_rel(double dx_ctrl, double dy_ctrl, + double dx_to, double dy_to) + { + rel_to_abs(&dx_ctrl, &dy_ctrl); + rel_to_abs(&dx_to, &dy_to); + m_vertices.add_vertex(dx_ctrl, dy_ctrl, path_cmd_curve3); + m_vertices.add_vertex(dx_to, dy_to, path_cmd_curve3); + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::curve3(double x_to, double y_to) + { + double x0; + double y0; + if(is_vertex(m_vertices.last_vertex(&x0, &y0))) + { + double x_ctrl; + double y_ctrl; + unsigned cmd = m_vertices.prev_vertex(&x_ctrl, &y_ctrl); + if(is_curve(cmd)) + { + x_ctrl = x0 + x0 - x_ctrl; + y_ctrl = y0 + y0 - y_ctrl; + } + else + { + x_ctrl = x0; + y_ctrl = y0; + } + curve3(x_ctrl, y_ctrl, x_to, y_to); + } + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::curve3_rel(double dx_to, double dy_to) + { + rel_to_abs(&dx_to, &dy_to); + curve3(dx_to, dy_to); + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::curve4(double x_ctrl1, double y_ctrl1, + double x_ctrl2, double y_ctrl2, + double x_to, double y_to) + { + m_vertices.add_vertex(x_ctrl1, y_ctrl1, path_cmd_curve4); + m_vertices.add_vertex(x_ctrl2, y_ctrl2, path_cmd_curve4); + m_vertices.add_vertex(x_to, y_to, path_cmd_curve4); + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::curve4_rel(double dx_ctrl1, double dy_ctrl1, + double dx_ctrl2, double dy_ctrl2, + double dx_to, double dy_to) + { + rel_to_abs(&dx_ctrl1, &dy_ctrl1); + rel_to_abs(&dx_ctrl2, &dy_ctrl2); + rel_to_abs(&dx_to, &dy_to); + m_vertices.add_vertex(dx_ctrl1, dy_ctrl1, path_cmd_curve4); + m_vertices.add_vertex(dx_ctrl2, dy_ctrl2, path_cmd_curve4); + m_vertices.add_vertex(dx_to, dy_to, path_cmd_curve4); + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::curve4(double x_ctrl2, double y_ctrl2, + double x_to, double y_to) + { + double x0; + double y0; + if(is_vertex(last_vertex(&x0, &y0))) + { + double x_ctrl1; + double y_ctrl1; + unsigned cmd = prev_vertex(&x_ctrl1, &y_ctrl1); + if(is_curve(cmd)) + { + x_ctrl1 = x0 + x0 - x_ctrl1; + y_ctrl1 = y0 + y0 - y_ctrl1; + } + else + { + x_ctrl1 = x0; + y_ctrl1 = y0; + } + curve4(x_ctrl1, y_ctrl1, x_ctrl2, y_ctrl2, x_to, y_to); + } + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::curve4_rel(double dx_ctrl2, double dy_ctrl2, + double dx_to, double dy_to) + { + rel_to_abs(&dx_ctrl2, &dy_ctrl2); + rel_to_abs(&dx_to, &dy_to); + curve4(dx_ctrl2, dy_ctrl2, dx_to, dy_to); + } + + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::end_poly(unsigned flags) + { + if(is_vertex(m_vertices.last_command())) + { + m_vertices.add_vertex(0.0, 0.0, path_cmd_end_poly | flags); + } + } + + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::close_polygon(unsigned flags) + { + end_poly(path_flags_close | flags); + } + + //------------------------------------------------------------------------ + template<class VC> + inline unsigned path_base<VC>::total_vertices() const + { + return m_vertices.total_vertices(); + } + + //------------------------------------------------------------------------ + template<class VC> + inline unsigned path_base<VC>::last_vertex(double* x, double* y) const + { + return m_vertices.last_vertex(x, y); + } + + //------------------------------------------------------------------------ + template<class VC> + inline unsigned path_base<VC>::prev_vertex(double* x, double* y) const + { + return m_vertices.prev_vertex(x, y); + } + + //------------------------------------------------------------------------ + template<class VC> + inline double path_base<VC>::last_x() const + { + return m_vertices.last_x(); + } + + //------------------------------------------------------------------------ + template<class VC> + inline double path_base<VC>::last_y() const + { + return m_vertices.last_y(); + } + + //------------------------------------------------------------------------ + template<class VC> + inline unsigned path_base<VC>::vertex(unsigned idx, double* x, double* y) const + { + return m_vertices.vertex(idx, x, y); + } + + //------------------------------------------------------------------------ + template<class VC> + inline unsigned path_base<VC>::command(unsigned idx) const + { + return m_vertices.command(idx); + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::modify_vertex(unsigned idx, double x, double y) + { + m_vertices.modify_vertex(idx, x, y); + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::modify_vertex(unsigned idx, double x, double y, unsigned cmd) + { + m_vertices.modify_vertex(idx, x, y, cmd); + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::modify_command(unsigned idx, unsigned cmd) + { + m_vertices.modify_command(idx, cmd); + } + + //------------------------------------------------------------------------ + template<class VC> + inline void path_base<VC>::rewind(unsigned path_id) + { + m_iterator = path_id; + } + + //------------------------------------------------------------------------ + template<class VC> + inline unsigned path_base<VC>::vertex(double* x, double* y) + { + if(m_iterator >= m_vertices.total_vertices()) return path_cmd_stop; + return m_vertices.vertex(m_iterator++, x, y); + } + + //------------------------------------------------------------------------ + template<class VC> + unsigned path_base<VC>::perceive_polygon_orientation(unsigned start, + unsigned end) + { + // Calculate signed area (double area to be exact) + //--------------------- + unsigned np = end - start; + double area = 0.0; + unsigned i; + for(i = 0; i < np; i++) + { + double x1, y1, x2, y2; + m_vertices.vertex(start + i, &x1, &y1); + m_vertices.vertex(start + (i + 1) % np, &x2, &y2); + area += x1 * y2 - y1 * x2; + } + return (area < 0.0) ? path_flags_cw : path_flags_ccw; + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::invert_polygon(unsigned start, unsigned end) + { + unsigned i; + unsigned tmp_cmd = m_vertices.command(start); + + --end; // Make "end" inclusive + + // Shift all commands to one position + for(i = start; i < end; i++) + { + m_vertices.modify_command(i, m_vertices.command(i + 1)); + } + + // Assign starting command to the ending command + m_vertices.modify_command(end, tmp_cmd); + + // Reverse the polygon + while(end > start) + { + m_vertices.swap_vertices(start++, end--); + } + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::invert_polygon(unsigned start) + { + // Skip all non-vertices at the beginning + while(start < m_vertices.total_vertices() && + !is_vertex(m_vertices.command(start))) ++start; + + // Skip all insignificant move_to + while(start+1 < m_vertices.total_vertices() && + is_move_to(m_vertices.command(start)) && + is_move_to(m_vertices.command(start+1))) ++start; + + // Find the last vertex + unsigned end = start + 1; + while(end < m_vertices.total_vertices() && + !is_next_poly(m_vertices.command(end))) ++end; + + invert_polygon(start, end); + } + + //------------------------------------------------------------------------ + template<class VC> + unsigned path_base<VC>::arrange_polygon_orientation(unsigned start, + path_flags_e orientation) + { + if(orientation == path_flags_none) return start; + + // Skip all non-vertices at the beginning + while(start < m_vertices.total_vertices() && + !is_vertex(m_vertices.command(start))) ++start; + + // Skip all insignificant move_to + while(start+1 < m_vertices.total_vertices() && + is_move_to(m_vertices.command(start)) && + is_move_to(m_vertices.command(start+1))) ++start; + + // Find the last vertex + unsigned end = start + 1; + while(end < m_vertices.total_vertices() && + !is_next_poly(m_vertices.command(end))) ++end; + + if(end - start > 2) + { + if(perceive_polygon_orientation(start, end) != unsigned(orientation)) + { + // Invert polygon, set orientation flag, and skip all end_poly + invert_polygon(start, end); + unsigned cmd; + while(end < m_vertices.total_vertices() && + is_end_poly(cmd = m_vertices.command(end))) + { + m_vertices.modify_command(end++, set_orientation(cmd, orientation)); + } + } + } + return end; + } + + //------------------------------------------------------------------------ + template<class VC> + unsigned path_base<VC>::arrange_orientations(unsigned start, + path_flags_e orientation) + { + if(orientation != path_flags_none) + { + while(start < m_vertices.total_vertices()) + { + start = arrange_polygon_orientation(start, orientation); + if(is_stop(m_vertices.command(start))) + { + ++start; + break; + } + } + } + return start; + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::arrange_orientations_all_paths(path_flags_e orientation) + { + if(orientation != path_flags_none) + { + unsigned start = 0; + while(start < m_vertices.total_vertices()) + { + start = arrange_orientations(start, orientation); + } + } + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::flip_x(double x1, double x2) + { + unsigned i; + double x, y; + for(i = 0; i < m_vertices.total_vertices(); i++) + { + unsigned cmd = m_vertices.vertex(i, &x, &y); + if(is_vertex(cmd)) + { + m_vertices.modify_vertex(i, x2 - x + x1, y); + } + } + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::flip_y(double y1, double y2) + { + unsigned i; + double x, y; + for(i = 0; i < m_vertices.total_vertices(); i++) + { + unsigned cmd = m_vertices.vertex(i, &x, &y); + if(is_vertex(cmd)) + { + m_vertices.modify_vertex(i, x, y2 - y + y1); + } + } + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::translate(double dx, double dy, unsigned path_id) + { + unsigned num_ver = m_vertices.total_vertices(); + for(; path_id < num_ver; path_id++) + { + double x, y; + unsigned cmd = m_vertices.vertex(path_id, &x, &y); + if(is_stop(cmd)) break; + if(is_vertex(cmd)) + { + x += dx; + y += dy; + m_vertices.modify_vertex(path_id, x, y); + } + } + } + + //------------------------------------------------------------------------ + template<class VC> + void path_base<VC>::translate_all_paths(double dx, double dy) + { + unsigned idx; + unsigned num_ver = m_vertices.total_vertices(); + for(idx = 0; idx < num_ver; idx++) + { + double x, y; + if(is_vertex(m_vertices.vertex(idx, &x, &y))) + { + x += dx; + y += dy; + m_vertices.modify_vertex(idx, x, y); + } + } + } + + //-----------------------------------------------------vertex_stl_storage + template<class Container> class vertex_stl_storage + { + public: + typedef typename Container::value_type vertex_type; + typedef typename vertex_type::value_type value_type; + + void remove_all() { m_vertices.clear(); } + void free_all() { m_vertices.clear(); } + + void add_vertex(double x, double y, unsigned cmd) + { + m_vertices.push_back(vertex_type(value_type(x), + value_type(y), + int8u(cmd))); + } + + void modify_vertex(unsigned idx, double x, double y) + { + vertex_type& v = m_vertices[idx]; + v.x = value_type(x); + v.y = value_type(y); + } + + void modify_vertex(unsigned idx, double x, double y, unsigned cmd) + { + vertex_type& v = m_vertices[idx]; + v.x = value_type(x); + v.y = value_type(y); + v.cmd = int8u(cmd); + } + + void modify_command(unsigned idx, unsigned cmd) + { + m_vertices[idx].cmd = int8u(cmd); + } + + void swap_vertices(unsigned v1, unsigned v2) + { + vertex_type t = m_vertices[v1]; + m_vertices[v1] = m_vertices[v2]; + m_vertices[v2] = t; + } + + unsigned last_command() const + { + return m_vertices.size() ? + m_vertices[m_vertices.size() - 1].cmd : + path_cmd_stop; + } + + unsigned last_vertex(double* x, double* y) const + { + if(m_vertices.size() == 0) + { + *x = *y = 0.0; + return path_cmd_stop; + } + return vertex(m_vertices.size() - 1, x, y); + } + + unsigned prev_vertex(double* x, double* y) const + { + if(m_vertices.size() < 2) + { + *x = *y = 0.0; + return path_cmd_stop; + } + return vertex(m_vertices.size() - 2, x, y); + } + + double last_x() const + { + return m_vertices.size() ? m_vertices[m_vertices.size() - 1].x : 0.0; + } + + double last_y() const + { + return m_vertices.size() ? m_vertices[m_vertices.size() - 1].y : 0.0; + } + + unsigned total_vertices() const + { + return m_vertices.size(); + } + + unsigned vertex(unsigned idx, double* x, double* y) const + { + const vertex_type& v = m_vertices[idx]; + *x = v.x; + *y = v.y; + return v.cmd; + } + + unsigned command(unsigned idx) const + { + return m_vertices[idx].cmd; + } + + private: + Container m_vertices; + }; + + //-----------------------------------------------------------path_storage + typedef path_base<vertex_block_storage<double> > path_storage; + + // Example of declarations path_storage with pod_bvector as a container + //----------------------------------------------------------------------- + //typedef path_base<vertex_stl_storage<pod_bvector<vertex_d> > > path_storage; + +} + + + +// Example of declarations path_storage with std::vector as a container +//--------------------------------------------------------------------------- +//#include <vector> +//namespace agg +//{ +// typedef path_base<vertex_stl_storage<std::vector<vertex_d> > > stl_path_storage; +//} + + + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_path_storage_integer.h b/jni/desmume/src/android/agg/include/agg_path_storage_integer.h new file mode 100755 index 0000000..59ac00a --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_path_storage_integer.h @@ -0,0 +1,304 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_PATH_STORAGE_INTEGER_INCLUDED +#define AGG_PATH_STORAGE_INTEGER_INCLUDED + +#include <string.h> +#include "agg_array.h" + +namespace agg +{ + //---------------------------------------------------------vertex_integer + template<class T, unsigned CoordShift=6> struct vertex_integer + { + enum path_cmd + { + cmd_move_to = 0, + cmd_line_to = 1, + cmd_curve3 = 2, + cmd_curve4 = 3 + }; + + enum coord_scale_e + { + coord_shift = CoordShift, + coord_scale = 1 << coord_shift + }; + + T x,y; + vertex_integer() {} + vertex_integer(T x_, T y_, unsigned flag) : + x(((x_ << 1) & ~1) | (flag & 1)), + y(((y_ << 1) & ~1) | (flag >> 1)) {} + + unsigned vertex(double* x_, double* y_, + double dx=0, double dy=0, + double scale=1.0) const + { + *x_ = dx + (double(x >> 1) / coord_scale) * scale; + *y_ = dy + (double(y >> 1) / coord_scale) * scale; + switch(((y & 1) << 1) | (x & 1)) + { + case cmd_move_to: return path_cmd_move_to; + case cmd_line_to: return path_cmd_line_to; + case cmd_curve3: return path_cmd_curve3; + case cmd_curve4: return path_cmd_curve4; + } + return path_cmd_stop; + } + }; + + + //---------------------------------------------------path_storage_integer + template<class T, unsigned CoordShift=6> class path_storage_integer + { + public: + typedef T value_type; + typedef vertex_integer<T, CoordShift> vertex_integer_type; + + //-------------------------------------------------------------------- + path_storage_integer() : m_storage(), m_vertex_idx(0), m_closed(true) {} + + //-------------------------------------------------------------------- + void remove_all() { m_storage.remove_all(); } + + //-------------------------------------------------------------------- + void move_to(T x, T y) + { + m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_move_to)); + } + + //-------------------------------------------------------------------- + void line_to(T x, T y) + { + m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_line_to)); + } + + //-------------------------------------------------------------------- + void curve3(T x_ctrl, T y_ctrl, + T x_to, T y_to) + { + m_storage.add(vertex_integer_type(x_ctrl, y_ctrl, vertex_integer_type::cmd_curve3)); + m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve3)); + } + + //-------------------------------------------------------------------- + void curve4(T x_ctrl1, T y_ctrl1, + T x_ctrl2, T y_ctrl2, + T x_to, T y_to) + { + m_storage.add(vertex_integer_type(x_ctrl1, y_ctrl1, vertex_integer_type::cmd_curve4)); + m_storage.add(vertex_integer_type(x_ctrl2, y_ctrl2, vertex_integer_type::cmd_curve4)); + m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve4)); + } + + //-------------------------------------------------------------------- + void close_polygon() {} + + //-------------------------------------------------------------------- + unsigned size() const { return m_storage.size(); } + unsigned vertex(unsigned idx, double* x, double* y) const + { + return m_storage[idx].vertex(x, y); + } + + //-------------------------------------------------------------------- + unsigned byte_size() const { return m_storage.size() * sizeof(vertex_integer_type); } + void serialize(int8u* ptr) const + { + unsigned i; + for(i = 0; i < m_storage.size(); i++) + { + memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type)); + ptr += sizeof(vertex_integer_type); + } + } + + //-------------------------------------------------------------------- + void rewind(unsigned) + { + m_vertex_idx = 0; + m_closed = true; + } + + //-------------------------------------------------------------------- + unsigned vertex(double* x, double* y) + { + if(m_storage.size() < 2 || m_vertex_idx > m_storage.size()) + { + *x = 0; + *y = 0; + return path_cmd_stop; + } + if(m_vertex_idx == m_storage.size()) + { + *x = 0; + *y = 0; + ++m_vertex_idx; + return path_cmd_end_poly | path_flags_close; + } + unsigned cmd = m_storage[m_vertex_idx].vertex(x, y); + if(is_move_to(cmd) && !m_closed) + { + *x = 0; + *y = 0; + m_closed = true; + return path_cmd_end_poly | path_flags_close; + } + m_closed = false; + ++m_vertex_idx; + return cmd; + } + + //-------------------------------------------------------------------- + rect_d bounding_rect() const + { + rect_d bounds(1e100, 1e100, -1e100, -1e100); + if(m_storage.size() == 0) + { + bounds.x1 = bounds.y1 = bounds.x2 = bounds.y2 = 0.0; + } + else + { + unsigned i; + for(i = 0; i < m_storage.size(); i++) + { + double x, y; + m_storage[i].vertex(&x, &y); + if(x < bounds.x1) bounds.x1 = x; + if(y < bounds.y1) bounds.y1 = y; + if(x > bounds.x2) bounds.x2 = x; + if(y > bounds.y2) bounds.y2 = y; + } + } + return bounds; + } + + private: + pod_bvector<vertex_integer_type, 6> m_storage; + unsigned m_vertex_idx; + bool m_closed; + }; + + + + + //-----------------------------------------serialized_integer_path_adaptor + template<class T, unsigned CoordShift=6> class serialized_integer_path_adaptor + { + public: + typedef vertex_integer<T, CoordShift> vertex_integer_type; + + //-------------------------------------------------------------------- + serialized_integer_path_adaptor() : + m_data(0), + m_end(0), + m_ptr(0), + m_dx(0.0), + m_dy(0.0), + m_scale(1.0), + m_vertices(0) + {} + + //-------------------------------------------------------------------- + serialized_integer_path_adaptor(const int8u* data, unsigned size, + double dx, double dy) : + m_data(data), + m_end(data + size), + m_ptr(data), + m_dx(dx), + m_dy(dy), + m_vertices(0) + {} + + //-------------------------------------------------------------------- + void init(const int8u* data, unsigned size, + double dx, double dy, double scale=1.0) + { + m_data = data; + m_end = data + size; + m_ptr = data; + m_dx = dx; + m_dy = dy; + m_scale = scale; + m_vertices = 0; + } + + + //-------------------------------------------------------------------- + void rewind(unsigned) + { + m_ptr = m_data; + m_vertices = 0; + } + + //-------------------------------------------------------------------- + unsigned vertex(double* x, double* y) + { + if(m_data == 0 || m_ptr > m_end) + { + *x = 0; + *y = 0; + return path_cmd_stop; + } + + if(m_ptr == m_end) + { + *x = 0; + *y = 0; + m_ptr += sizeof(vertex_integer_type); + return path_cmd_end_poly | path_flags_close; + } + + vertex_integer_type v; + memcpy(&v, m_ptr, sizeof(vertex_integer_type)); + unsigned cmd = v.vertex(x, y, m_dx, m_dy, m_scale); + if(is_move_to(cmd) && m_vertices > 2) + { + *x = 0; + *y = 0; + m_vertices = 0; + return path_cmd_end_poly | path_flags_close; + } + ++m_vertices; + m_ptr += sizeof(vertex_integer_type); + return cmd; + } + + private: + const int8u* m_data; + const int8u* m_end; + const int8u* m_ptr; + double m_dx; + double m_dy; + double m_scale; + unsigned m_vertices; + }; + +} + + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_pattern_filters_rgba.h b/jni/desmume/src/android/agg/include/agg_pattern_filters_rgba.h new file mode 100755 index 0000000..ebd1e05 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_pattern_filters_rgba.h @@ -0,0 +1,132 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_PATTERN_FILTERS_RGBA8_INCLUDED +#define AGG_PATTERN_FILTERS_RGBA8_INCLUDED + +#include "agg_basics.h" +#include "agg_line_aa_basics.h" +#include "agg_color_rgba.h" + + +namespace agg +{ + + //=======================================================pattern_filter_nn + template<class ColorT> struct pattern_filter_nn + { + typedef ColorT color_type; + static unsigned dilation() { return 0; } + + static void AGG_INLINE pixel_low_res(color_type const* const* buf, + color_type* p, int x, int y) + { + *p = buf[y][x]; + } + + static void AGG_INLINE pixel_high_res(color_type const* const* buf, + color_type* p, int x, int y) + { + *p = buf[y >> line_subpixel_shift] + [x >> line_subpixel_shift]; + } + }; + + typedef pattern_filter_nn<rgba8> pattern_filter_nn_rgba8; + typedef pattern_filter_nn<rgba16> pattern_filter_nn_rgba16; + + + //===========================================pattern_filter_bilinear_rgba + template<class ColorT> struct pattern_filter_bilinear_rgba + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + + + static unsigned dilation() { return 1; } + + static AGG_INLINE void pixel_low_res(color_type const* const* buf, + color_type* p, int x, int y) + { + *p = buf[y][x]; + } + + static AGG_INLINE void pixel_high_res(color_type const* const* buf, + color_type* p, int x, int y) + { + calc_type r, g, b, a; + r = g = b = a = line_subpixel_scale * line_subpixel_scale / 2; + + calc_type weight; + int x_lr = x >> line_subpixel_shift; + int y_lr = y >> line_subpixel_shift; + + x &= line_subpixel_mask; + y &= line_subpixel_mask; + const color_type* ptr = buf[y_lr] + x_lr; + + weight = (line_subpixel_scale - x) * + (line_subpixel_scale - y); + r += weight * ptr->r; + g += weight * ptr->g; + b += weight * ptr->b; + a += weight * ptr->a; + + ++ptr; + + weight = x * (line_subpixel_scale - y); + r += weight * ptr->r; + g += weight * ptr->g; + b += weight * ptr->b; + a += weight * ptr->a; + + ptr = buf[y_lr + 1] + x_lr; + + weight = (line_subpixel_scale - x) * y; + r += weight * ptr->r; + g += weight * ptr->g; + b += weight * ptr->b; + a += weight * ptr->a; + + ++ptr; + + weight = x * y; + r += weight * ptr->r; + g += weight * ptr->g; + b += weight * ptr->b; + a += weight * ptr->a; + + p->r = (value_type)(r >> line_subpixel_shift * 2); + p->g = (value_type)(g >> line_subpixel_shift * 2); + p->b = (value_type)(b >> line_subpixel_shift * 2); + p->a = (value_type)(a >> line_subpixel_shift * 2); + } + }; + + typedef pattern_filter_bilinear_rgba<rgba8> pattern_filter_bilinear_rgba8; + typedef pattern_filter_bilinear_rgba<rgba16> pattern_filter_bilinear_rgba16; +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_pixfmt_amask_adaptor.h b/jni/desmume/src/android/agg/include/agg_pixfmt_amask_adaptor.h new file mode 100755 index 0000000..aa43c04 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_pixfmt_amask_adaptor.h @@ -0,0 +1,249 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED +#define AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED + + +#include <string.h> +#include "agg_array.h" +#include "agg_rendering_buffer.h" + + +namespace agg +{ + //==================================================pixfmt_amask_adaptor + template<class PixFmt, class AlphaMask> class pixfmt_amask_adaptor + { + public: + typedef PixFmt pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::row_data row_data; + typedef AlphaMask amask_type; + typedef typename amask_type::cover_type cover_type; + + private: + enum span_extra_tail_e { span_extra_tail = 256 }; + + void realloc_span(unsigned len) + { + if(len > m_span.size()) + { + m_span.resize(len + span_extra_tail); + } + } + + void init_span(unsigned len) + { + realloc_span(len); + memset(&m_span[0], amask_type::cover_full, len * sizeof(cover_type)); + } + + void init_span(unsigned len, const cover_type* covers) + { + realloc_span(len); + memcpy(&m_span[0], covers, len * sizeof(cover_type)); + } + + + public: + pixfmt_amask_adaptor(pixfmt_type& pixf, const amask_type& mask) : + m_pixf(&pixf), m_mask(&mask), m_span() + {} + + void attach_pixfmt(pixfmt_type& pixf) { m_pixf = &pixf; } + void attach_alpha_mask(const amask_type& mask) { m_mask = &mask; } + + //-------------------------------------------------------------------- + template<class PixFmt2> + bool attach_pixfmt(PixFmt2& pixf, int x1, int y1, int x2, int y2) + { + return m_pixf->attach(pixf, x1, y1, x2, y2); + } + + //-------------------------------------------------------------------- + unsigned width() const { return m_pixf->width(); } + unsigned height() const { return m_pixf->height(); } + + //-------------------------------------------------------------------- + color_type pixel(int x, int y) + { + return m_pixf->pixel(x, y); + } + + //-------------------------------------------------------------------- + void copy_pixel(int x, int y, const color_type& c) + { + m_pixf->blend_pixel(x, y, c, m_mask->pixel(x, y)); + } + + //-------------------------------------------------------------------- + void blend_pixel(int x, int y, const color_type& c, cover_type cover) + { + m_pixf->blend_pixel(x, y, c, m_mask->combine_pixel(x, y, cover)); + } + + //-------------------------------------------------------------------- + void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + realloc_span(len); + m_mask->fill_hspan(x, y, &m_span[0], len); + m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]); + } + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, + unsigned len, + const color_type& c, + cover_type cover) + { + init_span(len); + m_mask->combine_hspan(x, y, &m_span[0], len); + m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]); + } + + //-------------------------------------------------------------------- + void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + realloc_span(len); + m_mask->fill_vspan(x, y, &m_span[0], len); + m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]); + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + cover_type cover) + { + init_span(len); + m_mask->combine_vspan(x, y, &m_span[0], len); + m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]); + } + + //-------------------------------------------------------------------- + void copy_from(const rendering_buffer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + m_pixf->copy_from(from, xdst, ydst, xsrc, ysrc, len); + } + + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const cover_type* covers) + { + init_span(len, covers); + m_mask->combine_hspan(x, y, &m_span[0], len); + m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]); + } + + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const cover_type* covers) + { + init_span(len, covers); + m_mask->combine_vspan(x, y, &m_span[0], len); + m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]); + } + + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, unsigned len, const color_type* colors) + { + realloc_span(len); + m_mask->fill_hspan(x, y, &m_span[0], len); + m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover_full); + } + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, unsigned len, const color_type* colors) + { + realloc_span(len); + m_mask->fill_vspan(x, y, &m_span[0], len); + m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover_full); + } + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const cover_type* covers, + cover_type cover = cover_full) + { + if(covers) + { + init_span(len, covers); + m_mask->combine_hspan(x, y, &m_span[0], len); + } + else + { + realloc_span(len); + m_mask->fill_hspan(x, y, &m_span[0], len); + } + m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover); + } + + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const cover_type* covers, + cover_type cover = cover_full) + { + if(covers) + { + init_span(len, covers); + m_mask->combine_vspan(x, y, &m_span[0], len); + } + else + { + realloc_span(len); + m_mask->fill_vspan(x, y, &m_span[0], len); + } + m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover); + } + + private: + pixfmt_type* m_pixf; + const amask_type* m_mask; + pod_array<cover_type> m_span; + }; + +} + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_pixfmt_gray.h b/jni/desmume/src/android/agg/include/agg_pixfmt_gray.h new file mode 100755 index 0000000..8f3f4ec --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_pixfmt_gray.h @@ -0,0 +1,679 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_PIXFMT_GRAY_INCLUDED +#define AGG_PIXFMT_GRAY_INCLUDED + +#include <string.h> +#include "agg_basics.h" +#include "agg_color_gray.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + + //============================================================blender_gray + template<class ColorT> struct blender_gray + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e { base_shift = color_type::base_shift }; + + static AGG_INLINE void blend_pix(value_type* p, unsigned cv, + unsigned alpha, unsigned cover=0) + { + *p = (value_type)((((cv - calc_type(*p)) * alpha) + (calc_type(*p) << base_shift)) >> base_shift); + } + }; + + + //======================================================blender_gray_pre + template<class ColorT> struct blender_gray_pre + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e { base_shift = color_type::base_shift }; + + static AGG_INLINE void blend_pix(value_type* p, unsigned cv, + unsigned alpha, unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (base_shift - 8); + *p = (value_type)((*p * alpha + cv * cover) >> base_shift); + } + + static AGG_INLINE void blend_pix(value_type* p, unsigned cv, + unsigned alpha) + { + *p = (value_type)(((*p * (color_type::base_mask - alpha)) >> base_shift) + cv); + } + }; + + + + //=====================================================apply_gamma_dir_gray + template<class ColorT, class GammaLut> class apply_gamma_dir_gray + { + public: + typedef typename ColorT::value_type value_type; + + apply_gamma_dir_gray(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + *p = m_gamma.dir(*p); + } + + private: + const GammaLut& m_gamma; + }; + + + + //=====================================================apply_gamma_inv_gray + template<class ColorT, class GammaLut> class apply_gamma_inv_gray + { + public: + typedef typename ColorT::value_type value_type; + + apply_gamma_inv_gray(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + *p = m_gamma.inv(*p); + } + + private: + const GammaLut& m_gamma; + }; + + + + //=================================================pixfmt_alpha_blend_gray + template<class Blender, class RenBuf, unsigned Step=1, unsigned Offset=0> + class pixfmt_alpha_blend_gray + { + public: + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef int order_type; // A fake one + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask, + pix_width = sizeof(value_type), + pix_step = Step, + pix_offset = Offset + }; + + private: + //-------------------------------------------------------------------- + static AGG_INLINE void copy_or_blend_pix(value_type* p, + const color_type& c, + unsigned cover) + { + if (c.a) + { + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + *p = c.v; + } + else + { + Blender::blend_pix(p, c.v, alpha, cover); + } + } + } + + + static AGG_INLINE void copy_or_blend_pix(value_type* p, + const color_type& c) + { + if (c.a) + { + if(c.a == base_mask) + { + *p = c.v; + } + else + { + Blender::blend_pix(p, c.v, c.a); + } + } + } + + + public: + //-------------------------------------------------------------------- + explicit pixfmt_alpha_blend_gray(rbuf_type& rb) : + m_rbuf(&rb) + {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + //-------------------------------------------------------------------- + + template<class PixFmt> + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) + { + rect_i r(x1, y1, x2, y2); + if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) + { + int stride = pixf.stride(); + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + (r.x2 - r.x1) + 1, + (r.y2 - r.y1) + 1, + stride); + return true; + } + return false; + } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- + int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + row_data row(int y) const { return m_rbuf->row(y); } + + const int8u* pix_ptr(int x, int y) const + { + return m_rbuf->row_ptr(y) + x * Step + Offset; + } + + int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + x * Step + Offset; + } + + //-------------------------------------------------------------------- + AGG_INLINE static void make_pix(int8u* p, const color_type& c) + { + *(value_type*)p = c.v; + } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + value_type* p = (value_type*)m_rbuf->row_ptr(y) + x * Step + Offset; + return color_type(*p); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_pixel(int x, int y, const color_type& c) + { + *((value_type*)m_rbuf->row_ptr(x, y, 1) + x * Step + Offset) = c.v; + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) + { + copy_or_blend_pix((value_type*) + m_rbuf->row_ptr(x, y, 1) + x * Step + Offset, + c, + cover); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y, len) + x * Step + Offset; + + do + { + *p = c.v; + p += Step; + } + while(--len); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + do + { + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; + + *p = c.v; + } + while(--len); + } + + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) + { + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y, len) + x * Step + Offset; + + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + do + { + *p = c.v; + p += Step; + } + while(--len); + } + else + { + do + { + Blender::blend_pix(p, c.v, alpha, cover); + p += Step; + } + while(--len); + } + } + } + + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) + { + value_type* p; + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + do + { + p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; + + *p = c.v; + } + while(--len); + } + else + { + do + { + p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; + + Blender::blend_pix(p, c.v, alpha, cover); + } + while(--len); + } + } + } + + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (c.a) + { + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y, len) + x * Step + Offset; + + do + { + calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; + if(alpha == base_mask) + { + *p = c.v; + } + else + { + Blender::blend_pix(p, c.v, alpha, *covers); + } + p += Step; + ++covers; + } + while(--len); + } + } + + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (c.a) + { + do + { + calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; + + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; + + if(alpha == base_mask) + { + *p = c.v; + } + else + { + Blender::blend_pix(p, c.v, alpha, *covers); + } + ++covers; + } + while(--len); + } + } + + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y, len) + x * Step + Offset; + + do + { + *p = colors->v; + p += Step; + ++colors; + } + while(--len); + } + + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; + *p = colors->v; + ++colors; + } + while(--len); + } + + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y, len) + x * Step + Offset; + + if(covers) + { + do + { + copy_or_blend_pix(p, *colors++, *covers++); + p += Step; + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + if(colors->a == base_mask) + { + *p = colors->v; + } + else + { + copy_or_blend_pix(p, *colors); + } + p += Step; + ++colors; + } + while(--len); + } + else + { + do + { + copy_or_blend_pix(p, *colors++, cover); + p += Step; + } + while(--len); + } + } + } + + + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + value_type* p; + if(covers) + { + do + { + p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; + + copy_or_blend_pix(p, *colors++, *covers++); + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; + + if(colors->a == base_mask) + { + *p = colors->v; + } + else + { + copy_or_blend_pix(p, *colors); + } + ++colors; + } + while(--len); + } + else + { + do + { + p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; + + copy_or_blend_pix(p, *colors++, cover); + } + while(--len); + } + } + } + + //-------------------------------------------------------------------- + template<class Function> void for_each_pixel(Function f) + { + unsigned y; + for(y = 0; y < height(); ++y) + { + row_data r = m_rbuf->row(y); + if(r.ptr) + { + unsigned len = r.x2 - r.x1 + 1; + + value_type* p = (value_type*) + m_rbuf->row_ptr(r.x1, y, len) + r.x1 * Step + Offset; + + do + { + f(p); + p += Step; + } + while(--len); + } + } + } + + //-------------------------------------------------------------------- + template<class GammaLut> void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_gray<color_type, GammaLut>(g)); + } + + //-------------------------------------------------------------------- + template<class GammaLut> void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_gray<color_type, GammaLut>(g)); + } + + //-------------------------------------------------------------------- + template<class RenBuf2> + void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + const int8u* p = from.row_ptr(ysrc); + if(p) + { + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; + do + { + copy_or_blend_pix(pdst, + color, + (*psrc * cover + base_mask) >> base_shift); + ++psrc; + ++pdst; + } + while(--len); + } + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from_lut(const SrcPixelFormatRenderer& from, + const color_type* color_lut, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; + do + { + copy_or_blend_pix(pdst, color_lut[*psrc], cover); + ++psrc; + ++pdst; + } + while(--len); + } + } + + private: + rbuf_type* m_rbuf; + }; + + typedef blender_gray<gray8> blender_gray8; + typedef blender_gray_pre<gray8> blender_gray8_pre; + typedef blender_gray<gray16> blender_gray16; + typedef blender_gray_pre<gray16> blender_gray16_pre; + + typedef pixfmt_alpha_blend_gray<blender_gray8, rendering_buffer> pixfmt_gray8; //----pixfmt_gray8 + typedef pixfmt_alpha_blend_gray<blender_gray8_pre, rendering_buffer> pixfmt_gray8_pre; //----pixfmt_gray8_pre + typedef pixfmt_alpha_blend_gray<blender_gray16, rendering_buffer> pixfmt_gray16; //----pixfmt_gray16 + typedef pixfmt_alpha_blend_gray<blender_gray16_pre, rendering_buffer> pixfmt_gray16_pre; //----pixfmt_gray16_pre +} + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_pixfmt_rgb.h b/jni/desmume/src/android/agg/include/agg_pixfmt_rgb.h new file mode 100755 index 0000000..4894717 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_pixfmt_rgb.h @@ -0,0 +1,869 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_PIXFMT_RGB_INCLUDED +#define AGG_PIXFMT_RGB_INCLUDED + +#include <string.h> +#include "agg_basics.h" +#include "agg_color_rgba.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + + //=====================================================apply_gamma_dir_rgb + template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgb + { + public: + typedef typename ColorT::value_type value_type; + + apply_gamma_dir_rgb(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.dir(p[Order::R]); + p[Order::G] = m_gamma.dir(p[Order::G]); + p[Order::B] = m_gamma.dir(p[Order::B]); + } + + private: + const GammaLut& m_gamma; + }; + + + + //=====================================================apply_gamma_inv_rgb + template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgb + { + public: + typedef typename ColorT::value_type value_type; + + apply_gamma_inv_rgb(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.inv(p[Order::R]); + p[Order::G] = m_gamma.inv(p[Order::G]); + p[Order::B] = m_gamma.inv(p[Order::B]); + } + + private: + const GammaLut& m_gamma; + }; + + + //=========================================================blender_rgb + template<class ColorT, class Order> struct blender_rgb + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e { base_shift = color_type::base_shift }; + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover=0) + { + p[Order::R] += (value_type)(((cr - p[Order::R]) * alpha) >> base_shift); + p[Order::G] += (value_type)(((cg - p[Order::G]) * alpha) >> base_shift); + p[Order::B] += (value_type)(((cb - p[Order::B]) * alpha) >> base_shift); + } + }; + + + //======================================================blender_rgb_pre + template<class ColorT, class Order> struct blender_rgb_pre + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e { base_shift = color_type::base_shift }; + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (base_shift - 8); + p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * alpha + cg * cover) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift); + } + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha) + { + alpha = color_type::base_mask - alpha; + p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr); + p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg); + p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb); + } + + }; + + + + //===================================================blender_rgb_gamma + template<class ColorT, class Order, class Gamma> class blender_rgb_gamma + { + public: + typedef ColorT color_type; + typedef Order order_type; + typedef Gamma gamma_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e { base_shift = color_type::base_shift }; + + //-------------------------------------------------------------------- + blender_rgb_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover=0) + { + calc_type r = m_gamma->dir(p[Order::R]); + calc_type g = m_gamma->dir(p[Order::G]); + calc_type b = m_gamma->dir(p[Order::B]); + p[Order::R] = m_gamma->inv((((m_gamma->dir(cr) - r) * alpha) >> base_shift) + r); + p[Order::G] = m_gamma->inv((((m_gamma->dir(cg) - g) * alpha) >> base_shift) + g); + p[Order::B] = m_gamma->inv((((m_gamma->dir(cb) - b) * alpha) >> base_shift) + b); + } + + private: + const gamma_type* m_gamma; + }; + + + + + //==================================================pixfmt_alpha_blend_rgb + template<class Blender, class RenBuf> class pixfmt_alpha_blend_rgb + { + public: + typedef RenBuf rbuf_type; + typedef Blender blender_type; + typedef typename rbuf_type::row_data row_data; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask, + pix_width = sizeof(value_type) * 3 + }; + + private: + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(value_type* p, + const color_type& c, + unsigned cover) + { + if (c.a) + { + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + } + else + { + m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); + } + } + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(value_type* p, + const color_type& c) + { + if (c.a) + { + if(c.a == base_mask) + { + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + } + else + { + m_blender.blend_pix(p, c.r, c.g, c.b, c.a); + } + } + } + + + public: + //-------------------------------------------------------------------- + explicit pixfmt_alpha_blend_rgb(rbuf_type& rb) : + m_rbuf(&rb) + {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + + //-------------------------------------------------------------------- + template<class PixFmt> + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) + { + rect_i r(x1, y1, x2, y2); + if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) + { + int stride = pixf.stride(); + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + (r.x2 - r.x1) + 1, + (r.y2 - r.y1) + 1, + stride); + return true; + } + return false; + } + + //-------------------------------------------------------------------- + Blender& blender() { return m_blender; } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + x * pix_width; + } + + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + return m_rbuf->row_ptr(y) + x * pix_width; + } + + //-------------------------------------------------------------------- + AGG_INLINE static void make_pix(int8u* p, const color_type& c) + { + ((value_type*)p)[order_type::R] = c.r; + ((value_type*)p)[order_type::G] = c.g; + ((value_type*)p)[order_type::B] = c.b; + } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + value_type* p = (value_type*)m_rbuf->row_ptr(y) + x + x + x; + return color_type(p[order_type::R], + p[order_type::G], + p[order_type::B]); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_pixel(int x, int y, const color_type& c) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + x + x + x; + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) + { + copy_or_blend_pix((value_type*)m_rbuf->row_ptr(x, y, 1) + x + x + x, c, cover); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + x + x + x; + do + { + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + p += 3; + } + while(--len); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + do + { + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x + x + x; + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + } + while(--len); + } + + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) + { + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y, len) + x + x + x; + + calc_type alpha = (calc_type(c.a) * (calc_type(cover) + 1)) >> 8; + if(alpha == base_mask) + { + do + { + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + p += 3; + } + while(--len); + } + else + { + do + { + m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); + p += 3; + } + while(--len); + } + } + } + + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) + { + value_type* p; + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + do + { + p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x + x + x; + + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + } + while(--len); + } + else + { + do + { + p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x + x + x; + + m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); + } + while(--len); + } + } + } + + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (c.a) + { + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y, len) + x + x + x; + + do + { + calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; + if(alpha == base_mask) + { + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + } + else + { + m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers); + } + p += 3; + ++covers; + } + while(--len); + } + } + + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (c.a) + { + do + { + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x + x + x; + + calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; + if(alpha == base_mask) + { + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + } + else + { + m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers); + } + ++covers; + } + while(--len); + } + } + + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y, len) + x + x + x; + + do + { + p[order_type::R] = colors->r; + p[order_type::G] = colors->g; + p[order_type::B] = colors->b; + ++colors; + p += 3; + } + while(--len); + } + + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x + x + x; + p[order_type::R] = colors->r; + p[order_type::G] = colors->g; + p[order_type::B] = colors->b; + ++colors; + } + while(--len); + } + + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + value_type* p = (value_type*) + m_rbuf->row_ptr(x, y, len) + x + x + x; + + if(covers) + { + do + { + copy_or_blend_pix(p, *colors++, *covers++); + p += 3; + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + copy_or_blend_pix(p, *colors++); + p += 3; + } + while(--len); + } + else + { + do + { + copy_or_blend_pix(p, *colors++, cover); + p += 3; + } + while(--len); + } + } + } + + + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + value_type* p; + if(covers) + { + do + { + p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x + x + x; + + copy_or_blend_pix(p, *colors++, *covers++); + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x + x + x; + + copy_or_blend_pix(p, *colors++); + } + while(--len); + } + else + { + do + { + p = (value_type*) + m_rbuf->row_ptr(x, y++, 1) + x + x + x; + + copy_or_blend_pix(p, *colors++, cover); + } + while(--len); + } + } + } + + //-------------------------------------------------------------------- + template<class Function> void for_each_pixel(Function f) + { + unsigned y; + for(y = 0; y < height(); ++y) + { + row_data r = m_rbuf->row(y); + if(r.ptr) + { + unsigned len = r.x2 - r.x1 + 1; + value_type* p = (value_type*) + m_rbuf->row_ptr(r.x1, y, len) + r.x1 * 3; + do + { + f(p); + p += 3; + } + while(--len); + } + } + } + + //-------------------------------------------------------------------- + template<class GammaLut> void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_rgb<color_type, order_type, GammaLut>(g)); + } + + //-------------------------------------------------------------------- + template<class GammaLut> void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_rgb<color_type, order_type, GammaLut>(g)); + } + + //-------------------------------------------------------------------- + template<class RenBuf2> + void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + const int8u* p = from.row_ptr(ysrc); + if(p) + { + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } + } + + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from(const SrcPixelFormatRenderer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::order_type src_order; + + const value_type* psrc = (const value_type*)from.row_ptr(ysrc); + if(psrc) + { + psrc += xsrc * 4; + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3; + + if(cover == 255) + { + do + { + value_type alpha = psrc[src_order::A]; + if(alpha) + { + if(alpha == base_mask) + { + pdst[order_type::R] = psrc[src_order::R]; + pdst[order_type::G] = psrc[src_order::G]; + pdst[order_type::B] = psrc[src_order::B]; + } + else + { + m_blender.blend_pix(pdst, + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + alpha); + } + } + psrc += 4; + pdst += 3; + } + while(--len); + } + else + { + color_type color; + do + { + color.r = psrc[src_order::R]; + color.g = psrc[src_order::G]; + color.b = psrc[src_order::B]; + color.a = psrc[src_order::A]; + copy_or_blend_pix(pdst, color, cover); + psrc += 4; + pdst += 3; + } + while(--len); + } + } + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3; + do + { + copy_or_blend_pix(pdst, + color, + (*psrc * cover + base_mask) >> base_shift); + ++psrc; + pdst += 3; + } + while(--len); + } + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from_lut(const SrcPixelFormatRenderer& from, + const color_type* color_lut, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3; + + if(cover == 255) + { + do + { + const color_type& color = color_lut[*psrc]; + m_blender.blend_pix(pdst, + color.r, color.g, color.b, color.a); + ++psrc; + pdst += 3; + } + while(--len); + } + else + { + do + { + copy_or_blend_pix(pdst, color_lut[*psrc], cover); + ++psrc; + pdst += 3; + } + while(--len); + } + } + } + + private: + rbuf_type* m_rbuf; + Blender m_blender; + }; + + typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba8, order_rgb>, rendering_buffer> pixfmt_rgb24; //----pixfmt_rgb24 + typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba8, order_bgr>, rendering_buffer> pixfmt_bgr24; //----pixfmt_bgr24 + typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba16, order_rgb>, rendering_buffer> pixfmt_rgb48; //----pixfmt_rgb48 + typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba16, order_bgr>, rendering_buffer> pixfmt_bgr48; //----pixfmt_bgr48 + + typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba8, order_rgb>, rendering_buffer> pixfmt_rgb24_pre; //----pixfmt_rgb24_pre + typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba8, order_bgr>, rendering_buffer> pixfmt_bgr24_pre; //----pixfmt_bgr24_pre + typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba16, order_rgb>, rendering_buffer> pixfmt_rgb48_pre; //----pixfmt_rgb48_pre + typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba16, order_bgr>, rendering_buffer> pixfmt_bgr48_pre; //----pixfmt_bgr48_pre + + //-----------------------------------------------------pixfmt_rgb24_gamma + template<class Gamma> class pixfmt_rgb24_gamma : + public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer> + { + public: + pixfmt_rgb24_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + //-----------------------------------------------------pixfmt_bgr24_gamma + template<class Gamma> class pixfmt_bgr24_gamma : + public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer> + { + public: + pixfmt_bgr24_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + //-----------------------------------------------------pixfmt_rgb48_gamma + template<class Gamma> class pixfmt_rgb48_gamma : + public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer> + { + public: + pixfmt_rgb48_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + //-----------------------------------------------------pixfmt_bgr48_gamma + template<class Gamma> class pixfmt_bgr48_gamma : + public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer> + { + public: + pixfmt_bgr48_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + +} + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_pixfmt_rgb_packed.h b/jni/desmume/src/android/agg/include/agg_pixfmt_rgb_packed.h new file mode 100755 index 0000000..cf163cd --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_pixfmt_rgb_packed.h @@ -0,0 +1,1318 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_PIXFMT_RGB_PACKED_INCLUDED +#define AGG_PIXFMT_RGB_PACKED_INCLUDED + +#include <string.h> +#include "agg_basics.h" +#include "agg_color_rgba.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + //=========================================================blender_rgb555 + struct blender_rgb555 + { + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = (rgb >> 7) & 0xF8; + calc_type g = (rgb >> 2) & 0xF8; + calc_type b = (rgb << 3) & 0xF8; + *p = (pixel_type) + (((((cr - r) * alpha + (r << 8)) >> 1) & 0x7C00) | + ((((cg - g) * alpha + (g << 8)) >> 6) & 0x03E0) | + (((cb - b) * alpha + (b << 8)) >> 11) | 0x8000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 7) | + ((g & 0xF8) << 2) | + (b >> 3) | 0x8000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 7) & 0xF8, + (p >> 2) & 0xF8, + (p << 3) & 0xF8); + } + }; + + + //=====================================================blender_rgb555_pre + struct blender_rgb555_pre + { + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + pixel_type rgb = *p; + calc_type r = (rgb >> 7) & 0xF8; + calc_type g = (rgb >> 2) & 0xF8; + calc_type b = (rgb << 3) & 0xF8; + *p = (pixel_type) + ((((r * alpha + cr * cover) >> 1) & 0x7C00) | + (((g * alpha + cg * cover) >> 6) & 0x03E0) | + ((b * alpha + cb * cover) >> 11) | 0x8000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 7) | + ((g & 0xF8) << 2) | + (b >> 3) | 0x8000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 7) & 0xF8, + (p >> 2) & 0xF8, + (p << 3) & 0xF8); + } + }; + + + + + //=====================================================blender_rgb555_gamma + template<class Gamma> class blender_rgb555_gamma + { + public: + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + typedef Gamma gamma_type; + + blender_rgb555_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = m_gamma->dir((rgb >> 7) & 0xF8); + calc_type g = m_gamma->dir((rgb >> 2) & 0xF8); + calc_type b = m_gamma->dir((rgb << 3) & 0xF8); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 8)) >> 8) << 7) & 0x7C00) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 8)) >> 8) << 2) & 0x03E0) | + (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 8)) >> 8) >> 3) | 0x8000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 7) | + ((g & 0xF8) << 2) | + (b >> 3) | 0x8000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 7) & 0xF8, + (p >> 2) & 0xF8, + (p << 3) & 0xF8); + } + + private: + const Gamma* m_gamma; + }; + + + + + + //=========================================================blender_rgb565 + struct blender_rgb565 + { + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = (rgb >> 8) & 0xF8; + calc_type g = (rgb >> 3) & 0xFC; + calc_type b = (rgb << 3) & 0xF8; + *p = (pixel_type) + (((((cr - r) * alpha + (r << 8)) ) & 0xF800) | + ((((cg - g) * alpha + (g << 8)) >> 5) & 0x07E0) | + (((cb - b) * alpha + (b << 8)) >> 11)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 8) & 0xF8, + (p >> 3) & 0xFC, + (p << 3) & 0xF8); + } + }; + + + + //=====================================================blender_rgb565_pre + struct blender_rgb565_pre + { + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + pixel_type rgb = *p; + calc_type r = (rgb >> 8) & 0xF8; + calc_type g = (rgb >> 3) & 0xFC; + calc_type b = (rgb << 3) & 0xF8; + *p = (pixel_type) + ((((r * alpha + cr * cover) ) & 0xF800) | + (((g * alpha + cg * cover) >> 5 ) & 0x07E0) | + ((b * alpha + cb * cover) >> 11)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 8) & 0xF8, + (p >> 3) & 0xFC, + (p << 3) & 0xF8); + } + }; + + + + //=====================================================blender_rgb565_gamma + template<class Gamma> class blender_rgb565_gamma + { + public: + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + typedef Gamma gamma_type; + + blender_rgb565_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = m_gamma->dir((rgb >> 8) & 0xF8); + calc_type g = m_gamma->dir((rgb >> 3) & 0xFC); + calc_type b = m_gamma->dir((rgb << 3) & 0xF8); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 8)) >> 8) << 8) & 0xF800) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 8)) >> 8) << 3) & 0x07E0) | + (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 8)) >> 8) >> 3)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 8) & 0xF8, + (p >> 3) & 0xFC, + (p << 3) & 0xF8); + } + + private: + const Gamma* m_gamma; + }; + + + + //=====================================================blender_rgbAAA + struct blender_rgbAAA + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = (rgb >> 14) & 0xFFC0; + calc_type g = (rgb >> 4) & 0xFFC0; + calc_type b = (rgb << 6) & 0xFFC0; + *p = (pixel_type) + (((((cr - r) * alpha + (r << 16)) >> 2) & 0x3FF00000) | + ((((cg - g) * alpha + (g << 16)) >> 12) & 0x000FFC00) | + (((cb - b) * alpha + (b << 16)) >> 22) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (b >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 14) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p << 6) & 0xFFC0); + } + }; + + + + //==================================================blender_rgbAAA_pre + struct blender_rgbAAA_pre + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (color_type::base_shift - 8); + pixel_type rgb = *p; + calc_type r = (rgb >> 14) & 0xFFC0; + calc_type g = (rgb >> 4) & 0xFFC0; + calc_type b = (rgb << 6) & 0xFFC0; + *p = (pixel_type) + ((((r * alpha + cr * cover) >> 2) & 0x3FF00000) | + (((g * alpha + cg * cover) >> 12) & 0x000FFC00) | + ((b * alpha + cb * cover) >> 22) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (b >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 14) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p << 6) & 0xFFC0); + } + }; + + + + //=================================================blender_rgbAAA_gamma + template<class Gamma> class blender_rgbAAA_gamma + { + public: + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + typedef Gamma gamma_type; + + blender_rgbAAA_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = m_gamma->dir((rgb >> 14) & 0xFFC0); + calc_type g = m_gamma->dir((rgb >> 4) & 0xFFC0); + calc_type b = m_gamma->dir((rgb << 6) & 0xFFC0); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) << 14) & 0x3FF00000) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 4 ) & 0x000FFC00) | + (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) >> 6 ) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (b >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 14) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p << 6) & 0xFFC0); + } + private: + const Gamma* m_gamma; + }; + + + //=====================================================blender_bgrAAA + struct blender_bgrAAA + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type bgr = *p; + calc_type b = (bgr >> 14) & 0xFFC0; + calc_type g = (bgr >> 4) & 0xFFC0; + calc_type r = (bgr << 6) & 0xFFC0; + *p = (pixel_type) + (((((cb - b) * alpha + (b << 16)) >> 2) & 0x3FF00000) | + ((((cg - g) * alpha + (g << 16)) >> 12) & 0x000FFC00) | + (((cr - r) * alpha + (r << 16)) >> 22) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (r >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 6) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p >> 14) & 0xFFC0); + } + }; + + + + //=================================================blender_bgrAAA_pre + struct blender_bgrAAA_pre + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (color_type::base_shift - 8); + pixel_type bgr = *p; + calc_type b = (bgr >> 14) & 0xFFC0; + calc_type g = (bgr >> 4) & 0xFFC0; + calc_type r = (bgr << 6) & 0xFFC0; + *p = (pixel_type) + ((((b * alpha + cb * cover) >> 2) & 0x3FF00000) | + (((g * alpha + cg * cover) >> 12) & 0x000FFC00) | + ((r * alpha + cr * cover) >> 22) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (r >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 6) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p >> 14) & 0xFFC0); + } + }; + + + + //=================================================blender_bgrAAA_gamma + template<class Gamma> class blender_bgrAAA_gamma + { + public: + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + typedef Gamma gamma_type; + + blender_bgrAAA_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type bgr = *p; + calc_type b = m_gamma->dir((bgr >> 14) & 0xFFC0); + calc_type g = m_gamma->dir((bgr >> 4) & 0xFFC0); + calc_type r = m_gamma->dir((bgr << 6) & 0xFFC0); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) << 14) & 0x3FF00000) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 4 ) & 0x000FFC00) | + (m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) >> 6 ) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (r >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 6) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p >> 14) & 0xFFC0); + } + + private: + const Gamma* m_gamma; + }; + + + + //=====================================================blender_rgbBBA + struct blender_rgbBBA + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = (rgb >> 16) & 0xFFE0; + calc_type g = (rgb >> 5) & 0xFFE0; + calc_type b = (rgb << 6) & 0xFFC0; + *p = (pixel_type) + (((((cr - r) * alpha + (r << 16)) ) & 0xFFE00000) | + ((((cg - g) * alpha + (g << 16)) >> 11) & 0x001FFC00) | + (((cb - b) * alpha + (b << 16)) >> 22)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 16) & 0xFFE0, + (p >> 5) & 0xFFE0, + (p << 6) & 0xFFC0); + } + }; + + + //=================================================blender_rgbBBA_pre + struct blender_rgbBBA_pre + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (color_type::base_shift - 8); + pixel_type rgb = *p; + calc_type r = (rgb >> 16) & 0xFFE0; + calc_type g = (rgb >> 5) & 0xFFE0; + calc_type b = (rgb << 6) & 0xFFC0; + *p = (pixel_type) + ((((r * alpha + cr * cover) ) & 0xFFE00000) | + (((g * alpha + cg * cover) >> 11) & 0x001FFC00) | + ((b * alpha + cb * cover) >> 22)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 16) & 0xFFE0, + (p >> 5) & 0xFFE0, + (p << 6) & 0xFFC0); + } + }; + + + + //=================================================blender_rgbBBA_gamma + template<class Gamma> class blender_rgbBBA_gamma + { + public: + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + typedef Gamma gamma_type; + + blender_rgbBBA_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = m_gamma->dir((rgb >> 16) & 0xFFE0); + calc_type g = m_gamma->dir((rgb >> 5) & 0xFFE0); + calc_type b = m_gamma->dir((rgb << 6) & 0xFFC0); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) << 16) & 0xFFE00000) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 5 ) & 0x001FFC00) | + (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) >> 6 )); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 16) & 0xFFE0, + (p >> 5) & 0xFFE0, + (p << 6) & 0xFFC0); + } + + private: + const Gamma* m_gamma; + }; + + + //=====================================================blender_bgrABB + struct blender_bgrABB + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type bgr = *p; + calc_type b = (bgr >> 16) & 0xFFC0; + calc_type g = (bgr >> 6) & 0xFFE0; + calc_type r = (bgr << 5) & 0xFFE0; + *p = (pixel_type) + (((((cb - b) * alpha + (b << 16)) ) & 0xFFC00000) | + ((((cg - g) * alpha + (g << 16)) >> 10) & 0x003FF800) | + (((cr - r) * alpha + (r << 16)) >> 21)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 5) & 0xFFE0, + (p >> 6) & 0xFFE0, + (p >> 16) & 0xFFC0); + } + }; + + + //=================================================blender_bgrABB_pre + struct blender_bgrABB_pre + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (color_type::base_shift - 8); + pixel_type bgr = *p; + calc_type b = (bgr >> 16) & 0xFFC0; + calc_type g = (bgr >> 6) & 0xFFE0; + calc_type r = (bgr << 5) & 0xFFE0; + *p = (pixel_type) + ((((b * alpha + cb * cover) ) & 0xFFC00000) | + (((g * alpha + cg * cover) >> 10) & 0x003FF800) | + ((r * alpha + cr * cover) >> 21)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 5) & 0xFFE0, + (p >> 6) & 0xFFE0, + (p >> 16) & 0xFFC0); + } + }; + + + + //=================================================blender_bgrABB_gamma + template<class Gamma> class blender_bgrABB_gamma + { + public: + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + typedef Gamma gamma_type; + + blender_bgrABB_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type bgr = *p; + calc_type b = m_gamma->dir((bgr >> 16) & 0xFFC0); + calc_type g = m_gamma->dir((bgr >> 6) & 0xFFE0); + calc_type r = m_gamma->dir((bgr << 5) & 0xFFE0); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) << 16) & 0xFFC00000) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 6 ) & 0x003FF800) | + (m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) >> 5 )); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 5) & 0xFFE0, + (p >> 6) & 0xFFE0, + (p >> 16) & 0xFFC0); + } + + private: + const Gamma* m_gamma; + }; + + + + //===========================================pixfmt_alpha_blend_rgb_packed + template<class Blender, class RenBuf> class pixfmt_alpha_blend_rgb_packed + { + public: + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::pixel_type pixel_type; + typedef int order_type; // A fake one + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask, + pix_width = sizeof(pixel_type) + }; + + private: + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover) + { + if (c.a) + { + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + *p = m_blender.make_pix(c.r, c.g, c.b); + } + else + { + m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); + } + } + } + + public: + //-------------------------------------------------------------------- + explicit pixfmt_alpha_blend_rgb_packed(rbuf_type& rb) : m_rbuf(&rb) {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + + //-------------------------------------------------------------------- + template<class PixFmt> + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) + { + rect_i r(x1, y1, x2, y2); + if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) + { + int stride = pixf.stride(); + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + (r.x2 - r.x1) + 1, + (r.y2 - r.y1) + 1, + stride); + return true; + } + return false; + } + + Blender& blender() { return m_blender; } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + x * pix_width; + } + + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + return m_rbuf->row_ptr(y) + x * pix_width; + } + + //-------------------------------------------------------------------- + AGG_INLINE void make_pix(int8u* p, const color_type& c) + { + *(pixel_type*)p = m_blender.make_pix(c.r, c.g, c.b); + } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + return m_blender.make_color(((pixel_type*)m_rbuf->row_ptr(y))[x]); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_pixel(int x, int y, const color_type& c) + { + ((pixel_type*) + m_rbuf->row_ptr(x, y, 1))[x] = + m_blender.make_pix(c.r, c.g, c.b); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) + { + copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y, 1) + x, c, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; + pixel_type v = m_blender.make_pix(c.r, c.g, c.b); + do + { + *p++ = v; + } + while(--len); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type v = m_blender.make_pix(c.r, c.g, c.b); + do + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x; + *p = v; + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + pixel_type v = m_blender.make_pix(c.r, c.g, c.b); + do + { + *p++ = v; + } + while(--len); + } + else + { + do + { + m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); + ++p; + } + while(--len); + } + } + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) + { + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + pixel_type v = m_blender.make_pix(c.r, c.g, c.b); + do + { + ((pixel_type*)m_rbuf->row_ptr(x, y++, 1))[x] = v; + } + while(--len); + } + else + { + do + { + m_blender.blend_pix( + (pixel_type*)m_rbuf->row_ptr(x, y++, 1), + c.r, c.g, c.b, alpha, cover); + } + while(--len); + } + } + } + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; + do + { + copy_or_blend_pix(p, c, *covers++); + ++p; + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + do + { + copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x, + c, *covers++); + } + while(--len); + } + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; + do + { + *p++ = m_blender.make_pix(colors->r, colors->g, colors->b); + ++colors; + } + while(--len); + } + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x; + *p = m_blender.make_pix(colors->r, colors->g, colors->b); + ++colors; + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; + do + { + copy_or_blend_pix(p++, *colors++, covers ? *covers++ : cover); + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + do + { + copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x, + *colors++, covers ? *covers++ : cover); + } + while(--len); + } + + //-------------------------------------------------------------------- + template<class RenBuf2> + void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + const int8u* p = from.row_ptr(ysrc); + if(p) + { + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from(const SrcPixelFormatRenderer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::order_type src_order; + + const value_type* psrc = (const value_type*)from.row_ptr(ysrc); + if(psrc) + { + psrc += xsrc * 4; + pixel_type* pdst = + (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; + do + { + value_type alpha = psrc[src_order::A]; + if(alpha) + { + if(alpha == base_mask && cover == 255) + { + *pdst = m_blender.make_pix(psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B]); + } + else + { + m_blender.blend_pix(pdst, + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + alpha, + cover); + } + } + psrc += 4; + ++pdst; + } + while(--len); + } + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + pixel_type* pdst = + (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; + + do + { + m_blender.blend_pix(pdst, + color.r, color.g, color.b, color.a, + cover); + ++psrc; + ++pdst; + } + while(--len); + } + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from_lut(const SrcPixelFormatRenderer& from, + const color_type* color_lut, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + pixel_type* pdst = + (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; + + do + { + const color_type& color = color_lut[*psrc]; + m_blender.blend_pix(pdst, + color.r, color.g, color.b, color.a, + cover); + ++psrc; + ++pdst; + } + while(--len); + } + } + + + + private: + rbuf_type* m_rbuf; + Blender m_blender; + }; + + typedef pixfmt_alpha_blend_rgb_packed<blender_rgb555, rendering_buffer> pixfmt_rgb555; //----pixfmt_rgb555 + typedef pixfmt_alpha_blend_rgb_packed<blender_rgb565, rendering_buffer> pixfmt_rgb565; //----pixfmt_rgb565 + + typedef pixfmt_alpha_blend_rgb_packed<blender_rgb555_pre, rendering_buffer> pixfmt_rgb555_pre; //----pixfmt_rgb555_pre + typedef pixfmt_alpha_blend_rgb_packed<blender_rgb565_pre, rendering_buffer> pixfmt_rgb565_pre; //----pixfmt_rgb565_pre + + typedef pixfmt_alpha_blend_rgb_packed<blender_rgbAAA, rendering_buffer> pixfmt_rgbAAA; //----pixfmt_rgbAAA + typedef pixfmt_alpha_blend_rgb_packed<blender_bgrAAA, rendering_buffer> pixfmt_bgrAAA; //----pixfmt_bgrAAA + typedef pixfmt_alpha_blend_rgb_packed<blender_rgbBBA, rendering_buffer> pixfmt_rgbBBA; //----pixfmt_rgbBBA + typedef pixfmt_alpha_blend_rgb_packed<blender_bgrABB, rendering_buffer> pixfmt_bgrABB; //----pixfmt_bgrABB + + typedef pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_pre, rendering_buffer> pixfmt_rgbAAA_pre; //----pixfmt_rgbAAA_pre + typedef pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_pre, rendering_buffer> pixfmt_bgrAAA_pre; //----pixfmt_bgrAAA_pre + typedef pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_pre, rendering_buffer> pixfmt_rgbBBA_pre; //----pixfmt_rgbBBA_pre + typedef pixfmt_alpha_blend_rgb_packed<blender_bgrABB_pre, rendering_buffer> pixfmt_bgrABB_pre; //----pixfmt_bgrABB_pre + + + //-----------------------------------------------------pixfmt_rgb555_gamma + template<class Gamma> class pixfmt_rgb555_gamma : + public pixfmt_alpha_blend_rgb_packed<blender_rgb555_gamma<Gamma>, + rendering_buffer> + { + public: + pixfmt_rgb555_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb_packed<blender_rgb555_gamma<Gamma>, + rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + + //-----------------------------------------------------pixfmt_rgb565_gamma + template<class Gamma> class pixfmt_rgb565_gamma : + public pixfmt_alpha_blend_rgb_packed<blender_rgb565_gamma<Gamma>, rendering_buffer> + { + public: + pixfmt_rgb565_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb_packed<blender_rgb565_gamma<Gamma>, rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + + //-----------------------------------------------------pixfmt_rgbAAA_gamma + template<class Gamma> class pixfmt_rgbAAA_gamma : + public pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_gamma<Gamma>, + rendering_buffer> + { + public: + pixfmt_rgbAAA_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb_packed<blender_rgbAAA_gamma<Gamma>, + rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + + //-----------------------------------------------------pixfmt_bgrAAA_gamma + template<class Gamma> class pixfmt_bgrAAA_gamma : + public pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_gamma<Gamma>, + rendering_buffer> + { + public: + pixfmt_bgrAAA_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb_packed<blender_bgrAAA_gamma<Gamma>, + rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + + //-----------------------------------------------------pixfmt_rgbBBA_gamma + template<class Gamma> class pixfmt_rgbBBA_gamma : + public pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_gamma<Gamma>, + rendering_buffer> + { + public: + pixfmt_rgbBBA_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb_packed<blender_rgbBBA_gamma<Gamma>, + rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + + //-----------------------------------------------------pixfmt_bgrABB_gamma + template<class Gamma> class pixfmt_bgrABB_gamma : + public pixfmt_alpha_blend_rgb_packed<blender_bgrABB_gamma<Gamma>, + rendering_buffer> + { + public: + pixfmt_bgrABB_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb_packed<blender_bgrABB_gamma<Gamma>, + rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + +} + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_pixfmt_rgba.h b/jni/desmume/src/android/agg/include/agg_pixfmt_rgba.h new file mode 100755 index 0000000..79d10dc --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_pixfmt_rgba.h @@ -0,0 +1,2911 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_PIXFMT_RGBA_INCLUDED +#define AGG_PIXFMT_RGBA_INCLUDED + +#include <string.h> +#include <math.h> +#include "agg_basics.h" +#include "agg_color_rgba.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + + //=========================================================multiplier_rgba + template<class ColorT, class Order> struct multiplier_rgba + { + typedef typename ColorT::value_type value_type; + typedef typename ColorT::calc_type calc_type; + + //-------------------------------------------------------------------- + static AGG_INLINE void premultiply(value_type* p) + { + calc_type a = p[Order::A]; + if(a < ColorT::base_mask) + { + if(a == 0) + { + p[Order::R] = p[Order::G] = p[Order::B] = 0; + return; + } + p[Order::R] = value_type((p[Order::R] * a + ColorT::base_mask) >> ColorT::base_shift); + p[Order::G] = value_type((p[Order::G] * a + ColorT::base_mask) >> ColorT::base_shift); + p[Order::B] = value_type((p[Order::B] * a + ColorT::base_mask) >> ColorT::base_shift); + } + } + + + //-------------------------------------------------------------------- + static AGG_INLINE void demultiply(value_type* p) + { + calc_type a = p[Order::A]; + if(a < ColorT::base_mask) + { + if(a == 0) + { + p[Order::R] = p[Order::G] = p[Order::B] = 0; + return; + } + calc_type r = (calc_type(p[Order::R]) * ColorT::base_mask) / a; + calc_type g = (calc_type(p[Order::G]) * ColorT::base_mask) / a; + calc_type b = (calc_type(p[Order::B]) * ColorT::base_mask) / a; + p[Order::R] = value_type((r > ColorT::base_mask) ? ColorT::base_mask : r); + p[Order::G] = value_type((g > ColorT::base_mask) ? ColorT::base_mask : g); + p[Order::B] = value_type((b > ColorT::base_mask) ? ColorT::base_mask : b); + } + } + }; + + //=====================================================apply_gamma_dir_rgba + template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgba + { + public: + typedef typename ColorT::value_type value_type; + + apply_gamma_dir_rgba(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.dir(p[Order::R]); + p[Order::G] = m_gamma.dir(p[Order::G]); + p[Order::B] = m_gamma.dir(p[Order::B]); + } + + private: + const GammaLut& m_gamma; + }; + + //=====================================================apply_gamma_inv_rgba + template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgba + { + public: + typedef typename ColorT::value_type value_type; + + apply_gamma_inv_rgba(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.inv(p[Order::R]); + p[Order::G] = m_gamma.inv(p[Order::G]); + p[Order::B] = m_gamma.inv(p[Order::B]); + } + + private: + const GammaLut& m_gamma; + }; + + + + + + + + + + + //=============================================================blender_rgba + template<class ColorT, class Order> struct blender_rgba + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover=0) + { + calc_type r = p[Order::R]; + calc_type g = p[Order::G]; + calc_type b = p[Order::B]; + calc_type a = p[Order::A]; + p[Order::R] = (value_type)(((cr - r) * alpha + (r << base_shift)) >> base_shift); + p[Order::G] = (value_type)(((cg - g) * alpha + (g << base_shift)) >> base_shift); + p[Order::B] = (value_type)(((cb - b) * alpha + (b << base_shift)) >> base_shift); + p[Order::A] = (value_type)((alpha + a) - ((alpha * a + base_mask) >> base_shift)); + } + }; + + //=========================================================blender_rgba_pre + template<class ColorT, class Order> struct blender_rgba_pre + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (base_shift - 8); + p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * alpha + cg * cover) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift); + p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); + } + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha) + { + alpha = color_type::base_mask - alpha; + p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr); + p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg); + p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb); + p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); + } + }; + + //======================================================blender_rgba_plain + template<class ColorT, class Order> struct blender_rgba_plain + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e { base_shift = color_type::base_shift }; + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover=0) + { + if(alpha == 0) return; + calc_type a = p[Order::A]; + calc_type r = p[Order::R] * a; + calc_type g = p[Order::G] * a; + calc_type b = p[Order::B] * a; + a = ((alpha + a) << base_shift) - alpha * a; + p[Order::A] = (value_type)(a >> base_shift); + p[Order::R] = (value_type)((((cr << base_shift) - r) * alpha + (r << base_shift)) / a); + p[Order::G] = (value_type)((((cg << base_shift) - g) * alpha + (g << base_shift)) / a); + p[Order::B] = (value_type)((((cb << base_shift) - b) * alpha + (b << base_shift)) / a); + } + }; + + + + + + + + + + + + //=========================================================comp_op_rgba_clear + template<class ColorT, class Order> struct comp_op_rgba_clear + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(value_type* p, + unsigned, unsigned, unsigned, unsigned, + unsigned cover) + { + if(cover < 255) + { + cover = 255 - cover; + p[Order::R] = (value_type)((p[Order::R] * cover + 255) >> 8); + p[Order::G] = (value_type)((p[Order::G] * cover + 255) >> 8); + p[Order::B] = (value_type)((p[Order::B] * cover + 255) >> 8); + p[Order::A] = (value_type)((p[Order::A] * cover + 255) >> 8); + } + else + { + p[0] = p[1] = p[2] = p[3] = 0; + } + } + }; + + //===========================================================comp_op_rgba_src + template<class ColorT, class Order> struct comp_op_rgba_src + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + unsigned alpha = 255 - cover; + p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8)); + p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8)); + p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8)); + p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8)); + } + else + { + p[Order::R] = sr; + p[Order::G] = sg; + p[Order::B] = sb; + p[Order::A] = sa; + } + } + }; + + //===========================================================comp_op_rgba_dst + template<class ColorT, class Order> struct comp_op_rgba_dst + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + + static AGG_INLINE void blend_pix(value_type*, + unsigned, unsigned, unsigned, + unsigned, unsigned) + { + } + }; + + //======================================================comp_op_rgba_src_over + template<class ColorT, class Order> struct comp_op_rgba_src_over + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Sca + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + calc_type s1a = base_mask - sa; + p[Order::R] = (value_type)(sr + ((p[Order::R] * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(sg + ((p[Order::G] * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(sb + ((p[Order::B] * s1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); + } + }; + + //======================================================comp_op_rgba_dst_over + template<class ColorT, class Order> struct comp_op_rgba_dst_over + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Dca + Sca.(1 - Da) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + calc_type d1a = base_mask - p[Order::A]; + p[Order::R] = (value_type)(p[Order::R] + ((sr * d1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(p[Order::G] + ((sg * d1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(p[Order::B] + ((sb * d1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); + } + }; + + //======================================================comp_op_rgba_src_in + template<class ColorT, class Order> struct comp_op_rgba_src_in + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Sca.Da + // Da' = Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + calc_type da = p[Order::A]; + if(cover < 255) + { + unsigned alpha = 255 - cover; + p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8)); + } + else + { + p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift); + p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift); + } + } + }; + + //======================================================comp_op_rgba_dst_in + template<class ColorT, class Order> struct comp_op_rgba_dst_in + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Dca.Sa + // Da' = Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned, unsigned, unsigned, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sa = base_mask - ((cover * (base_mask - sa) + 255) >> 8); + } + p[Order::R] = (value_type)((p[Order::R] * sa + base_mask) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * sa + base_mask) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * sa + base_mask) >> base_shift); + p[Order::A] = (value_type)((p[Order::A] * sa + base_mask) >> base_shift); + } + }; + + //======================================================comp_op_rgba_src_out + template<class ColorT, class Order> struct comp_op_rgba_src_out + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Sca.(1 - Da) + // Da' = Sa.(1 - Da) + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + calc_type da = base_mask - p[Order::A]; + if(cover < 255) + { + unsigned alpha = 255 - cover; + p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8)); + } + else + { + p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift); + p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift); + } + } + }; + + //======================================================comp_op_rgba_dst_out + template<class ColorT, class Order> struct comp_op_rgba_dst_out + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Dca.(1 - Sa) + // Da' = Da.(1 - Sa) + static AGG_INLINE void blend_pix(value_type* p, + unsigned, unsigned, unsigned, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sa = (sa * cover + 255) >> 8; + } + sa = base_mask - sa; + p[Order::R] = (value_type)((p[Order::R] * sa + base_shift) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * sa + base_shift) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * sa + base_shift) >> base_shift); + p[Order::A] = (value_type)((p[Order::A] * sa + base_shift) >> base_shift); + } + }; + + //=====================================================comp_op_rgba_src_atop + template<class ColorT, class Order> struct comp_op_rgba_src_atop + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Sca.Da + Dca.(1 - Sa) + // Da' = Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + calc_type da = p[Order::A]; + sa = base_mask - sa; + p[Order::R] = (value_type)((sr * da + p[Order::R] * sa + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg * da + p[Order::G] * sa + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb * da + p[Order::B] * sa + base_mask) >> base_shift); + } + }; + + //=====================================================comp_op_rgba_dst_atop + template<class ColorT, class Order> struct comp_op_rgba_dst_atop + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Dca.Sa + Sca.(1 - Da) + // Da' = Sa + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + calc_type da = base_mask - p[Order::A]; + if(cover < 255) + { + unsigned alpha = 255 - cover; + sr = (p[Order::R] * sa + sr * da + base_mask) >> base_shift; + sg = (p[Order::G] * sa + sg * da + base_mask) >> base_shift; + sb = (p[Order::B] * sa + sb * da + base_mask) >> base_shift; + p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8)); + p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8)); + p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8)); + p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8)); + + } + else + { + p[Order::R] = (value_type)((p[Order::R] * sa + sr * da + base_mask) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * sa + sg * da + base_mask) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * sa + sb * da + base_mask) >> base_shift); + p[Order::A] = (value_type)sa; + } + } + }; + + //=========================================================comp_op_rgba_xor + template<class ColorT, class Order> struct comp_op_rgba_xor + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - 2.Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type s1a = base_mask - sa; + calc_type d1a = base_mask - p[Order::A]; + p[Order::R] = (value_type)((p[Order::R] * s1a + sr * d1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * s1a + sg * d1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * s1a + sb * d1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask/2) >> (base_shift - 1))); + } + } + }; + + //=========================================================comp_op_rgba_plus + template<class ColorT, class Order> struct comp_op_rgba_plus + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Sca + Dca + // Da' = Sa + Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type dr = p[Order::R] + sr; + calc_type dg = p[Order::G] + sg; + calc_type db = p[Order::B] + sb; + calc_type da = p[Order::A] + sa; + p[Order::R] = (dr > base_mask) ? (value_type)base_mask : dr; + p[Order::G] = (dg > base_mask) ? (value_type)base_mask : dg; + p[Order::B] = (db > base_mask) ? (value_type)base_mask : db; + p[Order::A] = (da > base_mask) ? (value_type)base_mask : da; + } + } + }; + + //========================================================comp_op_rgba_minus + template<class ColorT, class Order> struct comp_op_rgba_minus + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Dca - Sca + // Da' = 1 - (1 - Sa).(1 - Da) + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type dr = p[Order::R] - sr; + calc_type dg = p[Order::G] - sg; + calc_type db = p[Order::B] - sb; + p[Order::R] = (dr > base_mask) ? 0 : dr; + p[Order::G] = (dg > base_mask) ? 0 : dg; + p[Order::B] = (db > base_mask) ? 0 : db; + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); + //p[Order::A] = (value_type)(base_mask - (((base_mask - sa) * (base_mask - p[Order::A]) + base_mask) >> base_shift)); + } + } + }; + + //=====================================================comp_op_rgba_multiply + template<class ColorT, class Order> struct comp_op_rgba_multiply + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type s1a = base_mask - sa; + calc_type d1a = base_mask - p[Order::A]; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + p[Order::R] = (value_type)((sr * dr + sr * d1a + dr * s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg * dg + sg * d1a + dg * s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb * db + sb * d1a + db * s1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); + } + } + }; + + //=====================================================comp_op_rgba_screen + template<class ColorT, class Order> struct comp_op_rgba_screen + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Sca + Dca - Sca.Dca + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + p[Order::R] = (value_type)(sr + dr - ((sr * dr + base_mask) >> base_shift)); + p[Order::G] = (value_type)(sg + dg - ((sg * dg + base_mask) >> base_shift)); + p[Order::B] = (value_type)(sb + db - ((sb * db + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + //=====================================================comp_op_rgba_overlay + template<class ColorT, class Order> struct comp_op_rgba_overlay + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // if 2.Dca < Da + // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + calc_type sada = sa * p[Order::A]; + + p[Order::R] = (value_type)(((2*dr < da) ? + 2*sr*dr + sr*d1a + dr*s1a : + sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift); + + p[Order::G] = (value_type)(((2*dg < da) ? + 2*sg*dg + sg*d1a + dg*s1a : + sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift); + + p[Order::B] = (value_type)(((2*db < da) ? + 2*sb*db + sb*d1a + db*s1a : + sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift); + + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + + template<class T> inline T sd_min(T a, T b) { return (a < b) ? a : b; } + template<class T> inline T sd_max(T a, T b) { return (a > b) ? a : b; } + + //=====================================================comp_op_rgba_darken + template<class ColorT, class Order> struct comp_op_rgba_darken + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + + p[Order::R] = (value_type)((sd_min(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((sd_min(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((sd_min(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + //=====================================================comp_op_rgba_lighten + template<class ColorT, class Order> struct comp_op_rgba_lighten + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + + p[Order::R] = (value_type)((sd_max(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((sd_max(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((sd_max(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + //=====================================================comp_op_rgba_color_dodge + template<class ColorT, class Order> struct comp_op_rgba_color_dodge + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // if Sca.Da + Dca.Sa >= Sa.Da + // Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + long_type drsa = dr * sa; + long_type dgsa = dg * sa; + long_type dbsa = db * sa; + long_type srda = sr * da; + long_type sgda = sg * da; + long_type sbda = sb * da; + long_type sada = sa * da; + + p[Order::R] = (value_type)((srda + drsa >= sada) ? + (sada + sr * d1a + dr * s1a + base_mask) >> base_shift : + drsa / (base_mask - (sr << base_shift) / sa) + ((sr * d1a + dr * s1a + base_mask) >> base_shift)); + + p[Order::G] = (value_type)((sgda + dgsa >= sada) ? + (sada + sg * d1a + dg * s1a + base_mask) >> base_shift : + dgsa / (base_mask - (sg << base_shift) / sa) + ((sg * d1a + dg * s1a + base_mask) >> base_shift)); + + p[Order::B] = (value_type)((sbda + dbsa >= sada) ? + (sada + sb * d1a + db * s1a + base_mask) >> base_shift : + dbsa / (base_mask - (sb << base_shift) / sa) + ((sb * d1a + db * s1a + base_mask) >> base_shift)); + + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + //=====================================================comp_op_rgba_color_burn + template<class ColorT, class Order> struct comp_op_rgba_color_burn + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // if Sca.Da + Dca.Sa <= Sa.Da + // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + long_type drsa = dr * sa; + long_type dgsa = dg * sa; + long_type dbsa = db * sa; + long_type srda = sr * da; + long_type sgda = sg * da; + long_type sbda = sb * da; + long_type sada = sa * da; + + p[Order::R] = (value_type)(((srda + drsa <= sada) ? + sr * d1a + dr * s1a : + sa * (srda + drsa - sada) / sr + sr * d1a + dr * s1a + base_mask) >> base_shift); + + p[Order::G] = (value_type)(((sgda + dgsa <= sada) ? + sg * d1a + dg * s1a : + sa * (sgda + dgsa - sada) / sg + sg * d1a + dg * s1a + base_mask) >> base_shift); + + p[Order::B] = (value_type)(((sbda + dbsa <= sada) ? + sb * d1a + db * s1a : + sa * (sbda + dbsa - sada) / sb + sb * d1a + db * s1a + base_mask) >> base_shift); + + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + //=====================================================comp_op_rgba_hard_light + template<class ColorT, class Order> struct comp_op_rgba_hard_light + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // if 2.Sca < Sa + // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + calc_type sada = sa * da; + + p[Order::R] = (value_type)(((2*sr < sa) ? + 2*sr*dr + sr*d1a + dr*s1a : + sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift); + + p[Order::G] = (value_type)(((2*sg < sa) ? + 2*sg*dg + sg*d1a + dg*s1a : + sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift); + + p[Order::B] = (value_type)(((2*sb < sa) ? + 2*sb*db + sb*d1a + db*s1a : + sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift); + + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + //=====================================================comp_op_rgba_soft_light + template<class ColorT, class Order> struct comp_op_rgba_soft_light + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // if 2.Sca < Sa + // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise if 8.Dca <= Da + // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa).(3 - 8.Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = (Dca.Sa + ((Dca/Da)^(0.5).Da - Dca).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + + static AGG_INLINE void blend_pix(value_type* p, + unsigned r, unsigned g, unsigned b, + unsigned a, unsigned cover) + { + double sr = double(r * cover) / (base_mask * 255); + double sg = double(g * cover) / (base_mask * 255); + double sb = double(b * cover) / (base_mask * 255); + double sa = double(a * cover) / (base_mask * 255); + if(sa > 0) + { + double dr = double(p[Order::R]) / base_mask; + double dg = double(p[Order::G]) / base_mask; + double db = double(p[Order::B]) / base_mask; + double da = double(p[Order::A] ? p[Order::A] : 1) / base_mask; + if(cover < 255) + { + a = (a * cover + 255) >> 8; + } + + if(2*sr < sa) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); + else if(8*dr <= da) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)*(3 - 8*dr/da)) + sr*(1 - da) + dr*(1 - sa); + else dr = (dr*sa + (sqrt(dr/da)*da - dr)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); + + if(2*sg < sa) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); + else if(8*dg <= da) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)*(3 - 8*dg/da)) + sg*(1 - da) + dg*(1 - sa); + else dg = (dg*sa + (sqrt(dg/da)*da - dg)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); + + if(2*sb < sa) db = db*(sa + (1 - db/da)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); + else if(8*db <= da) db = db*(sa + (1 - db/da)*(2*sb - sa)*(3 - 8*db/da)) + sb*(1 - da) + db*(1 - sa); + else db = (db*sa + (sqrt(db/da)*da - db)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); + + p[Order::R] = (value_type)uround(dr * base_mask); + p[Order::G] = (value_type)uround(dg * base_mask); + p[Order::B] = (value_type)uround(db * base_mask); + p[Order::A] = (value_type)(a + p[Order::A] - ((a * p[Order::A] + base_mask) >> base_shift)); + } + } + }; + + //=====================================================comp_op_rgba_difference + template<class ColorT, class Order> struct comp_op_rgba_difference + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask + }; + + // Dca' = Sca + Dca - 2.min(Sca.Da, Dca.Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + p[Order::R] = (value_type)(sr + dr - ((2 * sd_min(sr*da, dr*sa) + base_mask) >> base_shift)); + p[Order::G] = (value_type)(sg + dg - ((2 * sd_min(sg*da, dg*sa) + base_mask) >> base_shift)); + p[Order::B] = (value_type)(sb + db - ((2 * sd_min(sb*da, db*sa) + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + //=====================================================comp_op_rgba_exclusion + template<class ColorT, class Order> struct comp_op_rgba_exclusion + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + p[Order::R] = (value_type)((sr*da + dr*sa - 2*sr*dr + sr*d1a + dr*s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg*da + dg*sa - 2*sg*dg + sg*d1a + dg*s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb*da + db*sa - 2*sb*db + sb*d1a + db*s1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + //=====================================================comp_op_rgba_contrast + template<class ColorT, class Order> struct comp_op_rgba_contrast + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + long_type dr = p[Order::R]; + long_type dg = p[Order::G]; + long_type db = p[Order::B]; + int da = p[Order::A]; + long_type d2a = da >> 1; + unsigned s2a = sa >> 1; + + int r = (int)((((dr - d2a) * int((sr - s2a)*2 + base_mask)) >> base_shift) + d2a); + int g = (int)((((dg - d2a) * int((sg - s2a)*2 + base_mask)) >> base_shift) + d2a); + int b = (int)((((db - d2a) * int((sb - s2a)*2 + base_mask)) >> base_shift) + d2a); + + r = (r < 0) ? 0 : r; + g = (g < 0) ? 0 : g; + b = (b < 0) ? 0 : b; + + p[Order::R] = (value_type)((r > da) ? da : r); + p[Order::G] = (value_type)((g > da) ? da : g); + p[Order::B] = (value_type)((b > da) ? da : b); + } + }; + + //=====================================================comp_op_rgba_invert + template<class ColorT, class Order> struct comp_op_rgba_invert + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = (Da - Dca) * Sa + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + sa = (sa * cover + 255) >> 8; + if(sa) + { + calc_type da = p[Order::A]; + calc_type dr = ((da - p[Order::R]) * sa + base_mask) >> base_shift; + calc_type dg = ((da - p[Order::G]) * sa + base_mask) >> base_shift; + calc_type db = ((da - p[Order::B]) * sa + base_mask) >> base_shift; + calc_type s1a = base_mask - sa; + p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + //=================================================comp_op_rgba_invert_rgb + template<class ColorT, class Order> struct comp_op_rgba_invert_rgb + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = (Da - Dca) * Sca + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type da = p[Order::A]; + calc_type dr = ((da - p[Order::R]) * sr + base_mask) >> base_shift; + calc_type dg = ((da - p[Order::G]) * sg + base_mask) >> base_shift; + calc_type db = ((da - p[Order::B]) * sb + base_mask) >> base_shift; + calc_type s1a = base_mask - sa; + p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + + + + + //======================================================comp_op_table_rgba + template<class ColorT, class Order> struct comp_op_table_rgba + { + typedef typename ColorT::value_type value_type; + typedef void (*comp_op_func_type)(value_type* p, + unsigned cr, + unsigned cg, + unsigned cb, + unsigned ca, + unsigned cover); + static comp_op_func_type g_comp_op_func[]; + }; + + //==========================================================g_comp_op_func + template<class ColorT, class Order> + typename comp_op_table_rgba<ColorT, Order>::comp_op_func_type + comp_op_table_rgba<ColorT, Order>::g_comp_op_func[] = + { + comp_op_rgba_clear <ColorT,Order>::blend_pix, + comp_op_rgba_src <ColorT,Order>::blend_pix, + comp_op_rgba_dst <ColorT,Order>::blend_pix, + comp_op_rgba_src_over <ColorT,Order>::blend_pix, + comp_op_rgba_dst_over <ColorT,Order>::blend_pix, + comp_op_rgba_src_in <ColorT,Order>::blend_pix, + comp_op_rgba_dst_in <ColorT,Order>::blend_pix, + comp_op_rgba_src_out <ColorT,Order>::blend_pix, + comp_op_rgba_dst_out <ColorT,Order>::blend_pix, + comp_op_rgba_src_atop <ColorT,Order>::blend_pix, + comp_op_rgba_dst_atop <ColorT,Order>::blend_pix, + comp_op_rgba_xor <ColorT,Order>::blend_pix, + comp_op_rgba_plus <ColorT,Order>::blend_pix, + comp_op_rgba_minus <ColorT,Order>::blend_pix, + comp_op_rgba_multiply <ColorT,Order>::blend_pix, + comp_op_rgba_screen <ColorT,Order>::blend_pix, + comp_op_rgba_overlay <ColorT,Order>::blend_pix, + comp_op_rgba_darken <ColorT,Order>::blend_pix, + comp_op_rgba_lighten <ColorT,Order>::blend_pix, + comp_op_rgba_color_dodge<ColorT,Order>::blend_pix, + comp_op_rgba_color_burn <ColorT,Order>::blend_pix, + comp_op_rgba_hard_light <ColorT,Order>::blend_pix, + comp_op_rgba_soft_light <ColorT,Order>::blend_pix, + comp_op_rgba_difference <ColorT,Order>::blend_pix, + comp_op_rgba_exclusion <ColorT,Order>::blend_pix, + comp_op_rgba_contrast <ColorT,Order>::blend_pix, + comp_op_rgba_invert <ColorT,Order>::blend_pix, + comp_op_rgba_invert_rgb <ColorT,Order>::blend_pix, + 0 + }; + + + //==============================================================comp_op_e + enum comp_op_e + { + comp_op_clear, //----comp_op_clear + comp_op_src, //----comp_op_src + comp_op_dst, //----comp_op_dst + comp_op_src_over, //----comp_op_src_over + comp_op_dst_over, //----comp_op_dst_over + comp_op_src_in, //----comp_op_src_in + comp_op_dst_in, //----comp_op_dst_in + comp_op_src_out, //----comp_op_src_out + comp_op_dst_out, //----comp_op_dst_out + comp_op_src_atop, //----comp_op_src_atop + comp_op_dst_atop, //----comp_op_dst_atop + comp_op_xor, //----comp_op_xor + comp_op_plus, //----comp_op_plus + comp_op_minus, //----comp_op_minus + comp_op_multiply, //----comp_op_multiply + comp_op_screen, //----comp_op_screen + comp_op_overlay, //----comp_op_overlay + comp_op_darken, //----comp_op_darken + comp_op_lighten, //----comp_op_lighten + comp_op_color_dodge, //----comp_op_color_dodge + comp_op_color_burn, //----comp_op_color_burn + comp_op_hard_light, //----comp_op_hard_light + comp_op_soft_light, //----comp_op_soft_light + comp_op_difference, //----comp_op_difference + comp_op_exclusion, //----comp_op_exclusion + comp_op_contrast, //----comp_op_contrast + comp_op_invert, //----comp_op_invert + comp_op_invert_rgb, //----comp_op_invert_rgb + + end_of_comp_op_e + }; + + + + + + + + //====================================================comp_op_adaptor_rgba + template<class ColorT, class Order> struct comp_op_adaptor_rgba + { + typedef Order order_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op] + (p, (cr * ca + base_mask) >> base_shift, + (cg * ca + base_mask) >> base_shift, + (cb * ca + base_mask) >> base_shift, + ca, cover); + } + }; + + //=========================================comp_op_adaptor_clip_to_dst_rgba + template<class ColorT, class Order> struct comp_op_adaptor_clip_to_dst_rgba + { + typedef Order order_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + cr = (cr * ca + base_mask) >> base_shift; + cg = (cg * ca + base_mask) >> base_shift; + cb = (cb * ca + base_mask) >> base_shift; + unsigned da = p[Order::A]; + comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op] + (p, (cr * da + base_mask) >> base_shift, + (cg * da + base_mask) >> base_shift, + (cb * da + base_mask) >> base_shift, + (ca * da + base_mask) >> base_shift, + cover); + } + }; + + //================================================comp_op_adaptor_rgba_pre + template<class ColorT, class Order> struct comp_op_adaptor_rgba_pre + { + typedef Order order_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op](p, cr, cg, cb, ca, cover); + } + }; + + //=====================================comp_op_adaptor_clip_to_dst_rgba_pre + template<class ColorT, class Order> struct comp_op_adaptor_clip_to_dst_rgba_pre + { + typedef Order order_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + unsigned da = p[Order::A]; + comp_op_table_rgba<ColorT, Order>::g_comp_op_func[op] + (p, (cr * da + base_mask) >> base_shift, + (cg * da + base_mask) >> base_shift, + (cb * da + base_mask) >> base_shift, + (ca * da + base_mask) >> base_shift, + cover); + } + }; + + //=======================================================comp_adaptor_rgba + template<class BlenderPre> struct comp_adaptor_rgba + { + typedef typename BlenderPre::order_type order_type; + typedef typename BlenderPre::color_type color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + BlenderPre::blend_pix(p, + (cr * ca + base_mask) >> base_shift, + (cg * ca + base_mask) >> base_shift, + (cb * ca + base_mask) >> base_shift, + ca, cover); + } + }; + + //==========================================comp_adaptor_clip_to_dst_rgba + template<class BlenderPre> struct comp_adaptor_clip_to_dst_rgba + { + typedef typename BlenderPre::order_type order_type; + typedef typename BlenderPre::color_type color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + cr = (cr * ca + base_mask) >> base_shift; + cg = (cg * ca + base_mask) >> base_shift; + cb = (cb * ca + base_mask) >> base_shift; + unsigned da = p[order_type::A]; + BlenderPre::blend_pix(p, + (cr * da + base_mask) >> base_shift, + (cg * da + base_mask) >> base_shift, + (cb * da + base_mask) >> base_shift, + (ca * da + base_mask) >> base_shift, + cover); + } + }; + + //======================================comp_adaptor_clip_to_dst_rgba_pre + template<class BlenderPre> struct comp_adaptor_clip_to_dst_rgba_pre + { + typedef typename BlenderPre::order_type order_type; + typedef typename BlenderPre::color_type color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + unsigned da = p[order_type::A]; + BlenderPre::blend_pix(p, + (cr * da + base_mask) >> base_shift, + (cg * da + base_mask) >> base_shift, + (cb * da + base_mask) >> base_shift, + (ca * da + base_mask) >> base_shift, + cover); + } + }; + + + + + + + //===============================================copy_or_blend_rgba_wrapper + template<class Blender> struct copy_or_blend_rgba_wrapper + { + typedef typename Blender::color_type color_type; + typedef typename Blender::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + static AGG_INLINE void copy_or_blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha) + { + if(alpha) + { + if(alpha == base_mask) + { + p[order_type::R] = cr; + p[order_type::G] = cg; + p[order_type::B] = cb; + p[order_type::A] = base_mask; + } + else + { + Blender::blend_pix(p, cr, cg, cb, alpha); + } + } + } + + //-------------------------------------------------------------------- + static AGG_INLINE void copy_or_blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + if(cover == 255) + { + copy_or_blend_pix(p, cr, cg, cb, alpha); + } + else + { + if(alpha) + { + alpha = (alpha * (cover + 1)) >> 8; + if(alpha == base_mask) + { + p[order_type::R] = cr; + p[order_type::G] = cg; + p[order_type::B] = cb; + p[order_type::A] = base_mask; + } + else + { + Blender::blend_pix(p, cr, cg, cb, alpha, cover); + } + } + } + } + }; + + + + + + + //=================================================pixfmt_alpha_blend_rgba + template<class Blender, class RenBuf, class PixelT = int32u> + class pixfmt_alpha_blend_rgba + { + public: + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef PixelT pixel_type; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef copy_or_blend_rgba_wrapper<blender_type> cob_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask, + pix_width = sizeof(pixel_type) + }; + + //-------------------------------------------------------------------- + pixfmt_alpha_blend_rgba() : m_rbuf(0) {} + explicit pixfmt_alpha_blend_rgba(rbuf_type& rb) : m_rbuf(&rb) {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + + //-------------------------------------------------------------------- + template<class PixFmt> + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) + { + rect_i r(x1, y1, x2, y2); + if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) + { + int stride = pixf.stride(); + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + (r.x2 - r.x1) + 1, + (r.y2 - r.y1) + 1, + stride); + return true; + } + return false; + } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + x * pix_width; + } + + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + return m_rbuf->row_ptr(y) + x * pix_width; + } + + + //-------------------------------------------------------------------- + AGG_INLINE static void make_pix(int8u* p, const color_type& c) + { + ((value_type*)p)[order_type::R] = c.r; + ((value_type*)p)[order_type::G] = c.g; + ((value_type*)p)[order_type::B] = c.b; + ((value_type*)p)[order_type::A] = c.a; + } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + const value_type* p = (const value_type*)m_rbuf->row_ptr(y); + if(p) + { + p += x << 2; + return color_type(p[order_type::R], + p[order_type::G], + p[order_type::B], + p[order_type::A]); + } + return color_type::no_color(); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_pixel(int x, int y, const color_type& c) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2); + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + p[order_type::A] = c.a; + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) + { + cob_type::copy_or_blend_pix( + (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), + c.r, c.g, c.b, c.a, + cover); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + pixel_type v; + ((value_type*)&v)[order_type::R] = c.r; + ((value_type*)&v)[order_type::G] = c.g; + ((value_type*)&v)[order_type::B] = c.b; + ((value_type*)&v)[order_type::A] = c.a; + do + { + *(pixel_type*)p = v; + p += 4; + } + while(--len); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type v; + ((value_type*)&v)[order_type::R] = c.r; + ((value_type*)&v)[order_type::G] = c.g; + ((value_type*)&v)[order_type::B] = c.b; + ((value_type*)&v)[order_type::A] = c.a; + do + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + *(pixel_type*)p = v; + } + while(--len); + } + + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + pixel_type v; + ((value_type*)&v)[order_type::R] = c.r; + ((value_type*)&v)[order_type::G] = c.g; + ((value_type*)&v)[order_type::B] = c.b; + ((value_type*)&v)[order_type::A] = c.a; + do + { + *(pixel_type*)p = v; + p += 4; + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + blender_type::blend_pix(p, c.r, c.g, c.b, alpha); + p += 4; + } + while(--len); + } + else + { + do + { + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); + p += 4; + } + while(--len); + } + } + } + } + + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) + { + value_type* p; + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + pixel_type v; + ((value_type*)&v)[order_type::R] = c.r; + ((value_type*)&v)[order_type::G] = c.g; + ((value_type*)&v)[order_type::B] = c.b; + ((value_type*)&v)[order_type::A] = c.a; + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + *(pixel_type*)p = v; + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + blender_type::blend_pix(p, c.r, c.g, c.b, alpha); + } + while(--len); + } + else + { + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); + } + while(--len); + } + } + } + } + + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (c.a) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; + if(alpha == base_mask) + { + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + p[order_type::A] = base_mask; + } + else + { + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers); + } + p += 4; + ++covers; + } + while(--len); + } + } + + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (c.a) + { + do + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; + if(alpha == base_mask) + { + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + p[order_type::A] = base_mask; + } + else + { + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers); + } + ++covers; + } + while(--len); + } + } + + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + p[order_type::R] = colors->r; + p[order_type::G] = colors->g; + p[order_type::B] = colors->b; + p[order_type::A] = colors->a; + ++colors; + p += 4; + } + while(--len); + } + + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + p[order_type::R] = colors->r; + p[order_type::G] = colors->g; + p[order_type::B] = colors->b; + p[order_type::A] = colors->a; + ++colors; + } + while(--len); + } + + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + if(covers) + { + do + { + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a, + *covers++); + p += 4; + ++colors; + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a); + p += 4; + ++colors; + } + while(--len); + } + else + { + do + { + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a, + cover); + p += 4; + ++colors; + } + while(--len); + } + } + } + + + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + value_type* p; + if(covers) + { + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a, + *covers++); + ++colors; + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a); + ++colors; + } + while(--len); + } + else + { + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a, + cover); + ++colors; + } + while(--len); + } + } + } + + //-------------------------------------------------------------------- + template<class Function> void for_each_pixel(Function f) + { + unsigned y; + for(y = 0; y < height(); ++y) + { + row_data r = m_rbuf->row(y); + if(r.ptr) + { + unsigned len = r.x2 - r.x1 + 1; + value_type* p = + (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2); + do + { + f(p); + p += 4; + } + while(--len); + } + } + } + + //-------------------------------------------------------------------- + void premultiply() + { + for_each_pixel(multiplier_rgba<color_type, order_type>::premultiply); + } + + //-------------------------------------------------------------------- + void demultiply() + { + for_each_pixel(multiplier_rgba<color_type, order_type>::demultiply); + } + + //-------------------------------------------------------------------- + template<class GammaLut> void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_rgba<color_type, order_type, GammaLut>(g)); + } + + //-------------------------------------------------------------------- + template<class GammaLut> void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_rgba<color_type, order_type, GammaLut>(g)); + } + + //-------------------------------------------------------------------- + template<class RenBuf2> void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + const int8u* p = from.row_ptr(ysrc); + if(p) + { + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from(const SrcPixelFormatRenderer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::order_type src_order; + const value_type* psrc = (value_type*)from.row_ptr(ysrc); + if(psrc) + { + psrc += xsrc << 2; + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + int incp = 4; + if(xdst > xsrc) + { + psrc += (len-1) << 2; + pdst += (len-1) << 2; + incp = -4; + } + + if(cover == 255) + { + do + { + cob_type::copy_or_blend_pix(pdst, + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + psrc[src_order::A]); + psrc += incp; + pdst += incp; + } + while(--len); + } + else + { + do + { + cob_type::copy_or_blend_pix(pdst, + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + psrc[src_order::A], + cover); + psrc += incp; + pdst += incp; + } + while(--len); + } + } + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + do + { + cob_type::copy_or_blend_pix(pdst, + color.r, color.g, color.b, color.a, + (*psrc * cover + base_mask) >> base_shift); + ++psrc; + pdst += 4; + } + while(--len); + } + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from_lut(const SrcPixelFormatRenderer& from, + const color_type* color_lut, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + + if(cover == 255) + { + do + { + const color_type& color = color_lut[*psrc]; + cob_type::copy_or_blend_pix(pdst, + color.r, color.g, color.b, color.a); + ++psrc; + pdst += 4; + } + while(--len); + } + else + { + do + { + const color_type& color = color_lut[*psrc]; + cob_type::copy_or_blend_pix(pdst, + color.r, color.g, color.b, color.a, + cover); + ++psrc; + pdst += 4; + } + while(--len); + } + } + } + + private: + rbuf_type* m_rbuf; + }; + + + + + //================================================pixfmt_custom_blend_rgba + template<class Blender, class RenBuf> class pixfmt_custom_blend_rgba + { + public: + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask, + pix_width = sizeof(value_type) * 4 + }; + + + //-------------------------------------------------------------------- + pixfmt_custom_blend_rgba() : m_rbuf(0), m_comp_op(3) {} + explicit pixfmt_custom_blend_rgba(rbuf_type& rb, unsigned comp_op=3) : + m_rbuf(&rb), + m_comp_op(comp_op) + {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + + //-------------------------------------------------------------------- + template<class PixFmt> + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) + { + rect_i r(x1, y1, x2, y2); + if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) + { + int stride = pixf.stride(); + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + (r.x2 - r.x1) + 1, + (r.y2 - r.y1) + 1, + stride); + return true; + } + return false; + } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + x * pix_width; + } + + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + return m_rbuf->row_ptr(y) + x * pix_width; + } + + //-------------------------------------------------------------------- + void comp_op(unsigned op) { m_comp_op = op; } + unsigned comp_op() const { return m_comp_op; } + + //-------------------------------------------------------------------- + AGG_INLINE static void make_pix(int8u* p, const color_type& c) + { + ((value_type*)p)[order_type::R] = c.r; + ((value_type*)p)[order_type::G] = c.g; + ((value_type*)p)[order_type::B] = c.b; + ((value_type*)p)[order_type::A] = c.a; + } + + //-------------------------------------------------------------------- + color_type pixel(int x, int y) const + { + const value_type* p = (value_type*)m_rbuf->row_ptr(y) + (x << 2); + return color_type(p[order_type::R], + p[order_type::G], + p[order_type::B], + p[order_type::A]); + } + + //-------------------------------------------------------------------- + void copy_pixel(int x, int y, const color_type& c) + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), + c.r, c.g, c.b, c.a, 255); + } + + //-------------------------------------------------------------------- + void blend_pixel(int x, int y, const color_type& c, int8u cover) + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), + c.r, c.g, c.b, c.a, + cover); + } + + //-------------------------------------------------------------------- + void copy_hline(int x, int y, unsigned len, const color_type& c) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);; + do + { + blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, 255); + p += 4; + } + while(--len); + } + + //-------------------------------------------------------------------- + void copy_vline(int x, int y, unsigned len, const color_type& c) + { + do + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), + c.r, c.g, c.b, c.a, 255); + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, unsigned len, + const color_type& c, int8u cover) + { + + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, cover); + p += 4; + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, unsigned len, + const color_type& c, int8u cover) + { + + do + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), + c.r, c.g, c.b, c.a, + cover); + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, unsigned len, + const color_type& c, const int8u* covers) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + blender_type::blend_pix(m_comp_op, + p, c.r, c.g, c.b, c.a, + *covers++); + p += 4; + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, unsigned len, + const color_type& c, const int8u* covers) + { + do + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), + c.r, c.g, c.b, c.a, + *covers++); + } + while(--len); + } + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + p[order_type::R] = colors->r; + p[order_type::G] = colors->g; + p[order_type::B] = colors->b; + p[order_type::A] = colors->a; + ++colors; + p += 4; + } + while(--len); + } + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + p[order_type::R] = colors->r; + p[order_type::G] = colors->g; + p[order_type::B] = colors->b; + p[order_type::A] = colors->a; + ++colors; + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + blender_type::blend_pix(m_comp_op, + p, + colors->r, + colors->g, + colors->b, + colors->a, + covers ? *covers++ : cover); + p += 4; + ++colors; + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + do + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), + colors->r, + colors->g, + colors->b, + colors->a, + covers ? *covers++ : cover); + ++colors; + } + while(--len); + + } + + //-------------------------------------------------------------------- + template<class Function> void for_each_pixel(Function f) + { + unsigned y; + for(y = 0; y < height(); ++y) + { + row_data r = m_rbuf->row(y); + if(r.ptr) + { + unsigned len = r.x2 - r.x1 + 1; + value_type* p = + (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2); + do + { + f(p); + p += 4; + } + while(--len); + } + } + } + + //-------------------------------------------------------------------- + void premultiply() + { + for_each_pixel(multiplier_rgba<color_type, order_type>::premultiply); + } + + //-------------------------------------------------------------------- + void demultiply() + { + for_each_pixel(multiplier_rgba<color_type, order_type>::demultiply); + } + + //-------------------------------------------------------------------- + template<class GammaLut> void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_rgba<color_type, order_type, GammaLut>(g)); + } + + //-------------------------------------------------------------------- + template<class GammaLut> void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_rgba<color_type, order_type, GammaLut>(g)); + } + + //-------------------------------------------------------------------- + template<class RenBuf2> void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + const int8u* p = from.row_ptr(ysrc); + if(p) + { + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from(const SrcPixelFormatRenderer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::order_type src_order; + const value_type* psrc = (const value_type*)from.row_ptr(ysrc); + if(psrc) + { + psrc += xsrc << 2; + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + + int incp = 4; + if(xdst > xsrc) + { + psrc += (len-1) << 2; + pdst += (len-1) << 2; + incp = -4; + } + + do + { + blender_type::blend_pix(m_comp_op, + pdst, + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + psrc[src_order::A], + cover); + psrc += incp; + pdst += incp; + } + while(--len); + } + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + do + { + blender_type::blend_pix(m_comp_op, + pdst, + color.r, color.g, color.b, color.a, + (*psrc * cover + base_mask) >> base_shift); + ++psrc; + pdst += 4; + } + while(--len); + } + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from_lut(const SrcPixelFormatRenderer& from, + const color_type* color_lut, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + do + { + const color_type& color = color_lut[*psrc]; + blender_type::blend_pix(m_comp_op, + pdst, + color.r, color.g, color.b, color.a, + cover); + ++psrc; + pdst += 4; + } + while(--len); + } + } + + private: + rbuf_type* m_rbuf; + unsigned m_comp_op; + }; + + + + + //----------------------------------------------------------------------- + typedef blender_rgba<rgba8, order_rgba> blender_rgba32; //----blender_rgba32 + typedef blender_rgba<rgba8, order_argb> blender_argb32; //----blender_argb32 + typedef blender_rgba<rgba8, order_abgr> blender_abgr32; //----blender_abgr32 + typedef blender_rgba<rgba8, order_bgra> blender_bgra32; //----blender_bgra32 + + typedef blender_rgba_pre<rgba8, order_rgba> blender_rgba32_pre; //----blender_rgba32_pre + typedef blender_rgba_pre<rgba8, order_argb> blender_argb32_pre; //----blender_argb32_pre + typedef blender_rgba_pre<rgba8, order_abgr> blender_abgr32_pre; //----blender_abgr32_pre + typedef blender_rgba_pre<rgba8, order_bgra> blender_bgra32_pre; //----blender_bgra32_pre + + typedef blender_rgba_plain<rgba8, order_rgba> blender_rgba32_plain; //----blender_rgba32_plain + typedef blender_rgba_plain<rgba8, order_argb> blender_argb32_plain; //----blender_argb32_plain + typedef blender_rgba_plain<rgba8, order_abgr> blender_abgr32_plain; //----blender_abgr32_plain + typedef blender_rgba_plain<rgba8, order_bgra> blender_bgra32_plain; //----blender_bgra32_plain + + typedef blender_rgba<rgba16, order_rgba> blender_rgba64; //----blender_rgba64 + typedef blender_rgba<rgba16, order_argb> blender_argb64; //----blender_argb64 + typedef blender_rgba<rgba16, order_abgr> blender_abgr64; //----blender_abgr64 + typedef blender_rgba<rgba16, order_bgra> blender_bgra64; //----blender_bgra64 + + typedef blender_rgba_pre<rgba16, order_rgba> blender_rgba64_pre; //----blender_rgba64_pre + typedef blender_rgba_pre<rgba16, order_argb> blender_argb64_pre; //----blender_argb64_pre + typedef blender_rgba_pre<rgba16, order_abgr> blender_abgr64_pre; //----blender_abgr64_pre + typedef blender_rgba_pre<rgba16, order_bgra> blender_bgra64_pre; //----blender_bgra64_pre + + + //----------------------------------------------------------------------- + typedef int32u pixel32_type; + typedef pixfmt_alpha_blend_rgba<blender_rgba32, rendering_buffer, pixel32_type> pixfmt_rgba32; //----pixfmt_rgba32 + typedef pixfmt_alpha_blend_rgba<blender_argb32, rendering_buffer, pixel32_type> pixfmt_argb32; //----pixfmt_argb32 + typedef pixfmt_alpha_blend_rgba<blender_abgr32, rendering_buffer, pixel32_type> pixfmt_abgr32; //----pixfmt_abgr32 + typedef pixfmt_alpha_blend_rgba<blender_bgra32, rendering_buffer, pixel32_type> pixfmt_bgra32; //----pixfmt_bgra32 + + typedef pixfmt_alpha_blend_rgba<blender_rgba32_pre, rendering_buffer, pixel32_type> pixfmt_rgba32_pre; //----pixfmt_rgba32_pre + typedef pixfmt_alpha_blend_rgba<blender_argb32_pre, rendering_buffer, pixel32_type> pixfmt_argb32_pre; //----pixfmt_argb32_pre + typedef pixfmt_alpha_blend_rgba<blender_abgr32_pre, rendering_buffer, pixel32_type> pixfmt_abgr32_pre; //----pixfmt_abgr32_pre + typedef pixfmt_alpha_blend_rgba<blender_bgra32_pre, rendering_buffer, pixel32_type> pixfmt_bgra32_pre; //----pixfmt_bgra32_pre + + typedef pixfmt_alpha_blend_rgba<blender_rgba32_plain, rendering_buffer, pixel32_type> pixfmt_rgba32_plain; //----pixfmt_rgba32_plain + typedef pixfmt_alpha_blend_rgba<blender_argb32_plain, rendering_buffer, pixel32_type> pixfmt_argb32_plain; //----pixfmt_argb32_plain + typedef pixfmt_alpha_blend_rgba<blender_abgr32_plain, rendering_buffer, pixel32_type> pixfmt_abgr32_plain; //----pixfmt_abgr32_plain + typedef pixfmt_alpha_blend_rgba<blender_bgra32_plain, rendering_buffer, pixel32_type> pixfmt_bgra32_plain; //----pixfmt_bgra32_plain + + struct pixel64_type { int16u c[4]; }; + typedef pixfmt_alpha_blend_rgba<blender_rgba64, rendering_buffer, pixel64_type> pixfmt_rgba64; //----pixfmt_rgba64 + typedef pixfmt_alpha_blend_rgba<blender_argb64, rendering_buffer, pixel64_type> pixfmt_argb64; //----pixfmt_argb64 + typedef pixfmt_alpha_blend_rgba<blender_abgr64, rendering_buffer, pixel64_type> pixfmt_abgr64; //----pixfmt_abgr64 + typedef pixfmt_alpha_blend_rgba<blender_bgra64, rendering_buffer, pixel64_type> pixfmt_bgra64; //----pixfmt_bgra64 + + typedef pixfmt_alpha_blend_rgba<blender_rgba64_pre, rendering_buffer, pixel64_type> pixfmt_rgba64_pre; //----pixfmt_rgba64_pre + typedef pixfmt_alpha_blend_rgba<blender_argb64_pre, rendering_buffer, pixel64_type> pixfmt_argb64_pre; //----pixfmt_argb64_pre + typedef pixfmt_alpha_blend_rgba<blender_abgr64_pre, rendering_buffer, pixel64_type> pixfmt_abgr64_pre; //----pixfmt_abgr64_pre + typedef pixfmt_alpha_blend_rgba<blender_bgra64_pre, rendering_buffer, pixel64_type> pixfmt_bgra64_pre; //----pixfmt_bgra64_pre +} + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_pixfmt_transposer.h b/jni/desmume/src/android/agg/include/agg_pixfmt_transposer.h new file mode 100755 index 0000000..cc2fa99 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_pixfmt_transposer.h @@ -0,0 +1,166 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_PIXFMT_TRANSPOSER_INCLUDED +#define AGG_PIXFMT_TRANSPOSER_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //=======================================================pixfmt_transposer + template<class PixFmt> class pixfmt_transposer + { + public: + typedef PixFmt pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::row_data row_data; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + + //-------------------------------------------------------------------- + pixfmt_transposer() : m_pixf(0) {} + explicit pixfmt_transposer(pixfmt_type& pixf) : m_pixf(&pixf) {} + void attach(pixfmt_type& pixf) { m_pixf = &pixf; } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_pixf->height(); } + AGG_INLINE unsigned height() const { return m_pixf->width(); } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + return m_pixf->pixel(y, x); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_pixel(int x, int y, const color_type& c) + { + m_pixf->copy_pixel(y, x, c); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pixel(int x, int y, + const color_type& c, + int8u cover) + { + m_pixf->blend_pixel(y, x, c, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + m_pixf->copy_vline(y, x, len, c); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + m_pixf->copy_hline(y, x, len, c); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_hline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + m_pixf->blend_vline(y, x, len, c, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + m_pixf->blend_hline(y, x, len, c, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + m_pixf->blend_solid_vspan(y, x, len, c, covers); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + m_pixf->blend_solid_hspan(y, x, len, c, covers); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + m_pixf->copy_color_vspan(y, x, len, colors); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + m_pixf->copy_color_hspan(y, x, len, colors); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + m_pixf->blend_color_vspan(y, x, len, colors, covers, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + m_pixf->blend_color_hspan(y, x, len, colors, covers, cover); + } + + private: + pixfmt_type* m_pixf; + }; +} + +#endif + + diff --git a/jni/desmume/src/android/agg/include/agg_rasterizer_cells_aa.h b/jni/desmume/src/android/agg/include/agg_rasterizer_cells_aa.h new file mode 100755 index 0000000..d3bb138 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_rasterizer_cells_aa.h @@ -0,0 +1,764 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// The author gratefully acknowleges the support of David Turner, +// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType +// libray - in producing this work. See http://www.freetype.org for details. +// +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_RASTERIZER_CELLS_AA_INCLUDED +#define AGG_RASTERIZER_CELLS_AA_INCLUDED + +#include <string.h> +#include <math.h> +#include "agg_math.h" +#include "agg_array.h" + + +namespace agg +{ + + //-----------------------------------------------------rasterizer_cells_aa + // An internal class that implements the main rasterization algorithm. + // Used in the rasterizer. Should not be used direcly. + template<class Cell> class rasterizer_cells_aa + { + enum cell_block_scale_e + { + cell_block_shift = 12, + cell_block_size = 1 << cell_block_shift, + cell_block_mask = cell_block_size - 1, + cell_block_pool = 256, + cell_block_limit = 1024 + }; + + struct sorted_y + { + unsigned start; + unsigned num; + }; + + public: + typedef Cell cell_type; + typedef rasterizer_cells_aa<Cell> self_type; + + ~rasterizer_cells_aa(); + rasterizer_cells_aa(); + + void reset(); + void style(const cell_type& style_cell); + void line(int x1, int y1, int x2, int y2); + + int min_x() const { return m_min_x; } + int min_y() const { return m_min_y; } + int max_x() const { return m_max_x; } + int max_y() const { return m_max_y; } + + void sort_cells(); + + unsigned total_cells() const + { + return m_num_cells; + } + + unsigned scanline_num_cells(unsigned y) const + { + return m_sorted_y[y - m_min_y].num; + } + + const cell_type* const* scanline_cells(unsigned y) const + { + return m_sorted_cells.data() + m_sorted_y[y - m_min_y].start; + } + + bool sorted() const { return m_sorted; } + + private: + rasterizer_cells_aa(const self_type&); + const self_type& operator = (const self_type&); + + void set_curr_cell(int x, int y); + void add_curr_cell(); + void render_hline(int ey, int x1, int y1, int x2, int y2); + void allocate_block(); + + private: + unsigned m_num_blocks; + unsigned m_max_blocks; + unsigned m_curr_block; + unsigned m_num_cells; + cell_type** m_cells; + cell_type* m_curr_cell_ptr; + pod_vector<cell_type*> m_sorted_cells; + pod_vector<sorted_y> m_sorted_y; + cell_type m_curr_cell; + cell_type m_style_cell; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; + bool m_sorted; + }; + + + + + //------------------------------------------------------------------------ + template<class Cell> + rasterizer_cells_aa<Cell>::~rasterizer_cells_aa() + { + if(m_num_blocks) + { + cell_type** ptr = m_cells + m_num_blocks - 1; + while(m_num_blocks--) + { + pod_allocator<cell_type>::deallocate(*ptr, cell_block_size); + ptr--; + } + pod_allocator<cell_type*>::deallocate(m_cells, m_max_blocks); + } + } + + //------------------------------------------------------------------------ + template<class Cell> + rasterizer_cells_aa<Cell>::rasterizer_cells_aa() : + m_num_blocks(0), + m_max_blocks(0), + m_curr_block(0), + m_num_cells(0), + m_cells(0), + m_curr_cell_ptr(0), + m_sorted_cells(), + m_sorted_y(), + m_min_x(0x7FFFFFFF), + m_min_y(0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF), + m_sorted(false) + { + m_style_cell.initial(); + m_curr_cell.initial(); + } + + //------------------------------------------------------------------------ + template<class Cell> + void rasterizer_cells_aa<Cell>::reset() + { + m_num_cells = 0; + m_curr_block = 0; + m_curr_cell.initial(); + m_style_cell.initial(); + m_sorted = false; + m_min_x = 0x7FFFFFFF; + m_min_y = 0x7FFFFFFF; + m_max_x = -0x7FFFFFFF; + m_max_y = -0x7FFFFFFF; + } + + //------------------------------------------------------------------------ + template<class Cell> + AGG_INLINE void rasterizer_cells_aa<Cell>::add_curr_cell() + { + if(m_curr_cell.area | m_curr_cell.cover) + { + if((m_num_cells & cell_block_mask) == 0) + { + if(m_num_blocks >= cell_block_limit) return; + allocate_block(); + } + *m_curr_cell_ptr++ = m_curr_cell; + ++m_num_cells; + } + } + + //------------------------------------------------------------------------ + template<class Cell> + AGG_INLINE void rasterizer_cells_aa<Cell>::set_curr_cell(int x, int y) + { + if(m_curr_cell.not_equal(x, y, m_style_cell)) + { + add_curr_cell(); + m_curr_cell.style(m_style_cell); + m_curr_cell.x = x; + m_curr_cell.y = y; + m_curr_cell.cover = 0; + m_curr_cell.area = 0; + } + } + + //------------------------------------------------------------------------ + template<class Cell> + AGG_INLINE void rasterizer_cells_aa<Cell>::render_hline(int ey, + int x1, int y1, + int x2, int y2) + { + int ex1 = x1 >> poly_subpixel_shift; + int ex2 = x2 >> poly_subpixel_shift; + int fx1 = x1 & poly_subpixel_mask; + int fx2 = x2 & poly_subpixel_mask; + + int delta, p, first, dx; + int incr, lift, mod, rem; + + //trivial case. Happens often + if(y1 == y2) + { + set_curr_cell(ex2, ey); + return; + } + + //everything is located in a single cell. That is easy! + if(ex1 == ex2) + { + delta = y2 - y1; + m_curr_cell.cover += delta; + m_curr_cell.area += (fx1 + fx2) * delta; + return; + } + + //ok, we'll have to render a run of adjacent cells on the same + //hline... + p = (poly_subpixel_scale - fx1) * (y2 - y1); + first = poly_subpixel_scale; + incr = 1; + + dx = x2 - x1; + + if(dx < 0) + { + p = fx1 * (y2 - y1); + first = 0; + incr = -1; + dx = -dx; + } + + delta = p / dx; + mod = p % dx; + + if(mod < 0) + { + delta--; + mod += dx; + } + + m_curr_cell.cover += delta; + m_curr_cell.area += (fx1 + first) * delta; + + ex1 += incr; + set_curr_cell(ex1, ey); + y1 += delta; + + if(ex1 != ex2) + { + p = poly_subpixel_scale * (y2 - y1 + delta); + lift = p / dx; + rem = p % dx; + + if (rem < 0) + { + lift--; + rem += dx; + } + + mod -= dx; + + while (ex1 != ex2) + { + delta = lift; + mod += rem; + if(mod >= 0) + { + mod -= dx; + delta++; + } + + m_curr_cell.cover += delta; + m_curr_cell.area += poly_subpixel_scale * delta; + y1 += delta; + ex1 += incr; + set_curr_cell(ex1, ey); + } + } + delta = y2 - y1; + m_curr_cell.cover += delta; + m_curr_cell.area += (fx2 + poly_subpixel_scale - first) * delta; + } + + //------------------------------------------------------------------------ + template<class Cell> + AGG_INLINE void rasterizer_cells_aa<Cell>::style(const cell_type& style_cell) + { + m_style_cell.style(style_cell); + } + + //------------------------------------------------------------------------ + template<class Cell> + void rasterizer_cells_aa<Cell>::line(int x1, int y1, int x2, int y2) + { + enum dx_limit_e { dx_limit = 16384 << poly_subpixel_shift }; + + int dx = x2 - x1; + + if(dx >= dx_limit || dx <= -dx_limit) + { + int cx = (x1 + x2) >> 1; + int cy = (y1 + y2) >> 1; + line(x1, y1, cx, cy); + line(cx, cy, x2, y2); + } + + int dy = y2 - y1; + int ex1 = x1 >> poly_subpixel_shift; + int ex2 = x2 >> poly_subpixel_shift; + int ey1 = y1 >> poly_subpixel_shift; + int ey2 = y2 >> poly_subpixel_shift; + int fy1 = y1 & poly_subpixel_mask; + int fy2 = y2 & poly_subpixel_mask; + + int x_from, x_to; + int p, rem, mod, lift, delta, first, incr; + + if(ex1 < m_min_x) m_min_x = ex1; + if(ex1 > m_max_x) m_max_x = ex1; + if(ey1 < m_min_y) m_min_y = ey1; + if(ey1 > m_max_y) m_max_y = ey1; + if(ex2 < m_min_x) m_min_x = ex2; + if(ex2 > m_max_x) m_max_x = ex2; + if(ey2 < m_min_y) m_min_y = ey2; + if(ey2 > m_max_y) m_max_y = ey2; + + set_curr_cell(ex1, ey1); + + //everything is on a single hline + if(ey1 == ey2) + { + render_hline(ey1, x1, fy1, x2, fy2); + return; + } + + //Vertical line - we have to calculate start and end cells, + //and then - the common values of the area and coverage for + //all cells of the line. We know exactly there's only one + //cell, so, we don't have to call render_hline(). + incr = 1; + if(dx == 0) + { + int ex = x1 >> poly_subpixel_shift; + int two_fx = (x1 - (ex << poly_subpixel_shift)) << 1; + int area; + + first = poly_subpixel_scale; + if(dy < 0) + { + first = 0; + incr = -1; + } + + x_from = x1; + + //render_hline(ey1, x_from, fy1, x_from, first); + delta = first - fy1; + m_curr_cell.cover += delta; + m_curr_cell.area += two_fx * delta; + + ey1 += incr; + set_curr_cell(ex, ey1); + + delta = first + first - poly_subpixel_scale; + area = two_fx * delta; + while(ey1 != ey2) + { + //render_hline(ey1, x_from, poly_subpixel_scale - first, x_from, first); + m_curr_cell.cover = delta; + m_curr_cell.area = area; + ey1 += incr; + set_curr_cell(ex, ey1); + } + //render_hline(ey1, x_from, poly_subpixel_scale - first, x_from, fy2); + delta = fy2 - poly_subpixel_scale + first; + m_curr_cell.cover += delta; + m_curr_cell.area += two_fx * delta; + return; + } + + //ok, we have to render several hlines + p = (poly_subpixel_scale - fy1) * dx; + first = poly_subpixel_scale; + + if(dy < 0) + { + p = fy1 * dx; + first = 0; + incr = -1; + dy = -dy; + } + + delta = p / dy; + mod = p % dy; + + if(mod < 0) + { + delta--; + mod += dy; + } + + x_from = x1 + delta; + render_hline(ey1, x1, fy1, x_from, first); + + ey1 += incr; + set_curr_cell(x_from >> poly_subpixel_shift, ey1); + + if(ey1 != ey2) + { + p = poly_subpixel_scale * dx; + lift = p / dy; + rem = p % dy; + + if(rem < 0) + { + lift--; + rem += dy; + } + mod -= dy; + + while(ey1 != ey2) + { + delta = lift; + mod += rem; + if (mod >= 0) + { + mod -= dy; + delta++; + } + + x_to = x_from + delta; + render_hline(ey1, x_from, poly_subpixel_scale - first, x_to, first); + x_from = x_to; + + ey1 += incr; + set_curr_cell(x_from >> poly_subpixel_shift, ey1); + } + } + render_hline(ey1, x_from, poly_subpixel_scale - first, x2, fy2); + } + + //------------------------------------------------------------------------ + template<class Cell> + void rasterizer_cells_aa<Cell>::allocate_block() + { + if(m_curr_block >= m_num_blocks) + { + if(m_num_blocks >= m_max_blocks) + { + cell_type** new_cells = + pod_allocator<cell_type*>::allocate(m_max_blocks + + cell_block_pool); + + if(m_cells) + { + memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell_type*)); + pod_allocator<cell_type*>::deallocate(m_cells, m_max_blocks); + } + m_cells = new_cells; + m_max_blocks += cell_block_pool; + } + + m_cells[m_num_blocks++] = + pod_allocator<cell_type>::allocate(cell_block_size); + + } + m_curr_cell_ptr = m_cells[m_curr_block++]; + } + + + + //------------------------------------------------------------------------ + template <class T> static AGG_INLINE void swap_cells(T* a, T* b) + { + T temp = *a; + *a = *b; + *b = temp; + } + + + //------------------------------------------------------------------------ + enum + { + qsort_threshold = 9 + }; + + + //------------------------------------------------------------------------ + template<class Cell> + void qsort_cells(Cell** start, unsigned num) + { + Cell** stack[80]; + Cell*** top; + Cell** limit; + Cell** base; + + limit = start + num; + base = start; + top = stack; + + for (;;) + { + int len = int(limit - base); + + Cell** i; + Cell** j; + Cell** pivot; + + if(len > qsort_threshold) + { + // we use base + len/2 as the pivot + pivot = base + len / 2; + swap_cells(base, pivot); + + i = base + 1; + j = limit - 1; + + // now ensure that *i <= *base <= *j + if((*j)->x < (*i)->x) + { + swap_cells(i, j); + } + + if((*base)->x < (*i)->x) + { + swap_cells(base, i); + } + + if((*j)->x < (*base)->x) + { + swap_cells(base, j); + } + + for(;;) + { + int x = (*base)->x; + do i++; while( (*i)->x < x ); + do j--; while( x < (*j)->x ); + + if(i > j) + { + break; + } + + swap_cells(i, j); + } + + swap_cells(base, j); + + // now, push the largest sub-array + if(j - base > limit - i) + { + top[0] = base; + top[1] = j; + base = i; + } + else + { + top[0] = i; + top[1] = limit; + limit = j; + } + top += 2; + } + else + { + // the sub-array is small, perform insertion sort + j = base; + i = j + 1; + + for(; i < limit; j = i, i++) + { + for(; j[1]->x < (*j)->x; j--) + { + swap_cells(j + 1, j); + if (j == base) + { + break; + } + } + } + + if(top > stack) + { + top -= 2; + base = top[0]; + limit = top[1]; + } + else + { + break; + } + } + } + } + + + //------------------------------------------------------------------------ + template<class Cell> + void rasterizer_cells_aa<Cell>::sort_cells() + { + if(m_sorted) return; //Perform sort only the first time. + + add_curr_cell(); + m_curr_cell.x = 0x7FFFFFFF; + m_curr_cell.y = 0x7FFFFFFF; + m_curr_cell.cover = 0; + m_curr_cell.area = 0; + + if(m_num_cells == 0) return; + +// DBG: Check to see if min/max works well. +//for(unsigned nc = 0; nc < m_num_cells; nc++) +//{ +// cell_type* cell = m_cells[nc >> cell_block_shift] + (nc & cell_block_mask); +// if(cell->x < m_min_x || +// cell->y < m_min_y || +// cell->x > m_max_x || +// cell->y > m_max_y) +// { +// cell = cell; // Breakpoint here +// } +//} + // Allocate the array of cell pointers + m_sorted_cells.allocate(m_num_cells, 16); + + // Allocate and zero the Y array + m_sorted_y.allocate(m_max_y - m_min_y + 1, 16); + m_sorted_y.zero(); + + // Create the Y-histogram (count the numbers of cells for each Y) + cell_type** block_ptr = m_cells; + cell_type* cell_ptr; + unsigned nb = m_num_cells >> cell_block_shift; + unsigned i; + while(nb--) + { + cell_ptr = *block_ptr++; + i = cell_block_size; + while(i--) + { + m_sorted_y[cell_ptr->y - m_min_y].start++; + ++cell_ptr; + } + } + + cell_ptr = *block_ptr++; + i = m_num_cells & cell_block_mask; + while(i--) + { + m_sorted_y[cell_ptr->y - m_min_y].start++; + ++cell_ptr; + } + + // Convert the Y-histogram into the array of starting indexes + unsigned start = 0; + for(i = 0; i < m_sorted_y.size(); i++) + { + unsigned v = m_sorted_y[i].start; + m_sorted_y[i].start = start; + start += v; + } + + // Fill the cell pointer array sorted by Y + block_ptr = m_cells; + nb = m_num_cells >> cell_block_shift; + while(nb--) + { + cell_ptr = *block_ptr++; + i = cell_block_size; + while(i--) + { + sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y]; + m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr; + ++curr_y.num; + ++cell_ptr; + } + } + + cell_ptr = *block_ptr++; + i = m_num_cells & cell_block_mask; + while(i--) + { + sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y]; + m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr; + ++curr_y.num; + ++cell_ptr; + } + + // Finally arrange the X-arrays + for(i = 0; i < m_sorted_y.size(); i++) + { + const sorted_y& curr_y = m_sorted_y[i]; + if(curr_y.num) + { + qsort_cells(m_sorted_cells.data() + curr_y.start, curr_y.num); + } + } + m_sorted = true; + } + + + + //------------------------------------------------------scanline_hit_test + class scanline_hit_test + { + public: + scanline_hit_test(int x) : m_x(x), m_hit(false) {} + + void reset_spans() {} + void finalize(int) {} + void add_cell(int x, int) + { + if(m_x == x) m_hit = true; + } + void add_span(int x, int len, int) + { + if(m_x >= x && m_x < x+len) m_hit = true; + } + unsigned num_spans() const { return 1; } + bool hit() const { return m_hit; } + + private: + int m_x; + bool m_hit; + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_rasterizer_compound_aa.h b/jni/desmume/src/android/agg/include/agg_rasterizer_compound_aa.h new file mode 100755 index 0000000..15b88b5 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_rasterizer_compound_aa.h @@ -0,0 +1,698 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.3 +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// +// The author gratefully acknowleges the support of David Turner, +// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType +// libray - in producing this work. See http://www.freetype.org for details. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- +#ifndef AGG_RASTERIZER_COMPOUND_AA_INCLUDED +#define AGG_RASTERIZER_COMPOUND_AA_INCLUDED + +#include "agg_rasterizer_cells_aa.h" +#include "agg_rasterizer_sl_clip.h" + +namespace agg +{ + + //-----------------------------------------------------------cell_style_aa + // A pixel cell. There're no constructors defined and it was done + // intentionally in order to avoid extra overhead when allocating an + // array of cells. + struct cell_style_aa + { + int x; + int y; + int cover; + int area; + int16 left, right; + + void initial() + { + x = 0x7FFFFFFF; + y = 0x7FFFFFFF; + cover = 0; + area = 0; + left = -1; + right = -1; + } + + void style(const cell_style_aa& c) + { + left = c.left; + right = c.right; + } + + int not_equal(int ex, int ey, const cell_style_aa& c) const + { + return (ex - x) | (ey - y) | (left - c.left) | (right - c.right); + } + }; + + + //===========================================================layer_order_e + enum layer_order_e + { + layer_unsorted, //------layer_unsorted + layer_direct, //------layer_direct + layer_inverse //------layer_inverse + }; + + + //==================================================rasterizer_compound_aa + template<class Clip=rasterizer_sl_clip_int> class rasterizer_compound_aa + { + struct style_info + { + unsigned start_cell; + unsigned num_cells; + int last_x; + }; + + struct cell_info + { + int x, area, cover; + }; + + public: + typedef Clip clip_type; + typedef typename Clip::conv_type conv_type; + typedef typename Clip::coord_type coord_type; + + enum aa_scale_e + { + aa_shift = 8, + aa_scale = 1 << aa_shift, + aa_mask = aa_scale - 1, + aa_scale2 = aa_scale * 2, + aa_mask2 = aa_scale2 - 1 + }; + + //-------------------------------------------------------------------- + rasterizer_compound_aa() : + m_outline(), + m_clipper(), + m_filling_rule(fill_non_zero), + m_layer_order(layer_direct), + m_styles(), // Active Styles + m_ast(), // Active Style Table (unique values) + m_asm(), // Active Style Mask + m_cells(), + m_cover_buf(), + m_master_alpha(), + m_min_style(0x7FFFFFFF), + m_max_style(-0x7FFFFFFF), + m_start_x(0), + m_start_y(0), + m_scan_y(0x7FFFFFFF), + m_sl_start(0), + m_sl_len(0) + {} + + //-------------------------------------------------------------------- + void reset(); + void reset_clipping(); + void clip_box(double x1, double y1, double x2, double y2); + void filling_rule(filling_rule_e filling_rule); + void layer_order(layer_order_e order); + void master_alpha(int style, double alpha); + + //-------------------------------------------------------------------- + void styles(int left, int right); + void move_to(int x, int y); + void line_to(int x, int y); + void move_to_d(double x, double y); + void line_to_d(double x, double y); + void add_vertex(double x, double y, unsigned cmd); + + void edge(int x1, int y1, int x2, int y2); + void edge_d(double x1, double y1, double x2, double y2); + + //------------------------------------------------------------------- + template<class VertexSource> + void add_path(VertexSource& vs, unsigned path_id=0) + { + double x; + double y; + + unsigned cmd; + vs.rewind(path_id); + if(m_outline.sorted()) reset(); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + add_vertex(x, y, cmd); + } + } + + + //-------------------------------------------------------------------- + int min_x() const { return m_outline.min_x(); } + int min_y() const { return m_outline.min_y(); } + int max_x() const { return m_outline.max_x(); } + int max_y() const { return m_outline.max_y(); } + int min_style() const { return m_min_style; } + int max_style() const { return m_max_style; } + + //-------------------------------------------------------------------- + void sort(); + bool rewind_scanlines(); + unsigned sweep_styles(); + int scanline_start() const { return m_sl_start; } + unsigned scanline_length() const { return m_sl_len; } + unsigned style(unsigned style_idx) const; + + cover_type* allocate_cover_buffer(unsigned len); + + //-------------------------------------------------------------------- + bool navigate_scanline(int y); + bool hit_test(int tx, int ty); + + //-------------------------------------------------------------------- + AGG_INLINE unsigned calculate_alpha(int area, unsigned master_alpha) const + { + int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift); + if(cover < 0) cover = -cover; + if(m_filling_rule == fill_even_odd) + { + cover &= aa_mask2; + if(cover > aa_scale) + { + cover = aa_scale2 - cover; + } + } + if(cover > aa_mask) cover = aa_mask; + return (cover * master_alpha + aa_mask) >> aa_shift; + } + + //-------------------------------------------------------------------- + // Sweeps one scanline with one style index. The style ID can be + // determined by calling style(). + template<class Scanline> bool sweep_scanline(Scanline& sl, int style_idx) + { + int scan_y = m_scan_y - 1; + if(scan_y > m_outline.max_y()) return false; + + sl.reset_spans(); + + unsigned master_alpha = aa_mask; + + if(style_idx < 0) + { + style_idx = 0; + } + else + { + style_idx++; + master_alpha = m_master_alpha[m_ast[style_idx] + m_min_style - 1]; + } + + const style_info& st = m_styles[m_ast[style_idx]]; + + unsigned num_cells = st.num_cells; + cell_info* cell = &m_cells[st.start_cell]; + + int cover = 0; + while(num_cells--) + { + unsigned alpha; + int x = cell->x; + int area = cell->area; + + cover += cell->cover; + + ++cell; + + if(area) + { + alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area, + master_alpha); + sl.add_cell(x, alpha); + x++; + } + + if(num_cells && cell->x > x) + { + alpha = calculate_alpha(cover << (poly_subpixel_shift + 1), + master_alpha); + if(alpha) + { + sl.add_span(x, cell->x - x, alpha); + } + } + } + + if(sl.num_spans() == 0) return false; + sl.finalize(scan_y); + return true; + } + + private: + void add_style(int style_id); + void allocate_master_alpha(); + + //-------------------------------------------------------------------- + // Disable copying + rasterizer_compound_aa(const rasterizer_compound_aa<Clip>&); + const rasterizer_compound_aa<Clip>& + operator = (const rasterizer_compound_aa<Clip>&); + + private: + rasterizer_cells_aa<cell_style_aa> m_outline; + clip_type m_clipper; + filling_rule_e m_filling_rule; + layer_order_e m_layer_order; + pod_vector<style_info> m_styles; // Active Styles + pod_vector<unsigned> m_ast; // Active Style Table (unique values) + pod_vector<int8u> m_asm; // Active Style Mask + pod_vector<cell_info> m_cells; + pod_vector<cover_type> m_cover_buf; + pod_bvector<unsigned> m_master_alpha; + + int m_min_style; + int m_max_style; + coord_type m_start_x; + coord_type m_start_y; + int m_scan_y; + int m_sl_start; + unsigned m_sl_len; + }; + + + + + + + + + + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::reset() + { + m_outline.reset(); + m_min_style = 0x7FFFFFFF; + m_max_style = -0x7FFFFFFF; + m_scan_y = 0x7FFFFFFF; + m_sl_start = 0; + m_sl_len = 0; + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::filling_rule(filling_rule_e filling_rule) + { + m_filling_rule = filling_rule; + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::layer_order(layer_order_e order) + { + m_layer_order = order; + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::clip_box(double x1, double y1, + double x2, double y2) + { + reset(); + m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1), + conv_type::upscale(x2), conv_type::upscale(y2)); + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::reset_clipping() + { + reset(); + m_clipper.reset_clipping(); + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::styles(int left, int right) + { + cell_style_aa cell; + cell.initial(); + cell.left = (int16)left; + cell.right = (int16)right; + m_outline.style(cell); + if(left >= 0 && left < m_min_style) m_min_style = left; + if(left >= 0 && left > m_max_style) m_max_style = left; + if(right >= 0 && right < m_min_style) m_min_style = right; + if(right >= 0 && right > m_max_style) m_max_style = right; + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::move_to(int x, int y) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(m_start_x = conv_type::downscale(x), + m_start_y = conv_type::downscale(y)); + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::line_to(int x, int y) + { + m_clipper.line_to(m_outline, + conv_type::downscale(x), + conv_type::downscale(y)); + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::move_to_d(double x, double y) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(m_start_x = conv_type::upscale(x), + m_start_y = conv_type::upscale(y)); + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::line_to_d(double x, double y) + { + m_clipper.line_to(m_outline, + conv_type::upscale(x), + conv_type::upscale(y)); + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::add_vertex(double x, double y, unsigned cmd) + { + if(is_move_to(cmd)) + { + move_to_d(x, y); + } + else + if(is_vertex(cmd)) + { + line_to_d(x, y); + } + else + if(is_close(cmd)) + { + m_clipper.line_to(m_outline, m_start_x, m_start_y); + } + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::edge(int x1, int y1, int x2, int y2) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1)); + m_clipper.line_to(m_outline, + conv_type::downscale(x2), + conv_type::downscale(y2)); + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::edge_d(double x1, double y1, + double x2, double y2) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1)); + m_clipper.line_to(m_outline, + conv_type::upscale(x2), + conv_type::upscale(y2)); + } + + //------------------------------------------------------------------------ + template<class Clip> + AGG_INLINE void rasterizer_compound_aa<Clip>::sort() + { + m_outline.sort_cells(); + } + + //------------------------------------------------------------------------ + template<class Clip> + AGG_INLINE bool rasterizer_compound_aa<Clip>::rewind_scanlines() + { + m_outline.sort_cells(); + if(m_outline.total_cells() == 0) + { + return false; + } + if(m_max_style < m_min_style) + { + return false; + } + m_scan_y = m_outline.min_y(); + m_styles.allocate(m_max_style - m_min_style + 2, 128); + allocate_master_alpha(); + return true; + } + + //------------------------------------------------------------------------ + template<class Clip> + AGG_INLINE void rasterizer_compound_aa<Clip>::add_style(int style_id) + { + if(style_id < 0) style_id = 0; + else style_id -= m_min_style - 1; + + unsigned nbyte = style_id >> 3; + unsigned mask = 1 << (style_id & 7); + + style_info* style = &m_styles[style_id]; + if((m_asm[nbyte] & mask) == 0) + { + m_ast.add(style_id); + m_asm[nbyte] |= mask; + style->start_cell = 0; + style->num_cells = 0; + style->last_x = -0x7FFFFFFF; + } + ++style->start_cell; + } + + //------------------------------------------------------------------------ + // Returns the number of styles + template<class Clip> + unsigned rasterizer_compound_aa<Clip>::sweep_styles() + { + for(;;) + { + if(m_scan_y > m_outline.max_y()) return 0; + unsigned num_cells = m_outline.scanline_num_cells(m_scan_y); + const cell_style_aa* const* cells = m_outline.scanline_cells(m_scan_y); + unsigned num_styles = m_max_style - m_min_style + 2; + const cell_style_aa* curr_cell; + unsigned style_id; + style_info* style; + cell_info* cell; + + m_cells.allocate(num_cells * 2, 256); // Each cell can have two styles + m_ast.capacity(num_styles, 64); + m_asm.allocate((num_styles + 7) >> 3, 8); + m_asm.zero(); + + if(num_cells) + { + // Pre-add zero (for no-fill style, that is, -1). + // We need that to ensure that the "-1 style" would go first. + m_asm[0] |= 1; + m_ast.add(0); + style = &m_styles[0]; + style->start_cell = 0; + style->num_cells = 0; + style->last_x = -0x7FFFFFFF; + + m_sl_start = cells[0]->x; + m_sl_len = cells[num_cells-1]->x - m_sl_start + 1; + while(num_cells--) + { + curr_cell = *cells++; + add_style(curr_cell->left); + add_style(curr_cell->right); + } + + // Convert the Y-histogram into the array of starting indexes + unsigned i; + unsigned start_cell = 0; + for(i = 0; i < m_ast.size(); i++) + { + style_info& st = m_styles[m_ast[i]]; + unsigned v = st.start_cell; + st.start_cell = start_cell; + start_cell += v; + } + + cells = m_outline.scanline_cells(m_scan_y); + num_cells = m_outline.scanline_num_cells(m_scan_y); + + while(num_cells--) + { + curr_cell = *cells++; + style_id = (curr_cell->left < 0) ? 0 : + curr_cell->left - m_min_style + 1; + + style = &m_styles[style_id]; + if(curr_cell->x == style->last_x) + { + cell = &m_cells[style->start_cell + style->num_cells - 1]; + cell->area += curr_cell->area; + cell->cover += curr_cell->cover; + } + else + { + cell = &m_cells[style->start_cell + style->num_cells]; + cell->x = curr_cell->x; + cell->area = curr_cell->area; + cell->cover = curr_cell->cover; + style->last_x = curr_cell->x; + style->num_cells++; + } + + style_id = (curr_cell->right < 0) ? 0 : + curr_cell->right - m_min_style + 1; + + style = &m_styles[style_id]; + if(curr_cell->x == style->last_x) + { + cell = &m_cells[style->start_cell + style->num_cells - 1]; + cell->area -= curr_cell->area; + cell->cover -= curr_cell->cover; + } + else + { + cell = &m_cells[style->start_cell + style->num_cells]; + cell->x = curr_cell->x; + cell->area = -curr_cell->area; + cell->cover = -curr_cell->cover; + style->last_x = curr_cell->x; + style->num_cells++; + } + } + } + if(m_ast.size() > 1) break; + ++m_scan_y; + } + ++m_scan_y; + + if(m_layer_order != layer_unsorted) + { + range_adaptor<pod_vector<unsigned> > ra(m_ast, 1, m_ast.size() - 1); + if(m_layer_order == layer_direct) quick_sort(ra, unsigned_greater); + else quick_sort(ra, unsigned_less); + } + + return m_ast.size() - 1; + } + + //------------------------------------------------------------------------ + // Returns style ID depending of the existing style index + template<class Clip> + AGG_INLINE + unsigned rasterizer_compound_aa<Clip>::style(unsigned style_idx) const + { + return m_ast[style_idx + 1] + m_min_style - 1; + } + + //------------------------------------------------------------------------ + template<class Clip> + AGG_INLINE bool rasterizer_compound_aa<Clip>::navigate_scanline(int y) + { + m_outline.sort_cells(); + if(m_outline.total_cells() == 0) + { + return false; + } + if(m_max_style < m_min_style) + { + return false; + } + if(y < m_outline.min_y() || y > m_outline.max_y()) + { + return false; + } + m_scan_y = y; + m_styles.allocate(m_max_style - m_min_style + 2, 128); + allocate_master_alpha(); + return true; + } + + //------------------------------------------------------------------------ + template<class Clip> + bool rasterizer_compound_aa<Clip>::hit_test(int tx, int ty) + { + if(!navigate_scanline(ty)) + { + return false; + } + + unsigned num_styles = sweep_styles(); + if(num_styles <= 0) + { + return false; + } + + scanline_hit_test sl(tx); + sweep_scanline(sl, -1); + return sl.hit(); + } + + //------------------------------------------------------------------------ + template<class Clip> + cover_type* rasterizer_compound_aa<Clip>::allocate_cover_buffer(unsigned len) + { + m_cover_buf.allocate(len, 256); + return &m_cover_buf[0]; + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::allocate_master_alpha() + { + while((int)m_master_alpha.size() <= m_max_style) + { + m_master_alpha.add(aa_mask); + } + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_compound_aa<Clip>::master_alpha(int style, double alpha) + { + if(style >= 0) + { + while((int)m_master_alpha.size() <= style) + { + m_master_alpha.add(aa_mask); + } + m_master_alpha[style] = uround(alpha * aa_mask); + } + } + +} + + + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_rasterizer_outline.h b/jni/desmume/src/android/agg/include/agg_rasterizer_outline.h new file mode 100755 index 0000000..91bf119 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_rasterizer_outline.h @@ -0,0 +1,157 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_RASTERIZER_OUTLINE_INCLUDED +#define AGG_RASTERIZER_OUTLINE_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //======================================================rasterizer_outline + template<class Renderer> class rasterizer_outline + { + public: + explicit rasterizer_outline(Renderer& ren) : + m_ren(&ren), + m_start_x(0), + m_start_y(0), + m_vertices(0) + {} + void attach(Renderer& ren) { m_ren = &ren; } + + + //-------------------------------------------------------------------- + void move_to(int x, int y) + { + m_vertices = 1; + m_ren->move_to(m_start_x = x, m_start_y = y); + } + + //-------------------------------------------------------------------- + void line_to(int x, int y) + { + ++m_vertices; + m_ren->line_to(x, y); + } + + //-------------------------------------------------------------------- + void move_to_d(double x, double y) + { + move_to(m_ren->coord(x), m_ren->coord(y)); + } + + //-------------------------------------------------------------------- + void line_to_d(double x, double y) + { + line_to(m_ren->coord(x), m_ren->coord(y)); + } + + //-------------------------------------------------------------------- + void close() + { + if(m_vertices > 2) + { + line_to(m_start_x, m_start_y); + } + m_vertices = 0; + } + + //-------------------------------------------------------------------- + void add_vertex(double x, double y, unsigned cmd) + { + if(is_move_to(cmd)) + { + move_to_d(x, y); + } + else + { + if(is_end_poly(cmd)) + { + if(is_closed(cmd)) close(); + } + else + { + line_to_d(x, y); + } + } + } + + + //-------------------------------------------------------------------- + template<class VertexSource> + void add_path(VertexSource& vs, unsigned path_id=0) + { + double x; + double y; + + unsigned cmd; + vs.rewind(path_id); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + add_vertex(x, y, cmd); + } + } + + + //-------------------------------------------------------------------- + template<class VertexSource, class ColorStorage, class PathId> + void render_all_paths(VertexSource& vs, + const ColorStorage& colors, + const PathId& path_id, + unsigned num_paths) + { + for(unsigned i = 0; i < num_paths; i++) + { + m_ren->line_color(colors[i]); + add_path(vs, path_id[i]); + } + } + + + //-------------------------------------------------------------------- + template<class Ctrl> void render_ctrl(Ctrl& c) + { + unsigned i; + for(i = 0; i < c.num_paths(); i++) + { + m_ren->line_color(c.color(i)); + add_path(c, i); + } + } + + + private: + Renderer* m_ren; + int m_start_x; + int m_start_y; + unsigned m_vertices; + }; + + +} + + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_rasterizer_outline_aa.h b/jni/desmume/src/android/agg/include/agg_rasterizer_outline_aa.h new file mode 100755 index 0000000..4d6dd57 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_rasterizer_outline_aa.h @@ -0,0 +1,609 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_RASTERIZER_OUTLINE_AA_INCLUDED +#define AGG_RASTERIZER_OUTLINE_AA_INCLUDED + +#include "agg_basics.h" +#include "agg_line_aa_basics.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + + //------------------------------------------------------------------------- + inline bool cmp_dist_start(int d) { return d > 0; } + inline bool cmp_dist_end(int d) { return d <= 0; } + + + + //-----------------------------------------------------------line_aa_vertex + // Vertex (x, y) with the distance to the next one. The last vertex has + // the distance between the last and the first points + struct line_aa_vertex + { + int x; + int y; + int len; + + line_aa_vertex() {} + line_aa_vertex(int x_, int y_) : + x(x_), + y(y_), + len(0) + { + } + + bool operator () (const line_aa_vertex& val) + { + double dx = val.x - x; + double dy = val.y - y; + return (len = uround(sqrt(dx * dx + dy * dy))) > + (line_subpixel_scale + line_subpixel_scale / 2); + } + }; + + + //----------------------------------------------------------outline_aa_join_e + enum outline_aa_join_e + { + outline_no_join, //-----outline_no_join + outline_miter_join, //-----outline_miter_join + outline_round_join, //-----outline_round_join + outline_miter_accurate_join //-----outline_accurate_join + }; + + //=======================================================rasterizer_outline_aa + template<class Renderer, class Coord=line_coord> class rasterizer_outline_aa + { + private: + //------------------------------------------------------------------------ + struct draw_vars + { + unsigned idx; + int x1, y1, x2, y2; + line_parameters curr, next; + int lcurr, lnext; + int xb1, yb1, xb2, yb2; + unsigned flags; + }; + + void draw(draw_vars& dv, unsigned start, unsigned end); + + public: + typedef line_aa_vertex vertex_type; + typedef vertex_sequence<vertex_type, 6> vertex_storage_type; + + explicit rasterizer_outline_aa(Renderer& ren) : + m_ren(&ren), + m_line_join(ren.accurate_join_only() ? + outline_miter_accurate_join : + outline_round_join), + m_round_cap(false), + m_start_x(0), + m_start_y(0) + {} + void attach(Renderer& ren) { m_ren = &ren; } + + //------------------------------------------------------------------------ + void line_join(outline_aa_join_e join) + { + m_line_join = m_ren->accurate_join_only() ? + outline_miter_accurate_join : + join; + } + bool line_join() const { return m_line_join; } + + //------------------------------------------------------------------------ + void round_cap(bool v) { m_round_cap = v; } + bool round_cap() const { return m_round_cap; } + + //------------------------------------------------------------------------ + void move_to(int x, int y) + { + m_src_vertices.modify_last(vertex_type(m_start_x = x, m_start_y = y)); + } + + //------------------------------------------------------------------------ + void line_to(int x, int y) + { + m_src_vertices.add(vertex_type(x, y)); + } + + //------------------------------------------------------------------------ + void move_to_d(double x, double y) + { + move_to(Coord::conv(x), Coord::conv(y)); + } + + //------------------------------------------------------------------------ + void line_to_d(double x, double y) + { + line_to(Coord::conv(x), Coord::conv(y)); + } + + //------------------------------------------------------------------------ + void render(bool close_polygon); + + //------------------------------------------------------------------------ + void add_vertex(double x, double y, unsigned cmd) + { + if(is_move_to(cmd)) + { + render(false); + move_to_d(x, y); + } + else + { + if(is_end_poly(cmd)) + { + render(is_closed(cmd)); + if(is_closed(cmd)) + { + move_to(m_start_x, m_start_y); + } + } + else + { + line_to_d(x, y); + } + } + } + + //------------------------------------------------------------------------ + template<class VertexSource> + void add_path(VertexSource& vs, unsigned path_id=0) + { + double x; + double y; + + unsigned cmd; + vs.rewind(path_id); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + add_vertex(x, y, cmd); + } + render(false); + } + + + //------------------------------------------------------------------------ + template<class VertexSource, class ColorStorage, class PathId> + void render_all_paths(VertexSource& vs, + const ColorStorage& colors, + const PathId& path_id, + unsigned num_paths) + { + for(unsigned i = 0; i < num_paths; i++) + { + m_ren->color(colors[i]); + add_path(vs, path_id[i]); + } + } + + + //------------------------------------------------------------------------ + template<class Ctrl> void render_ctrl(Ctrl& c) + { + unsigned i; + for(i = 0; i < c.num_paths(); i++) + { + m_ren->color(c.color(i)); + add_path(c, i); + } + } + + private: + rasterizer_outline_aa(const rasterizer_outline_aa<Renderer, Coord>&); + const rasterizer_outline_aa<Renderer, Coord>& operator = + (const rasterizer_outline_aa<Renderer, Coord>&); + + Renderer* m_ren; + vertex_storage_type m_src_vertices; + outline_aa_join_e m_line_join; + bool m_round_cap; + int m_start_x; + int m_start_y; + }; + + + + + + + + + //---------------------------------------------------------------------------- + template<class Renderer, class Coord> + void rasterizer_outline_aa<Renderer, Coord>::draw(draw_vars& dv, + unsigned start, + unsigned end) + { + unsigned i; + const vertex_storage_type::value_type* v; + + for(i = start; i < end; i++) + { + if(m_line_join == outline_round_join) + { + dv.xb1 = dv.curr.x1 + (dv.curr.y2 - dv.curr.y1); + dv.yb1 = dv.curr.y1 - (dv.curr.x2 - dv.curr.x1); + dv.xb2 = dv.curr.x2 + (dv.curr.y2 - dv.curr.y1); + dv.yb2 = dv.curr.y2 - (dv.curr.x2 - dv.curr.x1); + } + + switch(dv.flags) + { + case 0: m_ren->line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break; + case 1: m_ren->line2(dv.curr, dv.xb2, dv.yb2); break; + case 2: m_ren->line1(dv.curr, dv.xb1, dv.yb1); break; + case 3: m_ren->line0(dv.curr); break; + } + + if(m_line_join == outline_round_join && (dv.flags & 2) == 0) + { + m_ren->pie(dv.curr.x2, dv.curr.y2, + dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y2 - (dv.curr.x2 - dv.curr.x1), + dv.curr.x2 + (dv.next.y2 - dv.next.y1), + dv.curr.y2 - (dv.next.x2 - dv.next.x1)); + } + + dv.x1 = dv.x2; + dv.y1 = dv.y2; + dv.lcurr = dv.lnext; + dv.lnext = m_src_vertices[dv.idx].len; + + ++dv.idx; + if(dv.idx >= m_src_vertices.size()) dv.idx = 0; + + v = &m_src_vertices[dv.idx]; + dv.x2 = v->x; + dv.y2 = v->y; + + dv.curr = dv.next; + dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext); + dv.xb1 = dv.xb2; + dv.yb1 = dv.yb2; + + switch(m_line_join) + { + case outline_no_join: + dv.flags = 3; + break; + + case outline_miter_join: + dv.flags >>= 1; + dv.flags |= ((dv.curr.diagonal_quadrant() == + dv.next.diagonal_quadrant()) << 1); + if((dv.flags & 2) == 0) + { + bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); + } + break; + + case outline_round_join: + dv.flags >>= 1; + dv.flags |= ((dv.curr.diagonal_quadrant() == + dv.next.diagonal_quadrant()) << 1); + break; + + case outline_miter_accurate_join: + dv.flags = 0; + bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); + break; + } + } + } + + + + + //---------------------------------------------------------------------------- + template<class Renderer, class Coord> + void rasterizer_outline_aa<Renderer, Coord>::render(bool close_polygon) + { + m_src_vertices.close(close_polygon); + draw_vars dv; + const vertex_storage_type::value_type* v; + int x1; + int y1; + int x2; + int y2; + int lprev; + + if(close_polygon) + { + if(m_src_vertices.size() >= 3) + { + dv.idx = 2; + + v = &m_src_vertices[m_src_vertices.size() - 1]; + x1 = v->x; + y1 = v->y; + lprev = v->len; + + v = &m_src_vertices[0]; + x2 = v->x; + y2 = v->y; + dv.lcurr = v->len; + line_parameters prev(x1, y1, x2, y2, lprev); + + v = &m_src_vertices[1]; + dv.x1 = v->x; + dv.y1 = v->y; + dv.lnext = v->len; + dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr); + + v = &m_src_vertices[dv.idx]; + dv.x2 = v->x; + dv.y2 = v->y; + dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext); + + dv.xb1 = 0; + dv.yb1 = 0; + dv.xb2 = 0; + dv.yb2 = 0; + + switch(m_line_join) + { + case outline_no_join: + dv.flags = 3; + break; + + case outline_miter_join: + case outline_round_join: + dv.flags = + (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) | + ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); + break; + + case outline_miter_accurate_join: + dv.flags = 0; + break; + } + + if((dv.flags & 1) == 0 && m_line_join != outline_round_join) + { + bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); + } + + if((dv.flags & 2) == 0 && m_line_join != outline_round_join) + { + bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); + } + draw(dv, 0, m_src_vertices.size()); + } + } + else + { + switch(m_src_vertices.size()) + { + case 0: + case 1: + break; + + case 2: + { + v = &m_src_vertices[0]; + x1 = v->x; + y1 = v->y; + lprev = v->len; + v = &m_src_vertices[1]; + x2 = v->x; + y2 = v->y; + line_parameters lp(x1, y1, x2, y2, lprev); + if(m_round_cap) + { + m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); + } + m_ren->line3(lp, + x1 + (y2 - y1), + y1 - (x2 - x1), + x2 + (y2 - y1), + y2 - (x2 - x1)); + if(m_round_cap) + { + m_ren->semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1)); + } + } + break; + + case 3: + { + int x3, y3; + int lnext; + v = &m_src_vertices[0]; + x1 = v->x; + y1 = v->y; + lprev = v->len; + v = &m_src_vertices[1]; + x2 = v->x; + y2 = v->y; + lnext = v->len; + v = &m_src_vertices[2]; + x3 = v->x; + y3 = v->y; + line_parameters lp1(x1, y1, x2, y2, lprev); + line_parameters lp2(x2, y2, x3, y3, lnext); + + if(m_round_cap) + { + m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); + } + + if(m_line_join == outline_round_join) + { + m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1), + x2 + (y2 - y1), y2 - (x2 - x1)); + + m_ren->pie(x2, y2, x2 + (y2 - y1), y2 - (x2 - x1), + x2 + (y3 - y2), y2 - (x3 - x2)); + + m_ren->line3(lp2, x2 + (y3 - y2), y2 - (x3 - x2), + x3 + (y3 - y2), y3 - (x3 - x2)); + } + else + { + bisectrix(lp1, lp2, &dv.xb1, &dv.yb1); + m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1), + dv.xb1, dv.yb1); + + m_ren->line3(lp2, dv.xb1, dv.yb1, + x3 + (y3 - y2), y3 - (x3 - x2)); + } + if(m_round_cap) + { + m_ren->semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2)); + } + } + break; + + default: + { + dv.idx = 3; + + v = &m_src_vertices[0]; + x1 = v->x; + y1 = v->y; + lprev = v->len; + + v = &m_src_vertices[1]; + x2 = v->x; + y2 = v->y; + dv.lcurr = v->len; + line_parameters prev(x1, y1, x2, y2, lprev); + + v = &m_src_vertices[2]; + dv.x1 = v->x; + dv.y1 = v->y; + dv.lnext = v->len; + dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr); + + v = &m_src_vertices[dv.idx]; + dv.x2 = v->x; + dv.y2 = v->y; + dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext); + + dv.xb1 = 0; + dv.yb1 = 0; + dv.xb2 = 0; + dv.yb2 = 0; + + switch(m_line_join) + { + case outline_no_join: + dv.flags = 3; + break; + + case outline_miter_join: + case outline_round_join: + dv.flags = + (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) | + ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); + break; + + case outline_miter_accurate_join: + dv.flags = 0; + break; + } + + if(m_round_cap) + { + m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); + } + if((dv.flags & 1) == 0) + { + if(m_line_join == outline_round_join) + { + m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), + x2 + (y2 - y1), y2 - (x2 - x1)); + m_ren->pie(prev.x2, prev.y2, + x2 + (y2 - y1), y2 - (x2 - x1), + dv.curr.x1 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y1 - (dv.curr.x2 - dv.curr.x1)); + } + else + { + bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); + m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), + dv.xb1, dv.yb1); + } + } + else + { + m_ren->line1(prev, + x1 + (y2 - y1), + y1 - (x2 - x1)); + } + if((dv.flags & 2) == 0 && m_line_join != outline_round_join) + { + bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); + } + + draw(dv, 1, m_src_vertices.size() - 2); + + if((dv.flags & 1) == 0) + { + if(m_line_join == outline_round_join) + { + m_ren->line3(dv.curr, + dv.curr.x1 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y1 - (dv.curr.x2 - dv.curr.x1), + dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); + } + else + { + m_ren->line3(dv.curr, dv.xb1, dv.yb1, + dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); + } + } + else + { + m_ren->line2(dv.curr, + dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); + } + if(m_round_cap) + { + m_ren->semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2, + dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); + } + + } + break; + } + } + m_src_vertices.remove_all(); + } + + +} + + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_rasterizer_scanline_aa.h b/jni/desmume/src/android/agg/include/agg_rasterizer_scanline_aa.h new file mode 100755 index 0000000..80e138c --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_rasterizer_scanline_aa.h @@ -0,0 +1,520 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// The author gratefully acknowleges the support of David Turner, +// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType +// libray - in producing this work. See http://www.freetype.org for details. +// +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_RASTERIZER_SCANLINE_AA_INCLUDED +#define AGG_RASTERIZER_SCANLINE_AA_INCLUDED + +#include "agg_rasterizer_cells_aa.h" +#include "agg_rasterizer_sl_clip.h" +#include "agg_gamma_functions.h" + + +namespace agg +{ + + + //-----------------------------------------------------------------cell_aa + // A pixel cell. There're no constructors defined and it was done + // intentionally in order to avoid extra overhead when allocating an + // array of cells. + struct cell_aa + { + int x; + int y; + int cover; + int area; + + void initial() + { + x = 0x7FFFFFFF; + y = 0x7FFFFFFF; + cover = 0; + area = 0; + } + + void style(const cell_aa&) {} + + int not_equal(int ex, int ey, const cell_aa&) const + { + return (ex - x) | (ey - y); + } + }; + + + //==================================================rasterizer_scanline_aa + // Polygon rasterizer that is used to render filled polygons with + // high-quality Anti-Aliasing. Internally, by default, the class uses + // integer coordinates in format 24.8, i.e. 24 bits for integer part + // and 8 bits for fractional - see poly_subpixel_shift. This class can be + // used in the following way: + // + // 1. filling_rule(filling_rule_e ft) - optional. + // + // 2. gamma() - optional. + // + // 3. reset() + // + // 4. move_to(x, y) / line_to(x, y) - make the polygon. One can create + // more than one contour, but each contour must consist of at least 3 + // vertices, i.e. move_to(x1, y1); line_to(x2, y2); line_to(x3, y3); + // is the absolute minimum of vertices that define a triangle. + // The algorithm does not check either the number of vertices nor + // coincidence of their coordinates, but in the worst case it just + // won't draw anything. + // The orger of the vertices (clockwise or counterclockwise) + // is important when using the non-zero filling rule (fill_non_zero). + // In this case the vertex order of all the contours must be the same + // if you want your intersecting polygons to be without "holes". + // You actually can use different vertices order. If the contours do not + // intersect each other the order is not important anyway. If they do, + // contours with the same vertex order will be rendered without "holes" + // while the intersecting contours with different orders will have "holes". + // + // filling_rule() and gamma() can be called anytime before "sweeping". + //------------------------------------------------------------------------ + template<class Clip=rasterizer_sl_clip_int> class rasterizer_scanline_aa + { + enum status + { + status_initial, + status_move_to, + status_line_to, + status_closed + }; + + public: + typedef Clip clip_type; + typedef typename Clip::conv_type conv_type; + typedef typename Clip::coord_type coord_type; + + enum aa_scale_e + { + aa_shift = 8, + aa_scale = 1 << aa_shift, + aa_mask = aa_scale - 1, + aa_scale2 = aa_scale * 2, + aa_mask2 = aa_scale2 - 1 + }; + + //-------------------------------------------------------------------- + rasterizer_scanline_aa() : + m_outline(), + m_clipper(), + m_filling_rule(fill_non_zero), + m_auto_close(true), + m_start_x(0), + m_start_y(0), + m_status(status_initial) + { + int i; + for(i = 0; i < aa_scale; i++) m_gamma[i] = i; + } + + //-------------------------------------------------------------------- + template<class GammaF> + rasterizer_scanline_aa(const GammaF& gamma_function) : + m_outline(), + m_clipper(m_outline), + m_filling_rule(fill_non_zero), + m_auto_close(true), + m_start_x(0), + m_start_y(0), + m_status(status_initial) + { + gamma(gamma_function); + } + + //-------------------------------------------------------------------- + void reset(); + void reset_clipping(); + void clip_box(double x1, double y1, double x2, double y2); + void filling_rule(filling_rule_e filling_rule); + void auto_close(bool flag) { m_auto_close = flag; } + + //-------------------------------------------------------------------- + template<class GammaF> void gamma(const GammaF& gamma_function) + { + int i; + for(i = 0; i < aa_scale; i++) + { + m_gamma[i] = uround(gamma_function(double(i) / aa_mask) * aa_mask); + } + } + + //-------------------------------------------------------------------- + unsigned apply_gamma(unsigned cover) const + { + return m_gamma[cover]; + } + + //-------------------------------------------------------------------- + void move_to(int x, int y); + void line_to(int x, int y); + void move_to_d(double x, double y); + void line_to_d(double x, double y); + void close_polygon(); + void add_vertex(double x, double y, unsigned cmd); + + void edge(int x1, int y1, int x2, int y2); + void edge_d(double x1, double y1, double x2, double y2); + + //------------------------------------------------------------------- + template<class VertexSource> + void add_path(VertexSource& vs, unsigned path_id=0) + { + double x; + double y; + + unsigned cmd; + vs.rewind(path_id); + if(m_outline.sorted()) reset(); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + add_vertex(x, y, cmd); + } + } + + //-------------------------------------------------------------------- + int min_x() const { return m_outline.min_x(); } + int min_y() const { return m_outline.min_y(); } + int max_x() const { return m_outline.max_x(); } + int max_y() const { return m_outline.max_y(); } + + //-------------------------------------------------------------------- + void sort(); + bool rewind_scanlines(); + bool navigate_scanline(int y); + + //-------------------------------------------------------------------- + AGG_INLINE unsigned calculate_alpha(int area) const + { + int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift); + + if(cover < 0) cover = -cover; + if(m_filling_rule == fill_even_odd) + { + cover &= aa_mask2; + if(cover > aa_scale) + { + cover = aa_scale2 - cover; + } + } + if(cover > aa_mask) cover = aa_mask; + return m_gamma[cover]; + } + + //-------------------------------------------------------------------- + template<class Scanline> bool sweep_scanline(Scanline& sl) + { + for(;;) + { + if(m_scan_y > m_outline.max_y()) return false; + sl.reset_spans(); + unsigned num_cells = m_outline.scanline_num_cells(m_scan_y); + const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y); + int cover = 0; + + while(num_cells) + { + const cell_aa* cur_cell = *cells; + int x = cur_cell->x; + int area = cur_cell->area; + unsigned alpha; + + cover += cur_cell->cover; + + //accumulate all cells with the same X + while(--num_cells) + { + cur_cell = *++cells; + if(cur_cell->x != x) break; + area += cur_cell->area; + cover += cur_cell->cover; + } + + if(area) + { + alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area); + if(alpha) + { + sl.add_cell(x, alpha); + } + x++; + } + + if(num_cells && cur_cell->x > x) + { + alpha = calculate_alpha(cover << (poly_subpixel_shift + 1)); + if(alpha) + { + sl.add_span(x, cur_cell->x - x, alpha); + } + } + } + + if(sl.num_spans()) break; + ++m_scan_y; + } + + sl.finalize(m_scan_y); + ++m_scan_y; + return true; + } + + //-------------------------------------------------------------------- + bool hit_test(int tx, int ty); + + + private: + //-------------------------------------------------------------------- + // Disable copying + rasterizer_scanline_aa(const rasterizer_scanline_aa<Clip>&); + const rasterizer_scanline_aa<Clip>& + operator = (const rasterizer_scanline_aa<Clip>&); + + private: + rasterizer_cells_aa<cell_aa> m_outline; + clip_type m_clipper; + int m_gamma[aa_scale]; + filling_rule_e m_filling_rule; + bool m_auto_close; + coord_type m_start_x; + coord_type m_start_y; + unsigned m_status; + int m_scan_y; + }; + + + + + + + + + + + + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_scanline_aa<Clip>::reset() + { + m_outline.reset(); + m_status = status_initial; + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_scanline_aa<Clip>::filling_rule(filling_rule_e filling_rule) + { + m_filling_rule = filling_rule; + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_scanline_aa<Clip>::clip_box(double x1, double y1, + double x2, double y2) + { + reset(); + m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1), + conv_type::upscale(x2), conv_type::upscale(y2)); + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_scanline_aa<Clip>::reset_clipping() + { + reset(); + m_clipper.reset_clipping(); + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_scanline_aa<Clip>::close_polygon() + { + if(m_status == status_line_to) + { + m_clipper.line_to(m_outline, m_start_x, m_start_y); + m_status = status_closed; + } + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_scanline_aa<Clip>::move_to(int x, int y) + { + if(m_outline.sorted()) reset(); + if(m_auto_close) close_polygon(); + m_clipper.move_to(m_start_x = conv_type::downscale(x), + m_start_y = conv_type::downscale(y)); + m_status = status_move_to; + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_scanline_aa<Clip>::line_to(int x, int y) + { + m_clipper.line_to(m_outline, + conv_type::downscale(x), + conv_type::downscale(y)); + m_status = status_line_to; + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_scanline_aa<Clip>::move_to_d(double x, double y) + { + if(m_outline.sorted()) reset(); + if(m_auto_close) close_polygon(); + m_clipper.move_to(m_start_x = conv_type::upscale(x), + m_start_y = conv_type::upscale(y)); + m_status = status_move_to; + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_scanline_aa<Clip>::line_to_d(double x, double y) + { + m_clipper.line_to(m_outline, + conv_type::upscale(x), + conv_type::upscale(y)); + m_status = status_line_to; + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_scanline_aa<Clip>::add_vertex(double x, double y, unsigned cmd) + { + if(is_move_to(cmd)) + { + move_to_d(x, y); + } + else + if(is_vertex(cmd)) + { + line_to_d(x, y); + } + else + if(is_close(cmd)) + { + close_polygon(); + } + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_scanline_aa<Clip>::edge(int x1, int y1, int x2, int y2) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1)); + m_clipper.line_to(m_outline, + conv_type::downscale(x2), + conv_type::downscale(y2)); + m_status = status_move_to; + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_scanline_aa<Clip>::edge_d(double x1, double y1, + double x2, double y2) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1)); + m_clipper.line_to(m_outline, + conv_type::upscale(x2), + conv_type::upscale(y2)); + m_status = status_move_to; + } + + //------------------------------------------------------------------------ + template<class Clip> + void rasterizer_scanline_aa<Clip>::sort() + { + if(m_auto_close) close_polygon(); + m_outline.sort_cells(); + } + + //------------------------------------------------------------------------ + template<class Clip> + AGG_INLINE bool rasterizer_scanline_aa<Clip>::rewind_scanlines() + { + if(m_auto_close) close_polygon(); + m_outline.sort_cells(); + if(m_outline.total_cells() == 0) + { + return false; + } + m_scan_y = m_outline.min_y(); + return true; + } + + + //------------------------------------------------------------------------ + template<class Clip> + AGG_INLINE bool rasterizer_scanline_aa<Clip>::navigate_scanline(int y) + { + if(m_auto_close) close_polygon(); + m_outline.sort_cells(); + if(m_outline.total_cells() == 0 || + y < m_outline.min_y() || + y > m_outline.max_y()) + { + return false; + } + m_scan_y = y; + return true; + } + + //------------------------------------------------------------------------ + template<class Clip> + bool rasterizer_scanline_aa<Clip>::hit_test(int tx, int ty) + { + if(!navigate_scanline(ty)) return false; + scanline_hit_test sl(tx); + sweep_scanline(sl); + return sl.hit(); + } + + + +} + + + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_rasterizer_sl_clip.h b/jni/desmume/src/android/agg/include/agg_rasterizer_sl_clip.h new file mode 100755 index 0000000..cdfee1a --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_rasterizer_sl_clip.h @@ -0,0 +1,361 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_RASTERIZER_SL_CLIP_INCLUDED +#define AGG_RASTERIZER_SL_CLIP_INCLUDED + +#include "agg_clip_liang_barsky.h" + +namespace agg +{ + //--------------------------------------------------------poly_max_coord_e + enum poly_max_coord_e + { + poly_max_coord = (1 << 30) - 1 //----poly_max_coord + }; + + //------------------------------------------------------------ras_conv_int + struct ras_conv_int + { + typedef int coord_type; + static AGG_INLINE int mul_div(double a, double b, double c) + { + return iround(a * b / c); + } + static int xi(int v) { return v; } + static int yi(int v) { return v; } + static int upscale(double v) { return iround(v * poly_subpixel_scale); } + static int downscale(int v) { return v; } + }; + + //--------------------------------------------------------ras_conv_int_sat + struct ras_conv_int_sat + { + typedef int coord_type; + static AGG_INLINE int mul_div(double a, double b, double c) + { + return saturation<poly_max_coord>::iround(a * b / c); + } + static int xi(int v) { return v; } + static int yi(int v) { return v; } + static int upscale(double v) + { + return saturation<poly_max_coord>::iround(v * poly_subpixel_scale); + } + static int downscale(int v) { return v; } + }; + + //---------------------------------------------------------ras_conv_int_3x + struct ras_conv_int_3x + { + typedef int coord_type; + static AGG_INLINE int mul_div(double a, double b, double c) + { + return iround(a * b / c); + } + static int xi(int v) { return v * 3; } + static int yi(int v) { return v; } + static int upscale(double v) { return iround(v * poly_subpixel_scale); } + static int downscale(int v) { return v; } + }; + + //-----------------------------------------------------------ras_conv_dbl + struct ras_conv_dbl + { + typedef double coord_type; + static AGG_INLINE double mul_div(double a, double b, double c) + { + return a * b / c; + } + static int xi(double v) { return iround(v * poly_subpixel_scale); } + static int yi(double v) { return iround(v * poly_subpixel_scale); } + static double upscale(double v) { return v; } + static double downscale(int v) { return v / double(poly_subpixel_scale); } + }; + + //--------------------------------------------------------ras_conv_dbl_3x + struct ras_conv_dbl_3x + { + typedef double coord_type; + static AGG_INLINE double mul_div(double a, double b, double c) + { + return a * b / c; + } + static int xi(double v) { return iround(v * poly_subpixel_scale * 3); } + static int yi(double v) { return iround(v * poly_subpixel_scale); } + static double upscale(double v) { return v; } + static double downscale(int v) { return v / double(poly_subpixel_scale); } + }; + + + + + + //------------------------------------------------------rasterizer_sl_clip + template<class Conv> class rasterizer_sl_clip + { + public: + typedef Conv conv_type; + typedef typename Conv::coord_type coord_type; + typedef rect_base<coord_type> rect_type; + + //-------------------------------------------------------------------- + rasterizer_sl_clip() : + m_clip_box(0,0,0,0), + m_x1(0), + m_y1(0), + m_f1(0), + m_clipping(false) + {} + + //-------------------------------------------------------------------- + void reset_clipping() + { + m_clipping = false; + } + + //-------------------------------------------------------------------- + void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2) + { + m_clip_box = rect_type(x1, y1, x2, y2); + m_clip_box.normalize(); + m_clipping = true; + } + + //-------------------------------------------------------------------- + void move_to(coord_type x1, coord_type y1) + { + m_x1 = x1; + m_y1 = y1; + if(m_clipping) m_f1 = clipping_flags(x1, y1, m_clip_box); + } + + private: + //------------------------------------------------------------------------ + template<class Rasterizer> + AGG_INLINE void line_clip_y(Rasterizer& ras, + coord_type x1, coord_type y1, + coord_type x2, coord_type y2, + unsigned f1, unsigned f2) const + { + f1 &= 10; + f2 &= 10; + if((f1 | f2) == 0) + { + // Fully visible + ras.line(Conv::xi(x1), Conv::yi(y1), Conv::xi(x2), Conv::yi(y2)); + } + else + { + if(f1 == f2) + { + // Invisible by Y + return; + } + + coord_type tx1 = x1; + coord_type ty1 = y1; + coord_type tx2 = x2; + coord_type ty2 = y2; + + if(f1 & 8) // y1 < clip.y1 + { + tx1 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1); + ty1 = m_clip_box.y1; + } + + if(f1 & 2) // y1 > clip.y2 + { + tx1 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1); + ty1 = m_clip_box.y2; + } + + if(f2 & 8) // y2 < clip.y1 + { + tx2 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1); + ty2 = m_clip_box.y1; + } + + if(f2 & 2) // y2 > clip.y2 + { + tx2 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1); + ty2 = m_clip_box.y2; + } + ras.line(Conv::xi(tx1), Conv::yi(ty1), + Conv::xi(tx2), Conv::yi(ty2)); + } + } + + + public: + //-------------------------------------------------------------------- + template<class Rasterizer> + void line_to(Rasterizer& ras, coord_type x2, coord_type y2) + { + if(m_clipping) + { + unsigned f2 = clipping_flags(x2, y2, m_clip_box); + + if((m_f1 & 10) == (f2 & 10) && (m_f1 & 10) != 0) + { + // Invisible by Y + m_x1 = x2; + m_y1 = y2; + m_f1 = f2; + return; + } + + coord_type x1 = m_x1; + coord_type y1 = m_y1; + unsigned f1 = m_f1; + coord_type y3, y4; + unsigned f3, f4; + + switch(((f1 & 5) << 1) | (f2 & 5)) + { + case 0: // Visible by X + line_clip_y(ras, x1, y1, x2, y2, f1, f2); + break; + + case 1: // x2 > clip.x2 + y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + line_clip_y(ras, x1, y1, m_clip_box.x2, y3, f1, f3); + line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x2, y2, f3, f2); + break; + + case 2: // x1 > clip.x2 + y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3); + line_clip_y(ras, m_clip_box.x2, y3, x2, y2, f3, f2); + break; + + case 3: // x1 > clip.x2 && x2 > clip.x2 + line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y2, f1, f2); + break; + + case 4: // x2 < clip.x1 + y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + line_clip_y(ras, x1, y1, m_clip_box.x1, y3, f1, f3); + line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x1, y2, f3, f2); + break; + + case 6: // x1 > clip.x2 && x2 < clip.x1 + y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); + y4 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + f4 = clipping_flags_y(y4, m_clip_box); + line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3); + line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x1, y4, f3, f4); + line_clip_y(ras, m_clip_box.x1, y4, m_clip_box.x1, y2, f4, f2); + break; + + case 8: // x1 < clip.x1 + y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3); + line_clip_y(ras, m_clip_box.x1, y3, x2, y2, f3, f2); + break; + + case 9: // x1 < clip.x1 && x2 > clip.x2 + y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); + y4 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + f4 = clipping_flags_y(y4, m_clip_box); + line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3); + line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x2, y4, f3, f4); + line_clip_y(ras, m_clip_box.x2, y4, m_clip_box.x2, y2, f4, f2); + break; + + case 12: // x1 < clip.x1 && x2 < clip.x1 + line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y2, f1, f2); + break; + } + m_f1 = f2; + } + else + { + ras.line(Conv::xi(m_x1), Conv::yi(m_y1), + Conv::xi(x2), Conv::yi(y2)); + } + m_x1 = x2; + m_y1 = y2; + } + + + private: + rect_type m_clip_box; + coord_type m_x1; + coord_type m_y1; + unsigned m_f1; + bool m_clipping; + }; + + + + + //---------------------------------------------------rasterizer_sl_no_clip + class rasterizer_sl_no_clip + { + public: + typedef ras_conv_int conv_type; + typedef int coord_type; + + rasterizer_sl_no_clip() : m_x1(0), m_y1(0) {} + + void reset_clipping() {} + void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2) {} + void move_to(coord_type x1, coord_type y1) { m_x1 = x1; m_y1 = y1; } + + template<class Rasterizer> + void line_to(Rasterizer& ras, coord_type x2, coord_type y2) + { + ras.line(m_x1, m_y1, x2, y2); + m_x1 = x2; + m_y1 = y2; + } + + private: + int m_x1, m_y1; + }; + + + // -----rasterizer_sl_clip_int + // -----rasterizer_sl_clip_int_sat + // -----rasterizer_sl_clip_int_3x + // -----rasterizer_sl_clip_dbl + // -----rasterizer_sl_clip_dbl_3x + //------------------------------------------------------------------------ + typedef rasterizer_sl_clip<ras_conv_int> rasterizer_sl_clip_int; + typedef rasterizer_sl_clip<ras_conv_int_sat> rasterizer_sl_clip_int_sat; + typedef rasterizer_sl_clip<ras_conv_int_3x> rasterizer_sl_clip_int_3x; + typedef rasterizer_sl_clip<ras_conv_dbl> rasterizer_sl_clip_dbl; + typedef rasterizer_sl_clip<ras_conv_dbl_3x> rasterizer_sl_clip_dbl_3x; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_renderer_base.h b/jni/desmume/src/android/agg/include/agg_renderer_base.h new file mode 100755 index 0000000..1808944 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_renderer_base.h @@ -0,0 +1,723 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERER_BASE_INCLUDED +#define AGG_RENDERER_BASE_INCLUDED + +#include "agg_basics.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + + //-----------------------------------------------------------renderer_base + template<class PixelFormat> class renderer_base + { + public: + typedef PixelFormat pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::row_data row_data; + + //-------------------------------------------------------------------- + renderer_base() : m_ren(0), m_clip_box(1, 1, 0, 0) {} + explicit renderer_base(pixfmt_type& ren) : + m_ren(&ren), + m_clip_box(0, 0, ren.width() - 1, ren.height() - 1) + {} + void attach(pixfmt_type& ren) + { + m_ren = &ren; + m_clip_box = rect_i(0, 0, ren.width() - 1, ren.height() - 1); + } + + //-------------------------------------------------------------------- + const pixfmt_type& ren() const { return *m_ren; } + pixfmt_type& ren() { return *m_ren; } + + //-------------------------------------------------------------------- + unsigned width() const { return m_ren->width(); } + unsigned height() const { return m_ren->height(); } + + //-------------------------------------------------------------------- + bool clip_box(int x1, int y1, int x2, int y2) + { + rect_i cb(x1, y1, x2, y2); + cb.normalize(); + if(cb.clip(rect_i(0, 0, width() - 1, height() - 1))) + { + m_clip_box = cb; + return true; + } + m_clip_box.x1 = 1; + m_clip_box.y1 = 1; + m_clip_box.x2 = 0; + m_clip_box.y2 = 0; + return false; + } + + //-------------------------------------------------------------------- + void reset_clipping(bool visibility) + { + if(visibility) + { + m_clip_box.x1 = 0; + m_clip_box.y1 = 0; + m_clip_box.x2 = width() - 1; + m_clip_box.y2 = height() - 1; + } + else + { + m_clip_box.x1 = 1; + m_clip_box.y1 = 1; + m_clip_box.x2 = 0; + m_clip_box.y2 = 0; + } + } + + //-------------------------------------------------------------------- + void clip_box_naked(int x1, int y1, int x2, int y2) + { + m_clip_box.x1 = x1; + m_clip_box.y1 = y1; + m_clip_box.x2 = x2; + m_clip_box.y2 = y2; + } + + //-------------------------------------------------------------------- + bool inbox(int x, int y) const + { + return x >= m_clip_box.x1 && y >= m_clip_box.y1 && + x <= m_clip_box.x2 && y <= m_clip_box.y2; + } + + //-------------------------------------------------------------------- + const rect_i& clip_box() const { return m_clip_box; } + int xmin() const { return m_clip_box.x1; } + int ymin() const { return m_clip_box.y1; } + int xmax() const { return m_clip_box.x2; } + int ymax() const { return m_clip_box.y2; } + + //-------------------------------------------------------------------- + const rect_i& bounding_clip_box() const { return m_clip_box; } + int bounding_xmin() const { return m_clip_box.x1; } + int bounding_ymin() const { return m_clip_box.y1; } + int bounding_xmax() const { return m_clip_box.x2; } + int bounding_ymax() const { return m_clip_box.y2; } + + //-------------------------------------------------------------------- + void clear(const color_type& c) + { + unsigned y; + if(width()) + { + for(y = 0; y < height(); y++) + { + m_ren->copy_hline(0, y, width(), c); + } + } + } + + + //-------------------------------------------------------------------- + void copy_pixel(int x, int y, const color_type& c) + { + if(inbox(x, y)) + { + m_ren->copy_pixel(x, y, c); + } + } + + //-------------------------------------------------------------------- + void blend_pixel(int x, int y, const color_type& c, cover_type cover) + { + if(inbox(x, y)) + { + m_ren->blend_pixel(x, y, c, cover); + } + } + + //-------------------------------------------------------------------- + color_type pixel(int x, int y) const + { + return inbox(x, y) ? + m_ren->pixel(x, y) : + color_type::no_color(); + } + + //-------------------------------------------------------------------- + void copy_hline(int x1, int y, int x2, const color_type& c) + { + if(x1 > x2) { int t = x2; x2 = x1; x1 = t; } + if(y > ymax()) return; + if(y < ymin()) return; + if(x1 > xmax()) return; + if(x2 < xmin()) return; + + if(x1 < xmin()) x1 = xmin(); + if(x2 > xmax()) x2 = xmax(); + + m_ren->copy_hline(x1, y, x2 - x1 + 1, c); + } + + //-------------------------------------------------------------------- + void copy_vline(int x, int y1, int y2, const color_type& c) + { + if(y1 > y2) { int t = y2; y2 = y1; y1 = t; } + if(x > xmax()) return; + if(x < xmin()) return; + if(y1 > ymax()) return; + if(y2 < ymin()) return; + + if(y1 < ymin()) y1 = ymin(); + if(y2 > ymax()) y2 = ymax(); + + m_ren->copy_vline(x, y1, y2 - y1 + 1, c); + } + + //-------------------------------------------------------------------- + void blend_hline(int x1, int y, int x2, + const color_type& c, cover_type cover) + { + if(x1 > x2) { int t = x2; x2 = x1; x1 = t; } + if(y > ymax()) return; + if(y < ymin()) return; + if(x1 > xmax()) return; + if(x2 < xmin()) return; + + if(x1 < xmin()) x1 = xmin(); + if(x2 > xmax()) x2 = xmax(); + + m_ren->blend_hline(x1, y, x2 - x1 + 1, c, cover); + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y1, int y2, + const color_type& c, cover_type cover) + { + if(y1 > y2) { int t = y2; y2 = y1; y1 = t; } + if(x > xmax()) return; + if(x < xmin()) return; + if(y1 > ymax()) return; + if(y2 < ymin()) return; + + if(y1 < ymin()) y1 = ymin(); + if(y2 > ymax()) y2 = ymax(); + + m_ren->blend_vline(x, y1, y2 - y1 + 1, c, cover); + } + + + //-------------------------------------------------------------------- + void copy_bar(int x1, int y1, int x2, int y2, const color_type& c) + { + rect_i rc(x1, y1, x2, y2); + rc.normalize(); + if(rc.clip(clip_box())) + { + int y; + for(y = rc.y1; y <= rc.y2; y++) + { + m_ren->copy_hline(rc.x1, y, unsigned(rc.x2 - rc.x1 + 1), c); + } + } + } + + //-------------------------------------------------------------------- + void blend_bar(int x1, int y1, int x2, int y2, + const color_type& c, cover_type cover) + { + rect_i rc(x1, y1, x2, y2); + rc.normalize(); + if(rc.clip(clip_box())) + { + int y; + for(y = rc.y1; y <= rc.y2; y++) + { + m_ren->blend_hline(rc.x1, + y, + unsigned(rc.x2 - rc.x1 + 1), + c, + cover); + } + } + } + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, int len, + const color_type& c, + const cover_type* covers) + { + if(y > ymax()) return; + if(y < ymin()) return; + + if(x < xmin()) + { + len -= xmin() - x; + if(len <= 0) return; + covers += xmin() - x; + x = xmin(); + } + if(x + len > xmax()) + { + len = xmax() - x + 1; + if(len <= 0) return; + } + m_ren->blend_solid_hspan(x, y, len, c, covers); + } + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, int len, + const color_type& c, + const cover_type* covers) + { + if(x > xmax()) return; + if(x < xmin()) return; + + if(y < ymin()) + { + len -= ymin() - y; + if(len <= 0) return; + covers += ymin() - y; + y = ymin(); + } + if(y + len > ymax()) + { + len = ymax() - y + 1; + if(len <= 0) return; + } + m_ren->blend_solid_vspan(x, y, len, c, covers); + } + + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, int len, const color_type* colors) + { + if(y > ymax()) return; + if(y < ymin()) return; + + if(x < xmin()) + { + int d = xmin() - x; + len -= d; + if(len <= 0) return; + colors += d; + x = xmin(); + } + if(x + len > xmax()) + { + len = xmax() - x + 1; + if(len <= 0) return; + } + m_ren->copy_color_hspan(x, y, len, colors); + } + + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, int len, const color_type* colors) + { + if(x > xmax()) return; + if(x < xmin()) return; + + if(y < ymin()) + { + int d = ymin() - y; + len -= d; + if(len <= 0) return; + colors += d; + y = ymin(); + } + if(y + len > ymax()) + { + len = ymax() - y + 1; + if(len <= 0) return; + } + m_ren->copy_color_vspan(x, y, len, colors); + } + + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, int len, + const color_type* colors, + const cover_type* covers, + cover_type cover = agg::cover_full) + { + if(y > ymax()) return; + if(y < ymin()) return; + + if(x < xmin()) + { + int d = xmin() - x; + len -= d; + if(len <= 0) return; + if(covers) covers += d; + colors += d; + x = xmin(); + } + if(x + len > xmax()) + { + len = xmax() - x + 1; + if(len <= 0) return; + } + m_ren->blend_color_hspan(x, y, len, colors, covers, cover); + } + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, int len, + const color_type* colors, + const cover_type* covers, + cover_type cover = agg::cover_full) + { + if(x > xmax()) return; + if(x < xmin()) return; + + if(y < ymin()) + { + int d = ymin() - y; + len -= d; + if(len <= 0) return; + if(covers) covers += d; + colors += d; + y = ymin(); + } + if(y + len > ymax()) + { + len = ymax() - y + 1; + if(len <= 0) return; + } + m_ren->blend_color_vspan(x, y, len, colors, covers, cover); + } + + //-------------------------------------------------------------------- + rect_i clip_rect_area(rect_i& dst, rect_i& src, int wsrc, int hsrc) const + { + rect_i rc(0,0,0,0); + rect_i cb = clip_box(); + ++cb.x2; + ++cb.y2; + + if(src.x1 < 0) + { + dst.x1 -= src.x1; + src.x1 = 0; + } + if(src.y1 < 0) + { + dst.y1 -= src.y1; + src.y1 = 0; + } + + if(src.x2 > wsrc) src.x2 = wsrc; + if(src.y2 > hsrc) src.y2 = hsrc; + + if(dst.x1 < cb.x1) + { + src.x1 += cb.x1 - dst.x1; + dst.x1 = cb.x1; + } + if(dst.y1 < cb.y1) + { + src.y1 += cb.y1 - dst.y1; + dst.y1 = cb.y1; + } + + if(dst.x2 > cb.x2) dst.x2 = cb.x2; + if(dst.y2 > cb.y2) dst.y2 = cb.y2; + + rc.x2 = dst.x2 - dst.x1; + rc.y2 = dst.y2 - dst.y1; + + if(rc.x2 > src.x2 - src.x1) rc.x2 = src.x2 - src.x1; + if(rc.y2 > src.y2 - src.y1) rc.y2 = src.y2 - src.y1; + return rc; + } + + //-------------------------------------------------------------------- + template<class RenBuf> + void copy_from(const RenBuf& src, + const rect_i* rect_src_ptr = 0, + int dx = 0, + int dy = 0) + { + rect_i rsrc(0, 0, src.width(), src.height()); + if(rect_src_ptr) + { + rsrc.x1 = rect_src_ptr->x1; + rsrc.y1 = rect_src_ptr->y1; + rsrc.x2 = rect_src_ptr->x2 + 1; + rsrc.y2 = rect_src_ptr->y2 + 1; + } + + // Version with xdst, ydst (absolute positioning) + //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); + + // Version with dx, dy (relative positioning) + rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); + + rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); + + if(rc.x2 > 0) + { + int incy = 1; + if(rdst.y1 > rsrc.y1) + { + rsrc.y1 += rc.y2 - 1; + rdst.y1 += rc.y2 - 1; + incy = -1; + } + while(rc.y2 > 0) + { + m_ren->copy_from(src, + rdst.x1, rdst.y1, + rsrc.x1, rsrc.y1, + rc.x2); + rdst.y1 += incy; + rsrc.y1 += incy; + --rc.y2; + } + } + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from(const SrcPixelFormatRenderer& src, + const rect_i* rect_src_ptr = 0, + int dx = 0, + int dy = 0, + cover_type cover = agg::cover_full) + { + rect_i rsrc(0, 0, src.width(), src.height()); + if(rect_src_ptr) + { + rsrc.x1 = rect_src_ptr->x1; + rsrc.y1 = rect_src_ptr->y1; + rsrc.x2 = rect_src_ptr->x2 + 1; + rsrc.y2 = rect_src_ptr->y2 + 1; + } + + // Version with xdst, ydst (absolute positioning) + //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); + + // Version with dx, dy (relative positioning) + rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); + rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); + + if(rc.x2 > 0) + { + int incy = 1; + if(rdst.y1 > rsrc.y1) + { + rsrc.y1 += rc.y2 - 1; + rdst.y1 += rc.y2 - 1; + incy = -1; + } + while(rc.y2 > 0) + { + typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1); + if(rw.ptr) + { + int x1src = rsrc.x1; + int x1dst = rdst.x1; + int len = rc.x2; + if(rw.x1 > x1src) + { + x1dst += rw.x1 - x1src; + len -= rw.x1 - x1src; + x1src = rw.x1; + } + if(len > 0) + { + if(x1src + len-1 > rw.x2) + { + len -= x1src + len - rw.x2 - 1; + } + if(len > 0) + { + m_ren->blend_from(src, + x1dst, rdst.y1, + x1src, rsrc.y1, + len, + cover); + } + } + } + rdst.y1 += incy; + rsrc.y1 += incy; + --rc.y2; + } + } + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from_color(const SrcPixelFormatRenderer& src, + const color_type& color, + const rect_i* rect_src_ptr = 0, + int dx = 0, + int dy = 0, + cover_type cover = agg::cover_full) + { + rect_i rsrc(0, 0, src.width(), src.height()); + if(rect_src_ptr) + { + rsrc.x1 = rect_src_ptr->x1; + rsrc.y1 = rect_src_ptr->y1; + rsrc.x2 = rect_src_ptr->x2 + 1; + rsrc.y2 = rect_src_ptr->y2 + 1; + } + + // Version with xdst, ydst (absolute positioning) + //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); + + // Version with dx, dy (relative positioning) + rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); + rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); + + if(rc.x2 > 0) + { + int incy = 1; + if(rdst.y1 > rsrc.y1) + { + rsrc.y1 += rc.y2 - 1; + rdst.y1 += rc.y2 - 1; + incy = -1; + } + while(rc.y2 > 0) + { + typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1); + if(rw.ptr) + { + int x1src = rsrc.x1; + int x1dst = rdst.x1; + int len = rc.x2; + if(rw.x1 > x1src) + { + x1dst += rw.x1 - x1src; + len -= rw.x1 - x1src; + x1src = rw.x1; + } + if(len > 0) + { + if(x1src + len-1 > rw.x2) + { + len -= x1src + len - rw.x2 - 1; + } + if(len > 0) + { + m_ren->blend_from_color(src, + color, + x1dst, rdst.y1, + x1src, rsrc.y1, + len, + cover); + } + } + } + rdst.y1 += incy; + rsrc.y1 += incy; + --rc.y2; + } + } + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from_lut(const SrcPixelFormatRenderer& src, + const color_type* color_lut, + const rect_i* rect_src_ptr = 0, + int dx = 0, + int dy = 0, + cover_type cover = agg::cover_full) + { + rect_i rsrc(0, 0, src.width(), src.height()); + if(rect_src_ptr) + { + rsrc.x1 = rect_src_ptr->x1; + rsrc.y1 = rect_src_ptr->y1; + rsrc.x2 = rect_src_ptr->x2 + 1; + rsrc.y2 = rect_src_ptr->y2 + 1; + } + + // Version with xdst, ydst (absolute positioning) + //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); + + // Version with dx, dy (relative positioning) + rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); + rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); + + if(rc.x2 > 0) + { + int incy = 1; + if(rdst.y1 > rsrc.y1) + { + rsrc.y1 += rc.y2 - 1; + rdst.y1 += rc.y2 - 1; + incy = -1; + } + while(rc.y2 > 0) + { + typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1); + if(rw.ptr) + { + int x1src = rsrc.x1; + int x1dst = rdst.x1; + int len = rc.x2; + if(rw.x1 > x1src) + { + x1dst += rw.x1 - x1src; + len -= rw.x1 - x1src; + x1src = rw.x1; + } + if(len > 0) + { + if(x1src + len-1 > rw.x2) + { + len -= x1src + len - rw.x2 - 1; + } + if(len > 0) + { + m_ren->blend_from_lut(src, + color_lut, + x1dst, rdst.y1, + x1src, rsrc.y1, + len, + cover); + } + } + } + rdst.y1 += incy; + rsrc.y1 += incy; + --rc.y2; + } + } + } + + private: + pixfmt_type* m_ren; + rect_i m_clip_box; + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_renderer_markers.h b/jni/desmume/src/android/agg/include/agg_renderer_markers.h new file mode 100755 index 0000000..59ec2a4 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_renderer_markers.h @@ -0,0 +1,711 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERER_MARKERS_INCLUDED +#define AGG_RENDERER_MARKERS_INCLUDED + +#include "agg_basics.h" +#include "agg_renderer_primitives.h" + +namespace agg +{ + + //---------------------------------------------------------------marker_e + enum marker_e + { + marker_square, + marker_diamond, + marker_circle, + marker_crossed_circle, + marker_semiellipse_left, + marker_semiellipse_right, + marker_semiellipse_up, + marker_semiellipse_down, + marker_triangle_left, + marker_triangle_right, + marker_triangle_up, + marker_triangle_down, + marker_four_rays, + marker_cross, + marker_x, + marker_dash, + marker_dot, + marker_pixel, + + end_of_markers + }; + + + + //--------------------------------------------------------renderer_markers + template<class BaseRenderer> class renderer_markers : + public renderer_primitives<BaseRenderer> + { + public: + typedef renderer_primitives<BaseRenderer> base_type; + typedef BaseRenderer base_ren_type; + typedef typename base_ren_type::color_type color_type; + + //-------------------------------------------------------------------- + renderer_markers(base_ren_type& rbuf) : + base_type(rbuf) + {} + + //-------------------------------------------------------------------- + bool visible(int x, int y, int r) const + { + rect_i rc(x-r, y-r, x+y, y+r); + return rc.clip(base_type::ren().bounding_clip_box()); + } + + //-------------------------------------------------------------------- + void square(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) base_type::outlined_rectangle(x-r, y-r, x+r, y+r); + else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + + //-------------------------------------------------------------------- + void diamond(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r; + int dx = 0; + do + { + base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full); + + if(dx) + { + base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full); + base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full); + } + ++dy; + ++dx; + } + while(dy <= 0); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + //-------------------------------------------------------------------- + void circle(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) base_type::outlined_ellipse(x, y, r, r); + else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + + + + //-------------------------------------------------------------------- + void crossed_circle(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + base_type::outlined_ellipse(x, y, r, r); + int r6 = r + (r >> 1); + if(r <= 2) r6++; + r >>= 1; + base_type::ren().blend_hline(x-r6, y, x-r, base_type::line_color(), cover_full); + base_type::ren().blend_hline(x+r, y, x+r6, base_type::line_color(), cover_full); + base_type::ren().blend_vline(x, y-r6, y-r, base_type::line_color(), cover_full); + base_type::ren().blend_vline(x, y+r, y+r6, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //------------------------------------------------------------------------ + void semiellipse_left(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int r8 = r * 4 / 5; + int dy = -r; + int dx = 0; + ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8); + do + { + dx += ei.dx(); + dy += ei.dy(); + + base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full); + + if(ei.dy() && dx) + { + base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); + } + ++ei; + } + while(dy < r8); + base_type::ren().blend_vline(x+dy, y-dx, y+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void semiellipse_right(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int r8 = r * 4 / 5; + int dy = -r; + int dx = 0; + ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8); + do + { + dx += ei.dx(); + dy += ei.dy(); + + base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full); + + if(ei.dy() && dx) + { + base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); + } + ++ei; + } + while(dy < r8); + base_type::ren().blend_vline(x-dy, y-dx, y+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void semiellipse_up(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int r8 = r * 4 / 5; + int dy = -r; + int dx = 0; + ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8); + do + { + dx += ei.dx(); + dy += ei.dy(); + + base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full); + + if(ei.dy() && dx) + { + base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full); + } + ++ei; + } + while(dy < r8); + base_type::ren().blend_hline(x-dx, y-dy-1, x+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void semiellipse_down(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int r8 = r * 4 / 5; + int dy = -r; + int dx = 0; + ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8); + do + { + dx += ei.dx(); + dy += ei.dy(); + + base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full); + + if(ei.dy() && dx) + { + base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full); + } + ++ei; + } + while(dy < r8); + base_type::ren().blend_hline(x-dx, y+dy+1, x+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void triangle_left(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r; + int dx = 0; + int flip = 0; + int r6 = r * 3 / 5; + do + { + base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full); + + if(dx) + { + base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); + } + ++dy; + dx += flip; + flip ^= 1; + } + while(dy < r6); + base_type::ren().blend_vline(x+dy, y-dx, y+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void triangle_right(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r; + int dx = 0; + int flip = 0; + int r6 = r * 3 / 5; + do + { + base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full); + + if(dx) + { + base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); + } + ++dy; + dx += flip; + flip ^= 1; + } + while(dy < r6); + base_type::ren().blend_vline(x-dy, y-dx, y+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void triangle_up(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r; + int dx = 0; + int flip = 0; + int r6 = r * 3 / 5; + do + { + base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full); + + if(dx) + { + base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full); + } + ++dy; + dx += flip; + flip ^= 1; + } + while(dy < r6); + base_type::ren().blend_hline(x-dx, y-dy, x+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void triangle_down(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r; + int dx = 0; + int flip = 0; + int r6 = r * 3 / 5; + do + { + base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full); + + if(dx) + { + base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full); + } + ++dy; + dx += flip; + flip ^= 1; + } + while(dy < r6); + base_type::ren().blend_hline(x-dx, y+dy, x+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void four_rays(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r; + int dx = 0; + int flip = 0; + int r3 = -(r / 3); + do + { + base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full); + + if(dx) + { + base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full); + base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full); + base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); + base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); + } + ++dy; + dx += flip; + flip ^= 1; + } + while(dy <= r3); + base_type::solid_rectangle(x+r3+1, y+r3+1, x-r3-1, y-r3-1); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void cross(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + base_type::ren().blend_vline(x, y-r, y+r, base_type::line_color(), cover_full); + base_type::ren().blend_hline(x-r, y, x+r, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void xing(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r * 7 / 10; + do + { + base_type::ren().blend_pixel(x + dy, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dy, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dy, y - dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dy, y - dy, base_type::line_color(), cover_full); + ++dy; + } + while(dy < 0); + } + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + + + //-------------------------------------------------------------------- + void dash(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) base_type::ren().blend_hline(x-r, y, x+r, base_type::line_color(), cover_full); + else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + + + //-------------------------------------------------------------------- + void dot(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) base_type::solid_ellipse(x, y, r, r); + else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + + //-------------------------------------------------------------------- + void pixel(int x, int y, int) + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + + //-------------------------------------------------------------------- + void marker(int x, int y, int r, marker_e type) + { + switch(type) + { + case marker_square: square(x, y, r); break; + case marker_diamond: diamond(x, y, r); break; + case marker_circle: circle(x, y, r); break; + case marker_crossed_circle: crossed_circle(x, y, r); break; + case marker_semiellipse_left: semiellipse_left(x, y, r); break; + case marker_semiellipse_right: semiellipse_right(x, y, r); break; + case marker_semiellipse_up: semiellipse_up(x, y, r); break; + case marker_semiellipse_down: semiellipse_down(x, y, r); break; + case marker_triangle_left: triangle_left(x, y, r); break; + case marker_triangle_right: triangle_right(x, y, r); break; + case marker_triangle_up: triangle_up(x, y, r); break; + case marker_triangle_down: triangle_down(x, y, r); break; + case marker_four_rays: four_rays(x, y, r); break; + case marker_cross: cross(x, y, r); break; + case marker_x: xing(x, y, r); break; + case marker_dash: dash(x, y, r); break; + case marker_dot: dot(x, y, r); break; + case marker_pixel: pixel(x, y, r); break; + } + } + + + //-------------------------------------------------------------------- + template<class T> + void markers(int n, const T* x, const T* y, T r, marker_e type) + { + if(n <= 0) return; + if(r == 0) + { + do + { + base_type::ren().blend_pixel(int(*x), int(*y), base_type::fill_color(), cover_full); + ++x; + ++y; + } + while(--n); + return; + } + + switch(type) + { + case marker_square: do { square (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_diamond: do { diamond (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_circle: do { circle (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_crossed_circle: do { crossed_circle (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_semiellipse_left: do { semiellipse_left (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_semiellipse_right: do { semiellipse_right(int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_semiellipse_up: do { semiellipse_up (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_semiellipse_down: do { semiellipse_down (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_triangle_left: do { triangle_left (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_triangle_right: do { triangle_right (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_triangle_up: do { triangle_up (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_triangle_down: do { triangle_down (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_four_rays: do { four_rays (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_cross: do { cross (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_x: do { xing (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_dash: do { dash (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_dot: do { dot (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_pixel: do { pixel (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + } + } + + //-------------------------------------------------------------------- + template<class T> + void markers(int n, const T* x, const T* y, const T* r, marker_e type) + { + if(n <= 0) return; + switch(type) + { + case marker_square: do { square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_diamond: do { diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_circle: do { circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_crossed_circle: do { crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_semiellipse_left: do { semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_semiellipse_right: do { semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_semiellipse_up: do { semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_semiellipse_down: do { semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_triangle_left: do { triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_triangle_right: do { triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_triangle_up: do { triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_triangle_down: do { triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_four_rays: do { four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_cross: do { cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_x: do { xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_dash: do { dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_dot: do { dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_pixel: do { pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + } + } + + //-------------------------------------------------------------------- + template<class T> + void markers(int n, const T* x, const T* y, const T* r, const color_type* fc, marker_e type) + { + if(n <= 0) return; + switch(type) + { + case marker_square: do { base_type::fill_color(*fc); square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_diamond: do { base_type::fill_color(*fc); diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_circle: do { base_type::fill_color(*fc); circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_crossed_circle: do { base_type::fill_color(*fc); crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_semiellipse_left: do { base_type::fill_color(*fc); semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_semiellipse_right: do { base_type::fill_color(*fc); semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_semiellipse_up: do { base_type::fill_color(*fc); semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_semiellipse_down: do { base_type::fill_color(*fc); semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_triangle_left: do { base_type::fill_color(*fc); triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_triangle_right: do { base_type::fill_color(*fc); triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_triangle_up: do { base_type::fill_color(*fc); triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_triangle_down: do { base_type::fill_color(*fc); triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_four_rays: do { base_type::fill_color(*fc); four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_cross: do { base_type::fill_color(*fc); cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_x: do { base_type::fill_color(*fc); xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_dash: do { base_type::fill_color(*fc); dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_dot: do { base_type::fill_color(*fc); dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_pixel: do { base_type::fill_color(*fc); pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + } + } + + //-------------------------------------------------------------------- + template<class T> + void markers(int n, const T* x, const T* y, const T* r, const color_type* fc, const color_type* lc, marker_e type) + { + if(n <= 0) return; + switch(type) + { + case marker_square: do { base_type::fill_color(*fc); base_type::line_color(*lc); square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_diamond: do { base_type::fill_color(*fc); base_type::line_color(*lc); diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_circle: do { base_type::fill_color(*fc); base_type::line_color(*lc); circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_crossed_circle: do { base_type::fill_color(*fc); base_type::line_color(*lc); crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_semiellipse_left: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_semiellipse_right: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_semiellipse_up: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_semiellipse_down: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_triangle_left: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_triangle_right: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_triangle_up: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_triangle_down: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_four_rays: do { base_type::fill_color(*fc); base_type::line_color(*lc); four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_cross: do { base_type::fill_color(*fc); base_type::line_color(*lc); cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_x: do { base_type::fill_color(*fc); base_type::line_color(*lc); xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_dash: do { base_type::fill_color(*fc); base_type::line_color(*lc); dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_dot: do { base_type::fill_color(*fc); base_type::line_color(*lc); dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_pixel: do { base_type::fill_color(*fc); base_type::line_color(*lc); pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + } + } + }; + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_renderer_mclip.h b/jni/desmume/src/android/agg/include/agg_renderer_mclip.h new file mode 100755 index 0000000..4be5e7c --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_renderer_mclip.h @@ -0,0 +1,349 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERER_MCLIP_INCLUDED +#define AGG_RENDERER_MCLIP_INCLUDED + +#include "agg_basics.h" +#include "agg_array.h" +#include "agg_renderer_base.h" + +namespace agg +{ + + //----------------------------------------------------------renderer_mclip + template<class PixelFormat> class renderer_mclip + { + public: + typedef PixelFormat pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::row_data row_data; + typedef renderer_base<pixfmt_type> base_ren_type; + + //-------------------------------------------------------------------- + explicit renderer_mclip(pixfmt_type& pixf) : + m_ren(pixf), + m_curr_cb(0), + m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax()) + {} + void attach(pixfmt_type& pixf) + { + m_ren.attach(pixf); + reset_clipping(true); + } + + //-------------------------------------------------------------------- + const pixfmt_type& ren() const { return m_ren.ren(); } + pixfmt_type& ren() { return m_ren.ren(); } + + //-------------------------------------------------------------------- + unsigned width() const { return m_ren.width(); } + unsigned height() const { return m_ren.height(); } + + //-------------------------------------------------------------------- + const rect_i& clip_box() const { return m_ren.clip_box(); } + int xmin() const { return m_ren.xmin(); } + int ymin() const { return m_ren.ymin(); } + int xmax() const { return m_ren.xmax(); } + int ymax() const { return m_ren.ymax(); } + + //-------------------------------------------------------------------- + const rect_i& bounding_clip_box() const { return m_bounds; } + int bounding_xmin() const { return m_bounds.x1; } + int bounding_ymin() const { return m_bounds.y1; } + int bounding_xmax() const { return m_bounds.x2; } + int bounding_ymax() const { return m_bounds.y2; } + + //-------------------------------------------------------------------- + void first_clip_box() + { + m_curr_cb = 0; + if(m_clip.size()) + { + const rect_i& cb = m_clip[0]; + m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2); + } + } + + //-------------------------------------------------------------------- + bool next_clip_box() + { + if(++m_curr_cb < m_clip.size()) + { + const rect_i& cb = m_clip[m_curr_cb]; + m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2); + return true; + } + return false; + } + + //-------------------------------------------------------------------- + void reset_clipping(bool visibility) + { + m_ren.reset_clipping(visibility); + m_clip.remove_all(); + m_curr_cb = 0; + m_bounds = m_ren.clip_box(); + } + + //-------------------------------------------------------------------- + void add_clip_box(int x1, int y1, int x2, int y2) + { + rect_i cb(x1, y1, x2, y2); + cb.normalize(); + if(cb.clip(rect_i(0, 0, width() - 1, height() - 1))) + { + m_clip.add(cb); + if(cb.x1 < m_bounds.x1) m_bounds.x1 = cb.x1; + if(cb.y1 < m_bounds.y1) m_bounds.y1 = cb.y1; + if(cb.x2 > m_bounds.x2) m_bounds.x2 = cb.x2; + if(cb.y2 > m_bounds.y2) m_bounds.y2 = cb.y2; + } + } + + //-------------------------------------------------------------------- + void clear(const color_type& c) + { + m_ren.clear(c); + } + + //-------------------------------------------------------------------- + void copy_pixel(int x, int y, const color_type& c) + { + first_clip_box(); + do + { + if(m_ren.inbox(x, y)) + { + m_ren.ren().copy_pixel(x, y, c); + break; + } + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_pixel(int x, int y, const color_type& c, cover_type cover) + { + first_clip_box(); + do + { + if(m_ren.inbox(x, y)) + { + m_ren.ren().blend_pixel(x, y, c, cover); + break; + } + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + color_type pixel(int x, int y) const + { + if(m_ren.inbox(x, y)) + { + return m_ren.ren().pixel(x, y); + } + return color_type::no_color(); + } + + //-------------------------------------------------------------------- + void copy_hline(int x1, int y, int x2, const color_type& c) + { + first_clip_box(); + do + { + m_ren.copy_hline(x1, y, x2, c); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void copy_vline(int x, int y1, int y2, const color_type& c) + { + first_clip_box(); + do + { + m_ren.copy_vline(x, y1, y2, c); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_hline(int x1, int y, int x2, + const color_type& c, cover_type cover) + { + first_clip_box(); + do + { + m_ren.blend_hline(x1, y, x2, c, cover); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y1, int y2, + const color_type& c, cover_type cover) + { + first_clip_box(); + do + { + m_ren.blend_vline(x, y1, y2, c, cover); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void copy_bar(int x1, int y1, int x2, int y2, const color_type& c) + { + first_clip_box(); + do + { + m_ren.copy_bar(x1, y1, x2, y2, c); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_bar(int x1, int y1, int x2, int y2, + const color_type& c, cover_type cover) + { + first_clip_box(); + do + { + m_ren.blend_bar(x1, y1, x2, y2, c, cover); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, int len, + const color_type& c, const cover_type* covers) + { + first_clip_box(); + do + { + m_ren.blend_solid_hspan(x, y, len, c, covers); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, int len, + const color_type& c, const cover_type* covers) + { + first_clip_box(); + do + { + m_ren.blend_solid_vspan(x, y, len, c, covers); + } + while(next_clip_box()); + } + + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, int len, const color_type* colors) + { + first_clip_box(); + do + { + m_ren.copy_color_hspan(x, y, len, colors); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, int len, + const color_type* colors, + const cover_type* covers, + cover_type cover = cover_full) + { + first_clip_box(); + do + { + m_ren.blend_color_hspan(x, y, len, colors, covers, cover); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, int len, + const color_type* colors, + const cover_type* covers, + cover_type cover = cover_full) + { + first_clip_box(); + do + { + m_ren.blend_color_vspan(x, y, len, colors, covers, cover); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void copy_from(const rendering_buffer& from, + const rect_i* rc=0, + int x_to=0, + int y_to=0) + { + first_clip_box(); + do + { + m_ren.copy_from(from, rc, x_to, y_to); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + template<class SrcPixelFormatRenderer> + void blend_from(const SrcPixelFormatRenderer& src, + const rect_i* rect_src_ptr = 0, + int dx = 0, + int dy = 0, + cover_type cover = cover_full) + { + first_clip_box(); + do + { + m_ren.blend_from(src, rect_src_ptr, dx, dy, cover); + } + while(next_clip_box()); + } + + + private: + renderer_mclip(const renderer_mclip<PixelFormat>&); + const renderer_mclip<PixelFormat>& + operator = (const renderer_mclip<PixelFormat>&); + + base_ren_type m_ren; + pod_bvector<rect_i, 4> m_clip; + unsigned m_curr_cb; + rect_i m_bounds; + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_renderer_outline_aa.h b/jni/desmume/src/android/agg/include/agg_renderer_outline_aa.h new file mode 100755 index 0000000..ce25a2e --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_renderer_outline_aa.h @@ -0,0 +1,1847 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERER_OUTLINE_AA_INCLUDED +#define AGG_RENDERER_OUTLINE_AA_INCLUDED + +#include "agg_array.h" +#include "agg_math.h" +#include "agg_line_aa_basics.h" +#include "agg_dda_line.h" +#include "agg_ellipse_bresenham.h" +#include "agg_renderer_base.h" +#include "agg_gamma_functions.h" +#include "agg_clip_liang_barsky.h" + +namespace agg +{ + + //===================================================distance_interpolator0 + class distance_interpolator0 + { + public: + //--------------------------------------------------------------------- + distance_interpolator0() {} + distance_interpolator0(int x1, int y1, int x2, int y2, int x, int y) : + m_dx(line_mr(x2) - line_mr(x1)), + m_dy(line_mr(y2) - line_mr(y1)), + m_dist((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy - + (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx) + { + m_dx <<= line_mr_subpixel_shift; + m_dy <<= line_mr_subpixel_shift; + } + + //--------------------------------------------------------------------- + void inc_x() { m_dist += m_dy; } + int dist() const { return m_dist; } + + private: + //--------------------------------------------------------------------- + int m_dx; + int m_dy; + int m_dist; + }; + + //==================================================distance_interpolator00 + class distance_interpolator00 + { + public: + //--------------------------------------------------------------------- + distance_interpolator00() {} + distance_interpolator00(int xc, int yc, + int x1, int y1, int x2, int y2, + int x, int y) : + m_dx1(line_mr(x1) - line_mr(xc)), + m_dy1(line_mr(y1) - line_mr(yc)), + m_dx2(line_mr(x2) - line_mr(xc)), + m_dy2(line_mr(y2) - line_mr(yc)), + m_dist1((line_mr(x + line_subpixel_scale/2) - line_mr(x1)) * m_dy1 - + (line_mr(y + line_subpixel_scale/2) - line_mr(y1)) * m_dx1), + m_dist2((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy2 - + (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx2) + { + m_dx1 <<= line_mr_subpixel_shift; + m_dy1 <<= line_mr_subpixel_shift; + m_dx2 <<= line_mr_subpixel_shift; + m_dy2 <<= line_mr_subpixel_shift; + } + + //--------------------------------------------------------------------- + void inc_x() { m_dist1 += m_dy1; m_dist2 += m_dy2; } + int dist1() const { return m_dist1; } + int dist2() const { return m_dist2; } + + private: + //--------------------------------------------------------------------- + int m_dx1; + int m_dy1; + int m_dx2; + int m_dy2; + int m_dist1; + int m_dist2; + }; + + //===================================================distance_interpolator1 + class distance_interpolator1 + { + public: + //--------------------------------------------------------------------- + distance_interpolator1() {} + distance_interpolator1(int x1, int y1, int x2, int y2, int x, int y) : + m_dx(x2 - x1), + m_dy(y2 - y1), + m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - + double(y + line_subpixel_scale/2 - y2) * double(m_dx))) + { + m_dx <<= line_subpixel_shift; + m_dy <<= line_subpixel_shift; + } + + //--------------------------------------------------------------------- + void inc_x() { m_dist += m_dy; } + void dec_x() { m_dist -= m_dy; } + void inc_y() { m_dist -= m_dx; } + void dec_y() { m_dist += m_dx; } + + //--------------------------------------------------------------------- + void inc_x(int dy) + { + m_dist += m_dy; + if(dy > 0) m_dist -= m_dx; + if(dy < 0) m_dist += m_dx; + } + + //--------------------------------------------------------------------- + void dec_x(int dy) + { + m_dist -= m_dy; + if(dy > 0) m_dist -= m_dx; + if(dy < 0) m_dist += m_dx; + } + + //--------------------------------------------------------------------- + void inc_y(int dx) + { + m_dist -= m_dx; + if(dx > 0) m_dist += m_dy; + if(dx < 0) m_dist -= m_dy; + } + + void dec_y(int dx) + //--------------------------------------------------------------------- + { + m_dist += m_dx; + if(dx > 0) m_dist += m_dy; + if(dx < 0) m_dist -= m_dy; + } + + //--------------------------------------------------------------------- + int dist() const { return m_dist; } + int dx() const { return m_dx; } + int dy() const { return m_dy; } + + private: + //--------------------------------------------------------------------- + int m_dx; + int m_dy; + int m_dist; + }; + + + + + + //===================================================distance_interpolator2 + class distance_interpolator2 + { + public: + //--------------------------------------------------------------------- + distance_interpolator2() {} + distance_interpolator2(int x1, int y1, int x2, int y2, + int sx, int sy, int x, int y) : + m_dx(x2 - x1), + m_dy(y2 - y1), + m_dx_start(line_mr(sx) - line_mr(x1)), + m_dy_start(line_mr(sy) - line_mr(y1)), + + m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - + double(y + line_subpixel_scale/2 - y2) * double(m_dx))), + + m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - + (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start) + { + m_dx <<= line_subpixel_shift; + m_dy <<= line_subpixel_shift; + m_dx_start <<= line_mr_subpixel_shift; + m_dy_start <<= line_mr_subpixel_shift; + } + + distance_interpolator2(int x1, int y1, int x2, int y2, + int ex, int ey, int x, int y, int) : + m_dx(x2 - x1), + m_dy(y2 - y1), + m_dx_start(line_mr(ex) - line_mr(x2)), + m_dy_start(line_mr(ey) - line_mr(y2)), + + m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - + double(y + line_subpixel_scale/2 - y2) * double(m_dx))), + + m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_start - + (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_start) + { + m_dx <<= line_subpixel_shift; + m_dy <<= line_subpixel_shift; + m_dx_start <<= line_mr_subpixel_shift; + m_dy_start <<= line_mr_subpixel_shift; + } + + + //--------------------------------------------------------------------- + void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; } + void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; } + void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; } + void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; } + + //--------------------------------------------------------------------- + void inc_x(int dy) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + if(dy > 0) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + } + if(dy < 0) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + } + } + + //--------------------------------------------------------------------- + void dec_x(int dy) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + if(dy > 0) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + } + if(dy < 0) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + } + } + + //--------------------------------------------------------------------- + void inc_y(int dx) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + if(dx > 0) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + } + if(dx < 0) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + } + } + + //--------------------------------------------------------------------- + void dec_y(int dx) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + if(dx > 0) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + } + if(dx < 0) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + } + } + + //--------------------------------------------------------------------- + int dist() const { return m_dist; } + int dist_start() const { return m_dist_start; } + int dist_end() const { return m_dist_start; } + + //--------------------------------------------------------------------- + int dx() const { return m_dx; } + int dy() const { return m_dy; } + int dx_start() const { return m_dx_start; } + int dy_start() const { return m_dy_start; } + int dx_end() const { return m_dx_start; } + int dy_end() const { return m_dy_start; } + + private: + //--------------------------------------------------------------------- + int m_dx; + int m_dy; + int m_dx_start; + int m_dy_start; + + int m_dist; + int m_dist_start; + }; + + + + + + //===================================================distance_interpolator3 + class distance_interpolator3 + { + public: + //--------------------------------------------------------------------- + distance_interpolator3() {} + distance_interpolator3(int x1, int y1, int x2, int y2, + int sx, int sy, int ex, int ey, + int x, int y) : + m_dx(x2 - x1), + m_dy(y2 - y1), + m_dx_start(line_mr(sx) - line_mr(x1)), + m_dy_start(line_mr(sy) - line_mr(y1)), + m_dx_end(line_mr(ex) - line_mr(x2)), + m_dy_end(line_mr(ey) - line_mr(y2)), + + m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - + double(y + line_subpixel_scale/2 - y2) * double(m_dx))), + + m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - + (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start), + + m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end - + (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end) + { + m_dx <<= line_subpixel_shift; + m_dy <<= line_subpixel_shift; + m_dx_start <<= line_mr_subpixel_shift; + m_dy_start <<= line_mr_subpixel_shift; + m_dx_end <<= line_mr_subpixel_shift; + m_dy_end <<= line_mr_subpixel_shift; + } + + //--------------------------------------------------------------------- + void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_end += m_dy_end; } + void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; m_dist_end -= m_dy_end; } + void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_end -= m_dx_end; } + void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_end += m_dx_end; } + + //--------------------------------------------------------------------- + void inc_x(int dy) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_end += m_dy_end; + if(dy > 0) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_end -= m_dx_end; + } + if(dy < 0) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_end += m_dx_end; + } + } + + //--------------------------------------------------------------------- + void dec_x(int dy) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_end -= m_dy_end; + if(dy > 0) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_end -= m_dx_end; + } + if(dy < 0) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_end += m_dx_end; + } + } + + //--------------------------------------------------------------------- + void inc_y(int dx) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_end -= m_dx_end; + if(dx > 0) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_end += m_dy_end; + } + if(dx < 0) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_end -= m_dy_end; + } + } + + //--------------------------------------------------------------------- + void dec_y(int dx) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_end += m_dx_end; + if(dx > 0) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_end += m_dy_end; + } + if(dx < 0) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_end -= m_dy_end; + } + } + + //--------------------------------------------------------------------- + int dist() const { return m_dist; } + int dist_start() const { return m_dist_start; } + int dist_end() const { return m_dist_end; } + + //--------------------------------------------------------------------- + int dx() const { return m_dx; } + int dy() const { return m_dy; } + int dx_start() const { return m_dx_start; } + int dy_start() const { return m_dy_start; } + int dx_end() const { return m_dx_end; } + int dy_end() const { return m_dy_end; } + + private: + //--------------------------------------------------------------------- + int m_dx; + int m_dy; + int m_dx_start; + int m_dy_start; + int m_dx_end; + int m_dy_end; + + int m_dist; + int m_dist_start; + int m_dist_end; + }; + + + + + + //================================================line_interpolator_aa_base + template<class Renderer> class line_interpolator_aa_base + { + public: + typedef Renderer renderer_type; + typedef typename Renderer::color_type color_type; + + //--------------------------------------------------------------------- + enum max_half_width_e + { + max_half_width = 64 + }; + + //--------------------------------------------------------------------- + line_interpolator_aa_base(renderer_type& ren, const line_parameters& lp) : + m_lp(&lp), + m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) : + line_dbl_hr(lp.y2 - lp.y1), + lp.vertical ? abs(lp.y2 - lp.y1) : + abs(lp.x2 - lp.x1) + 1), + m_ren(ren), + m_len((lp.vertical == (lp.inc > 0)) ? -lp.len : lp.len), + m_x(lp.x1 >> line_subpixel_shift), + m_y(lp.y1 >> line_subpixel_shift), + m_old_x(m_x), + m_old_y(m_y), + m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) : + abs((lp.x2 >> line_subpixel_shift) - m_x))), + m_width(ren.subpixel_width()), + //m_max_extent(m_width >> (line_subpixel_shift - 2)), + m_max_extent((m_width + line_subpixel_mask) >> line_subpixel_shift), + m_step(0) + { + agg::dda2_line_interpolator li(0, lp.vertical ? + (lp.dy << agg::line_subpixel_shift) : + (lp.dx << agg::line_subpixel_shift), + lp.len); + + unsigned i; + int stop = m_width + line_subpixel_scale * 2; + for(i = 0; i < max_half_width; ++i) + { + m_dist[i] = li.y(); + if(m_dist[i] >= stop) break; + ++li; + } + m_dist[i++] = 0x7FFF0000; + } + + //--------------------------------------------------------------------- + template<class DI> int step_hor_base(DI& di) + { + ++m_li; + m_x += m_lp->inc; + m_y = (m_lp->y1 + m_li.y()) >> line_subpixel_shift; + + if(m_lp->inc > 0) di.inc_x(m_y - m_old_y); + else di.dec_x(m_y - m_old_y); + + m_old_y = m_y; + + return di.dist() / m_len; + } + + //--------------------------------------------------------------------- + template<class DI> int step_ver_base(DI& di) + { + ++m_li; + m_y += m_lp->inc; + m_x = (m_lp->x1 + m_li.y()) >> line_subpixel_shift; + + if(m_lp->inc > 0) di.inc_y(m_x - m_old_x); + else di.dec_y(m_x - m_old_x); + + m_old_x = m_x; + + return di.dist() / m_len; + } + + //--------------------------------------------------------------------- + bool vertical() const { return m_lp->vertical; } + int width() const { return m_width; } + int count() const { return m_count; } + + private: + line_interpolator_aa_base(const line_interpolator_aa_base<Renderer>&); + const line_interpolator_aa_base<Renderer>& + operator = (const line_interpolator_aa_base<Renderer>&); + + protected: + const line_parameters* m_lp; + dda2_line_interpolator m_li; + renderer_type& m_ren; + int m_len; + int m_x; + int m_y; + int m_old_x; + int m_old_y; + int m_count; + int m_width; + int m_max_extent; + int m_step; + int m_dist[max_half_width + 1]; + cover_type m_covers[max_half_width * 2 + 4]; + }; + + + + + + + + //====================================================line_interpolator_aa0 + template<class Renderer> class line_interpolator_aa0 : + public line_interpolator_aa_base<Renderer> + { + public: + typedef Renderer renderer_type; + typedef typename Renderer::color_type color_type; + typedef line_interpolator_aa_base<Renderer> base_type; + + //--------------------------------------------------------------------- + line_interpolator_aa0(renderer_type& ren, const line_parameters& lp) : + line_interpolator_aa_base<Renderer>(ren, lp), + m_di(lp.x1, lp.y1, lp.x2, lp.y2, + lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask) + { + base_type::m_li.adjust_forward(); + } + + //--------------------------------------------------------------------- + bool step_hor() + { + int dist; + int dy; + int s1 = base_type::step_hor_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + *p1++ = (cover_type)base_type::m_ren.cover(s1); + + dy = 1; + while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) + { + *p1++ = (cover_type)base_type::m_ren.cover(dist); + ++dy; + } + + dy = 1; + while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) + { + *--p0 = (cover_type)base_type::m_ren.cover(dist); + ++dy; + } + base_type::m_ren.blend_solid_vspan(base_type::m_x, + base_type::m_y - dy + 1, + unsigned(p1 - p0), + p0); + return ++base_type::m_step < base_type::m_count; + } + + //--------------------------------------------------------------------- + bool step_ver() + { + int dist; + int dx; + int s1 = base_type::step_ver_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + *p1++ = (cover_type)base_type::m_ren.cover(s1); + + dx = 1; + while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) + { + *p1++ = (cover_type)base_type::m_ren.cover(dist); + ++dx; + } + + dx = 1; + while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) + { + *--p0 = (cover_type)base_type::m_ren.cover(dist); + ++dx; + } + base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, + base_type::m_y, + unsigned(p1 - p0), + p0); + return ++base_type::m_step < base_type::m_count; + } + + private: + line_interpolator_aa0(const line_interpolator_aa0<Renderer>&); + const line_interpolator_aa0<Renderer>& + operator = (const line_interpolator_aa0<Renderer>&); + + //--------------------------------------------------------------------- + distance_interpolator1 m_di; + }; + + + + + + + //====================================================line_interpolator_aa1 + template<class Renderer> class line_interpolator_aa1 : + public line_interpolator_aa_base<Renderer> + { + public: + typedef Renderer renderer_type; + typedef typename Renderer::color_type color_type; + typedef line_interpolator_aa_base<Renderer> base_type; + + //--------------------------------------------------------------------- + line_interpolator_aa1(renderer_type& ren, const line_parameters& lp, + int sx, int sy) : + line_interpolator_aa_base<Renderer>(ren, lp), + m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, + lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask) + { + int dist1_start; + int dist2_start; + + int npix = 1; + + if(lp.vertical) + { + do + { + --base_type::m_li; + base_type::m_y -= lp.inc; + base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift; + + if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x); + else m_di.inc_y(base_type::m_x - base_type::m_old_x); + + base_type::m_old_x = base_type::m_x; + + dist1_start = dist2_start = m_di.dist_start(); + + int dx = 0; + if(dist1_start < 0) ++npix; + do + { + dist1_start += m_di.dy_start(); + dist2_start -= m_di.dy_start(); + if(dist1_start < 0) ++npix; + if(dist2_start < 0) ++npix; + ++dx; + } + while(base_type::m_dist[dx] <= base_type::m_width); + --base_type::m_step; + if(npix == 0) break; + npix = 0; + } + while(base_type::m_step >= -base_type::m_max_extent); + } + else + { + do + { + --base_type::m_li; + base_type::m_x -= lp.inc; + base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift; + + if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y); + else m_di.inc_x(base_type::m_y - base_type::m_old_y); + + base_type::m_old_y = base_type::m_y; + + dist1_start = dist2_start = m_di.dist_start(); + + int dy = 0; + if(dist1_start < 0) ++npix; + do + { + dist1_start -= m_di.dx_start(); + dist2_start += m_di.dx_start(); + if(dist1_start < 0) ++npix; + if(dist2_start < 0) ++npix; + ++dy; + } + while(base_type::m_dist[dy] <= base_type::m_width); + --base_type::m_step; + if(npix == 0) break; + npix = 0; + } + while(base_type::m_step >= -base_type::m_max_extent); + } + base_type::m_li.adjust_forward(); + } + + //--------------------------------------------------------------------- + bool step_hor() + { + int dist_start; + int dist; + int dy; + int s1 = base_type::step_hor_base(m_di); + + dist_start = m_di.dist_start(); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + *p1 = 0; + if(dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(s1); + } + ++p1; + + dy = 1; + while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) + { + dist_start -= m_di.dx_start(); + *p1 = 0; + if(dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(dist); + } + ++p1; + ++dy; + } + + dy = 1; + dist_start = m_di.dist_start(); + while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) + { + dist_start += m_di.dx_start(); + *--p0 = 0; + if(dist_start <= 0) + { + *p0 = (cover_type)base_type::m_ren.cover(dist); + } + ++dy; + } + + base_type::m_ren.blend_solid_vspan(base_type::m_x, + base_type::m_y - dy + 1, + unsigned(p1 - p0), + p0); + return ++base_type::m_step < base_type::m_count; + } + + //--------------------------------------------------------------------- + bool step_ver() + { + int dist_start; + int dist; + int dx; + int s1 = base_type::step_ver_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + dist_start = m_di.dist_start(); + + *p1 = 0; + if(dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(s1); + } + ++p1; + + dx = 1; + while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) + { + dist_start += m_di.dy_start(); + *p1 = 0; + if(dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(dist); + } + ++p1; + ++dx; + } + + dx = 1; + dist_start = m_di.dist_start(); + while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) + { + dist_start -= m_di.dy_start(); + *--p0 = 0; + if(dist_start <= 0) + { + *p0 = (cover_type)base_type::m_ren.cover(dist); + } + ++dx; + } + base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, + base_type::m_y, + unsigned(p1 - p0), + p0); + return ++base_type::m_step < base_type::m_count; + } + + private: + line_interpolator_aa1(const line_interpolator_aa1<Renderer>&); + const line_interpolator_aa1<Renderer>& + operator = (const line_interpolator_aa1<Renderer>&); + + //--------------------------------------------------------------------- + distance_interpolator2 m_di; + }; + + + + + + + + + + + + + //====================================================line_interpolator_aa2 + template<class Renderer> class line_interpolator_aa2 : + public line_interpolator_aa_base<Renderer> + { + public: + typedef Renderer renderer_type; + typedef typename Renderer::color_type color_type; + typedef line_interpolator_aa_base<Renderer> base_type; + + //--------------------------------------------------------------------- + line_interpolator_aa2(renderer_type& ren, const line_parameters& lp, + int ex, int ey) : + line_interpolator_aa_base<Renderer>(ren, lp), + m_di(lp.x1, lp.y1, lp.x2, lp.y2, ex, ey, + lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask, + 0) + { + base_type::m_li.adjust_forward(); + base_type::m_step -= base_type::m_max_extent; + } + + //--------------------------------------------------------------------- + bool step_hor() + { + int dist_end; + int dist; + int dy; + int s1 = base_type::step_hor_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + dist_end = m_di.dist_end(); + + int npix = 0; + *p1 = 0; + if(dist_end > 0) + { + *p1 = (cover_type)base_type::m_ren.cover(s1); + ++npix; + } + ++p1; + + dy = 1; + while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) + { + dist_end -= m_di.dx_end(); + *p1 = 0; + if(dist_end > 0) + { + *p1 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++p1; + ++dy; + } + + dy = 1; + dist_end = m_di.dist_end(); + while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) + { + dist_end += m_di.dx_end(); + *--p0 = 0; + if(dist_end > 0) + { + *p0 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++dy; + } + base_type::m_ren.blend_solid_vspan(base_type::m_x, + base_type::m_y - dy + 1, + unsigned(p1 - p0), + p0); + return npix && ++base_type::m_step < base_type::m_count; + } + + //--------------------------------------------------------------------- + bool step_ver() + { + int dist_end; + int dist; + int dx; + int s1 = base_type::step_ver_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + dist_end = m_di.dist_end(); + + int npix = 0; + *p1 = 0; + if(dist_end > 0) + { + *p1 = (cover_type)base_type::m_ren.cover(s1); + ++npix; + } + ++p1; + + dx = 1; + while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) + { + dist_end += m_di.dy_end(); + *p1 = 0; + if(dist_end > 0) + { + *p1 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++p1; + ++dx; + } + + dx = 1; + dist_end = m_di.dist_end(); + while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) + { + dist_end -= m_di.dy_end(); + *--p0 = 0; + if(dist_end > 0) + { + *p0 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++dx; + } + base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, + base_type::m_y, + unsigned(p1 - p0), + p0); + return npix && ++base_type::m_step < base_type::m_count; + } + + private: + line_interpolator_aa2(const line_interpolator_aa2<Renderer>&); + const line_interpolator_aa2<Renderer>& + operator = (const line_interpolator_aa2<Renderer>&); + + //--------------------------------------------------------------------- + distance_interpolator2 m_di; + }; + + + + + + + + + + + //====================================================line_interpolator_aa3 + template<class Renderer> class line_interpolator_aa3 : + public line_interpolator_aa_base<Renderer> + { + public: + typedef Renderer renderer_type; + typedef typename Renderer::color_type color_type; + typedef line_interpolator_aa_base<Renderer> base_type; + + //--------------------------------------------------------------------- + line_interpolator_aa3(renderer_type& ren, const line_parameters& lp, + int sx, int sy, int ex, int ey) : + line_interpolator_aa_base<Renderer>(ren, lp), + m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, + lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask) + { + int dist1_start; + int dist2_start; + int npix = 1; + if(lp.vertical) + { + do + { + --base_type::m_li; + base_type::m_y -= lp.inc; + base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift; + + if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x); + else m_di.inc_y(base_type::m_x - base_type::m_old_x); + + base_type::m_old_x = base_type::m_x; + + dist1_start = dist2_start = m_di.dist_start(); + + int dx = 0; + if(dist1_start < 0) ++npix; + do + { + dist1_start += m_di.dy_start(); + dist2_start -= m_di.dy_start(); + if(dist1_start < 0) ++npix; + if(dist2_start < 0) ++npix; + ++dx; + } + while(base_type::m_dist[dx] <= base_type::m_width); + if(npix == 0) break; + npix = 0; + } + while(--base_type::m_step >= -base_type::m_max_extent); + } + else + { + do + { + --base_type::m_li; + base_type::m_x -= lp.inc; + base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift; + + if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y); + else m_di.inc_x(base_type::m_y - base_type::m_old_y); + + base_type::m_old_y = base_type::m_y; + + dist1_start = dist2_start = m_di.dist_start(); + + int dy = 0; + if(dist1_start < 0) ++npix; + do + { + dist1_start -= m_di.dx_start(); + dist2_start += m_di.dx_start(); + if(dist1_start < 0) ++npix; + if(dist2_start < 0) ++npix; + ++dy; + } + while(base_type::m_dist[dy] <= base_type::m_width); + if(npix == 0) break; + npix = 0; + } + while(--base_type::m_step >= -base_type::m_max_extent); + } + base_type::m_li.adjust_forward(); + base_type::m_step -= base_type::m_max_extent; + } + + + //--------------------------------------------------------------------- + bool step_hor() + { + int dist_start; + int dist_end; + int dist; + int dy; + int s1 = base_type::step_hor_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + dist_start = m_di.dist_start(); + dist_end = m_di.dist_end(); + + int npix = 0; + *p1 = 0; + if(dist_end > 0) + { + if(dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(s1); + } + ++npix; + } + ++p1; + + dy = 1; + while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) + { + dist_start -= m_di.dx_start(); + dist_end -= m_di.dx_end(); + *p1 = 0; + if(dist_end > 0 && dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++p1; + ++dy; + } + + dy = 1; + dist_start = m_di.dist_start(); + dist_end = m_di.dist_end(); + while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) + { + dist_start += m_di.dx_start(); + dist_end += m_di.dx_end(); + *--p0 = 0; + if(dist_end > 0 && dist_start <= 0) + { + *p0 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++dy; + } + base_type::m_ren.blend_solid_vspan(base_type::m_x, + base_type::m_y - dy + 1, + unsigned(p1 - p0), + p0); + return npix && ++base_type::m_step < base_type::m_count; + } + + //--------------------------------------------------------------------- + bool step_ver() + { + int dist_start; + int dist_end; + int dist; + int dx; + int s1 = base_type::step_ver_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + dist_start = m_di.dist_start(); + dist_end = m_di.dist_end(); + + int npix = 0; + *p1 = 0; + if(dist_end > 0) + { + if(dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(s1); + } + ++npix; + } + ++p1; + + dx = 1; + while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) + { + dist_start += m_di.dy_start(); + dist_end += m_di.dy_end(); + *p1 = 0; + if(dist_end > 0 && dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++p1; + ++dx; + } + + dx = 1; + dist_start = m_di.dist_start(); + dist_end = m_di.dist_end(); + while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) + { + dist_start -= m_di.dy_start(); + dist_end -= m_di.dy_end(); + *--p0 = 0; + if(dist_end > 0 && dist_start <= 0) + { + *p0 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++dx; + } + base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, + base_type::m_y, + unsigned(p1 - p0), + p0); + return npix && ++base_type::m_step < base_type::m_count; + } + + private: + line_interpolator_aa3(const line_interpolator_aa3<Renderer>&); + const line_interpolator_aa3<Renderer>& + operator = (const line_interpolator_aa3<Renderer>&); + + //--------------------------------------------------------------------- + distance_interpolator3 m_di; + }; + + + + + //==========================================================line_profile_aa + // + // See Implementation agg_line_profile_aa.cpp + // + class line_profile_aa + { + public: + //--------------------------------------------------------------------- + typedef int8u value_type; + enum subpixel_scale_e + { + subpixel_shift = line_subpixel_shift, + subpixel_scale = 1 << subpixel_shift, + subpixel_mask = subpixel_scale - 1 + }; + + enum aa_scale_e + { + aa_shift = 8, + aa_scale = 1 << aa_shift, + aa_mask = aa_scale - 1 + }; + + //--------------------------------------------------------------------- + line_profile_aa() : + m_subpixel_width(0), + m_min_width(1.0), + m_smoother_width(1.0) + { + int i; + for(i = 0; i < aa_scale; i++) m_gamma[i] = (value_type)i; + } + + //--------------------------------------------------------------------- + template<class GammaF> + line_profile_aa(double w, const GammaF& gamma_function) : + m_subpixel_width(0), + m_min_width(1.0), + m_smoother_width(1.0) + { + gamma(gamma_function); + width(w); + } + + //--------------------------------------------------------------------- + void min_width(double w) { m_min_width = w; } + void smoother_width(double w) { m_smoother_width = w; } + + //--------------------------------------------------------------------- + template<class GammaF> void gamma(const GammaF& gamma_function) + { + int i; + for(i = 0; i < aa_scale; i++) + { + m_gamma[i] = value_type( + uround(gamma_function(double(i) / aa_mask) * aa_mask)); + } + } + + void width(double w); + + unsigned profile_size() const { return m_profile.size(); } + int subpixel_width() const { return m_subpixel_width; } + + //--------------------------------------------------------------------- + double min_width() const { return m_min_width; } + double smoother_width() const { return m_smoother_width; } + + //--------------------------------------------------------------------- + value_type value(int dist) const + { + return m_profile[dist + subpixel_scale*2]; + } + + private: + line_profile_aa(const line_profile_aa&); + const line_profile_aa& operator = (const line_profile_aa&); + + value_type* profile(double w); + void set(double center_width, double smoother_width); + + //--------------------------------------------------------------------- + pod_array<value_type> m_profile; + value_type m_gamma[aa_scale]; + int m_subpixel_width; + double m_min_width; + double m_smoother_width; + }; + + + //======================================================renderer_outline_aa + template<class BaseRenderer> class renderer_outline_aa + { + public: + //--------------------------------------------------------------------- + typedef BaseRenderer base_ren_type; + typedef renderer_outline_aa<base_ren_type> self_type; + typedef typename base_ren_type::color_type color_type; + + //--------------------------------------------------------------------- + renderer_outline_aa(base_ren_type& ren, const line_profile_aa& prof) : + m_ren(&ren), + m_profile(&prof), + m_clip_box(0,0,0,0), + m_clipping(false) + {} + void attach(base_ren_type& ren) { m_ren = &ren; } + + //--------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + + //--------------------------------------------------------------------- + void profile(const line_profile_aa& prof) { m_profile = &prof; } + const line_profile_aa& profile() const { return *m_profile; } + line_profile_aa& profile() { return *m_profile; } + + //--------------------------------------------------------------------- + int subpixel_width() const { return m_profile->subpixel_width(); } + + //--------------------------------------------------------------------- + void reset_clipping() { m_clipping = false; } + void clip_box(double x1, double y1, double x2, double y2) + { + m_clip_box.x1 = line_coord_sat::conv(x1); + m_clip_box.y1 = line_coord_sat::conv(y1); + m_clip_box.x2 = line_coord_sat::conv(x2); + m_clip_box.y2 = line_coord_sat::conv(y2); + m_clipping = true; + } + + //--------------------------------------------------------------------- + int cover(int d) const + { + return m_profile->value(d); + } + + //------------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, unsigned len, const cover_type* covers) + { + m_ren->blend_solid_hspan(x, y, len, m_color, covers); + } + + //------------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, unsigned len, const cover_type* covers) + { + m_ren->blend_solid_vspan(x, y, len, m_color, covers); + } + + //------------------------------------------------------------------------- + static bool accurate_join_only() { return false; } + + //------------------------------------------------------------------------- + template<class Cmp> + void semidot_hline(Cmp cmp, + int xc1, int yc1, int xc2, int yc2, + int x1, int y1, int x2) + { + cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4]; + cover_type* p0 = covers; + cover_type* p1 = covers; + int x = x1 << line_subpixel_shift; + int y = y1 << line_subpixel_shift; + int w = subpixel_width(); + distance_interpolator0 di(xc1, yc1, xc2, yc2, x, y); + x += line_subpixel_scale/2; + y += line_subpixel_scale/2; + + int x0 = x1; + int dx = x - xc1; + int dy = y - yc1; + do + { + int d = int(fast_sqrt(dx*dx + dy*dy)); + *p1 = 0; + if(cmp(di.dist()) && d <= w) + { + *p1 = (cover_type)cover(d); + } + ++p1; + dx += line_subpixel_scale; + di.inc_x(); + } + while(++x1 <= x2); + m_ren->blend_solid_hspan(x0, y1, + unsigned(p1 - p0), + color(), + p0); + } + + //------------------------------------------------------------------------- + template<class Cmp> + void semidot(Cmp cmp, int xc1, int yc1, int xc2, int yc2) + { + if(m_clipping && clipping_flags(xc1, yc1, m_clip_box)) return; + + int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift); + if(r < 1) r = 1; + ellipse_bresenham_interpolator ei(r, r); + int dx = 0; + int dy = -r; + int dy0 = dy; + int dx0 = dx; + int x = xc1 >> line_subpixel_shift; + int y = yc1 >> line_subpixel_shift; + + do + { + dx += ei.dx(); + dy += ei.dy(); + + if(dy != dy0) + { + semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0); + semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y-dy0, x+dx0); + } + dx0 = dx; + dy0 = dy; + ++ei; + } + while(dy < 0); + semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0); + } + + //------------------------------------------------------------------------- + void pie_hline(int xc, int yc, int xp1, int yp1, int xp2, int yp2, + int xh1, int yh1, int xh2) + { + if(m_clipping && clipping_flags(xc, yc, m_clip_box)) return; + + cover_type covers[line_interpolator_aa_base<self_type>::max_half_width * 2 + 4]; + cover_type* p0 = covers; + cover_type* p1 = covers; + int x = xh1 << line_subpixel_shift; + int y = yh1 << line_subpixel_shift; + int w = subpixel_width(); + + distance_interpolator00 di(xc, yc, xp1, yp1, xp2, yp2, x, y); + x += line_subpixel_scale/2; + y += line_subpixel_scale/2; + + int xh0 = xh1; + int dx = x - xc; + int dy = y - yc; + do + { + int d = int(fast_sqrt(dx*dx + dy*dy)); + *p1 = 0; + if(di.dist1() <= 0 && di.dist2() > 0 && d <= w) + { + *p1 = (cover_type)cover(d); + } + ++p1; + dx += line_subpixel_scale; + di.inc_x(); + } + while(++xh1 <= xh2); + m_ren->blend_solid_hspan(xh0, yh1, + unsigned(p1 - p0), + color(), + p0); + } + + + //------------------------------------------------------------------------- + void pie(int xc, int yc, int x1, int y1, int x2, int y2) + { + int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift); + if(r < 1) r = 1; + ellipse_bresenham_interpolator ei(r, r); + int dx = 0; + int dy = -r; + int dy0 = dy; + int dx0 = dx; + int x = xc >> line_subpixel_shift; + int y = yc >> line_subpixel_shift; + + do + { + dx += ei.dx(); + dy += ei.dy(); + + if(dy != dy0) + { + pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0); + pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y-dy0, x+dx0); + } + dx0 = dx; + dy0 = dy; + ++ei; + } + while(dy < 0); + pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0); + } + + //------------------------------------------------------------------------- + void line0_no_clip(const line_parameters& lp) + { + if(lp.len > line_max_length) + { + line_parameters lp1, lp2; + lp.divide(lp1, lp2); + line0_no_clip(lp1); + line0_no_clip(lp2); + return; + } + + line_interpolator_aa0<self_type> li(*this, lp); + if(li.count()) + { + if(li.vertical()) + { + while(li.step_ver()); + } + else + { + while(li.step_hor()); + } + } + } + + //------------------------------------------------------------------------- + void line0(const line_parameters& lp) + { + if(m_clipping) + { + int x1 = lp.x1; + int y1 = lp.y1; + int x2 = lp.x2; + int y2 = lp.y2; + unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); + if((flags & 4) == 0) + { + if(flags) + { + line_parameters lp2(x1, y1, x2, y2, + uround(calc_distance(x1, y1, x2, y2))); + line0_no_clip(lp2); + } + else + { + line0_no_clip(lp); + } + } + } + else + { + line0_no_clip(lp); + } + } + + //------------------------------------------------------------------------- + void line1_no_clip(const line_parameters& lp, int sx, int sy) + { + if(lp.len > line_max_length) + { + line_parameters lp1, lp2; + lp.divide(lp1, lp2); + line1_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1); + line1_no_clip(lp2, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1)); + return; + } + + fix_degenerate_bisectrix_start(lp, &sx, &sy); + line_interpolator_aa1<self_type> li(*this, lp, sx, sy); + if(li.vertical()) + { + while(li.step_ver()); + } + else + { + while(li.step_hor()); + } + } + + + //------------------------------------------------------------------------- + void line1(const line_parameters& lp, int sx, int sy) + { + if(m_clipping) + { + int x1 = lp.x1; + int y1 = lp.y1; + int x2 = lp.x2; + int y2 = lp.y2; + unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); + if((flags & 4) == 0) + { + if(flags) + { + line_parameters lp2(x1, y1, x2, y2, + uround(calc_distance(x1, y1, x2, y2))); + if(flags & 1) + { + sx = x1 + (y2 - y1); + sy = y1 - (x2 - x1); + } + else + { + while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) + { + sx = (lp.x1 + sx) >> 1; + sy = (lp.y1 + sy) >> 1; + } + } + line1_no_clip(lp2, sx, sy); + } + else + { + line1_no_clip(lp, sx, sy); + } + } + } + else + { + line1_no_clip(lp, sx, sy); + } + } + + //------------------------------------------------------------------------- + void line2_no_clip(const line_parameters& lp, int ex, int ey) + { + if(lp.len > line_max_length) + { + line_parameters lp1, lp2; + lp.divide(lp1, lp2); + line2_no_clip(lp1, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1)); + line2_no_clip(lp2, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1); + return; + } + + fix_degenerate_bisectrix_end(lp, &ex, &ey); + line_interpolator_aa2<self_type> li(*this, lp, ex, ey); + if(li.vertical()) + { + while(li.step_ver()); + } + else + { + while(li.step_hor()); + } + } + + //------------------------------------------------------------------------- + void line2(const line_parameters& lp, int ex, int ey) + { + if(m_clipping) + { + int x1 = lp.x1; + int y1 = lp.y1; + int x2 = lp.x2; + int y2 = lp.y2; + unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); + if((flags & 4) == 0) + { + if(flags) + { + line_parameters lp2(x1, y1, x2, y2, + uround(calc_distance(x1, y1, x2, y2))); + if(flags & 2) + { + ex = x2 + (y2 - y1); + ey = y2 - (x2 - x1); + } + else + { + while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len) + { + ex = (lp.x2 + ex) >> 1; + ey = (lp.y2 + ey) >> 1; + } + } + line2_no_clip(lp2, ex, ey); + } + else + { + line2_no_clip(lp, ex, ey); + } + } + } + else + { + line2_no_clip(lp, ex, ey); + } + } + + //------------------------------------------------------------------------- + void line3_no_clip(const line_parameters& lp, + int sx, int sy, int ex, int ey) + { + if(lp.len > line_max_length) + { + line_parameters lp1, lp2; + lp.divide(lp1, lp2); + int mx = lp1.x2 + (lp1.y2 - lp1.y1); + int my = lp1.y2 - (lp1.x2 - lp1.x1); + line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my); + line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1); + return; + } + + fix_degenerate_bisectrix_start(lp, &sx, &sy); + fix_degenerate_bisectrix_end(lp, &ex, &ey); + line_interpolator_aa3<self_type> li(*this, lp, sx, sy, ex, ey); + if(li.vertical()) + { + while(li.step_ver()); + } + else + { + while(li.step_hor()); + } + } + + //------------------------------------------------------------------------- + void line3(const line_parameters& lp, + int sx, int sy, int ex, int ey) + { + if(m_clipping) + { + int x1 = lp.x1; + int y1 = lp.y1; + int x2 = lp.x2; + int y2 = lp.y2; + unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); + if((flags & 4) == 0) + { + if(flags) + { + line_parameters lp2(x1, y1, x2, y2, + uround(calc_distance(x1, y1, x2, y2))); + if(flags & 1) + { + sx = x1 + (y2 - y1); + sy = y1 - (x2 - x1); + } + else + { + while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) + { + sx = (lp.x1 + sx) >> 1; + sy = (lp.y1 + sy) >> 1; + } + } + if(flags & 2) + { + ex = x2 + (y2 - y1); + ey = y2 - (x2 - x1); + } + else + { + while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len) + { + ex = (lp.x2 + ex) >> 1; + ey = (lp.y2 + ey) >> 1; + } + } + line3_no_clip(lp2, sx, sy, ex, ey); + } + else + { + line3_no_clip(lp, sx, sy, ex, ey); + } + } + } + else + { + line3_no_clip(lp, sx, sy, ex, ey); + } + } + + + private: + base_ren_type* m_ren; + const line_profile_aa* m_profile; + color_type m_color; + rect_i m_clip_box; + bool m_clipping; + }; + + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_renderer_outline_image.h b/jni/desmume/src/android/agg/include/agg_renderer_outline_image.h new file mode 100755 index 0000000..fbfac10 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_renderer_outline_image.h @@ -0,0 +1,1023 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERER_OUTLINE_IMAGE_INCLUDED +#define AGG_RENDERER_OUTLINE_IMAGE_INCLUDED + +#include "agg_array.h" +#include "agg_math.h" +#include "agg_line_aa_basics.h" +#include "agg_dda_line.h" +#include "agg_rendering_buffer.h" +#include "agg_clip_liang_barsky.h" + + +namespace agg +{ + //========================================================line_image_scale + template<class Source> class line_image_scale + { + public: + typedef typename Source::color_type color_type; + + line_image_scale(const Source& src, double height) : + m_source(src), + m_height(height), + m_scale(src.height() / height) + { + } + + double width() const { return m_source.width(); } + double height() const { return m_height; } + + color_type pixel(int x, int y) const + { + double src_y = (y + 0.5) * m_scale - 0.5; + int h = m_source.height() - 1; + int y1 = ufloor(src_y); + int y2 = y1 + 1; + color_type pix1 = (y1 < 0) ? color_type::no_color() : m_source.pixel(x, y1); + color_type pix2 = (y2 > h) ? color_type::no_color() : m_source.pixel(x, y2); + return pix1.gradient(pix2, src_y - y1); + } + + private: + line_image_scale(const line_image_scale<Source>&); + const line_image_scale<Source>& operator = (const line_image_scale<Source>&); + + const Source& m_source; + double m_height; + double m_scale; + }; + + + + //======================================================line_image_pattern + template<class Filter> class line_image_pattern + { + public: + typedef Filter filter_type; + typedef typename filter_type::color_type color_type; + + //-------------------------------------------------------------------- + line_image_pattern(const Filter& filter) : + m_filter(&filter), + m_dilation(filter.dilation() + 1), + m_dilation_hr(m_dilation << line_subpixel_shift), + m_data(), + m_width(0), + m_height(0), + m_width_hr(0), + m_half_height_hr(0), + m_offset_y_hr(0) + { + } + + // Create + //-------------------------------------------------------------------- + template<class Source> + line_image_pattern(const Filter& filter, const Source& src) : + m_filter(&filter), + m_dilation(filter.dilation() + 1), + m_dilation_hr(m_dilation << line_subpixel_shift), + m_data(), + m_width(0), + m_height(0), + m_width_hr(0), + m_half_height_hr(0), + m_offset_y_hr(0) + { + create(src); + } + + // Create + //-------------------------------------------------------------------- + template<class Source> void create(const Source& src) + { + m_height = uceil(src.height()); + m_width = uceil(src.width()); + m_width_hr = uround(src.width() * line_subpixel_scale); + m_half_height_hr = uround(src.height() * line_subpixel_scale/2); + m_offset_y_hr = m_dilation_hr + m_half_height_hr - line_subpixel_scale/2; + m_half_height_hr += line_subpixel_scale/2; + + m_data.resize((m_width + m_dilation * 2) * (m_height + m_dilation * 2)); + + m_buf.attach(&m_data[0], m_width + m_dilation * 2, + m_height + m_dilation * 2, + m_width + m_dilation * 2); + unsigned x, y; + color_type* d1; + color_type* d2; + for(y = 0; y < m_height; y++) + { + d1 = m_buf.row_ptr(y + m_dilation) + m_dilation; + for(x = 0; x < m_width; x++) + { + *d1++ = src.pixel(x, y); + } + } + + const color_type* s1; + const color_type* s2; + for(y = 0; y < m_dilation; y++) + { + //s1 = m_buf.row_ptr(m_height + m_dilation - 1) + m_dilation; + //s2 = m_buf.row_ptr(m_dilation) + m_dilation; + d1 = m_buf.row_ptr(m_dilation + m_height + y) + m_dilation; + d2 = m_buf.row_ptr(m_dilation - y - 1) + m_dilation; + for(x = 0; x < m_width; x++) + { + //*d1++ = color_type(*s1++, 0); + //*d2++ = color_type(*s2++, 0); + *d1++ = color_type::no_color(); + *d2++ = color_type::no_color(); + } + } + + unsigned h = m_height + m_dilation * 2; + for(y = 0; y < h; y++) + { + s1 = m_buf.row_ptr(y) + m_dilation; + s2 = m_buf.row_ptr(y) + m_dilation + m_width; + d1 = m_buf.row_ptr(y) + m_dilation + m_width; + d2 = m_buf.row_ptr(y) + m_dilation; + + for(x = 0; x < m_dilation; x++) + { + *d1++ = *s1++; + *--d2 = *--s2; + } + } + } + + //-------------------------------------------------------------------- + int pattern_width() const { return m_width_hr; } + int line_width() const { return m_half_height_hr; } + double width() const { return m_height; } + + //-------------------------------------------------------------------- + void pixel(color_type* p, int x, int y) const + { + m_filter->pixel_high_res(m_buf.rows(), + p, + x % m_width_hr + m_dilation_hr, + y + m_offset_y_hr); + } + + //-------------------------------------------------------------------- + const filter_type& filter() const { return *m_filter; } + + private: + line_image_pattern(const line_image_pattern<filter_type>&); + const line_image_pattern<filter_type>& + operator = (const line_image_pattern<filter_type>&); + + protected: + row_ptr_cache<color_type> m_buf; + const filter_type* m_filter; + unsigned m_dilation; + int m_dilation_hr; + pod_array<color_type> m_data; + unsigned m_width; + unsigned m_height; + int m_width_hr; + int m_half_height_hr; + int m_offset_y_hr; + }; + + + + + + + //=================================================line_image_pattern_pow2 + template<class Filter> class line_image_pattern_pow2 : + public line_image_pattern<Filter> + { + public: + typedef Filter filter_type; + typedef typename filter_type::color_type color_type; + typedef line_image_pattern<Filter> base_type; + + //-------------------------------------------------------------------- + line_image_pattern_pow2(const Filter& filter) : + line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask) {} + + //-------------------------------------------------------------------- + template<class Source> + line_image_pattern_pow2(const Filter& filter, const Source& src) : + line_image_pattern<Filter>(filter), m_mask(line_subpixel_mask) + { + create(src); + } + + //-------------------------------------------------------------------- + template<class Source> void create(const Source& src) + { + line_image_pattern<Filter>::create(src); + m_mask = 1; + while(m_mask < base_type::m_width) + { + m_mask <<= 1; + m_mask |= 1; + } + m_mask <<= line_subpixel_shift - 1; + m_mask |= line_subpixel_mask; + base_type::m_width_hr = m_mask + 1; + } + + //-------------------------------------------------------------------- + void pixel(color_type* p, int x, int y) const + { + base_type::m_filter->pixel_high_res( + base_type::m_buf.rows(), + p, + (x & m_mask) + base_type::m_dilation_hr, + y + base_type::m_offset_y_hr); + } + private: + unsigned m_mask; + }; + + + + + + + + //===================================================distance_interpolator4 + class distance_interpolator4 + { + public: + //--------------------------------------------------------------------- + distance_interpolator4() {} + distance_interpolator4(int x1, int y1, int x2, int y2, + int sx, int sy, int ex, int ey, + int len, double scale, int x, int y) : + m_dx(x2 - x1), + m_dy(y2 - y1), + m_dx_start(line_mr(sx) - line_mr(x1)), + m_dy_start(line_mr(sy) - line_mr(y1)), + m_dx_end(line_mr(ex) - line_mr(x2)), + m_dy_end(line_mr(ey) - line_mr(y2)), + + m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - + double(y + line_subpixel_scale/2 - y2) * double(m_dx))), + + m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - + (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start), + + m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end - + (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end), + m_len(uround(len / scale)) + { + double d = len * scale; + int dx = iround(((x2 - x1) << line_subpixel_shift) / d); + int dy = iround(((y2 - y1) << line_subpixel_shift) / d); + m_dx_pict = -dy; + m_dy_pict = dx; + m_dist_pict = ((x + line_subpixel_scale/2 - (x1 - dy)) * m_dy_pict - + (y + line_subpixel_scale/2 - (y1 + dx)) * m_dx_pict) >> + line_subpixel_shift; + + m_dx <<= line_subpixel_shift; + m_dy <<= line_subpixel_shift; + m_dx_start <<= line_mr_subpixel_shift; + m_dy_start <<= line_mr_subpixel_shift; + m_dx_end <<= line_mr_subpixel_shift; + m_dy_end <<= line_mr_subpixel_shift; + } + + //--------------------------------------------------------------------- + void inc_x() + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_pict += m_dy_pict; + m_dist_end += m_dy_end; + } + + //--------------------------------------------------------------------- + void dec_x() + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_pict -= m_dy_pict; + m_dist_end -= m_dy_end; + } + + //--------------------------------------------------------------------- + void inc_y() + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_pict -= m_dx_pict; + m_dist_end -= m_dx_end; + } + + //--------------------------------------------------------------------- + void dec_y() + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_pict += m_dx_pict; + m_dist_end += m_dx_end; + } + + //--------------------------------------------------------------------- + void inc_x(int dy) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_pict += m_dy_pict; + m_dist_end += m_dy_end; + if(dy > 0) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_pict -= m_dx_pict; + m_dist_end -= m_dx_end; + } + if(dy < 0) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_pict += m_dx_pict; + m_dist_end += m_dx_end; + } + } + + //--------------------------------------------------------------------- + void dec_x(int dy) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_pict -= m_dy_pict; + m_dist_end -= m_dy_end; + if(dy > 0) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_pict -= m_dx_pict; + m_dist_end -= m_dx_end; + } + if(dy < 0) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_pict += m_dx_pict; + m_dist_end += m_dx_end; + } + } + + //--------------------------------------------------------------------- + void inc_y(int dx) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_pict -= m_dx_pict; + m_dist_end -= m_dx_end; + if(dx > 0) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_pict += m_dy_pict; + m_dist_end += m_dy_end; + } + if(dx < 0) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_pict -= m_dy_pict; + m_dist_end -= m_dy_end; + } + } + + //--------------------------------------------------------------------- + void dec_y(int dx) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_pict += m_dx_pict; + m_dist_end += m_dx_end; + if(dx > 0) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_pict += m_dy_pict; + m_dist_end += m_dy_end; + } + if(dx < 0) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_pict -= m_dy_pict; + m_dist_end -= m_dy_end; + } + } + + //--------------------------------------------------------------------- + int dist() const { return m_dist; } + int dist_start() const { return m_dist_start; } + int dist_pict() const { return m_dist_pict; } + int dist_end() const { return m_dist_end; } + + //--------------------------------------------------------------------- + int dx() const { return m_dx; } + int dy() const { return m_dy; } + int dx_start() const { return m_dx_start; } + int dy_start() const { return m_dy_start; } + int dx_pict() const { return m_dx_pict; } + int dy_pict() const { return m_dy_pict; } + int dx_end() const { return m_dx_end; } + int dy_end() const { return m_dy_end; } + int len() const { return m_len; } + + private: + //--------------------------------------------------------------------- + int m_dx; + int m_dy; + int m_dx_start; + int m_dy_start; + int m_dx_pict; + int m_dy_pict; + int m_dx_end; + int m_dy_end; + + int m_dist; + int m_dist_start; + int m_dist_pict; + int m_dist_end; + int m_len; + }; + + + + + + //==================================================line_interpolator_image + template<class Renderer> class line_interpolator_image + { + public: + typedef Renderer renderer_type; + typedef typename Renderer::color_type color_type; + + //--------------------------------------------------------------------- + enum max_half_width_e + { + max_half_width = 64 + }; + + //--------------------------------------------------------------------- + line_interpolator_image(renderer_type& ren, const line_parameters& lp, + int sx, int sy, int ex, int ey, + int pattern_start, + double scale_x) : + m_lp(lp), + m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) : + line_dbl_hr(lp.y2 - lp.y1), + lp.vertical ? abs(lp.y2 - lp.y1) : + abs(lp.x2 - lp.x1) + 1), + m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, lp.len, scale_x, + lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask), + m_ren(ren), + m_x(lp.x1 >> line_subpixel_shift), + m_y(lp.y1 >> line_subpixel_shift), + m_old_x(m_x), + m_old_y(m_y), + m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) : + abs((lp.x2 >> line_subpixel_shift) - m_x))), + m_width(ren.subpixel_width()), + //m_max_extent(m_width >> (line_subpixel_shift - 2)), + m_max_extent((m_width + line_subpixel_scale) >> line_subpixel_shift), + m_start(pattern_start + (m_max_extent + 2) * ren.pattern_width()), + m_step(0) + { + agg::dda2_line_interpolator li(0, lp.vertical ? + (lp.dy << agg::line_subpixel_shift) : + (lp.dx << agg::line_subpixel_shift), + lp.len); + + unsigned i; + int stop = m_width + line_subpixel_scale * 2; + for(i = 0; i < max_half_width; ++i) + { + m_dist_pos[i] = li.y(); + if(m_dist_pos[i] >= stop) break; + ++li; + } + m_dist_pos[i] = 0x7FFF0000; + + int dist1_start; + int dist2_start; + int npix = 1; + + if(lp.vertical) + { + do + { + --m_li; + m_y -= lp.inc; + m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift; + + if(lp.inc > 0) m_di.dec_y(m_x - m_old_x); + else m_di.inc_y(m_x - m_old_x); + + m_old_x = m_x; + + dist1_start = dist2_start = m_di.dist_start(); + + int dx = 0; + if(dist1_start < 0) ++npix; + do + { + dist1_start += m_di.dy_start(); + dist2_start -= m_di.dy_start(); + if(dist1_start < 0) ++npix; + if(dist2_start < 0) ++npix; + ++dx; + } + while(m_dist_pos[dx] <= m_width); + if(npix == 0) break; + + npix = 0; + } + while(--m_step >= -m_max_extent); + } + else + { + do + { + --m_li; + + m_x -= lp.inc; + m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift; + + if(lp.inc > 0) m_di.dec_x(m_y - m_old_y); + else m_di.inc_x(m_y - m_old_y); + + m_old_y = m_y; + + dist1_start = dist2_start = m_di.dist_start(); + + int dy = 0; + if(dist1_start < 0) ++npix; + do + { + dist1_start -= m_di.dx_start(); + dist2_start += m_di.dx_start(); + if(dist1_start < 0) ++npix; + if(dist2_start < 0) ++npix; + ++dy; + } + while(m_dist_pos[dy] <= m_width); + if(npix == 0) break; + + npix = 0; + } + while(--m_step >= -m_max_extent); + } + m_li.adjust_forward(); + m_step -= m_max_extent; + } + + //--------------------------------------------------------------------- + bool step_hor() + { + ++m_li; + m_x += m_lp.inc; + m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift; + + if(m_lp.inc > 0) m_di.inc_x(m_y - m_old_y); + else m_di.dec_x(m_y - m_old_y); + + m_old_y = m_y; + + int s1 = m_di.dist() / m_lp.len; + int s2 = -s1; + + if(m_lp.inc < 0) s1 = -s1; + + int dist_start; + int dist_pict; + int dist_end; + int dy; + int dist; + + dist_start = m_di.dist_start(); + dist_pict = m_di.dist_pict() + m_start; + dist_end = m_di.dist_end(); + color_type* p0 = m_colors + max_half_width + 2; + color_type* p1 = p0; + + int npix = 0; + p1->clear(); + if(dist_end > 0) + { + if(dist_start <= 0) + { + m_ren.pixel(p1, dist_pict, s2); + } + ++npix; + } + ++p1; + + dy = 1; + while((dist = m_dist_pos[dy]) - s1 <= m_width) + { + dist_start -= m_di.dx_start(); + dist_pict -= m_di.dx_pict(); + dist_end -= m_di.dx_end(); + p1->clear(); + if(dist_end > 0 && dist_start <= 0) + { + if(m_lp.inc > 0) dist = -dist; + m_ren.pixel(p1, dist_pict, s2 - dist); + ++npix; + } + ++p1; + ++dy; + } + + dy = 1; + dist_start = m_di.dist_start(); + dist_pict = m_di.dist_pict() + m_start; + dist_end = m_di.dist_end(); + while((dist = m_dist_pos[dy]) + s1 <= m_width) + { + dist_start += m_di.dx_start(); + dist_pict += m_di.dx_pict(); + dist_end += m_di.dx_end(); + --p0; + p0->clear(); + if(dist_end > 0 && dist_start <= 0) + { + if(m_lp.inc > 0) dist = -dist; + m_ren.pixel(p0, dist_pict, s2 + dist); + ++npix; + } + ++dy; + } + m_ren.blend_color_vspan(m_x, + m_y - dy + 1, + unsigned(p1 - p0), + p0); + return npix && ++m_step < m_count; + } + + + + //--------------------------------------------------------------------- + bool step_ver() + { + ++m_li; + m_y += m_lp.inc; + m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift; + + if(m_lp.inc > 0) m_di.inc_y(m_x - m_old_x); + else m_di.dec_y(m_x - m_old_x); + + m_old_x = m_x; + + int s1 = m_di.dist() / m_lp.len; + int s2 = -s1; + + if(m_lp.inc > 0) s1 = -s1; + + int dist_start; + int dist_pict; + int dist_end; + int dist; + int dx; + + dist_start = m_di.dist_start(); + dist_pict = m_di.dist_pict() + m_start; + dist_end = m_di.dist_end(); + color_type* p0 = m_colors + max_half_width + 2; + color_type* p1 = p0; + + int npix = 0; + p1->clear(); + if(dist_end > 0) + { + if(dist_start <= 0) + { + m_ren.pixel(p1, dist_pict, s2); + } + ++npix; + } + ++p1; + + dx = 1; + while((dist = m_dist_pos[dx]) - s1 <= m_width) + { + dist_start += m_di.dy_start(); + dist_pict += m_di.dy_pict(); + dist_end += m_di.dy_end(); + p1->clear(); + if(dist_end > 0 && dist_start <= 0) + { + if(m_lp.inc > 0) dist = -dist; + m_ren.pixel(p1, dist_pict, s2 + dist); + ++npix; + } + ++p1; + ++dx; + } + + dx = 1; + dist_start = m_di.dist_start(); + dist_pict = m_di.dist_pict() + m_start; + dist_end = m_di.dist_end(); + while((dist = m_dist_pos[dx]) + s1 <= m_width) + { + dist_start -= m_di.dy_start(); + dist_pict -= m_di.dy_pict(); + dist_end -= m_di.dy_end(); + --p0; + p0->clear(); + if(dist_end > 0 && dist_start <= 0) + { + if(m_lp.inc > 0) dist = -dist; + m_ren.pixel(p0, dist_pict, s2 - dist); + ++npix; + } + ++dx; + } + m_ren.blend_color_hspan(m_x - dx + 1, + m_y, + unsigned(p1 - p0), + p0); + return npix && ++m_step < m_count; + } + + + //--------------------------------------------------------------------- + int pattern_end() const { return m_start + m_di.len(); } + + //--------------------------------------------------------------------- + bool vertical() const { return m_lp.vertical; } + int width() const { return m_width; } + int count() const { return m_count; } + + private: + line_interpolator_image(const line_interpolator_image<Renderer>&); + const line_interpolator_image<Renderer>& + operator = (const line_interpolator_image<Renderer>&); + + protected: + const line_parameters& m_lp; + dda2_line_interpolator m_li; + distance_interpolator4 m_di; + renderer_type& m_ren; + int m_plen; + int m_x; + int m_y; + int m_old_x; + int m_old_y; + int m_count; + int m_width; + int m_max_extent; + int m_start; + int m_step; + int m_dist_pos[max_half_width + 1]; + color_type m_colors[max_half_width * 2 + 4]; + }; + + + + + + + + + //===================================================renderer_outline_image + template<class BaseRenderer, class ImagePattern> + class renderer_outline_image + { + public: + //--------------------------------------------------------------------- + typedef BaseRenderer base_ren_type; + typedef renderer_outline_image<BaseRenderer, ImagePattern> self_type; + typedef typename base_ren_type::color_type color_type; + typedef ImagePattern pattern_type; + + + //--------------------------------------------------------------------- + renderer_outline_image(base_ren_type& ren, const pattern_type& patt) : + m_ren(&ren), + m_pattern(&patt), + m_start(0), + m_scale_x(1.0), + m_clip_box(0,0,0,0), + m_clipping(false) + {} + void attach(base_ren_type& ren) { m_ren = &ren; } + + //--------------------------------------------------------------------- + void pattern(const pattern_type& p) { m_pattern = &p; } + const pattern_type& pattern() const { return *m_pattern; } + + //--------------------------------------------------------------------- + void reset_clipping() { m_clipping = false; } + void clip_box(double x1, double y1, double x2, double y2) + { + m_clip_box.x1 = line_coord_sat::conv(x1); + m_clip_box.y1 = line_coord_sat::conv(y1); + m_clip_box.x2 = line_coord_sat::conv(x2); + m_clip_box.y2 = line_coord_sat::conv(y2); + m_clipping = true; + } + + //--------------------------------------------------------------------- + void scale_x(double s) { m_scale_x = s; } + double scale_x() const { return m_scale_x; } + + //--------------------------------------------------------------------- + void start_x(double s) { m_start = iround(s * line_subpixel_scale); } + double start_x() const { return double(m_start) / line_subpixel_scale; } + + //--------------------------------------------------------------------- + int subpixel_width() const { return m_pattern->line_width(); } + int pattern_width() const { return m_pattern->pattern_width(); } + double width() const { return double(subpixel_width()) / line_subpixel_scale; } + + //------------------------------------------------------------------------- + void pixel(color_type* p, int x, int y) const + { + m_pattern->pixel(p, x, y); + } + + //------------------------------------------------------------------------- + void blend_color_hspan(int x, int y, unsigned len, const color_type* colors) + { + m_ren->blend_color_hspan(x, y, len, colors, 0); + } + + //------------------------------------------------------------------------- + void blend_color_vspan(int x, int y, unsigned len, const color_type* colors) + { + m_ren->blend_color_vspan(x, y, len, colors, 0); + } + + //------------------------------------------------------------------------- + static bool accurate_join_only() { return true; } + + //------------------------------------------------------------------------- + template<class Cmp> + void semidot(Cmp, int, int, int, int) + { + } + + //------------------------------------------------------------------------- + void pie(int, int, int, int, int, int) + { + } + + //------------------------------------------------------------------------- + void line0(const line_parameters&) + { + } + + //------------------------------------------------------------------------- + void line1(const line_parameters&, int, int) + { + } + + //------------------------------------------------------------------------- + void line2(const line_parameters&, int, int) + { + } + + //------------------------------------------------------------------------- + void line3_no_clip(const line_parameters& lp, + int sx, int sy, int ex, int ey) + { + if(lp.len > line_max_length) + { + line_parameters lp1, lp2; + lp.divide(lp1, lp2); + int mx = lp1.x2 + (lp1.y2 - lp1.y1); + int my = lp1.y2 - (lp1.x2 - lp1.x1); + line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my); + line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1); + return; + } + + fix_degenerate_bisectrix_start(lp, &sx, &sy); + fix_degenerate_bisectrix_end(lp, &ex, &ey); + line_interpolator_image<self_type> li(*this, lp, + sx, sy, + ex, ey, + m_start, m_scale_x); + if(li.vertical()) + { + while(li.step_ver()); + } + else + { + while(li.step_hor()); + } + m_start += uround(lp.len / m_scale_x); + } + + //------------------------------------------------------------------------- + void line3(const line_parameters& lp, + int sx, int sy, int ex, int ey) + { + if(m_clipping) + { + int x1 = lp.x1; + int y1 = lp.y1; + int x2 = lp.x2; + int y2 = lp.y2; + unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); + int start = m_start; + if((flags & 4) == 0) + { + if(flags) + { + line_parameters lp2(x1, y1, x2, y2, + uround(calc_distance(x1, y1, x2, y2))); + if(flags & 1) + { + m_start += uround(calc_distance(lp.x1, lp.y1, x1, y1) / m_scale_x); + sx = x1 + (y2 - y1); + sy = y1 - (x2 - x1); + } + else + { + while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) + { + sx = (lp.x1 + sx) >> 1; + sy = (lp.y1 + sy) >> 1; + } + } + if(flags & 2) + { + ex = x2 + (y2 - y1); + ey = y2 - (x2 - x1); + } + else + { + while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len) + { + ex = (lp.x2 + ex) >> 1; + ey = (lp.y2 + ey) >> 1; + } + } + line3_no_clip(lp2, sx, sy, ex, ey); + } + else + { + line3_no_clip(lp, sx, sy, ex, ey); + } + } + m_start = start + uround(lp.len / m_scale_x); + } + else + { + line3_no_clip(lp, sx, sy, ex, ey); + } + } + + private: + base_ren_type* m_ren; + const pattern_type* m_pattern; + int m_start; + double m_scale_x; + rect_i m_clip_box; + bool m_clipping; + }; + + + + + +} + + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_renderer_primitives.h b/jni/desmume/src/android/agg/include/agg_renderer_primitives.h new file mode 100755 index 0000000..3e3c916 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_renderer_primitives.h @@ -0,0 +1,229 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERER_PRIMITIVES_INCLUDED +#define AGG_RENDERER_PRIMITIVES_INCLUDED + +#include "agg_basics.h" +#include "agg_renderer_base.h" +#include "agg_dda_line.h" +#include "agg_ellipse_bresenham.h" + +namespace agg +{ + //-----------------------------------------------------renderer_primitives + template<class BaseRenderer> class renderer_primitives + { + public: + typedef BaseRenderer base_ren_type; + typedef typename base_ren_type::color_type color_type; + + //-------------------------------------------------------------------- + explicit renderer_primitives(base_ren_type& ren) : + m_ren(&ren), + m_fill_color(), + m_line_color(), + m_curr_x(0), + m_curr_y(0) + {} + void attach(base_ren_type& ren) { m_ren = &ren; } + + //-------------------------------------------------------------------- + static int coord(double c) + { + return iround(c * line_bresenham_interpolator::subpixel_scale); + } + + //-------------------------------------------------------------------- + void fill_color(const color_type& c) { m_fill_color = c; } + void line_color(const color_type& c) { m_line_color = c; } + const color_type& fill_color() const { return m_fill_color; } + const color_type& line_color() const { return m_line_color; } + + //-------------------------------------------------------------------- + void rectangle(int x1, int y1, int x2, int y2) + { + m_ren->blend_hline(x1, y1, x2-1, m_line_color, cover_full); + m_ren->blend_vline(x2, y1, y2-1, m_line_color, cover_full); + m_ren->blend_hline(x1+1, y2, x2, m_line_color, cover_full); + m_ren->blend_vline(x1, y1+1, y2, m_line_color, cover_full); + } + + //-------------------------------------------------------------------- + void solid_rectangle(int x1, int y1, int x2, int y2) + { + m_ren->blend_bar(x1, y1, x2, y2, m_fill_color, cover_full); + } + + //-------------------------------------------------------------------- + void outlined_rectangle(int x1, int y1, int x2, int y2) + { + rectangle(x1, y1, x2, y2); + m_ren->blend_bar(x1+1, y1+1, x2-1, y2-1, m_fill_color, cover_full); + } + + //-------------------------------------------------------------------- + void ellipse(int x, int y, int rx, int ry) + { + ellipse_bresenham_interpolator ei(rx, ry); + int dx = 0; + int dy = -ry; + do + { + dx += ei.dx(); + dy += ei.dy(); + m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full); + m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full); + m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full); + m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full); + ++ei; + } + while(dy < 0); + } + + //-------------------------------------------------------------------- + void solid_ellipse(int x, int y, int rx, int ry) + { + ellipse_bresenham_interpolator ei(rx, ry); + int dx = 0; + int dy = -ry; + int dy0 = dy; + int dx0 = dx; + + do + { + dx += ei.dx(); + dy += ei.dy(); + + if(dy != dy0) + { + m_ren->blend_hline(x-dx0, y+dy0, x+dx0, m_fill_color, cover_full); + m_ren->blend_hline(x-dx0, y-dy0, x+dx0, m_fill_color, cover_full); + } + dx0 = dx; + dy0 = dy; + ++ei; + } + while(dy < 0); + m_ren->blend_hline(x-dx0, y+dy0, x+dx0, m_fill_color, cover_full); + } + + //-------------------------------------------------------------------- + void outlined_ellipse(int x, int y, int rx, int ry) + { + ellipse_bresenham_interpolator ei(rx, ry); + int dx = 0; + int dy = -ry; + + do + { + dx += ei.dx(); + dy += ei.dy(); + + m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full); + m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full); + m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full); + m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full); + + if(ei.dy() && dx) + { + m_ren->blend_hline(x-dx+1, y+dy, x+dx-1, m_fill_color, cover_full); + m_ren->blend_hline(x-dx+1, y-dy, x+dx-1, m_fill_color, cover_full); + } + ++ei; + } + while(dy < 0); + } + + //-------------------------------------------------------------------- + void line(int x1, int y1, int x2, int y2, bool last=false) + { + line_bresenham_interpolator li(x1, y1, x2, y2); + + unsigned len = li.len(); + if(len == 0) + { + if(last) + { + m_ren->blend_pixel(li.line_lr(x1), li.line_lr(y1), m_line_color, cover_full); + } + return; + } + + if(last) ++len; + + if(li.is_ver()) + { + do + { + m_ren->blend_pixel(li.x2(), li.y1(), m_line_color, cover_full); + li.vstep(); + } + while(--len); + } + else + { + do + { + m_ren->blend_pixel(li.x1(), li.y2(), m_line_color, cover_full); + li.hstep(); + } + while(--len); + } + } + + //-------------------------------------------------------------------- + void move_to(int x, int y) + { + m_curr_x = x; + m_curr_y = y; + } + + //-------------------------------------------------------------------- + void line_to(int x, int y, bool last=false) + { + line(m_curr_x, m_curr_y, x, y, last); + m_curr_x = x; + m_curr_y = y; + } + + //-------------------------------------------------------------------- + const base_ren_type& ren() const { return *m_ren; } + base_ren_type& ren() { return *m_ren; } + + //-------------------------------------------------------------------- + const rendering_buffer& rbuf() const { return m_ren->rbuf(); } + rendering_buffer& rbuf() { return m_ren->rbuf(); } + + private: + base_ren_type* m_ren; + color_type m_fill_color; + color_type m_line_color; + int m_curr_x; + int m_curr_y; + }; + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_renderer_raster_text.h b/jni/desmume/src/android/agg/include/agg_renderer_raster_text.h new file mode 100755 index 0000000..c99d929 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_renderer_raster_text.h @@ -0,0 +1,273 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERER_RASTER_TEXT_INCLUDED +#define AGG_RENDERER_RASTER_TEXT_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //==============================================renderer_raster_htext_solid + template<class BaseRenderer, class GlyphGenerator> + class renderer_raster_htext_solid + { + public: + typedef BaseRenderer ren_type; + typedef GlyphGenerator glyph_gen_type; + typedef typename glyph_gen_type::glyph_rect glyph_rect; + typedef typename ren_type::color_type color_type; + + renderer_raster_htext_solid(ren_type& ren, glyph_gen_type& glyph) : + m_ren(&ren), + m_glyph(&glyph) + {} + void attach(ren_type& ren) { m_ren = &ren; } + + //-------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + + //-------------------------------------------------------------------- + template<class CharT> + void render_text(double x, double y, const CharT* str, bool flip=false) + { + glyph_rect r; + while(*str) + { + m_glyph->prepare(&r, x, y, *str, flip); + if(r.x2 >= r.x1) + { + int i; + if(flip) + { + for(i = r.y1; i <= r.y2; i++) + { + m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1), + m_color, + m_glyph->span(r.y2 - i)); + } + } + else + { + for(i = r.y1; i <= r.y2; i++) + { + m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1), + m_color, + m_glyph->span(i - r.y1)); + } + } + } + x += r.dx; + y += r.dy; + ++str; + } + } + + private: + ren_type* m_ren; + glyph_gen_type* m_glyph; + color_type m_color; + }; + + + + //=============================================renderer_raster_vtext_solid + template<class BaseRenderer, class GlyphGenerator> + class renderer_raster_vtext_solid + { + public: + typedef BaseRenderer ren_type; + typedef GlyphGenerator glyph_gen_type; + typedef typename glyph_gen_type::glyph_rect glyph_rect; + typedef typename ren_type::color_type color_type; + + renderer_raster_vtext_solid(ren_type& ren, glyph_gen_type& glyph) : + m_ren(&ren), + m_glyph(&glyph) + { + } + + //-------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + + //-------------------------------------------------------------------- + template<class CharT> + void render_text(double x, double y, const CharT* str, bool flip=false) + { + glyph_rect r; + while(*str) + { + m_glyph->prepare(&r, x, y, *str, !flip); + if(r.x2 >= r.x1) + { + int i; + if(flip) + { + for(i = r.y1; i <= r.y2; i++) + { + m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1), + m_color, + m_glyph->span(i - r.y1)); + } + } + else + { + for(i = r.y1; i <= r.y2; i++) + { + m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1), + m_color, + m_glyph->span(r.y2 - i)); + } + } + } + x += r.dx; + y += r.dy; + ++str; + } + } + + private: + ren_type* m_ren; + glyph_gen_type* m_glyph; + color_type m_color; + }; + + + + + + + //===================================================renderer_raster_htext + template<class ScanlineRenderer, class GlyphGenerator> + class renderer_raster_htext + { + public: + typedef ScanlineRenderer ren_type; + typedef GlyphGenerator glyph_gen_type; + typedef typename glyph_gen_type::glyph_rect glyph_rect; + + class scanline_single_span + { + public: + typedef agg::cover_type cover_type; + + //---------------------------------------------------------------- + struct const_span + { + int x; + unsigned len; + const cover_type* covers; + + const_span() {} + const_span(int x_, unsigned len_, const cover_type* covers_) : + x(x_), len(len_), covers(covers_) + {} + }; + + typedef const const_span* const_iterator; + + //---------------------------------------------------------------- + scanline_single_span(int x, int y, unsigned len, + const cover_type* covers) : + m_y(y), + m_span(x, len, covers) + {} + + //---------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return 1; } + const_iterator begin() const { return &m_span; } + + private: + //---------------------------------------------------------------- + int m_y; + const_span m_span; + }; + + + + //-------------------------------------------------------------------- + renderer_raster_htext(ren_type& ren, glyph_gen_type& glyph) : + m_ren(&ren), + m_glyph(&glyph) + { + } + + + //-------------------------------------------------------------------- + template<class CharT> + void render_text(double x, double y, const CharT* str, bool flip=false) + { + glyph_rect r; + while(*str) + { + m_glyph->prepare(&r, x, y, *str, flip); + if(r.x2 >= r.x1) + { + m_ren->prepare(); + int i; + if(flip) + { + for(i = r.y1; i <= r.y2; i++) + { + m_ren->render( + scanline_single_span(r.x1, + i, + (r.x2 - r.x1 + 1), + m_glyph->span(r.y2 - i))); + } + } + else + { + for(i = r.y1; i <= r.y2; i++) + { + m_ren->render( + scanline_single_span(r.x1, + i, + (r.x2 - r.x1 + 1), + m_glyph->span(i - r.y1))); + } + } + } + x += r.dx; + y += r.dy; + ++str; + } + } + + private: + ren_type* m_ren; + glyph_gen_type* m_glyph; + }; + + + + +} + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_renderer_scanline.h b/jni/desmume/src/android/agg/include/agg_renderer_scanline.h new file mode 100755 index 0000000..c3bb6f0 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_renderer_scanline.h @@ -0,0 +1,861 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERER_SCANLINE_INCLUDED +#define AGG_RENDERER_SCANLINE_INCLUDED + +#include "agg_basics.h" +#include "agg_renderer_base.h" + +namespace agg +{ + + //================================================render_scanline_aa_solid + template<class Scanline, class BaseRenderer, class ColorT> + void render_scanline_aa_solid(const Scanline& sl, + BaseRenderer& ren, + const ColorT& color) + { + int y = sl.y(); + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + + for(;;) + { + int x = span->x; + if(span->len > 0) + { + ren.blend_solid_hspan(x, y, (unsigned)span->len, + color, + span->covers); + } + else + { + ren.blend_hline(x, y, (unsigned)(x - span->len - 1), + color, + *(span->covers)); + } + if(--num_spans == 0) break; + ++span; + } + } + + //===============================================render_scanlines_aa_solid + template<class Rasterizer, class Scanline, + class BaseRenderer, class ColorT> + void render_scanlines_aa_solid(Rasterizer& ras, Scanline& sl, + BaseRenderer& ren, const ColorT& color) + { + if(ras.rewind_scanlines()) + { + // Explicitly convert "color" to the BaseRenderer color type. + // For example, it can be called with color type "rgba", while + // "rgba8" is needed. Otherwise it will be implicitly + // converted in the loop many times. + //---------------------- + typename BaseRenderer::color_type ren_color(color); + + sl.reset(ras.min_x(), ras.max_x()); + while(ras.sweep_scanline(sl)) + { + //render_scanline_aa_solid(sl, ren, ren_color); + + // This code is equivalent to the above call (copy/paste). + // It's just a "manual" optimization for old compilers, + // like Microsoft Visual C++ v6.0 + //------------------------------- + int y = sl.y(); + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + + for(;;) + { + int x = span->x; + if(span->len > 0) + { + ren.blend_solid_hspan(x, y, (unsigned)span->len, + ren_color, + span->covers); + } + else + { + ren.blend_hline(x, y, (unsigned)(x - span->len - 1), + ren_color, + *(span->covers)); + } + if(--num_spans == 0) break; + ++span; + } + } + } + } + + //==============================================renderer_scanline_aa_solid + template<class BaseRenderer> class renderer_scanline_aa_solid + { + public: + typedef BaseRenderer base_ren_type; + typedef typename base_ren_type::color_type color_type; + + //-------------------------------------------------------------------- + renderer_scanline_aa_solid() : m_ren(0) {} + explicit renderer_scanline_aa_solid(base_ren_type& ren) : m_ren(&ren) {} + void attach(base_ren_type& ren) + { + m_ren = &ren; + } + + //-------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + template<class Scanline> void render(const Scanline& sl) + { + render_scanline_aa_solid(sl, *m_ren, m_color); + } + + private: + base_ren_type* m_ren; + color_type m_color; + }; + + + + + + + + + + + + + + //======================================================render_scanline_aa + template<class Scanline, class BaseRenderer, + class SpanAllocator, class SpanGenerator> + void render_scanline_aa(const Scanline& sl, BaseRenderer& ren, + SpanAllocator& alloc, SpanGenerator& span_gen) + { + int y = sl.y(); + + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + for(;;) + { + int x = span->x; + int len = span->len; + const typename Scanline::cover_type* covers = span->covers; + + if(len < 0) len = -len; + typename BaseRenderer::color_type* colors = alloc.allocate(len); + span_gen.generate(colors, x, y, len); + ren.blend_color_hspan(x, y, len, colors, + (span->len < 0) ? 0 : covers, *covers); + + if(--num_spans == 0) break; + ++span; + } + } + + //=====================================================render_scanlines_aa + template<class Rasterizer, class Scanline, class BaseRenderer, + class SpanAllocator, class SpanGenerator> + void render_scanlines_aa(Rasterizer& ras, Scanline& sl, BaseRenderer& ren, + SpanAllocator& alloc, SpanGenerator& span_gen) + { + if(ras.rewind_scanlines()) + { + sl.reset(ras.min_x(), ras.max_x()); + span_gen.prepare(); + while(ras.sweep_scanline(sl)) + { + render_scanline_aa(sl, ren, alloc, span_gen); + } + } + } + + //====================================================renderer_scanline_aa + template<class BaseRenderer, class SpanAllocator, class SpanGenerator> + class renderer_scanline_aa + { + public: + typedef BaseRenderer base_ren_type; + typedef SpanAllocator alloc_type; + typedef SpanGenerator span_gen_type; + + //-------------------------------------------------------------------- + renderer_scanline_aa() : m_ren(0), m_alloc(0), m_span_gen(0) {} + renderer_scanline_aa(base_ren_type& ren, + alloc_type& alloc, + span_gen_type& span_gen) : + m_ren(&ren), + m_alloc(&alloc), + m_span_gen(&span_gen) + {} + void attach(base_ren_type& ren, + alloc_type& alloc, + span_gen_type& span_gen) + { + m_ren = &ren; + m_alloc = &alloc; + m_span_gen = &span_gen; + } + + //-------------------------------------------------------------------- + void prepare() { m_span_gen->prepare(); } + + //-------------------------------------------------------------------- + template<class Scanline> void render(const Scanline& sl) + { + render_scanline_aa(sl, *m_ren, *m_alloc, *m_span_gen); + } + + private: + base_ren_type* m_ren; + alloc_type* m_alloc; + span_gen_type* m_span_gen; + }; + + + + + + + //===============================================render_scanline_bin_solid + template<class Scanline, class BaseRenderer, class ColorT> + void render_scanline_bin_solid(const Scanline& sl, + BaseRenderer& ren, + const ColorT& color) + { + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + for(;;) + { + ren.blend_hline(span->x, + sl.y(), + span->x - 1 + ((span->len < 0) ? + -span->len : + span->len), + color, + cover_full); + if(--num_spans == 0) break; + ++span; + } + } + + //==============================================render_scanlines_bin_solid + template<class Rasterizer, class Scanline, + class BaseRenderer, class ColorT> + void render_scanlines_bin_solid(Rasterizer& ras, Scanline& sl, + BaseRenderer& ren, const ColorT& color) + { + if(ras.rewind_scanlines()) + { + // Explicitly convert "color" to the BaseRenderer color type. + // For example, it can be called with color type "rgba", while + // "rgba8" is needed. Otherwise it will be implicitly + // converted in the loop many times. + //---------------------- + typename BaseRenderer::color_type ren_color(color); + + sl.reset(ras.min_x(), ras.max_x()); + while(ras.sweep_scanline(sl)) + { + //render_scanline_bin_solid(sl, ren, ren_color); + + // This code is equivalent to the above call (copy/paste). + // It's just a "manual" optimization for old compilers, + // like Microsoft Visual C++ v6.0 + //------------------------------- + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + for(;;) + { + ren.blend_hline(span->x, + sl.y(), + span->x - 1 + ((span->len < 0) ? + -span->len : + span->len), + ren_color, + cover_full); + if(--num_spans == 0) break; + ++span; + } + } + } + } + + //=============================================renderer_scanline_bin_solid + template<class BaseRenderer> class renderer_scanline_bin_solid + { + public: + typedef BaseRenderer base_ren_type; + typedef typename base_ren_type::color_type color_type; + + //-------------------------------------------------------------------- + renderer_scanline_bin_solid() : m_ren(0) {} + explicit renderer_scanline_bin_solid(base_ren_type& ren) : m_ren(&ren) {} + void attach(base_ren_type& ren) + { + m_ren = &ren; + } + + //-------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + template<class Scanline> void render(const Scanline& sl) + { + render_scanline_bin_solid(sl, *m_ren, m_color); + } + + private: + base_ren_type* m_ren; + color_type m_color; + }; + + + + + + + + + //======================================================render_scanline_bin + template<class Scanline, class BaseRenderer, + class SpanAllocator, class SpanGenerator> + void render_scanline_bin(const Scanline& sl, BaseRenderer& ren, + SpanAllocator& alloc, SpanGenerator& span_gen) + { + int y = sl.y(); + + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + for(;;) + { + int x = span->x; + int len = span->len; + if(len < 0) len = -len; + typename BaseRenderer::color_type* colors = alloc.allocate(len); + span_gen.generate(colors, x, y, len); + ren.blend_color_hspan(x, y, len, colors, 0, cover_full); + if(--num_spans == 0) break; + ++span; + } + } + + //=====================================================render_scanlines_bin + template<class Rasterizer, class Scanline, class BaseRenderer, + class SpanAllocator, class SpanGenerator> + void render_scanlines_bin(Rasterizer& ras, Scanline& sl, BaseRenderer& ren, + SpanAllocator& alloc, SpanGenerator& span_gen) + { + if(ras.rewind_scanlines()) + { + sl.reset(ras.min_x(), ras.max_x()); + span_gen.prepare(); + while(ras.sweep_scanline(sl)) + { + render_scanline_bin(sl, ren, alloc, span_gen); + } + } + } + + //====================================================renderer_scanline_bin + template<class BaseRenderer, class SpanAllocator, class SpanGenerator> + class renderer_scanline_bin + { + public: + typedef BaseRenderer base_ren_type; + typedef SpanAllocator alloc_type; + typedef SpanGenerator span_gen_type; + + //-------------------------------------------------------------------- + renderer_scanline_bin() : m_ren(0), m_alloc(0), m_span_gen(0) {} + renderer_scanline_bin(base_ren_type& ren, + alloc_type& alloc, + span_gen_type& span_gen) : + m_ren(&ren), + m_alloc(&alloc), + m_span_gen(&span_gen) + {} + void attach(base_ren_type& ren, + alloc_type& alloc, + span_gen_type& span_gen) + { + m_ren = &ren; + m_alloc = &alloc; + m_span_gen = &span_gen; + } + + //-------------------------------------------------------------------- + void prepare() { m_span_gen->prepare(); } + + //-------------------------------------------------------------------- + template<class Scanline> void render(const Scanline& sl) + { + render_scanline_bin(sl, *m_ren, *m_alloc, *m_span_gen); + } + + private: + base_ren_type* m_ren; + alloc_type* m_alloc; + span_gen_type* m_span_gen; + }; + + + + + + + + + + + //========================================================render_scanlines + template<class Rasterizer, class Scanline, class Renderer> + void render_scanlines(Rasterizer& ras, Scanline& sl, Renderer& ren) + { + if(ras.rewind_scanlines()) + { + sl.reset(ras.min_x(), ras.max_x()); + ren.prepare(); + while(ras.sweep_scanline(sl)) + { + ren.render(sl); + } + } + } + + //========================================================render_all_paths + template<class Rasterizer, class Scanline, class Renderer, + class VertexSource, class ColorStorage, class PathId> + void render_all_paths(Rasterizer& ras, + Scanline& sl, + Renderer& r, + VertexSource& vs, + const ColorStorage& as, + const PathId& path_id, + unsigned num_paths) + { + for(unsigned i = 0; i < num_paths; i++) + { + ras.reset(); + ras.add_path(vs, path_id[i]); + r.color(as[i]); + render_scanlines(ras, sl, r); + } + } + + + + + + + //=============================================render_scanlines_compound + template<class Rasterizer, + class ScanlineAA, + class ScanlineBin, + class BaseRenderer, + class SpanAllocator, + class StyleHandler> + void render_scanlines_compound(Rasterizer& ras, + ScanlineAA& sl_aa, + ScanlineBin& sl_bin, + BaseRenderer& ren, + SpanAllocator& alloc, + StyleHandler& sh) + { + if(ras.rewind_scanlines()) + { + int min_x = ras.min_x(); + int len = ras.max_x() - min_x + 2; + sl_aa.reset(min_x, ras.max_x()); + sl_bin.reset(min_x, ras.max_x()); + + typedef typename BaseRenderer::color_type color_type; + color_type* color_span = alloc.allocate(len * 2); + color_type* mix_buffer = color_span + len; + unsigned num_spans; + + unsigned num_styles; + unsigned style; + bool solid; + while((num_styles = ras.sweep_styles()) > 0) + { + typename ScanlineAA::const_iterator span_aa; + if(num_styles == 1) + { + // Optimization for a single style. Happens often + //------------------------- + if(ras.sweep_scanline(sl_aa, 0)) + { + style = ras.style(0); + if(sh.is_solid(style)) + { + // Just solid fill + //----------------------- + render_scanline_aa_solid(sl_aa, ren, sh.color(style)); + } + else + { + // Arbitrary span generator + //----------------------- + span_aa = sl_aa.begin(); + num_spans = sl_aa.num_spans(); + for(;;) + { + len = span_aa->len; + sh.generate_span(color_span, + span_aa->x, + sl_aa.y(), + len, + style); + + ren.blend_color_hspan(span_aa->x, + sl_aa.y(), + span_aa->len, + color_span, + span_aa->covers); + if(--num_spans == 0) break; + ++span_aa; + } + } + } + } + else + { + if(ras.sweep_scanline(sl_bin, -1)) + { + // Clear the spans of the mix_buffer + //-------------------- + typename ScanlineBin::const_iterator span_bin = sl_bin.begin(); + num_spans = sl_bin.num_spans(); + for(;;) + { + memset(mix_buffer + span_bin->x - min_x, + 0, + span_bin->len * sizeof(color_type)); + + if(--num_spans == 0) break; + ++span_bin; + } + + unsigned i; + for(i = 0; i < num_styles; i++) + { + style = ras.style(i); + solid = sh.is_solid(style); + + if(ras.sweep_scanline(sl_aa, i)) + { + color_type* colors; + color_type* cspan; + typename ScanlineAA::cover_type* covers; + span_aa = sl_aa.begin(); + num_spans = sl_aa.num_spans(); + if(solid) + { + // Just solid fill + //----------------------- + for(;;) + { + color_type c = sh.color(style); + len = span_aa->len; + colors = mix_buffer + span_aa->x - min_x; + covers = span_aa->covers; + do + { + if(*covers == cover_full) + { + *colors = c; + } + else + { + colors->add(c, *covers); + } + ++colors; + ++covers; + } + while(--len); + if(--num_spans == 0) break; + ++span_aa; + } + } + else + { + // Arbitrary span generator + //----------------------- + for(;;) + { + len = span_aa->len; + colors = mix_buffer + span_aa->x - min_x; + cspan = color_span; + sh.generate_span(cspan, + span_aa->x, + sl_aa.y(), + len, + style); + covers = span_aa->covers; + do + { + if(*covers == cover_full) + { + *colors = *cspan; + } + else + { + colors->add(*cspan, *covers); + } + ++cspan; + ++colors; + ++covers; + } + while(--len); + if(--num_spans == 0) break; + ++span_aa; + } + } + } + } + + // Emit the blended result as a color hspan + //------------------------- + span_bin = sl_bin.begin(); + num_spans = sl_bin.num_spans(); + for(;;) + { + ren.blend_color_hspan(span_bin->x, + sl_bin.y(), + span_bin->len, + mix_buffer + span_bin->x - min_x, + 0, + cover_full); + if(--num_spans == 0) break; + ++span_bin; + } + } // if(ras.sweep_scanline(sl_bin, -1)) + } // if(num_styles == 1) ... else + } // while((num_styles = ras.sweep_styles()) > 0) + } // if(ras.rewind_scanlines()) + } + + //=======================================render_scanlines_compound_layered + template<class Rasterizer, + class ScanlineAA, + class BaseRenderer, + class SpanAllocator, + class StyleHandler> + void render_scanlines_compound_layered(Rasterizer& ras, + ScanlineAA& sl_aa, + BaseRenderer& ren, + SpanAllocator& alloc, + StyleHandler& sh) + { + if(ras.rewind_scanlines()) + { + int min_x = ras.min_x(); + int len = ras.max_x() - min_x + 2; + sl_aa.reset(min_x, ras.max_x()); + + typedef typename BaseRenderer::color_type color_type; + color_type* color_span = alloc.allocate(len * 2); + color_type* mix_buffer = color_span + len; + cover_type* cover_buffer = ras.allocate_cover_buffer(len); + unsigned num_spans; + + unsigned num_styles; + unsigned style; + bool solid; + while((num_styles = ras.sweep_styles()) > 0) + { + typename ScanlineAA::const_iterator span_aa; + if(num_styles == 1) + { + // Optimization for a single style. Happens often + //------------------------- + if(ras.sweep_scanline(sl_aa, 0)) + { + style = ras.style(0); + if(sh.is_solid(style)) + { + // Just solid fill + //----------------------- + render_scanline_aa_solid(sl_aa, ren, sh.color(style)); + } + else + { + // Arbitrary span generator + //----------------------- + span_aa = sl_aa.begin(); + num_spans = sl_aa.num_spans(); + for(;;) + { + len = span_aa->len; + sh.generate_span(color_span, + span_aa->x, + sl_aa.y(), + len, + style); + + ren.blend_color_hspan(span_aa->x, + sl_aa.y(), + span_aa->len, + color_span, + span_aa->covers); + if(--num_spans == 0) break; + ++span_aa; + } + } + } + } + else + { + int sl_start = ras.scanline_start(); + unsigned sl_len = ras.scanline_length(); + + if(sl_len) + { + memset(mix_buffer + sl_start - min_x, + 0, + sl_len * sizeof(color_type)); + + memset(cover_buffer + sl_start - min_x, + 0, + sl_len * sizeof(cover_type)); + + int sl_y = 0x7FFFFFFF; + unsigned i; + for(i = 0; i < num_styles; i++) + { + style = ras.style(i); + solid = sh.is_solid(style); + + if(ras.sweep_scanline(sl_aa, i)) + { + unsigned cover; + color_type* colors; + color_type* cspan; + cover_type* src_covers; + cover_type* dst_covers; + span_aa = sl_aa.begin(); + num_spans = sl_aa.num_spans(); + sl_y = sl_aa.y(); + if(solid) + { + // Just solid fill + //----------------------- + for(;;) + { + color_type c = sh.color(style); + len = span_aa->len; + colors = mix_buffer + span_aa->x - min_x; + src_covers = span_aa->covers; + dst_covers = cover_buffer + span_aa->x - min_x; + do + { + cover = *src_covers; + if(*dst_covers + cover > cover_full) + { + cover = cover_full - *dst_covers; + } + if(cover) + { + colors->add(c, cover); + *dst_covers += cover; + } + ++colors; + ++src_covers; + ++dst_covers; + } + while(--len); + if(--num_spans == 0) break; + ++span_aa; + } + } + else + { + // Arbitrary span generator + //----------------------- + for(;;) + { + len = span_aa->len; + colors = mix_buffer + span_aa->x - min_x; + cspan = color_span; + sh.generate_span(cspan, + span_aa->x, + sl_aa.y(), + len, + style); + src_covers = span_aa->covers; + dst_covers = cover_buffer + span_aa->x - min_x; + do + { + cover = *src_covers; + if(*dst_covers + cover > cover_full) + { + cover = cover_full - *dst_covers; + } + if(cover) + { + colors->add(*cspan, cover); + *dst_covers += cover; + } + ++cspan; + ++colors; + ++src_covers; + ++dst_covers; + } + while(--len); + if(--num_spans == 0) break; + ++span_aa; + } + } + } + } + ren.blend_color_hspan(sl_start, + sl_y, + sl_len, + mix_buffer + sl_start - min_x, + 0, + cover_full); + } //if(sl_len) + } //if(num_styles == 1) ... else + } //while((num_styles = ras.sweep_styles()) > 0) + } //if(ras.rewind_scanlines()) + } + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_rendering_buffer.h b/jni/desmume/src/android/agg/include/agg_rendering_buffer.h new file mode 100755 index 0000000..3a39caa --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_rendering_buffer.h @@ -0,0 +1,305 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERING_BUFFER_INCLUDED +#define AGG_RENDERING_BUFFER_INCLUDED + +#include "agg_array.h" + +namespace agg +{ + + //===========================================================row_accessor + template<class T> class row_accessor + { + public: + typedef const_row_info<T> row_data; + + //------------------------------------------------------------------- + row_accessor() : + m_buf(0), + m_start(0), + m_width(0), + m_height(0), + m_stride(0) + { + } + + //-------------------------------------------------------------------- + row_accessor(T* buf, unsigned width, unsigned height, int stride) : + m_buf(0), + m_start(0), + m_width(0), + m_height(0), + m_stride(0) + { + attach(buf, width, height, stride); + } + + + //-------------------------------------------------------------------- + void attach(T* buf, unsigned width, unsigned height, int stride) + { + m_buf = m_start = buf; + m_width = width; + m_height = height; + m_stride = stride; + if(stride < 0) + { + m_start = m_buf - int(height - 1) * stride; + } + } + + //-------------------------------------------------------------------- + AGG_INLINE T* buf() { return m_buf; } + AGG_INLINE const T* buf() const { return m_buf; } + AGG_INLINE unsigned width() const { return m_width; } + AGG_INLINE unsigned height() const { return m_height; } + AGG_INLINE int stride() const { return m_stride; } + AGG_INLINE unsigned stride_abs() const + { + return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride); + } + + //-------------------------------------------------------------------- + AGG_INLINE T* row_ptr(int, int y, unsigned) + { + return m_start + y * m_stride; + } + AGG_INLINE T* row_ptr(int y) { return m_start + y * m_stride; } + AGG_INLINE const T* row_ptr(int y) const { return m_start + y * m_stride; } + AGG_INLINE row_data row (int y) const + { + return row_data(0, m_width-1, row_ptr(y)); + } + + //-------------------------------------------------------------------- + template<class RenBuf> + void copy_from(const RenBuf& src) + { + unsigned h = height(); + if(src.height() < h) h = src.height(); + + unsigned l = stride_abs(); + if(src.stride_abs() < l) l = src.stride_abs(); + + l *= sizeof(T); + + unsigned y; + unsigned w = width(); + for (y = 0; y < h; y++) + { + memcpy(row_ptr(0, y, w), src.row_ptr(y), l); + } + } + + //-------------------------------------------------------------------- + void clear(T value) + { + unsigned y; + unsigned w = width(); + unsigned stride = stride_abs(); + for(y = 0; y < height(); y++) + { + T* p = row_ptr(0, y, w); + unsigned x; + for(x = 0; x < stride; x++) + { + *p++ = value; + } + } + } + + private: + //-------------------------------------------------------------------- + T* m_buf; // Pointer to renrdering buffer + T* m_start; // Pointer to first pixel depending on stride + unsigned m_width; // Width in pixels + unsigned m_height; // Height in pixels + int m_stride; // Number of bytes per row. Can be < 0 + }; + + + + + //==========================================================row_ptr_cache + template<class T> class row_ptr_cache + { + public: + typedef const_row_info<T> row_data; + + //------------------------------------------------------------------- + row_ptr_cache() : + m_buf(0), + m_rows(), + m_width(0), + m_height(0), + m_stride(0) + { + } + + //-------------------------------------------------------------------- + row_ptr_cache(T* buf, unsigned width, unsigned height, int stride) : + m_buf(0), + m_rows(), + m_width(0), + m_height(0), + m_stride(0) + { + attach(buf, width, height, stride); + } + + //-------------------------------------------------------------------- + void attach(T* buf, unsigned width, unsigned height, int stride) + { + m_buf = buf; + m_width = width; + m_height = height; + m_stride = stride; + if(height > m_rows.size()) + { + m_rows.resize(height); + } + + T* row_ptr = m_buf; + + if(stride < 0) + { + row_ptr = m_buf - int(height - 1) * stride; + } + + T** rows = &m_rows[0]; + + while(height--) + { + *rows++ = row_ptr; + row_ptr += stride; + } + } + + //-------------------------------------------------------------------- + AGG_INLINE T* buf() { return m_buf; } + AGG_INLINE const T* buf() const { return m_buf; } + AGG_INLINE unsigned width() const { return m_width; } + AGG_INLINE unsigned height() const { return m_height; } + AGG_INLINE int stride() const { return m_stride; } + AGG_INLINE unsigned stride_abs() const + { + return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride); + } + + //-------------------------------------------------------------------- + AGG_INLINE T* row_ptr(int, int y, unsigned) + { + return m_rows[y]; + } + AGG_INLINE T* row_ptr(int y) { return m_rows[y]; } + AGG_INLINE const T* row_ptr(int y) const { return m_rows[y]; } + AGG_INLINE row_data row (int y) const + { + return row_data(0, m_width-1, m_rows[y]); + } + + //-------------------------------------------------------------------- + T const* const* rows() const { return &m_rows[0]; } + + //-------------------------------------------------------------------- + template<class RenBuf> + void copy_from(const RenBuf& src) + { + unsigned h = height(); + if(src.height() < h) h = src.height(); + + unsigned l = stride_abs(); + if(src.stride_abs() < l) l = src.stride_abs(); + + l *= sizeof(T); + + unsigned y; + unsigned w = width(); + for (y = 0; y < h; y++) + { + memcpy(row_ptr(0, y, w), src.row_ptr(y), l); + } + } + + //-------------------------------------------------------------------- + void clear(T value) + { + unsigned y; + unsigned w = width(); + unsigned stride = stride_abs(); + for(y = 0; y < height(); y++) + { + T* p = row_ptr(0, y, w); + unsigned x; + for(x = 0; x < stride; x++) + { + *p++ = value; + } + } + } + + private: + //-------------------------------------------------------------------- + T* m_buf; // Pointer to renrdering buffer + pod_array<T*> m_rows; // Pointers to each row of the buffer + unsigned m_width; // Width in pixels + unsigned m_height; // Height in pixels + int m_stride; // Number of bytes per row. Can be < 0 + }; + + + + + //========================================================rendering_buffer + // + // The definition of the main type for accessing the rows in the frame + // buffer. It provides functionality to navigate to the rows in a + // rectangular matrix, from top to bottom or from bottom to top depending + // on stride. + // + // row_accessor is cheap to create/destroy, but performs one multiplication + // when calling row_ptr(). + // + // row_ptr_cache creates an array of pointers to rows, so, the access + // via row_ptr() may be faster. But it requires memory allocation + // when creating. For example, on typical Intel Pentium hardware + // row_ptr_cache speeds span_image_filter_rgb_nn up to 10% + // + // It's used only in short hand typedefs like pixfmt_rgba32 and can be + // redefined in agg_config.h + // In real applications you can use both, depending on your needs + //------------------------------------------------------------------------ +#ifdef AGG_RENDERING_BUFFER + typedef AGG_RENDERING_BUFFER rendering_buffer; +#else +// typedef row_ptr_cache<int8u> rendering_buffer; + typedef row_accessor<int8u> rendering_buffer; +#endif + +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_rendering_buffer_dynarow.h b/jni/desmume/src/android/agg/include/agg_rendering_buffer_dynarow.h new file mode 100755 index 0000000..74fc3a6 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_rendering_buffer_dynarow.h @@ -0,0 +1,142 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERING_BUFFER_DYNAROW_INCLUDED +#define AGG_RENDERING_BUFFER_DYNAROW_INCLUDED + +#include "agg_array.h" + +namespace agg +{ + + //===============================================rendering_buffer_dynarow + // Rendering buffer class with dynamic allocation of the rows. + // The rows are allocated as needed when requesting for span_ptr(). + // The class automatically calculates min_x and max_x for each row. + // Generally it's more efficient to use this class as a temporary buffer + // for rendering a few lines and then to blend it with another buffer. + // + class rendering_buffer_dynarow + { + public: + typedef row_info<int8u> row_data; + + //------------------------------------------------------------------- + ~rendering_buffer_dynarow() + { + init(0,0,0); + } + + //------------------------------------------------------------------- + rendering_buffer_dynarow() : + m_rows(), + m_width(0), + m_height(0), + m_byte_width(0) + { + } + + // Allocate and clear the buffer + //-------------------------------------------------------------------- + rendering_buffer_dynarow(unsigned width, unsigned height, + unsigned byte_width) : + m_rows(height), + m_width(width), + m_height(height), + m_byte_width(byte_width) + { + memset(&m_rows[0], 0, sizeof(row_data) * height); + } + + // Allocate and clear the buffer + //-------------------------------------------------------------------- + void init(unsigned width, unsigned height, unsigned byte_width) + { + unsigned i; + for(i = 0; i < m_height; ++i) + { + pod_allocator<int8u>::deallocate((int8u*)m_rows[i].ptr, m_byte_width); + } + if(width && height) + { + m_width = width; + m_height = height; + m_byte_width = byte_width; + m_rows.resize(height); + memset(&m_rows[0], 0, sizeof(row_data) * height); + } + } + + //-------------------------------------------------------------------- + unsigned width() const { return m_width; } + unsigned height() const { return m_height; } + unsigned byte_width() const { return m_byte_width; } + + // The main function used for rendering. Returns pointer to the + // pre-allocated span. Memory for the row is allocated as needed. + //-------------------------------------------------------------------- + int8u* row_ptr(int x, int y, unsigned len) + { + row_data* r = &m_rows[y]; + int x2 = x + len - 1; + if(r->ptr) + { + if(x < r->x1) { r->x1 = x; } + if(x2 > r->x2) { r->x2 = x2; } + } + else + { + int8u* p = pod_allocator<int8u>::allocate(m_byte_width); + r->ptr = p; + r->x1 = x; + r->x2 = x2; + memset(p, 0, m_byte_width); + } + return (int8u*)r->ptr; + } + + //-------------------------------------------------------------------- + const int8u* row_ptr(int y) const { return m_rows[y].ptr; } + int8u* row_ptr(int y) { return row_ptr(0, y, m_width); } + row_data row (int y) const { return m_rows[y]; } + + private: + //-------------------------------------------------------------------- + // Prohibit copying + rendering_buffer_dynarow(const rendering_buffer_dynarow&); + const rendering_buffer_dynarow& operator = (const rendering_buffer_dynarow&); + + private: + //-------------------------------------------------------------------- + pod_array<row_data> m_rows; // Pointers to each row of the buffer + unsigned m_width; // Width in pixels + unsigned m_height; // Height in pixels + unsigned m_byte_width; // Width in bytes + }; + + +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_rounded_rect.h b/jni/desmume/src/android/agg/include/agg_rounded_rect.h new file mode 100755 index 0000000..fa46dee --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_rounded_rect.h @@ -0,0 +1,77 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_ROUNDED_RECT_INCLUDED +#define AGG_ROUNDED_RECT_INCLUDED + +#include "agg_basics.h" +#include "agg_arc.h" + +namespace agg +{ + //------------------------------------------------------------rounded_rect + // + // See Implemantation agg_rounded_rect.cpp + // + class rounded_rect + { + public: + rounded_rect() {} + rounded_rect(double x1, double y1, double x2, double y2, double r); + + void rect(double x1, double y1, double x2, double y2); + void radius(double r); + void radius(double rx, double ry); + void radius(double rx_bottom, double ry_bottom, double rx_top, double ry_top); + void radius(double rx1, double ry1, double rx2, double ry2, + double rx3, double ry3, double rx4, double ry4); + void normalize_radius(); + + void approximation_scale(double s) { m_arc.approximation_scale(s); } + double approximation_scale() const { return m_arc.approximation_scale(); } + + void rewind(unsigned); + unsigned vertex(double* x, double* y); + + private: + double m_x1; + double m_y1; + double m_x2; + double m_y2; + double m_rx1; + double m_ry1; + double m_rx2; + double m_ry2; + double m_rx3; + double m_ry3; + double m_rx4; + double m_ry4; + unsigned m_status; + arc m_arc; + }; + +} + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_scanline_bin.h b/jni/desmume/src/android/agg/include/agg_scanline_bin.h new file mode 100755 index 0000000..2d1988d --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_scanline_bin.h @@ -0,0 +1,269 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates (scanline32_bin) has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_SCANLINE_BIN_INCLUDED +#define AGG_SCANLINE_BIN_INCLUDED + +#include "agg_array.h" + +namespace agg +{ + + //=============================================================scanline_bin + // + // This is binary scaline container which supports the interface + // used in the rasterizer::render(). See description of agg_scanline_u8 + // for details. + // + //------------------------------------------------------------------------ + class scanline_bin + { + public: + typedef int32 coord_type; + + struct span + { + int16 x; + int16 len; + }; + + typedef const span* const_iterator; + + //-------------------------------------------------------------------- + scanline_bin() : + m_last_x(0x7FFFFFF0), + m_spans(), + m_cur_span(0) + { + } + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 3; + if(max_len > m_spans.size()) + { + m_spans.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_cur_span = &m_spans[0]; + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned) + { + if(x == m_last_x+1) + { + m_cur_span->len++; + } + else + { + ++m_cur_span; + m_cur_span->x = (int16)x; + m_cur_span->len = 1; + } + m_last_x = x; + } + + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned) + { + if(x == m_last_x+1) + { + m_cur_span->len = (int16)(m_cur_span->len + len); + } + else + { + ++m_cur_span; + m_cur_span->x = (int16)x; + m_cur_span->len = (int16)len; + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const void*) + { + add_span(x, len, 0); + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + m_cur_span = &m_spans[0]; + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } + const_iterator begin() const { return &m_spans[1]; } + + private: + scanline_bin(const scanline_bin&); + const scanline_bin operator = (const scanline_bin&); + + int m_last_x; + int m_y; + pod_array<span> m_spans; + span* m_cur_span; + }; + + + + + + + //===========================================================scanline32_bin + class scanline32_bin + { + public: + typedef int32 coord_type; + + //-------------------------------------------------------------------- + struct span + { + span() {} + span(coord_type x_, coord_type len_) : x(x_), len(len_) {} + + coord_type x; + coord_type len; + }; + typedef pod_bvector<span, 4> span_array_type; + + + //-------------------------------------------------------------------- + class const_iterator + { + public: + const_iterator(const span_array_type& spans) : + m_spans(spans), + m_span_idx(0) + {} + + const span& operator*() const { return m_spans[m_span_idx]; } + const span* operator->() const { return &m_spans[m_span_idx]; } + + void operator ++ () { ++m_span_idx; } + + private: + const span_array_type& m_spans; + unsigned m_span_idx; + }; + + + //-------------------------------------------------------------------- + scanline32_bin() : m_max_len(0), m_last_x(0x7FFFFFF0) {} + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + m_last_x = 0x7FFFFFF0; + m_spans.remove_all(); + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned) + { + if(x == m_last_x+1) + { + m_spans.last().len++; + } + else + { + m_spans.add(span(coord_type(x), 1)); + } + m_last_x = x; + } + + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned) + { + if(x == m_last_x+1) + { + m_spans.last().len += coord_type(len); + } + else + { + m_spans.add(span(coord_type(x), coord_type(len))); + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const void*) + { + add_span(x, len, 0); + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + m_spans.remove_all(); + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return m_spans.size(); } + const_iterator begin() const { return const_iterator(m_spans); } + + private: + scanline32_bin(const scanline32_bin&); + const scanline32_bin operator = (const scanline32_bin&); + + unsigned m_max_len; + int m_last_x; + int m_y; + span_array_type m_spans; + }; + + + + + +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_scanline_boolean_algebra.h b/jni/desmume/src/android/agg/include/agg_scanline_boolean_algebra.h new file mode 100755 index 0000000..cbae9f1 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_scanline_boolean_algebra.h @@ -0,0 +1,1576 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_SCANLINE_BOOLEAN_ALGEBRA_INCLUDED +#define AGG_SCANLINE_BOOLEAN_ALGEBRA_INCLUDED + +#include <stdlib.h> +#include <math.h> +#include "agg_basics.h" + + +namespace agg +{ + + //-----------------------------------------------sbool_combine_spans_bin + // Functor. + // Combine two binary encoded spans, i.e., when we don't have any + // anti-aliasing information, but only X and Length. The function + // is compatible with any type of scanlines. + //---------------- + template<class Scanline1, + class Scanline2, + class Scanline> + struct sbool_combine_spans_bin + { + void operator () (const typename Scanline1::const_iterator&, + const typename Scanline2::const_iterator&, + int x, unsigned len, + Scanline& sl) const + { + sl.add_span(x, len, cover_full); + } + }; + + + + //---------------------------------------------sbool_combine_spans_empty + // Functor. + // Combine two spans as empty ones. The functor does nothing + // and is used to XOR binary spans. + //---------------- + template<class Scanline1, + class Scanline2, + class Scanline> + struct sbool_combine_spans_empty + { + void operator () (const typename Scanline1::const_iterator&, + const typename Scanline2::const_iterator&, + int, unsigned, + Scanline&) const + {} + }; + + + + //--------------------------------------------------sbool_add_span_empty + // Functor. + // Add nothing. Used in conbine_shapes_sub + //---------------- + template<class Scanline1, + class Scanline> + struct sbool_add_span_empty + { + void operator () (const typename Scanline1::const_iterator&, + int, unsigned, + Scanline&) const + {} + }; + + + //----------------------------------------------------sbool_add_span_bin + // Functor. + // Add a binary span + //---------------- + template<class Scanline1, + class Scanline> + struct sbool_add_span_bin + { + void operator () (const typename Scanline1::const_iterator&, + int x, unsigned len, + Scanline& sl) const + { + sl.add_span(x, len, cover_full); + } + }; + + + + + //-----------------------------------------------------sbool_add_span_aa + // Functor. + // Add an anti-aliased span + // anti-aliasing information, but only X and Length. The function + // is compatible with any type of scanlines. + //---------------- + template<class Scanline1, + class Scanline> + struct sbool_add_span_aa + { + void operator () (const typename Scanline1::const_iterator& span, + int x, unsigned len, + Scanline& sl) const + { + if(span->len < 0) + { + sl.add_span(x, len, *span->covers); + } + else + if(span->len > 0) + { + const typename Scanline1::cover_type* covers = span->covers; + if(span->x < x) covers += x - span->x; + sl.add_cells(x, len, covers); + } + } + }; + + + + + //----------------------------------------------sbool_intersect_spans_aa + // Functor. + // Intersect two spans preserving the anti-aliasing information. + // The result is added to the "sl" scanline. + //------------------ + template<class Scanline1, + class Scanline2, + class Scanline, + unsigned CoverShift = cover_shift> + struct sbool_intersect_spans_aa + { + enum cover_scale_e + { + cover_shift = CoverShift, + cover_size = 1 << cover_shift, + cover_mask = cover_size - 1, + cover_full = cover_mask + }; + + + void operator () (const typename Scanline1::const_iterator& span1, + const typename Scanline2::const_iterator& span2, + int x, unsigned len, + Scanline& sl) const + { + unsigned cover; + const typename Scanline1::cover_type* covers1; + const typename Scanline2::cover_type* covers2; + + // Calculate the operation code and choose the + // proper combination algorithm. + // 0 = Both spans are of AA type + // 1 = span1 is solid, span2 is AA + // 2 = span1 is AA, span2 is solid + // 3 = Both spans are of solid type + //----------------- + switch((span1->len < 0) | ((span2->len < 0) << 1)) + { + case 0: // Both are AA spans + covers1 = span1->covers; + covers2 = span2->covers; + if(span1->x < x) covers1 += x - span1->x; + if(span2->x < x) covers2 += x - span2->x; + do + { + cover = *covers1++ * *covers2++; + sl.add_cell(x++, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + while(--len); + break; + + case 1: // span1 is solid, span2 is AA + covers2 = span2->covers; + if(span2->x < x) covers2 += x - span2->x; + if(*(span1->covers) == cover_full) + { + sl.add_cells(x, len, covers2); + } + else + { + do + { + cover = *(span1->covers) * *covers2++; + sl.add_cell(x++, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + while(--len); + } + break; + + case 2: // span1 is AA, span2 is solid + covers1 = span1->covers; + if(span1->x < x) covers1 += x - span1->x; + if(*(span2->covers) == cover_full) + { + sl.add_cells(x, len, covers1); + } + else + { + do + { + cover = *covers1++ * *(span2->covers); + sl.add_cell(x++, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + while(--len); + } + break; + + case 3: // Both are solid spans + cover = *(span1->covers) * *(span2->covers); + sl.add_span(x, len, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + break; + } + } + }; + + + + + + + //--------------------------------------------------sbool_unite_spans_aa + // Functor. + // Unite two spans preserving the anti-aliasing information. + // The result is added to the "sl" scanline. + //------------------ + template<class Scanline1, + class Scanline2, + class Scanline, + unsigned CoverShift = cover_shift> + struct sbool_unite_spans_aa + { + enum cover_scale_e + { + cover_shift = CoverShift, + cover_size = 1 << cover_shift, + cover_mask = cover_size - 1, + cover_full = cover_mask + }; + + + void operator () (const typename Scanline1::const_iterator& span1, + const typename Scanline2::const_iterator& span2, + int x, unsigned len, + Scanline& sl) const + { + unsigned cover; + const typename Scanline1::cover_type* covers1; + const typename Scanline2::cover_type* covers2; + + // Calculate the operation code and choose the + // proper combination algorithm. + // 0 = Both spans are of AA type + // 1 = span1 is solid, span2 is AA + // 2 = span1 is AA, span2 is solid + // 3 = Both spans are of solid type + //----------------- + switch((span1->len < 0) | ((span2->len < 0) << 1)) + { + case 0: // Both are AA spans + covers1 = span1->covers; + covers2 = span2->covers; + if(span1->x < x) covers1 += x - span1->x; + if(span2->x < x) covers2 += x - span2->x; + do + { + cover = cover_mask * cover_mask - + (cover_mask - *covers1++) * + (cover_mask - *covers2++); + sl.add_cell(x++, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + while(--len); + break; + + case 1: // span1 is solid, span2 is AA + covers2 = span2->covers; + if(span2->x < x) covers2 += x - span2->x; + if(*(span1->covers) == cover_full) + { + sl.add_span(x, len, cover_full); + } + else + { + do + { + cover = cover_mask * cover_mask - + (cover_mask - *(span1->covers)) * + (cover_mask - *covers2++); + sl.add_cell(x++, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + while(--len); + } + break; + + case 2: // span1 is AA, span2 is solid + covers1 = span1->covers; + if(span1->x < x) covers1 += x - span1->x; + if(*(span2->covers) == cover_full) + { + sl.add_span(x, len, cover_full); + } + else + { + do + { + cover = cover_mask * cover_mask - + (cover_mask - *covers1++) * + (cover_mask - *(span2->covers)); + sl.add_cell(x++, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + while(--len); + } + break; + + case 3: // Both are solid spans + cover = cover_mask * cover_mask - + (cover_mask - *(span1->covers)) * + (cover_mask - *(span2->covers)); + sl.add_span(x, len, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + break; + } + } + }; + + + //---------------------------------------------sbool_xor_formula_linear + template<unsigned CoverShift = cover_shift> + struct sbool_xor_formula_linear + { + enum cover_scale_e + { + cover_shift = CoverShift, + cover_size = 1 << cover_shift, + cover_mask = cover_size - 1 + }; + + static AGG_INLINE unsigned calculate(unsigned a, unsigned b) + { + unsigned cover = a + b; + if(cover > cover_mask) cover = cover_mask + cover_mask - cover; + return cover; + } + }; + + + //---------------------------------------------sbool_xor_formula_saddle + template<unsigned CoverShift = cover_shift> + struct sbool_xor_formula_saddle + { + enum cover_scale_e + { + cover_shift = CoverShift, + cover_size = 1 << cover_shift, + cover_mask = cover_size - 1 + }; + + static AGG_INLINE unsigned calculate(unsigned a, unsigned b) + { + unsigned k = a * b; + if(k == cover_mask * cover_mask) return 0; + + a = (cover_mask * cover_mask - (a << cover_shift) + k) >> cover_shift; + b = (cover_mask * cover_mask - (b << cover_shift) + k) >> cover_shift; + return cover_mask - ((a * b) >> cover_shift); + } + }; + + + //-------------------------------------------sbool_xor_formula_abs_diff + struct sbool_xor_formula_abs_diff + { + static AGG_INLINE unsigned calculate(unsigned a, unsigned b) + { + return unsigned(abs(int(a) - int(b))); + } + }; + + + + //----------------------------------------------------sbool_xor_spans_aa + // Functor. + // XOR two spans preserving the anti-aliasing information. + // The result is added to the "sl" scanline. + //------------------ + template<class Scanline1, + class Scanline2, + class Scanline, + class XorFormula, + unsigned CoverShift = cover_shift> + struct sbool_xor_spans_aa + { + enum cover_scale_e + { + cover_shift = CoverShift, + cover_size = 1 << cover_shift, + cover_mask = cover_size - 1, + cover_full = cover_mask + }; + + + void operator () (const typename Scanline1::const_iterator& span1, + const typename Scanline2::const_iterator& span2, + int x, unsigned len, + Scanline& sl) const + { + unsigned cover; + const typename Scanline1::cover_type* covers1; + const typename Scanline2::cover_type* covers2; + + // Calculate the operation code and choose the + // proper combination algorithm. + // 0 = Both spans are of AA type + // 1 = span1 is solid, span2 is AA + // 2 = span1 is AA, span2 is solid + // 3 = Both spans are of solid type + //----------------- + switch((span1->len < 0) | ((span2->len < 0) << 1)) + { + case 0: // Both are AA spans + covers1 = span1->covers; + covers2 = span2->covers; + if(span1->x < x) covers1 += x - span1->x; + if(span2->x < x) covers2 += x - span2->x; + do + { + cover = XorFormula::calculate(*covers1++, *covers2++); + if(cover) sl.add_cell(x, cover); + ++x; + } + while(--len); + break; + + case 1: // span1 is solid, span2 is AA + covers2 = span2->covers; + if(span2->x < x) covers2 += x - span2->x; + do + { + cover = XorFormula::calculate(*(span1->covers), *covers2++); + if(cover) sl.add_cell(x, cover); + ++x; + } + while(--len); + break; + + case 2: // span1 is AA, span2 is solid + covers1 = span1->covers; + if(span1->x < x) covers1 += x - span1->x; + do + { + cover = XorFormula::calculate(*covers1++, *(span2->covers)); + if(cover) sl.add_cell(x, cover); + ++x; + } + while(--len); + break; + + case 3: // Both are solid spans + cover = XorFormula::calculate(*(span1->covers), *(span2->covers)); + if(cover) sl.add_span(x, len, cover); + break; + + } + } + }; + + + + + + //-----------------------------------------------sbool_subtract_spans_aa + // Functor. + // Unite two spans preserving the anti-aliasing information. + // The result is added to the "sl" scanline. + //------------------ + template<class Scanline1, + class Scanline2, + class Scanline, + unsigned CoverShift = cover_shift> + struct sbool_subtract_spans_aa + { + enum cover_scale_e + { + cover_shift = CoverShift, + cover_size = 1 << cover_shift, + cover_mask = cover_size - 1, + cover_full = cover_mask + }; + + + void operator () (const typename Scanline1::const_iterator& span1, + const typename Scanline2::const_iterator& span2, + int x, unsigned len, + Scanline& sl) const + { + unsigned cover; + const typename Scanline1::cover_type* covers1; + const typename Scanline2::cover_type* covers2; + + // Calculate the operation code and choose the + // proper combination algorithm. + // 0 = Both spans are of AA type + // 1 = span1 is solid, span2 is AA + // 2 = span1 is AA, span2 is solid + // 3 = Both spans are of solid type + //----------------- + switch((span1->len < 0) | ((span2->len < 0) << 1)) + { + case 0: // Both are AA spans + covers1 = span1->covers; + covers2 = span2->covers; + if(span1->x < x) covers1 += x - span1->x; + if(span2->x < x) covers2 += x - span2->x; + do + { + cover = *covers1++ * (cover_mask - *covers2++); + if(cover) + { + sl.add_cell(x, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + ++x; + } + while(--len); + break; + + case 1: // span1 is solid, span2 is AA + covers2 = span2->covers; + if(span2->x < x) covers2 += x - span2->x; + do + { + cover = *(span1->covers) * (cover_mask - *covers2++); + if(cover) + { + sl.add_cell(x, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + ++x; + } + while(--len); + break; + + case 2: // span1 is AA, span2 is solid + covers1 = span1->covers; + if(span1->x < x) covers1 += x - span1->x; + if(*(span2->covers) != cover_full) + { + do + { + cover = *covers1++ * (cover_mask - *(span2->covers)); + if(cover) + { + sl.add_cell(x, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + ++x; + } + while(--len); + } + break; + + case 3: // Both are solid spans + cover = *(span1->covers) * (cover_mask - *(span2->covers)); + if(cover) + { + sl.add_span(x, len, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + break; + } + } + }; + + + + + + + //--------------------------------------------sbool_add_spans_and_render + template<class Scanline1, + class Scanline, + class Renderer, + class AddSpanFunctor> + void sbool_add_spans_and_render(const Scanline1& sl1, + Scanline& sl, + Renderer& ren, + AddSpanFunctor add_span) + { + sl.reset_spans(); + typename Scanline1::const_iterator span = sl1.begin(); + unsigned num_spans = sl1.num_spans(); + for(;;) + { + add_span(span, span->x, abs((int)span->len), sl); + if(--num_spans == 0) break; + ++span; + } + sl.finalize(sl1.y()); + ren.render(sl); + } + + + + + + + + //---------------------------------------------sbool_intersect_scanlines + // Intersect two scanlines, "sl1" and "sl2" and generate a new "sl" one. + // The combine_spans functor can be of type sbool_combine_spans_bin or + // sbool_intersect_spans_aa. First is a general functor to combine + // two spans without Anti-Aliasing, the second preserves the AA + // information, but works slower + // + template<class Scanline1, + class Scanline2, + class Scanline, + class CombineSpansFunctor> + void sbool_intersect_scanlines(const Scanline1& sl1, + const Scanline2& sl2, + Scanline& sl, + CombineSpansFunctor combine_spans) + { + sl.reset_spans(); + + unsigned num1 = sl1.num_spans(); + if(num1 == 0) return; + + unsigned num2 = sl2.num_spans(); + if(num2 == 0) return; + + typename Scanline1::const_iterator span1 = sl1.begin(); + typename Scanline2::const_iterator span2 = sl2.begin(); + + while(num1 && num2) + { + int xb1 = span1->x; + int xb2 = span2->x; + int xe1 = xb1 + abs((int)span1->len) - 1; + int xe2 = xb2 + abs((int)span2->len) - 1; + + // Determine what spans we should advance in the next step + // The span with the least ending X should be advanced + // advance_both is just an optimization when we ending + // coordinates are the same and we can advance both + //-------------- + bool advance_span1 = xe1 < xe2; + bool advance_both = xe1 == xe2; + + // Find the intersection of the spans + // and check if they intersect + //-------------- + if(xb1 < xb2) xb1 = xb2; + if(xe1 > xe2) xe1 = xe2; + if(xb1 <= xe1) + { + combine_spans(span1, span2, xb1, xe1 - xb1 + 1, sl); + } + + // Advance the spans + //-------------- + if(advance_both) + { + --num1; + --num2; + if(num1) ++span1; + if(num2) ++span2; + } + else + { + if(advance_span1) + { + --num1; + if(num1) ++span1; + } + else + { + --num2; + if(num2) ++span2; + } + } + } + } + + + + + + + + + //------------------------------------------------sbool_intersect_shapes + // Intersect the scanline shapes. Here the "Scanline Generator" + // abstraction is used. ScanlineGen1 and ScanlineGen2 are + // the generators, and can be of type rasterizer_scanline_aa<>. + // There function requires three scanline containers that can be of + // different types. + // "sl1" and "sl2" are used to retrieve scanlines from the generators, + // "sl" is ised as the resulting scanline to render it. + // The external "sl1" and "sl2" are used only for the sake of + // optimization and reusing of the scanline objects. + // the function calls sbool_intersect_scanlines with CombineSpansFunctor + // as the last argument. See sbool_intersect_scanlines for details. + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer, + class CombineSpansFunctor> + void sbool_intersect_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren, + CombineSpansFunctor combine_spans) + { + // Prepare the scanline generators. + // If anyone of them doesn't contain + // any scanlines, then return. + //----------------- + if(!sg1.rewind_scanlines()) return; + if(!sg2.rewind_scanlines()) return; + + // Get the bounding boxes + //---------------- + rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); + rect_i r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y()); + + // Calculate the intersection of the bounding + // boxes and return if they don't intersect. + //----------------- + rect_i ir = intersect_rectangles(r1, r2); + if(!ir.is_valid()) return; + + // Reset the scanlines and get two first ones + //----------------- + sl.reset(ir.x1, ir.x2); + sl1.reset(sg1.min_x(), sg1.max_x()); + sl2.reset(sg2.min_x(), sg2.max_x()); + if(!sg1.sweep_scanline(sl1)) return; + if(!sg2.sweep_scanline(sl2)) return; + + ren.prepare(); + + // The main loop + // Here we synchronize the scanlines with + // the same Y coordinate, ignoring all other ones. + // Only scanlines having the same Y-coordinate + // are to be combined. + //----------------- + for(;;) + { + while(sl1.y() < sl2.y()) + { + if(!sg1.sweep_scanline(sl1)) return; + } + while(sl2.y() < sl1.y()) + { + if(!sg2.sweep_scanline(sl2)) return; + } + + if(sl1.y() == sl2.y()) + { + // The Y coordinates are the same. + // Combine the scanlines, render if they contain any spans, + // and advance both generators to the next scanlines + //---------------------- + sbool_intersect_scanlines(sl1, sl2, sl, combine_spans); + if(sl.num_spans()) + { + sl.finalize(sl1.y()); + ren.render(sl); + } + if(!sg1.sweep_scanline(sl1)) return; + if(!sg2.sweep_scanline(sl2)) return; + } + } + } + + + + + + + + //-------------------------------------------------sbool_unite_scanlines + // Unite two scanlines, "sl1" and "sl2" and generate a new "sl" one. + // The combine_spans functor can be of type sbool_combine_spans_bin or + // sbool_intersect_spans_aa. First is a general functor to combine + // two spans without Anti-Aliasing, the second preserves the AA + // information, but works slower + // + template<class Scanline1, + class Scanline2, + class Scanline, + class AddSpanFunctor1, + class AddSpanFunctor2, + class CombineSpansFunctor> + void sbool_unite_scanlines(const Scanline1& sl1, + const Scanline2& sl2, + Scanline& sl, + AddSpanFunctor1 add_span1, + AddSpanFunctor2 add_span2, + CombineSpansFunctor combine_spans) + { + sl.reset_spans(); + + unsigned num1 = sl1.num_spans(); + unsigned num2 = sl2.num_spans(); + + typename Scanline1::const_iterator span1;// = sl1.begin(); + typename Scanline2::const_iterator span2;// = sl2.begin(); + + enum invalidation_e + { + invalid_b = 0xFFFFFFF, + invalid_e = invalid_b - 1 + }; + + // Initialize the spans as invalid + //--------------- + int xb1 = invalid_b; + int xb2 = invalid_b; + int xe1 = invalid_e; + int xe2 = invalid_e; + + // Initialize span1 if there are spans + //--------------- + if(num1) + { + span1 = sl1.begin(); + xb1 = span1->x; + xe1 = xb1 + abs((int)span1->len) - 1; + --num1; + } + + // Initialize span2 if there are spans + //--------------- + if(num2) + { + span2 = sl2.begin(); + xb2 = span2->x; + xe2 = xb2 + abs((int)span2->len) - 1; + --num2; + } + + + for(;;) + { + // Retrieve a new span1 if it's invalid + //---------------- + if(num1 && xb1 > xe1) + { + --num1; + ++span1; + xb1 = span1->x; + xe1 = xb1 + abs((int)span1->len) - 1; + } + + // Retrieve a new span2 if it's invalid + //---------------- + if(num2 && xb2 > xe2) + { + --num2; + ++span2; + xb2 = span2->x; + xe2 = xb2 + abs((int)span2->len) - 1; + } + + if(xb1 > xe1 && xb2 > xe2) break; + + // Calculate the intersection + //---------------- + int xb = xb1; + int xe = xe1; + if(xb < xb2) xb = xb2; + if(xe > xe2) xe = xe2; + int len = xe - xb + 1; // The length of the intersection + if(len > 0) + { + // The spans intersect, + // add the beginning of the span + //---------------- + if(xb1 < xb2) + { + add_span1(span1, xb1, xb2 - xb1, sl); + xb1 = xb2; + } + else + if(xb2 < xb1) + { + add_span2(span2, xb2, xb1 - xb2, sl); + xb2 = xb1; + } + + // Add the combination part of the spans + //---------------- + combine_spans(span1, span2, xb, len, sl); + + + // Invalidate the fully processed span or both + //---------------- + if(xe1 < xe2) + { + // Invalidate span1 and eat + // the processed part of span2 + //-------------- + xb1 = invalid_b; + xe1 = invalid_e; + xb2 += len; + } + else + if(xe2 < xe1) + { + // Invalidate span2 and eat + // the processed part of span1 + //-------------- + xb2 = invalid_b; + xe2 = invalid_e; + xb1 += len; + } + else + { + xb1 = invalid_b; // Invalidate both + xb2 = invalid_b; + xe1 = invalid_e; + xe2 = invalid_e; + } + } + else + { + // The spans do not intersect + //-------------- + if(xb1 < xb2) + { + // Advance span1 + //--------------- + if(xb1 <= xe1) + { + add_span1(span1, xb1, xe1 - xb1 + 1, sl); + } + xb1 = invalid_b; // Invalidate + xe1 = invalid_e; + } + else + { + // Advance span2 + //--------------- + if(xb2 <= xe2) + { + add_span2(span2, xb2, xe2 - xb2 + 1, sl); + } + xb2 = invalid_b; // Invalidate + xe2 = invalid_e; + } + } + } + } + + + + + //----------------------------------------------------sbool_unite_shapes + // Unite the scanline shapes. Here the "Scanline Generator" + // abstraction is used. ScanlineGen1 and ScanlineGen2 are + // the generators, and can be of type rasterizer_scanline_aa<>. + // There function requires three scanline containers that can be + // of different type. + // "sl1" and "sl2" are used to retrieve scanlines from the generators, + // "sl" is ised as the resulting scanline to render it. + // The external "sl1" and "sl2" are used only for the sake of + // optimization and reusing of the scanline objects. + // the function calls sbool_unite_scanlines with CombineSpansFunctor + // as the last argument. See sbool_unite_scanlines for details. + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer, + class AddSpanFunctor1, + class AddSpanFunctor2, + class CombineSpansFunctor> + void sbool_unite_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren, + AddSpanFunctor1 add_span1, + AddSpanFunctor2 add_span2, + CombineSpansFunctor combine_spans) + { + // Prepare the scanline generators. + // If anyone of them doesn't contain + // any scanlines, then return. + //----------------- + bool flag1 = sg1.rewind_scanlines(); + bool flag2 = sg2.rewind_scanlines(); + if(!flag1 && !flag2) return; + + // Get the bounding boxes + //---------------- + rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); + rect_i r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y()); + + // Calculate the union of the bounding boxes + //----------------- + rect_i ur(1,1,0,0); + if(flag1 && flag2) ur = unite_rectangles(r1, r2); + else if(flag1) ur = r1; + else if(flag2) ur = r2; + + if(!ur.is_valid()) return; + + ren.prepare(); + + // Reset the scanlines and get two first ones + //----------------- + sl.reset(ur.x1, ur.x2); + if(flag1) + { + sl1.reset(sg1.min_x(), sg1.max_x()); + flag1 = sg1.sweep_scanline(sl1); + } + + if(flag2) + { + sl2.reset(sg2.min_x(), sg2.max_x()); + flag2 = sg2.sweep_scanline(sl2); + } + + // The main loop + // Here we synchronize the scanlines with + // the same Y coordinate. + //----------------- + while(flag1 || flag2) + { + if(flag1 && flag2) + { + if(sl1.y() == sl2.y()) + { + // The Y coordinates are the same. + // Combine the scanlines, render if they contain any spans, + // and advance both generators to the next scanlines + //---------------------- + sbool_unite_scanlines(sl1, sl2, sl, + add_span1, add_span2, combine_spans); + if(sl.num_spans()) + { + sl.finalize(sl1.y()); + ren.render(sl); + } + flag1 = sg1.sweep_scanline(sl1); + flag2 = sg2.sweep_scanline(sl2); + } + else + { + if(sl1.y() < sl2.y()) + { + sbool_add_spans_and_render(sl1, sl, ren, add_span1); + flag1 = sg1.sweep_scanline(sl1); + } + else + { + sbool_add_spans_and_render(sl2, sl, ren, add_span2); + flag2 = sg2.sweep_scanline(sl2); + } + } + } + else + { + if(flag1) + { + sbool_add_spans_and_render(sl1, sl, ren, add_span1); + flag1 = sg1.sweep_scanline(sl1); + } + if(flag2) + { + sbool_add_spans_and_render(sl2, sl, ren, add_span2); + flag2 = sg2.sweep_scanline(sl2); + } + } + } + } + + + + + + + + + //-------------------------------------------------sbool_subtract_shapes + // Subtract the scanline shapes, "sg1-sg2". Here the "Scanline Generator" + // abstraction is used. ScanlineGen1 and ScanlineGen2 are + // the generators, and can be of type rasterizer_scanline_aa<>. + // There function requires three scanline containers that can be of + // different types. + // "sl1" and "sl2" are used to retrieve scanlines from the generators, + // "sl" is ised as the resulting scanline to render it. + // The external "sl1" and "sl2" are used only for the sake of + // optimization and reusing of the scanline objects. + // the function calls sbool_intersect_scanlines with CombineSpansFunctor + // as the last argument. See combine_scanlines_sub for details. + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer, + class AddSpanFunctor1, + class CombineSpansFunctor> + void sbool_subtract_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren, + AddSpanFunctor1 add_span1, + CombineSpansFunctor combine_spans) + { + // Prepare the scanline generators. + // Here "sg1" is master, "sg2" is slave. + //----------------- + if(!sg1.rewind_scanlines()) return; + bool flag2 = sg2.rewind_scanlines(); + + // Get the bounding box + //---------------- + rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); + + // Reset the scanlines and get two first ones + //----------------- + sl.reset(sg1.min_x(), sg1.max_x()); + sl1.reset(sg1.min_x(), sg1.max_x()); + sl2.reset(sg2.min_x(), sg2.max_x()); + if(!sg1.sweep_scanline(sl1)) return; + + if(flag2) flag2 = sg2.sweep_scanline(sl2); + + ren.prepare(); + + // A fake span2 processor + sbool_add_span_empty<Scanline2, Scanline> add_span2; + + // The main loop + // Here we synchronize the scanlines with + // the same Y coordinate, ignoring all other ones. + // Only scanlines having the same Y-coordinate + // are to be combined. + //----------------- + bool flag1 = true; + do + { + // Synchronize "slave" with "master" + //----------------- + while(flag2 && sl2.y() < sl1.y()) + { + flag2 = sg2.sweep_scanline(sl2); + } + + + if(flag2 && sl2.y() == sl1.y()) + { + // The Y coordinates are the same. + // Combine the scanlines and render if they contain any spans. + //---------------------- + sbool_unite_scanlines(sl1, sl2, sl, add_span1, add_span2, combine_spans); + if(sl.num_spans()) + { + sl.finalize(sl1.y()); + ren.render(sl); + } + } + else + { + sbool_add_spans_and_render(sl1, sl, ren, add_span1); + } + + // Advance the "master" + flag1 = sg1.sweep_scanline(sl1); + } + while(flag1); + } + + + + + + + + //---------------------------------------------sbool_intersect_shapes_aa + // Intersect two anti-aliased scanline shapes. + // Here the "Scanline Generator" abstraction is used. + // ScanlineGen1 and ScanlineGen2 are the generators, and can be of + // type rasterizer_scanline_aa<>. There function requires three + // scanline containers that can be of different types. + // "sl1" and "sl2" are used to retrieve scanlines from the generators, + // "sl" is ised as the resulting scanline to render it. + // The external "sl1" and "sl2" are used only for the sake of + // optimization and reusing of the scanline objects. + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_intersect_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_intersect_spans_aa<Scanline1, Scanline2, Scanline> combine_functor; + sbool_intersect_shapes(sg1, sg2, sl1, sl2, sl, ren, combine_functor); + } + + + + + + //--------------------------------------------sbool_intersect_shapes_bin + // Intersect two binary scanline shapes (without anti-aliasing). + // See intersect_shapes_aa for more comments + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_intersect_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_combine_spans_bin<Scanline1, Scanline2, Scanline> combine_functor; + sbool_intersect_shapes(sg1, sg2, sl1, sl2, sl, ren, combine_functor); + } + + + + + + //-------------------------------------------------sbool_unite_shapes_aa + // Unite two anti-aliased scanline shapes + // See intersect_shapes_aa for more comments + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_unite_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_aa<Scanline1, Scanline> add_functor1; + sbool_add_span_aa<Scanline2, Scanline> add_functor2; + sbool_unite_spans_aa<Scanline1, Scanline2, Scanline> combine_functor; + sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor1, add_functor2, combine_functor); + } + + + + + + //------------------------------------------------sbool_unite_shapes_bin + // Unite two binary scanline shapes (without anti-aliasing). + // See intersect_shapes_aa for more comments + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_unite_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_bin<Scanline1, Scanline> add_functor1; + sbool_add_span_bin<Scanline2, Scanline> add_functor2; + sbool_combine_spans_bin<Scanline1, Scanline2, Scanline> combine_functor; + sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor1, add_functor2, combine_functor); + } + + + + + + + + + + //---------------------------------------------------sbool_xor_shapes_aa + // Apply eXclusive OR to two anti-aliased scanline shapes. There's + // a modified "Linear" XOR used instead of classical "Saddle" one. + // The reason is to have the result absolutely conststent with what + // the scanline rasterizer produces. + // See intersect_shapes_aa for more comments + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_xor_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_aa<Scanline1, Scanline> add_functor1; + sbool_add_span_aa<Scanline2, Scanline> add_functor2; + sbool_xor_spans_aa<Scanline1, Scanline2, Scanline, + sbool_xor_formula_linear<> > combine_functor; + sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor1, add_functor2, combine_functor); + } + + + + //------------------------------------------sbool_xor_shapes_saddle_aa + // Apply eXclusive OR to two anti-aliased scanline shapes. + // There's the classical "Saddle" used to calculate the + // Anti-Aliasing values, that is: + // a XOR b : 1-((1-a+a*b)*(1-b+a*b)) + // See intersect_shapes_aa for more comments + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_xor_shapes_saddle_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_aa<Scanline1, Scanline> add_functor1; + sbool_add_span_aa<Scanline2, Scanline> add_functor2; + sbool_xor_spans_aa<Scanline1, + Scanline2, + Scanline, + sbool_xor_formula_saddle<> > combine_functor; + sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor1, add_functor2, combine_functor); + } + + + //--------------------------------------sbool_xor_shapes_abs_diff_aa + // Apply eXclusive OR to two anti-aliased scanline shapes. + // There's the absolute difference used to calculate + // Anti-Aliasing values, that is: + // a XOR b : abs(a-b) + // See intersect_shapes_aa for more comments + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_xor_shapes_abs_diff_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_aa<Scanline1, Scanline> add_functor1; + sbool_add_span_aa<Scanline2, Scanline> add_functor2; + sbool_xor_spans_aa<Scanline1, + Scanline2, + Scanline, + sbool_xor_formula_abs_diff> combine_functor; + sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor1, add_functor2, combine_functor); + } + + + + //--------------------------------------------------sbool_xor_shapes_bin + // Apply eXclusive OR to two binary scanline shapes (without anti-aliasing). + // See intersect_shapes_aa for more comments + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_xor_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_bin<Scanline1, Scanline> add_functor1; + sbool_add_span_bin<Scanline2, Scanline> add_functor2; + sbool_combine_spans_empty<Scanline1, Scanline2, Scanline> combine_functor; + sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor1, add_functor2, combine_functor); + } + + + + + + + //----------------------------------------------sbool_subtract_shapes_aa + // Subtract shapes "sg1-sg2" with anti-aliasing + // See intersect_shapes_aa for more comments + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_subtract_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_aa<Scanline1, Scanline> add_functor; + sbool_subtract_spans_aa<Scanline1, Scanline2, Scanline> combine_functor; + sbool_subtract_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor, combine_functor); + } + + + + + + //---------------------------------------------sbool_subtract_shapes_bin + // Subtract binary shapes "sg1-sg2" without anti-aliasing + // See intersect_shapes_aa for more comments + //---------- + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_subtract_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_bin<Scanline1, Scanline> add_functor; + sbool_combine_spans_empty<Scanline1, Scanline2, Scanline> combine_functor; + sbool_subtract_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor, combine_functor); + } + + + + + + + //------------------------------------------------------------sbool_op_e + enum sbool_op_e + { + sbool_or, //----sbool_or + sbool_and, //----sbool_and + sbool_xor, //----sbool_xor + sbool_xor_saddle, //----sbool_xor_saddle + sbool_xor_abs_diff, //----sbool_xor_abs_diff + sbool_a_minus_b, //----sbool_a_minus_b + sbool_b_minus_a //----sbool_b_minus_a + }; + + + + + + + //----------------------------------------------sbool_combine_shapes_bin + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_combine_shapes_bin(sbool_op_e op, + ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + switch(op) + { + case sbool_or : sbool_unite_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_and : sbool_intersect_shapes_bin(sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_xor : + case sbool_xor_saddle : + case sbool_xor_abs_diff: sbool_xor_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_a_minus_b : sbool_subtract_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_b_minus_a : sbool_subtract_shapes_bin (sg2, sg1, sl2, sl1, sl, ren); break; + } + } + + + + + //-----------------------------------------------sbool_combine_shapes_aa + template<class ScanlineGen1, + class ScanlineGen2, + class Scanline1, + class Scanline2, + class Scanline, + class Renderer> + void sbool_combine_shapes_aa(sbool_op_e op, + ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + switch(op) + { + case sbool_or : sbool_unite_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_and : sbool_intersect_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_xor : sbool_xor_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_xor_saddle : sbool_xor_shapes_saddle_aa (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_xor_abs_diff: sbool_xor_shapes_abs_diff_aa(sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_a_minus_b : sbool_subtract_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_b_minus_a : sbool_subtract_shapes_aa (sg2, sg1, sl2, sl1, sl, ren); break; + } + } + +} + + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_scanline_p.h b/jni/desmume/src/android/agg/include/agg_scanline_p.h new file mode 100755 index 0000000..0c29638 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_scanline_p.h @@ -0,0 +1,334 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates (scanline32_p) has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- +#ifndef AGG_SCANLINE_P_INCLUDED +#define AGG_SCANLINE_P_INCLUDED + +#include "agg_array.h" + +namespace agg +{ + + //=============================================================scanline_p8 + // + // This is a general purpose scaline container which supports the interface + // used in the rasterizer::render(). See description of scanline_u8 + // for details. + // + //------------------------------------------------------------------------ + class scanline_p8 + { + public: + typedef scanline_p8 self_type; + typedef int8u cover_type; + typedef int16 coord_type; + + //-------------------------------------------------------------------- + struct span + { + coord_type x; + coord_type len; // If negative, it's a solid span, covers is valid + const cover_type* covers; + }; + + typedef span* iterator; + typedef const span* const_iterator; + + scanline_p8() : + m_last_x(0x7FFFFFF0), + m_covers(), + m_cover_ptr(0), + m_spans(), + m_cur_span(0) + { + } + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 3; + if(max_len > m_spans.size()) + { + m_spans.resize(max_len); + m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_cover_ptr = &m_covers[0]; + m_cur_span = &m_spans[0]; + m_cur_span->len = 0; + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned cover) + { + *m_cover_ptr = (cover_type)cover; + if(x == m_last_x+1 && m_cur_span->len > 0) + { + m_cur_span->len++; + } + else + { + m_cur_span++; + m_cur_span->covers = m_cover_ptr; + m_cur_span->x = (int16)x; + m_cur_span->len = 1; + } + m_last_x = x; + m_cover_ptr++; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const cover_type* covers) + { + memcpy(m_cover_ptr, covers, len * sizeof(cover_type)); + if(x == m_last_x+1 && m_cur_span->len > 0) + { + m_cur_span->len += (int16)len; + } + else + { + m_cur_span++; + m_cur_span->covers = m_cover_ptr; + m_cur_span->x = (int16)x; + m_cur_span->len = (int16)len; + } + m_cover_ptr += len; + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned cover) + { + if(x == m_last_x+1 && + m_cur_span->len < 0 && + cover == *m_cur_span->covers) + { + m_cur_span->len -= (int16)len; + } + else + { + *m_cover_ptr = (cover_type)cover; + m_cur_span++; + m_cur_span->covers = m_cover_ptr++; + m_cur_span->x = (int16)x; + m_cur_span->len = (int16)(-int(len)); + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + m_cover_ptr = &m_covers[0]; + m_cur_span = &m_spans[0]; + m_cur_span->len = 0; + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } + const_iterator begin() const { return &m_spans[1]; } + + private: + scanline_p8(const self_type&); + const self_type& operator = (const self_type&); + + int m_last_x; + int m_y; + pod_array<cover_type> m_covers; + cover_type* m_cover_ptr; + pod_array<span> m_spans; + span* m_cur_span; + }; + + + + + + + + + //==========================================================scanline32_p8 + class scanline32_p8 + { + public: + typedef scanline32_p8 self_type; + typedef int8u cover_type; + typedef int32 coord_type; + + struct span + { + span() {} + span(coord_type x_, coord_type len_, const cover_type* covers_) : + x(x_), len(len_), covers(covers_) {} + + coord_type x; + coord_type len; // If negative, it's a solid span, covers is valid + const cover_type* covers; + }; + typedef pod_bvector<span, 4> span_array_type; + + + //-------------------------------------------------------------------- + class const_iterator + { + public: + const_iterator(const span_array_type& spans) : + m_spans(spans), + m_span_idx(0) + {} + + const span& operator*() const { return m_spans[m_span_idx]; } + const span* operator->() const { return &m_spans[m_span_idx]; } + + void operator ++ () { ++m_span_idx; } + + private: + const span_array_type& m_spans; + unsigned m_span_idx; + }; + + //-------------------------------------------------------------------- + scanline32_p8() : + m_max_len(0), + m_last_x(0x7FFFFFF0), + m_covers(), + m_cover_ptr(0) + { + } + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 3; + if(max_len > m_covers.size()) + { + m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_cover_ptr = &m_covers[0]; + m_spans.remove_all(); + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned cover) + { + *m_cover_ptr = cover_type(cover); + if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0) + { + m_spans.last().len++; + } + else + { + m_spans.add(span(coord_type(x), 1, m_cover_ptr)); + } + m_last_x = x; + m_cover_ptr++; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const cover_type* covers) + { + memcpy(m_cover_ptr, covers, len * sizeof(cover_type)); + if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0) + { + m_spans.last().len += coord_type(len); + } + else + { + m_spans.add(span(coord_type(x), coord_type(len), m_cover_ptr)); + } + m_cover_ptr += len; + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned cover) + { + if(x == m_last_x+1 && + m_spans.size() && + m_spans.last().len < 0 && + cover == *m_spans.last().covers) + { + m_spans.last().len -= coord_type(len); + } + else + { + *m_cover_ptr = cover_type(cover); + m_spans.add(span(coord_type(x), -coord_type(len), m_cover_ptr++)); + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + m_cover_ptr = &m_covers[0]; + m_spans.remove_all(); + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return m_spans.size(); } + const_iterator begin() const { return const_iterator(m_spans); } + + private: + scanline32_p8(const self_type&); + const self_type& operator = (const self_type&); + + unsigned m_max_len; + int m_last_x; + int m_y; + pod_array<cover_type> m_covers; + cover_type* m_cover_ptr; + span_array_type m_spans; + }; + + +} + + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_scanline_storage_aa.h b/jni/desmume/src/android/agg/include/agg_scanline_storage_aa.h new file mode 100755 index 0000000..62fcfbe --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_scanline_storage_aa.h @@ -0,0 +1,824 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_SCANLINE_STORAGE_AA_INCLUDED +#define AGG_SCANLINE_STORAGE_AA_INCLUDED + +#include <string.h> +#include <stdlib.h> +#include <math.h> +#include "agg_array.h" + + +namespace agg +{ + + //----------------------------------------------scanline_cell_storage + template<class T> class scanline_cell_storage + { + struct extra_span + { + unsigned len; + T* ptr; + }; + + public: + typedef T value_type; + + //--------------------------------------------------------------- + ~scanline_cell_storage() + { + remove_all(); + } + + //--------------------------------------------------------------- + scanline_cell_storage() : + m_cells(128-2), + m_extra_storage() + {} + + + // Copying + //--------------------------------------------------------------- + scanline_cell_storage(const scanline_cell_storage<T>& v) : + m_cells(v.m_cells), + m_extra_storage() + { + copy_extra_storage(v); + } + + //--------------------------------------------------------------- + const scanline_cell_storage<T>& + operator = (const scanline_cell_storage<T>& v) + { + remove_all(); + m_cells = v.m_cells; + copy_extra_storage(v); + return *this; + } + + //--------------------------------------------------------------- + void remove_all() + { + int i; + for(i = m_extra_storage.size()-1; i >= 0; --i) + { + pod_allocator<T>::deallocate(m_extra_storage[i].ptr, + m_extra_storage[i].len); + } + m_extra_storage.remove_all(); + m_cells.remove_all(); + } + + //--------------------------------------------------------------- + int add_cells(const T* cells, unsigned num_cells) + { + int idx = m_cells.allocate_continuous_block(num_cells); + if(idx >= 0) + { + T* ptr = &m_cells[idx]; + memcpy(ptr, cells, sizeof(T) * num_cells); + return idx; + } + extra_span s; + s.len = num_cells; + s.ptr = pod_allocator<T>::allocate(num_cells); + memcpy(s.ptr, cells, sizeof(T) * num_cells); + m_extra_storage.add(s); + return -int(m_extra_storage.size()); + } + + //--------------------------------------------------------------- + const T* operator [] (int idx) const + { + if(idx >= 0) + { + if((unsigned)idx >= m_cells.size()) return 0; + return &m_cells[(unsigned)idx]; + } + unsigned i = unsigned(-idx - 1); + if(i >= m_extra_storage.size()) return 0; + return m_extra_storage[i].ptr; + } + + //--------------------------------------------------------------- + T* operator [] (int idx) + { + if(idx >= 0) + { + if((unsigned)idx >= m_cells.size()) return 0; + return &m_cells[(unsigned)idx]; + } + unsigned i = unsigned(-idx - 1); + if(i >= m_extra_storage.size()) return 0; + return m_extra_storage[i].ptr; + } + + private: + void copy_extra_storage(const scanline_cell_storage<T>& v) + { + unsigned i; + for(i = 0; i < v.m_extra_storage.size(); ++i) + { + const extra_span& src = v.m_extra_storage[i]; + extra_span dst; + dst.len = src.len; + dst.ptr = pod_allocator<T>::allocate(dst.len); + memcpy(dst.ptr, src.ptr, dst.len * sizeof(T)); + m_extra_storage.add(dst); + } + } + + pod_bvector<T, 12> m_cells; + pod_bvector<extra_span, 6> m_extra_storage; + }; + + + + + + + //-----------------------------------------------scanline_storage_aa + template<class T> class scanline_storage_aa + { + public: + typedef T cover_type; + + //--------------------------------------------------------------- + struct span_data + { + int32 x; + int32 len; // If negative, it's a solid span, covers is valid + int covers_id; // The index of the cells in the scanline_cell_storage + }; + + //--------------------------------------------------------------- + struct scanline_data + { + int y; + unsigned num_spans; + unsigned start_span; + }; + + + //--------------------------------------------------------------- + class embedded_scanline + { + public: + + //----------------------------------------------------------- + class const_iterator + { + public: + struct span + { + int32 x; + int32 len; // If negative, it's a solid span, covers is valid + const T* covers; + }; + + const_iterator() : m_storage(0) {} + const_iterator(const embedded_scanline& sl) : + m_storage(sl.m_storage), + m_span_idx(sl.m_scanline.start_span) + { + init_span(); + } + + const span& operator*() const { return m_span; } + const span* operator->() const { return &m_span; } + + void operator ++ () + { + ++m_span_idx; + init_span(); + } + + private: + void init_span() + { + const span_data& s = m_storage->span_by_index(m_span_idx); + m_span.x = s.x; + m_span.len = s.len; + m_span.covers = m_storage->covers_by_index(s.covers_id); + } + + const scanline_storage_aa* m_storage; + unsigned m_span_idx; + span m_span; + }; + + friend class const_iterator; + + + //----------------------------------------------------------- + embedded_scanline(const scanline_storage_aa& storage) : + m_storage(&storage) + { + init(0); + } + + //----------------------------------------------------------- + void reset(int, int) {} + unsigned num_spans() const { return m_scanline.num_spans; } + int y() const { return m_scanline.y; } + const_iterator begin() const { return const_iterator(*this); } + + //----------------------------------------------------------- + void init(unsigned scanline_idx) + { + m_scanline_idx = scanline_idx; + m_scanline = m_storage->scanline_by_index(m_scanline_idx); + } + + private: + const scanline_storage_aa* m_storage; + scanline_data m_scanline; + unsigned m_scanline_idx; + }; + + + //--------------------------------------------------------------- + scanline_storage_aa() : + m_covers(), + m_spans(256-2), // Block increment size + m_scanlines(), + m_min_x( 0x7FFFFFFF), + m_min_y( 0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF), + m_cur_scanline(0) + { + m_fake_scanline.y = 0; + m_fake_scanline.num_spans = 0; + m_fake_scanline.start_span = 0; + m_fake_span.x = 0; + m_fake_span.len = 0; + m_fake_span.covers_id = 0; + } + + // Renderer Interface + //--------------------------------------------------------------- + void prepare() + { + m_covers.remove_all(); + m_scanlines.remove_all(); + m_spans.remove_all(); + m_min_x = 0x7FFFFFFF; + m_min_y = 0x7FFFFFFF; + m_max_x = -0x7FFFFFFF; + m_max_y = -0x7FFFFFFF; + m_cur_scanline = 0; + } + + //--------------------------------------------------------------- + template<class Scanline> void render(const Scanline& sl) + { + scanline_data sl_this; + + int y = sl.y(); + if(y < m_min_y) m_min_y = y; + if(y > m_max_y) m_max_y = y; + + sl_this.y = y; + sl_this.num_spans = sl.num_spans(); + sl_this.start_span = m_spans.size(); + typename Scanline::const_iterator span_iterator = sl.begin(); + + unsigned num_spans = sl_this.num_spans; + for(;;) + { + span_data sp; + + sp.x = span_iterator->x; + sp.len = span_iterator->len; + int len = abs(int(sp.len)); + sp.covers_id = + m_covers.add_cells(span_iterator->covers, + unsigned(len)); + m_spans.add(sp); + int x1 = sp.x; + int x2 = sp.x + len - 1; + if(x1 < m_min_x) m_min_x = x1; + if(x2 > m_max_x) m_max_x = x2; + if(--num_spans == 0) break; + ++span_iterator; + } + m_scanlines.add(sl_this); + } + + + //--------------------------------------------------------------- + // Iterate scanlines interface + int min_x() const { return m_min_x; } + int min_y() const { return m_min_y; } + int max_x() const { return m_max_x; } + int max_y() const { return m_max_y; } + + //--------------------------------------------------------------- + bool rewind_scanlines() + { + m_cur_scanline = 0; + return m_scanlines.size() > 0; + } + + + //--------------------------------------------------------------- + template<class Scanline> bool sweep_scanline(Scanline& sl) + { + sl.reset_spans(); + for(;;) + { + if(m_cur_scanline >= m_scanlines.size()) return false; + const scanline_data& sl_this = m_scanlines[m_cur_scanline]; + + unsigned num_spans = sl_this.num_spans; + unsigned span_idx = sl_this.start_span; + do + { + const span_data& sp = m_spans[span_idx++]; + const T* covers = covers_by_index(sp.covers_id); + if(sp.len < 0) + { + sl.add_span(sp.x, unsigned(-sp.len), *covers); + } + else + { + sl.add_cells(sp.x, sp.len, covers); + } + } + while(--num_spans); + ++m_cur_scanline; + if(sl.num_spans()) + { + sl.finalize(sl_this.y); + break; + } + } + return true; + } + + + //--------------------------------------------------------------- + // Specialization for embedded_scanline + bool sweep_scanline(embedded_scanline& sl) + { + do + { + if(m_cur_scanline >= m_scanlines.size()) return false; + sl.init(m_cur_scanline); + ++m_cur_scanline; + } + while(sl.num_spans() == 0); + return true; + } + + //--------------------------------------------------------------- + unsigned byte_size() const + { + unsigned i; + unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y + + for(i = 0; i < m_scanlines.size(); ++i) + { + size += sizeof(int32) * 3; // scanline size in bytes, Y, num_spans + + const scanline_data& sl_this = m_scanlines[i]; + + unsigned num_spans = sl_this.num_spans; + unsigned span_idx = sl_this.start_span; + do + { + const span_data& sp = m_spans[span_idx++]; + + size += sizeof(int32) * 2; // X, span_len + if(sp.len < 0) + { + size += sizeof(T); // cover + } + else + { + size += sizeof(T) * unsigned(sp.len); // covers + } + } + while(--num_spans); + } + return size; + } + + + //--------------------------------------------------------------- + static void write_int32(int8u* dst, int32 val) + { + dst[0] = ((const int8u*)&val)[0]; + dst[1] = ((const int8u*)&val)[1]; + dst[2] = ((const int8u*)&val)[2]; + dst[3] = ((const int8u*)&val)[3]; + } + + + //--------------------------------------------------------------- + void serialize(int8u* data) const + { + unsigned i; + + write_int32(data, min_x()); // min_x + data += sizeof(int32); + write_int32(data, min_y()); // min_y + data += sizeof(int32); + write_int32(data, max_x()); // max_x + data += sizeof(int32); + write_int32(data, max_y()); // max_y + data += sizeof(int32); + + for(i = 0; i < m_scanlines.size(); ++i) + { + const scanline_data& sl_this = m_scanlines[i]; + + int8u* size_ptr = data; + data += sizeof(int32); // Reserve space for scanline size in bytes + + write_int32(data, sl_this.y); // Y + data += sizeof(int32); + + write_int32(data, sl_this.num_spans); // num_spans + data += sizeof(int32); + + unsigned num_spans = sl_this.num_spans; + unsigned span_idx = sl_this.start_span; + do + { + const span_data& sp = m_spans[span_idx++]; + const T* covers = covers_by_index(sp.covers_id); + + write_int32(data, sp.x); // X + data += sizeof(int32); + + write_int32(data, sp.len); // span_len + data += sizeof(int32); + + if(sp.len < 0) + { + memcpy(data, covers, sizeof(T)); + data += sizeof(T); + } + else + { + memcpy(data, covers, unsigned(sp.len) * sizeof(T)); + data += sizeof(T) * unsigned(sp.len); + } + } + while(--num_spans); + write_int32(size_ptr, int32(unsigned(data - size_ptr))); + } + } + + + //--------------------------------------------------------------- + const scanline_data& scanline_by_index(unsigned i) const + { + return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline; + } + + //--------------------------------------------------------------- + const span_data& span_by_index(unsigned i) const + { + return (i < m_spans.size()) ? m_spans[i] : m_fake_span; + } + + //--------------------------------------------------------------- + const T* covers_by_index(int i) const + { + return m_covers[i]; + } + + private: + scanline_cell_storage<T> m_covers; + pod_bvector<span_data, 10> m_spans; + pod_bvector<scanline_data, 8> m_scanlines; + span_data m_fake_span; + scanline_data m_fake_scanline; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; + unsigned m_cur_scanline; + }; + + + typedef scanline_storage_aa<int8u> scanline_storage_aa8; //--------scanline_storage_aa8 + typedef scanline_storage_aa<int16u> scanline_storage_aa16; //--------scanline_storage_aa16 + typedef scanline_storage_aa<int32u> scanline_storage_aa32; //--------scanline_storage_aa32 + + + + + //------------------------------------------serialized_scanlines_adaptor_aa + template<class T> class serialized_scanlines_adaptor_aa + { + public: + typedef T cover_type; + + //--------------------------------------------------------------------- + class embedded_scanline + { + public: + typedef T cover_type; + + //----------------------------------------------------------------- + class const_iterator + { + public: + struct span + { + int32 x; + int32 len; // If negative, it's a solid span, "covers" is valid + const T* covers; + }; + + const_iterator() : m_ptr(0) {} + const_iterator(const embedded_scanline& sl) : + m_ptr(sl.m_ptr), + m_dx(sl.m_dx) + { + init_span(); + } + + const span& operator*() const { return m_span; } + const span* operator->() const { return &m_span; } + + void operator ++ () + { + if(m_span.len < 0) + { + m_ptr += sizeof(T); + } + else + { + m_ptr += m_span.len * sizeof(T); + } + init_span(); + } + + private: + int read_int32() + { + int32 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; + return val; + } + + void init_span() + { + m_span.x = read_int32() + m_dx; + m_span.len = read_int32(); + m_span.covers = m_ptr; + } + + const int8u* m_ptr; + span m_span; + int m_dx; + }; + + friend class const_iterator; + + + //----------------------------------------------------------------- + embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {} + + //----------------------------------------------------------------- + void reset(int, int) {} + unsigned num_spans() const { return m_num_spans; } + int y() const { return m_y; } + const_iterator begin() const { return const_iterator(*this); } + + + private: + //----------------------------------------------------------------- + int read_int32() + { + int32 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; + return val; + } + + public: + //----------------------------------------------------------------- + void init(const int8u* ptr, int dx, int dy) + { + m_ptr = ptr; + m_y = read_int32() + dy; + m_num_spans = unsigned(read_int32()); + m_dx = dx; + } + + private: + const int8u* m_ptr; + int m_y; + unsigned m_num_spans; + int m_dx; + }; + + + + public: + //-------------------------------------------------------------------- + serialized_scanlines_adaptor_aa() : + m_data(0), + m_end(0), + m_ptr(0), + m_dx(0), + m_dy(0), + m_min_x(0x7FFFFFFF), + m_min_y(0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF) + {} + + //-------------------------------------------------------------------- + serialized_scanlines_adaptor_aa(const int8u* data, unsigned size, + double dx, double dy) : + m_data(data), + m_end(data + size), + m_ptr(data), + m_dx(iround(dx)), + m_dy(iround(dy)), + m_min_x(0x7FFFFFFF), + m_min_y(0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF) + {} + + //-------------------------------------------------------------------- + void init(const int8u* data, unsigned size, double dx, double dy) + { + m_data = data; + m_end = data + size; + m_ptr = data; + m_dx = iround(dx); + m_dy = iround(dy); + m_min_x = 0x7FFFFFFF; + m_min_y = 0x7FFFFFFF; + m_max_x = -0x7FFFFFFF; + m_max_y = -0x7FFFFFFF; + } + + private: + //-------------------------------------------------------------------- + int read_int32() + { + int32 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; + return val; + } + + //-------------------------------------------------------------------- + unsigned read_int32u() + { + int32u val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; + return val; + } + + public: + // Iterate scanlines interface + //-------------------------------------------------------------------- + bool rewind_scanlines() + { + m_ptr = m_data; + if(m_ptr < m_end) + { + m_min_x = read_int32() + m_dx; + m_min_y = read_int32() + m_dy; + m_max_x = read_int32() + m_dx; + m_max_y = read_int32() + m_dy; + } + return m_ptr < m_end; + } + + //-------------------------------------------------------------------- + int min_x() const { return m_min_x; } + int min_y() const { return m_min_y; } + int max_x() const { return m_max_x; } + int max_y() const { return m_max_y; } + + //-------------------------------------------------------------------- + template<class Scanline> bool sweep_scanline(Scanline& sl) + { + sl.reset_spans(); + for(;;) + { + if(m_ptr >= m_end) return false; + + read_int32(); // Skip scanline size in bytes + int y = read_int32() + m_dy; + unsigned num_spans = read_int32(); + + do + { + int x = read_int32() + m_dx; + int len = read_int32(); + + if(len < 0) + { + sl.add_span(x, unsigned(-len), *m_ptr); + m_ptr += sizeof(T); + } + else + { + sl.add_cells(x, len, m_ptr); + m_ptr += len * sizeof(T); + } + } + while(--num_spans); + + if(sl.num_spans()) + { + sl.finalize(y); + break; + } + } + return true; + } + + + //-------------------------------------------------------------------- + // Specialization for embedded_scanline + bool sweep_scanline(embedded_scanline& sl) + { + do + { + if(m_ptr >= m_end) return false; + + unsigned byte_size = read_int32u(); + sl.init(m_ptr, m_dx, m_dy); + m_ptr += byte_size - sizeof(int32); + } + while(sl.num_spans() == 0); + return true; + } + + private: + const int8u* m_data; + const int8u* m_end; + const int8u* m_ptr; + int m_dx; + int m_dy; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; + }; + + + + typedef serialized_scanlines_adaptor_aa<int8u> serialized_scanlines_adaptor_aa8; //----serialized_scanlines_adaptor_aa8 + typedef serialized_scanlines_adaptor_aa<int16u> serialized_scanlines_adaptor_aa16; //----serialized_scanlines_adaptor_aa16 + typedef serialized_scanlines_adaptor_aa<int32u> serialized_scanlines_adaptor_aa32; //----serialized_scanlines_adaptor_aa32 + +} + + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_scanline_storage_bin.h b/jni/desmume/src/android/agg/include/agg_scanline_storage_bin.h new file mode 100755 index 0000000..f3b1494 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_scanline_storage_bin.h @@ -0,0 +1,595 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + + +#ifndef AGG_SCANLINE_STORAGE_BIN_INCLUDED +#define AGG_SCANLINE_STORAGE_BIN_INCLUDED + +#include <string.h> +#include <stdlib.h> +#include <math.h> +#include "agg_array.h" + + +namespace agg +{ + + //-----------------------------------------------scanline_storage_bin + class scanline_storage_bin + { + public: + //--------------------------------------------------------------- + struct span_data + { + int32 x; + int32 len; + }; + + //--------------------------------------------------------------- + struct scanline_data + { + int y; + unsigned num_spans; + unsigned start_span; + }; + + + //--------------------------------------------------------------- + class embedded_scanline + { + public: + + //----------------------------------------------------------- + class const_iterator + { + public: + const_iterator() : m_storage(0) {} + const_iterator(const embedded_scanline& sl) : + m_storage(sl.m_storage), + m_span_idx(sl.m_scanline.start_span) + { + m_span = m_storage->span_by_index(m_span_idx); + } + + const span_data& operator*() const { return m_span; } + const span_data* operator->() const { return &m_span; } + + void operator ++ () + { + ++m_span_idx; + m_span = m_storage->span_by_index(m_span_idx); + } + + private: + const scanline_storage_bin* m_storage; + unsigned m_span_idx; + span_data m_span; + }; + + friend class const_iterator; + + + //----------------------------------------------------------- + embedded_scanline(const scanline_storage_bin& storage) : + m_storage(&storage) + { + setup(0); + } + + //----------------------------------------------------------- + void reset(int, int) {} + unsigned num_spans() const { return m_scanline.num_spans; } + int y() const { return m_scanline.y; } + const_iterator begin() const { return const_iterator(*this); } + + //----------------------------------------------------------- + void setup(unsigned scanline_idx) + { + m_scanline_idx = scanline_idx; + m_scanline = m_storage->scanline_by_index(m_scanline_idx); + } + + private: + const scanline_storage_bin* m_storage; + scanline_data m_scanline; + unsigned m_scanline_idx; + }; + + + //--------------------------------------------------------------- + scanline_storage_bin() : + m_spans(256-2), // Block increment size + m_scanlines(), + m_min_x( 0x7FFFFFFF), + m_min_y( 0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF), + m_cur_scanline(0) + { + m_fake_scanline.y = 0; + m_fake_scanline.num_spans = 0; + m_fake_scanline.start_span = 0; + m_fake_span.x = 0; + m_fake_span.len = 0; + } + + // Renderer Interface + //--------------------------------------------------------------- + void prepare() + { + m_scanlines.remove_all(); + m_spans.remove_all(); + m_min_x = 0x7FFFFFFF; + m_min_y = 0x7FFFFFFF; + m_max_x = -0x7FFFFFFF; + m_max_y = -0x7FFFFFFF; + m_cur_scanline = 0; + } + + //--------------------------------------------------------------- + template<class Scanline> void render(const Scanline& sl) + { + scanline_data sl_this; + + int y = sl.y(); + if(y < m_min_y) m_min_y = y; + if(y > m_max_y) m_max_y = y; + + sl_this.y = y; + sl_this.num_spans = sl.num_spans(); + sl_this.start_span = m_spans.size(); + typename Scanline::const_iterator span_iterator = sl.begin(); + + unsigned num_spans = sl_this.num_spans; + for(;;) + { + span_data sp; + sp.x = span_iterator->x; + sp.len = (int32)abs((int)(span_iterator->len)); + m_spans.add(sp); + int x1 = sp.x; + int x2 = sp.x + sp.len - 1; + if(x1 < m_min_x) m_min_x = x1; + if(x2 > m_max_x) m_max_x = x2; + if(--num_spans == 0) break; + ++span_iterator; + } + m_scanlines.add(sl_this); + } + + + //--------------------------------------------------------------- + // Iterate scanlines interface + int min_x() const { return m_min_x; } + int min_y() const { return m_min_y; } + int max_x() const { return m_max_x; } + int max_y() const { return m_max_y; } + + //--------------------------------------------------------------- + bool rewind_scanlines() + { + m_cur_scanline = 0; + return m_scanlines.size() > 0; + } + + + //--------------------------------------------------------------- + template<class Scanline> bool sweep_scanline(Scanline& sl) + { + sl.reset_spans(); + for(;;) + { + if(m_cur_scanline >= m_scanlines.size()) return false; + const scanline_data& sl_this = m_scanlines[m_cur_scanline]; + + unsigned num_spans = sl_this.num_spans; + unsigned span_idx = sl_this.start_span; + do + { + const span_data& sp = m_spans[span_idx++]; + sl.add_span(sp.x, sp.len, cover_full); + } + while(--num_spans); + + ++m_cur_scanline; + if(sl.num_spans()) + { + sl.finalize(sl_this.y); + break; + } + } + return true; + } + + + //--------------------------------------------------------------- + // Specialization for embedded_scanline + bool sweep_scanline(embedded_scanline& sl) + { + do + { + if(m_cur_scanline >= m_scanlines.size()) return false; + sl.setup(m_cur_scanline); + ++m_cur_scanline; + } + while(sl.num_spans() == 0); + return true; + } + + + //--------------------------------------------------------------- + unsigned byte_size() const + { + unsigned i; + unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y + + for(i = 0; i < m_scanlines.size(); ++i) + { + size += sizeof(int32) * 2 + // Y, num_spans + unsigned(m_scanlines[i].num_spans) * sizeof(int32) * 2; // X, span_len + } + return size; + } + + + //--------------------------------------------------------------- + static void write_int32(int8u* dst, int32 val) + { + dst[0] = ((const int8u*)&val)[0]; + dst[1] = ((const int8u*)&val)[1]; + dst[2] = ((const int8u*)&val)[2]; + dst[3] = ((const int8u*)&val)[3]; + } + + + //--------------------------------------------------------------- + void serialize(int8u* data) const + { + unsigned i; + + write_int32(data, min_x()); // min_x + data += sizeof(int32); + write_int32(data, min_y()); // min_y + data += sizeof(int32); + write_int32(data, max_x()); // max_x + data += sizeof(int32); + write_int32(data, max_y()); // max_y + data += sizeof(int32); + + for(i = 0; i < m_scanlines.size(); ++i) + { + const scanline_data& sl_this = m_scanlines[i]; + + write_int32(data, sl_this.y); // Y + data += sizeof(int32); + + write_int32(data, sl_this.num_spans); // num_spans + data += sizeof(int32); + + unsigned num_spans = sl_this.num_spans; + unsigned span_idx = sl_this.start_span; + do + { + const span_data& sp = m_spans[span_idx++]; + + write_int32(data, sp.x); // X + data += sizeof(int32); + + write_int32(data, sp.len); // len + data += sizeof(int32); + } + while(--num_spans); + } + } + + + //--------------------------------------------------------------- + const scanline_data& scanline_by_index(unsigned i) const + { + return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline; + } + + //--------------------------------------------------------------- + const span_data& span_by_index(unsigned i) const + { + return (i < m_spans.size()) ? m_spans[i] : m_fake_span; + } + + + private: + pod_bvector<span_data, 10> m_spans; + pod_bvector<scanline_data, 8> m_scanlines; + span_data m_fake_span; + scanline_data m_fake_scanline; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; + unsigned m_cur_scanline; + }; + + + + + + + + + + + + + + //---------------------------------------serialized_scanlines_adaptor_bin + class serialized_scanlines_adaptor_bin + { + public: + typedef bool cover_type; + + //-------------------------------------------------------------------- + class embedded_scanline + { + public: + + //---------------------------------------------------------------- + class const_iterator + { + public: + struct span + { + int32 x; + int32 len; + }; + + const_iterator() : m_ptr(0) {} + const_iterator(const embedded_scanline& sl) : + m_ptr(sl.m_ptr), + m_dx(sl.m_dx) + { + m_span.x = read_int32() + m_dx; + m_span.len = read_int32(); + } + + const span& operator*() const { return m_span; } + const span* operator->() const { return &m_span; } + + void operator ++ () + { + m_span.x = read_int32() + m_dx; + m_span.len = read_int32(); + } + + private: + int read_int32() + { + int32 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; + return val; + } + + const int8u* m_ptr; + span m_span; + int m_dx; + }; + + friend class const_iterator; + + + //---------------------------------------------------------------- + embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {} + + //---------------------------------------------------------------- + void reset(int, int) {} + unsigned num_spans() const { return m_num_spans; } + int y() const { return m_y; } + const_iterator begin() const { return const_iterator(*this); } + + + private: + //---------------------------------------------------------------- + int read_int32() + { + int32 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; + return val; + } + + public: + //---------------------------------------------------------------- + void init(const int8u* ptr, int dx, int dy) + { + m_ptr = ptr; + m_y = read_int32() + dy; + m_num_spans = unsigned(read_int32()); + m_dx = dx; + } + + private: + const int8u* m_ptr; + int m_y; + unsigned m_num_spans; + int m_dx; + }; + + + + public: + //-------------------------------------------------------------------- + serialized_scanlines_adaptor_bin() : + m_data(0), + m_end(0), + m_ptr(0), + m_dx(0), + m_dy(0), + m_min_x(0x7FFFFFFF), + m_min_y(0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF) + {} + + //-------------------------------------------------------------------- + serialized_scanlines_adaptor_bin(const int8u* data, unsigned size, + double dx, double dy) : + m_data(data), + m_end(data + size), + m_ptr(data), + m_dx(iround(dx)), + m_dy(iround(dy)), + m_min_x(0x7FFFFFFF), + m_min_y(0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF) + {} + + //-------------------------------------------------------------------- + void init(const int8u* data, unsigned size, double dx, double dy) + { + m_data = data; + m_end = data + size; + m_ptr = data; + m_dx = iround(dx); + m_dy = iround(dy); + m_min_x = 0x7FFFFFFF; + m_min_y = 0x7FFFFFFF; + m_max_x = -0x7FFFFFFF; + m_max_y = -0x7FFFFFFF; + } + + private: + //-------------------------------------------------------------------- + int read_int32() + { + int32 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; + return val; + } + + public: + // Iterate scanlines interface + //-------------------------------------------------------------------- + bool rewind_scanlines() + { + m_ptr = m_data; + if(m_ptr < m_end) + { + m_min_x = read_int32() + m_dx; + m_min_y = read_int32() + m_dy; + m_max_x = read_int32() + m_dx; + m_max_y = read_int32() + m_dy; + } + return m_ptr < m_end; + } + + //-------------------------------------------------------------------- + int min_x() const { return m_min_x; } + int min_y() const { return m_min_y; } + int max_x() const { return m_max_x; } + int max_y() const { return m_max_y; } + + //-------------------------------------------------------------------- + template<class Scanline> bool sweep_scanline(Scanline& sl) + { + sl.reset_spans(); + for(;;) + { + if(m_ptr >= m_end) return false; + + int y = read_int32() + m_dy; + unsigned num_spans = read_int32(); + + do + { + int x = read_int32() + m_dx; + int len = read_int32(); + + if(len < 0) len = -len; + sl.add_span(x, unsigned(len), cover_full); + } + while(--num_spans); + + if(sl.num_spans()) + { + sl.finalize(y); + break; + } + } + return true; + } + + + //-------------------------------------------------------------------- + // Specialization for embedded_scanline + bool sweep_scanline(embedded_scanline& sl) + { + do + { + if(m_ptr >= m_end) return false; + + sl.init(m_ptr, m_dx, m_dy); + + // Jump to the next scanline + //-------------------------- + read_int32(); // Y + int num_spans = read_int32(); // num_spans + m_ptr += num_spans * sizeof(int32) * 2; + } + while(sl.num_spans() == 0); + return true; + } + + private: + const int8u* m_data; + const int8u* m_end; + const int8u* m_ptr; + int m_dx; + int m_dy; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; + }; + + + +} + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_scanline_u.h b/jni/desmume/src/android/agg/include/agg_scanline_u.h new file mode 100755 index 0000000..6894a73 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_scanline_u.h @@ -0,0 +1,508 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates (scanline32_u) has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_SCANLINE_U_INCLUDED +#define AGG_SCANLINE_U_INCLUDED + +#include "agg_array.h" + +namespace agg +{ + //=============================================================scanline_u8 + // + // Unpacked scanline container class + // + // This class is used to transfer data from a scanline rasterizer + // to the rendering buffer. It's organized very simple. The class stores + // information of horizontal spans to render it into a pixel-map buffer. + // Each span has staring X, length, and an array of bytes that determine the + // cover-values for each pixel. + // Before using this class you should know the minimal and maximal pixel + // coordinates of your scanline. The protocol of using is: + // 1. reset(min_x, max_x) + // 2. add_cell() / add_span() - accumulate scanline. + // When forming one scanline the next X coordinate must be always greater + // than the last stored one, i.e. it works only with ordered coordinates. + // 3. Call finalize(y) and render the scanline. + // 3. Call reset_spans() to prepare for the new scanline. + // + // 4. Rendering: + // + // Scanline provides an iterator class that allows you to extract + // the spans and the cover values for each pixel. Be aware that clipping + // has not been done yet, so you should perform it yourself. + // Use scanline_u8::iterator to render spans: + //------------------------------------------------------------------------- + // + // int y = sl.y(); // Y-coordinate of the scanline + // + // ************************************ + // ...Perform vertical clipping here... + // ************************************ + // + // scanline_u8::const_iterator span = sl.begin(); + // + // unsigned char* row = m_rbuf->row(y); // The the address of the beginning + // // of the current row + // + // unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that + // // num_spans is always greater than 0. + // + // do + // { + // const scanline_u8::cover_type* covers = + // span->covers; // The array of the cover values + // + // int num_pix = span->len; // Number of pixels of the span. + // // Always greater than 0, still it's + // // better to use "int" instead of + // // "unsigned" because it's more + // // convenient for clipping + // int x = span->x; + // + // ************************************** + // ...Perform horizontal clipping here... + // ...you have x, covers, and pix_count.. + // ************************************** + // + // unsigned char* dst = row + x; // Calculate the start address of the row. + // // In this case we assume a simple + // // grayscale image 1-byte per pixel. + // do + // { + // *dst++ = *covers++; // Hypotetical rendering. + // } + // while(--num_pix); + // + // ++span; + // } + // while(--num_spans); // num_spans cannot be 0, so this loop is quite safe + //------------------------------------------------------------------------ + // + // The question is: why should we accumulate the whole scanline when we + // could render just separate spans when they're ready? + // That's because using the scanline is generally faster. When is consists + // of more than one span the conditions for the processor cash system + // are better, because switching between two different areas of memory + // (that can be very large) occurs less frequently. + //------------------------------------------------------------------------ + class scanline_u8 + { + public: + typedef scanline_u8 self_type; + typedef int8u cover_type; + typedef int16 coord_type; + + //-------------------------------------------------------------------- + struct span + { + coord_type x; + coord_type len; + cover_type* covers; + }; + + typedef span* iterator; + typedef const span* const_iterator; + + //-------------------------------------------------------------------- + scanline_u8() : + m_min_x(0), + m_last_x(0x7FFFFFF0), + m_cur_span(0) + {} + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 2; + if(max_len > m_spans.size()) + { + m_spans.resize(max_len); + m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_min_x = min_x; + m_cur_span = &m_spans[0]; + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned cover) + { + x -= m_min_x; + m_covers[x] = (cover_type)cover; + if(x == m_last_x+1) + { + m_cur_span->len++; + } + else + { + m_cur_span++; + m_cur_span->x = (coord_type)(x + m_min_x); + m_cur_span->len = 1; + m_cur_span->covers = &m_covers[x]; + } + m_last_x = x; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const cover_type* covers) + { + x -= m_min_x; + memcpy(&m_covers[x], covers, len * sizeof(cover_type)); + if(x == m_last_x+1) + { + m_cur_span->len += (coord_type)len; + } + else + { + m_cur_span++; + m_cur_span->x = (coord_type)(x + m_min_x); + m_cur_span->len = (coord_type)len; + m_cur_span->covers = &m_covers[x]; + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned cover) + { + x -= m_min_x; + memset(&m_covers[x], cover, len); + if(x == m_last_x+1) + { + m_cur_span->len += (coord_type)len; + } + else + { + m_cur_span++; + m_cur_span->x = (coord_type)(x + m_min_x); + m_cur_span->len = (coord_type)len; + m_cur_span->covers = &m_covers[x]; + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + m_cur_span = &m_spans[0]; + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } + const_iterator begin() const { return &m_spans[1]; } + iterator begin() { return &m_spans[1]; } + + private: + scanline_u8(const self_type&); + const self_type& operator = (const self_type&); + + private: + int m_min_x; + int m_last_x; + int m_y; + pod_array<cover_type> m_covers; + pod_array<span> m_spans; + span* m_cur_span; + }; + + + + + //==========================================================scanline_u8_am + // + // The scanline container with alpha-masking + // + //------------------------------------------------------------------------ + template<class AlphaMask> + class scanline_u8_am : public scanline_u8 + { + public: + typedef scanline_u8 base_type; + typedef AlphaMask alpha_mask_type; + typedef base_type::cover_type cover_type; + typedef base_type::coord_type coord_type; + + scanline_u8_am() : base_type(), m_alpha_mask(0) {} + scanline_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {} + + //-------------------------------------------------------------------- + void finalize(int span_y) + { + base_type::finalize(span_y); + if(m_alpha_mask) + { + typename base_type::iterator span = base_type::begin(); + unsigned count = base_type::num_spans(); + do + { + m_alpha_mask->combine_hspan(span->x, + base_type::y(), + span->covers, + span->len); + ++span; + } + while(--count); + } + } + + private: + const AlphaMask* m_alpha_mask; + }; + + + + + //===========================================================scanline32_u8 + class scanline32_u8 + { + public: + typedef scanline32_u8 self_type; + typedef int8u cover_type; + typedef int32 coord_type; + + //-------------------------------------------------------------------- + struct span + { + span() {} + span(coord_type x_, coord_type len_, cover_type* covers_) : + x(x_), len(len_), covers(covers_) {} + + coord_type x; + coord_type len; + cover_type* covers; + }; + + typedef pod_bvector<span, 4> span_array_type; + + //-------------------------------------------------------------------- + class const_iterator + { + public: + const_iterator(const span_array_type& spans) : + m_spans(spans), + m_span_idx(0) + {} + + const span& operator*() const { return m_spans[m_span_idx]; } + const span* operator->() const { return &m_spans[m_span_idx]; } + + void operator ++ () { ++m_span_idx; } + + private: + const span_array_type& m_spans; + unsigned m_span_idx; + }; + + //-------------------------------------------------------------------- + class iterator + { + public: + iterator(span_array_type& spans) : + m_spans(spans), + m_span_idx(0) + {} + + span& operator*() { return m_spans[m_span_idx]; } + span* operator->() { return &m_spans[m_span_idx]; } + + void operator ++ () { ++m_span_idx; } + + private: + span_array_type& m_spans; + unsigned m_span_idx; + }; + + + + //-------------------------------------------------------------------- + scanline32_u8() : + m_min_x(0), + m_last_x(0x7FFFFFF0), + m_covers() + {} + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 2; + if(max_len > m_covers.size()) + { + m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_min_x = min_x; + m_spans.remove_all(); + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned cover) + { + x -= m_min_x; + m_covers[x] = cover_type(cover); + if(x == m_last_x+1) + { + m_spans.last().len++; + } + else + { + m_spans.add(span(coord_type(x + m_min_x), 1, &m_covers[x])); + } + m_last_x = x; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const cover_type* covers) + { + x -= m_min_x; + memcpy(&m_covers[x], covers, len * sizeof(cover_type)); + if(x == m_last_x+1) + { + m_spans.last().len += coord_type(len); + } + else + { + m_spans.add(span(coord_type(x + m_min_x), + coord_type(len), + &m_covers[x])); + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned cover) + { + x -= m_min_x; + memset(&m_covers[x], cover, len); + if(x == m_last_x+1) + { + m_spans.last().len += coord_type(len); + } + else + { + m_spans.add(span(coord_type(x + m_min_x), + coord_type(len), + &m_covers[x])); + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + m_spans.remove_all(); + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return m_spans.size(); } + const_iterator begin() const { return const_iterator(m_spans); } + iterator begin() { return iterator(m_spans); } + + private: + scanline32_u8(const self_type&); + const self_type& operator = (const self_type&); + + private: + int m_min_x; + int m_last_x; + int m_y; + pod_array<cover_type> m_covers; + span_array_type m_spans; + }; + + + + + //========================================================scanline32_u8_am + // + // The scanline container with alpha-masking + // + //------------------------------------------------------------------------ + template<class AlphaMask> + class scanline32_u8_am : public scanline32_u8 + { + public: + typedef scanline32_u8 base_type; + typedef AlphaMask alpha_mask_type; + typedef base_type::cover_type cover_type; + typedef base_type::coord_type coord_type; + + + scanline32_u8_am() : base_type(), m_alpha_mask(0) {} + scanline32_u8_am(const AlphaMask& am) : base_type(), m_alpha_mask(&am) {} + + //-------------------------------------------------------------------- + void finalize(int span_y) + { + base_type::finalize(span_y); + if(m_alpha_mask) + { + typename base_type::iterator span = base_type::begin(); + unsigned count = base_type::num_spans(); + do + { + m_alpha_mask->combine_hspan(span->x, + base_type::y(), + span->covers, + span->len); + ++span; + } + while(--count); + } + } + + private: + const AlphaMask* m_alpha_mask; + }; + + + +} + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_shorten_path.h b/jni/desmume/src/android/agg/include/agg_shorten_path.h new file mode 100755 index 0000000..ba72b94 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_shorten_path.h @@ -0,0 +1,75 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_SHORTEN_PATH_INCLUDED +#define AGG_SHORTEN_PATH_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + + //===========================================================shorten_path + template<class VertexSequence> + void shorten_path(VertexSequence& vs, double s, unsigned closed = 0) + { + typedef typename VertexSequence::value_type vertex_type; + + if(s > 0.0 && vs.size() > 1) + { + double d; + int n = int(vs.size() - 2); + while(n) + { + d = vs[n].dist; + if(d > s) break; + vs.remove_last(); + s -= d; + --n; + } + if(vs.size() < 2) + { + vs.remove_all(); + } + else + { + n = vs.size() - 1; + vertex_type& prev = vs[n-1]; + vertex_type& last = vs[n]; + d = (prev.dist - s) / prev.dist; + double x = prev.x + (last.x - prev.x) * d; + double y = prev.y + (last.y - prev.y) * d; + last.x = x; + last.y = y; + if(!prev(last)) vs.remove_last(); + vs.close(closed != 0); + } + } + } + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_simul_eq.h b/jni/desmume/src/android/agg/include/agg_simul_eq.h new file mode 100755 index 0000000..a19e9b6 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_simul_eq.h @@ -0,0 +1,153 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_SIMUL_EQ_INCLUDED +#define AGG_SIMUL_EQ_INCLUDED + +#include <math.h> +#include "agg_basics.h" + +namespace agg +{ + + //=============================================================swap_arrays + template<class T> void swap_arrays(T* a1, T* a2, unsigned n) + { + unsigned i; + for(i = 0; i < n; i++) + { + T tmp = *a1; + *a1++ = *a2; + *a2++ = tmp; + } + } + + + //============================================================matrix_pivot + template<unsigned Rows, unsigned Cols> + struct matrix_pivot + { + static int pivot(double m[Rows][Cols], unsigned row) + { + int k = int(row); + double max_val, tmp; + + max_val = -1.0; + unsigned i; + for(i = row; i < Rows; i++) + { + if((tmp = fabs(m[i][row])) > max_val && tmp != 0.0) + { + max_val = tmp; + k = i; + } + } + + if(m[k][row] == 0.0) + { + return -1; + } + + if(k != int(row)) + { + swap_arrays(m[k], m[row], Cols); + return k; + } + return 0; + } + }; + + + + //===============================================================simul_eq + template<unsigned Size, unsigned RightCols> + struct simul_eq + { + static bool solve(const double left[Size][Size], + const double right[Size][RightCols], + double result[Size][RightCols]) + { + unsigned i, j, k; + double a1; + + double tmp[Size][Size + RightCols]; + + for(i = 0; i < Size; i++) + { + for(j = 0; j < Size; j++) + { + tmp[i][j] = left[i][j]; + } + for(j = 0; j < RightCols; j++) + { + tmp[i][Size + j] = right[i][j]; + } + } + + for(k = 0; k < Size; k++) + { + if(matrix_pivot<Size, Size + RightCols>::pivot(tmp, k) < 0) + { + return false; // Singularity.... + } + + a1 = tmp[k][k]; + + for(j = k; j < Size + RightCols; j++) + { + tmp[k][j] /= a1; + } + + for(i = k + 1; i < Size; i++) + { + a1 = tmp[i][k]; + for (j = k; j < Size + RightCols; j++) + { + tmp[i][j] -= a1 * tmp[k][j]; + } + } + } + + + for(k = 0; k < RightCols; k++) + { + int m; + for(m = int(Size - 1); m >= 0; m--) + { + result[m][k] = tmp[m][Size + k]; + for(j = m + 1; j < Size; j++) + { + result[m][k] -= tmp[m][j] * result[j][k]; + } + } + } + return true; + } + + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_span_allocator.h b/jni/desmume/src/android/agg/include/agg_span_allocator.h new file mode 100755 index 0000000..0bb0e4b --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_span_allocator.h @@ -0,0 +1,63 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_ALLOCATOR_INCLUDED +#define AGG_SPAN_ALLOCATOR_INCLUDED + +#include "agg_array.h" + +namespace agg +{ + //----------------------------------------------------------span_allocator + template<class ColorT> class span_allocator + { + public: + typedef ColorT color_type; + + //-------------------------------------------------------------------- + AGG_INLINE color_type* allocate(unsigned span_len) + { + if(span_len > m_span.size()) + { + // To reduce the number of reallocs we align the + // span_len to 256 color elements. + // Well, I just like this number and it looks reasonable. + //----------------------- + m_span.resize(((span_len + 255) >> 8) << 8); + } + return &m_span[0]; + } + + AGG_INLINE color_type* span() { return &m_span[0]; } + AGG_INLINE unsigned max_span_len() const { return m_span.size(); } + + private: + pod_array<color_type> m_span; + }; +} + + +#endif + + diff --git a/jni/desmume/src/android/agg/include/agg_span_converter.h b/jni/desmume/src/android/agg/include/agg_span_converter.h new file mode 100755 index 0000000..2796e42 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_span_converter.h @@ -0,0 +1,65 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_CONVERTER_INCLUDED +#define AGG_SPAN_CONVERTER_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //----------------------------------------------------------span_converter + template<class SpanGenerator, class SpanConverter> class span_converter + { + public: + typedef typename SpanGenerator::color_type color_type; + + span_converter(SpanGenerator& span_gen, SpanConverter& span_cnv) : + m_span_gen(&span_gen), m_span_cnv(&span_cnv) {} + + void attach_generator(SpanGenerator& span_gen) { m_span_gen = &span_gen; } + void attach_converter(SpanConverter& span_cnv) { m_span_cnv = &span_cnv; } + + //-------------------------------------------------------------------- + void prepare() + { + m_span_gen->prepare(); + m_span_cnv->prepare(); + } + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + m_span_gen->generate(span, x, y, len); + m_span_cnv->generate(span, x, y, len); + } + + private: + SpanGenerator* m_span_gen; + SpanConverter* m_span_cnv; + }; + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_span_gouraud.h b/jni/desmume/src/android/agg/include/agg_span_gouraud.h new file mode 100755 index 0000000..7829e8f --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_span_gouraud.h @@ -0,0 +1,181 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_GOURAUD_INCLUDED +#define AGG_SPAN_GOURAUD_INCLUDED + +#include "agg_basics.h" +#include "agg_math.h" + +namespace agg +{ + + //============================================================span_gouraud + template<class ColorT> class span_gouraud + { + public: + typedef ColorT color_type; + + struct coord_type + { + double x; + double y; + color_type color; + }; + + //-------------------------------------------------------------------- + span_gouraud() : + m_vertex(0) + { + m_cmd[0] = path_cmd_stop; + } + + //-------------------------------------------------------------------- + span_gouraud(const color_type& c1, + const color_type& c2, + const color_type& c3, + double x1, double y1, + double x2, double y2, + double x3, double y3, + double d) : + m_vertex(0) + { + colors(c1, c2, c3); + triangle(x1, y1, x2, y2, x3, y3, d); + } + + //-------------------------------------------------------------------- + void colors(ColorT c1, ColorT c2, ColorT c3) + { + m_coord[0].color = c1; + m_coord[1].color = c2; + m_coord[2].color = c3; + } + + //-------------------------------------------------------------------- + // Sets the triangle and dilates it if needed. + // The trick here is to calculate beveled joins in the vertices of the + // triangle and render it as a 6-vertex polygon. + // It's necessary to achieve numerical stability. + // However, the coordinates to interpolate colors are calculated + // as miter joins (calc_intersection). + void triangle(double x1, double y1, + double x2, double y2, + double x3, double y3, + double d) + { + m_coord[0].x = m_x[0] = x1; + m_coord[0].y = m_y[0] = y1; + m_coord[1].x = m_x[1] = x2; + m_coord[1].y = m_y[1] = y2; + m_coord[2].x = m_x[2] = x3; + m_coord[2].y = m_y[2] = y3; + m_cmd[0] = path_cmd_move_to; + m_cmd[1] = path_cmd_line_to; + m_cmd[2] = path_cmd_line_to; + m_cmd[3] = path_cmd_stop; + + if(d != 0.0) + { + dilate_triangle(m_coord[0].x, m_coord[0].y, + m_coord[1].x, m_coord[1].y, + m_coord[2].x, m_coord[2].y, + m_x, m_y, d); + + calc_intersection(m_x[4], m_y[4], m_x[5], m_y[5], + m_x[0], m_y[0], m_x[1], m_y[1], + &m_coord[0].x, &m_coord[0].y); + + calc_intersection(m_x[0], m_y[0], m_x[1], m_y[1], + m_x[2], m_y[2], m_x[3], m_y[3], + &m_coord[1].x, &m_coord[1].y); + + calc_intersection(m_x[2], m_y[2], m_x[3], m_y[3], + m_x[4], m_y[4], m_x[5], m_y[5], + &m_coord[2].x, &m_coord[2].y); + m_cmd[3] = path_cmd_line_to; + m_cmd[4] = path_cmd_line_to; + m_cmd[5] = path_cmd_line_to; + m_cmd[6] = path_cmd_stop; + } + } + + //-------------------------------------------------------------------- + // Vertex Source Interface to feed the coordinates to the rasterizer + void rewind(unsigned) + { + m_vertex = 0; + } + + //-------------------------------------------------------------------- + unsigned vertex(double* x, double* y) + { + *x = m_x[m_vertex]; + *y = m_y[m_vertex]; + return m_cmd[m_vertex++]; + } + + protected: + //-------------------------------------------------------------------- + void arrange_vertices(coord_type* coord) const + { + coord[0] = m_coord[0]; + coord[1] = m_coord[1]; + coord[2] = m_coord[2]; + + if(m_coord[0].y > m_coord[2].y) + { + coord[0] = m_coord[2]; + coord[2] = m_coord[0]; + } + + coord_type tmp; + if(coord[0].y > coord[1].y) + { + tmp = coord[1]; + coord[1] = coord[0]; + coord[0] = tmp; + } + + if(coord[1].y > coord[2].y) + { + tmp = coord[2]; + coord[2] = coord[1]; + coord[1] = tmp; + } + } + + private: + //-------------------------------------------------------------------- + coord_type m_coord[3]; + double m_x[8]; + double m_y[8]; + unsigned m_cmd[8]; + unsigned m_vertex; + }; + +} + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_span_gouraud_gray.h b/jni/desmume/src/android/agg/include/agg_span_gouraud_gray.h new file mode 100755 index 0000000..40141c8 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_span_gouraud_gray.h @@ -0,0 +1,250 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_GOURAUD_GRAY_INCLUDED +#define AGG_SPAN_GOURAUD_GRAY_INCLUDED + +#include "agg_basics.h" +#include "agg_color_gray.h" +#include "agg_dda_line.h" +#include "agg_span_gouraud.h" + +namespace agg +{ + + //=======================================================span_gouraud_gray + template<class ColorT> class span_gouraud_gray : public span_gouraud<ColorT> + { + public: + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + typedef span_gouraud<color_type> base_type; + typedef typename base_type::coord_type coord_type; + enum subpixel_scale_e + { + subpixel_shift = 4, + subpixel_scale = 1 << subpixel_shift + }; + + private: + //-------------------------------------------------------------------- + struct gray_calc + { + void init(const coord_type& c1, const coord_type& c2) + { + m_x1 = c1.x - 0.5; + m_y1 = c1.y - 0.5; + m_dx = c2.x - c1.x; + double dy = c2.y - c1.y; + m_1dy = (fabs(dy) < 1e-10) ? 1e10 : 1.0 / dy; + m_v1 = c1.color.v; + m_a1 = c1.color.a; + m_dv = c2.color.v - m_v1; + m_da = c2.color.a - m_a1; + } + + void calc(double y) + { + double k = (y - m_y1) * m_1dy; + if(k < 0.0) k = 0.0; + if(k > 1.0) k = 1.0; + m_v = m_v1 + iround(m_dv * k); + m_a = m_a1 + iround(m_da * k); + m_x = iround((m_x1 + m_dx * k) * subpixel_scale); + } + + double m_x1; + double m_y1; + double m_dx; + double m_1dy; + int m_v1; + int m_a1; + int m_dv; + int m_da; + int m_v; + int m_a; + int m_x; + }; + + + public: + //-------------------------------------------------------------------- + span_gouraud_gray() {} + span_gouraud_gray(const color_type& c1, + const color_type& c2, + const color_type& c3, + double x1, double y1, + double x2, double y2, + double x3, double y3, + double d = 0) : + base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d) + {} + + //-------------------------------------------------------------------- + void prepare() + { + coord_type coord[3]; + base_type::arrange_vertices(coord); + + m_y2 = int(coord[1].y); + + m_swap = cross_product(coord[0].x, coord[0].y, + coord[2].x, coord[2].y, + coord[1].x, coord[1].y) < 0.0; + + m_c1.init(coord[0], coord[2]); + m_c2.init(coord[0], coord[1]); + m_c3.init(coord[1], coord[2]); + } + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + m_c1.calc(y); + const gray_calc* pc1 = &m_c1; + const gray_calc* pc2 = &m_c2; + + if(y < m_y2) + { + // Bottom part of the triangle (first subtriangle) + //------------------------- + m_c2.calc(y + m_c2.m_1dy); + } + else + { + // Upper part (second subtriangle) + //------------------------- + m_c3.calc(y - m_c3.m_1dy); + pc2 = &m_c3; + } + + if(m_swap) + { + // It means that the triangle is oriented clockwise, + // so that we need to swap the controlling structures + //------------------------- + const gray_calc* t = pc2; + pc2 = pc1; + pc1 = t; + } + + // Get the horizontal length with subpixel accuracy + // and protect it from division by zero + //------------------------- + int nlen = abs(pc2->m_x - pc1->m_x); + if(nlen <= 0) nlen = 1; + + dda_line_interpolator<14> v(pc1->m_v, pc2->m_v, nlen); + dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen); + + // Calculate the starting point of the gradient with subpixel + // accuracy and correct (roll back) the interpolators. + // This operation will also clip the beginning of the span + // if necessary. + //------------------------- + int start = pc1->m_x - (x << subpixel_shift); + v -= start; + a -= start; + nlen += start; + + int vv, va; + enum lim_e { lim = color_type::base_mask }; + + // Beginning part of the span. Since we rolled back the + // interpolators, the color values may have overflow. + // So that, we render the beginning part with checking + // for overflow. It lasts until "start" is positive; + // typically it's 1-2 pixels, but may be more in some cases. + //------------------------- + while(len && start > 0) + { + vv = v.y(); + va = a.y(); + if(vv < 0) vv = 0; if(vv > lim) vv = lim; + if(va < 0) va = 0; if(va > lim) va = lim; + span->v = (value_type)vv; + span->a = (value_type)va; + v += subpixel_scale; + a += subpixel_scale; + nlen -= subpixel_scale; + start -= subpixel_scale; + ++span; + --len; + } + + // Middle part, no checking for overflow. + // Actual spans can be longer than the calculated length + // because of anti-aliasing, thus, the interpolators can + // overflow. But while "nlen" is positive we are safe. + //------------------------- + while(len && nlen > 0) + { + span->v = (value_type)v.y(); + span->a = (value_type)a.y(); + v += subpixel_scale; + a += subpixel_scale; + nlen -= subpixel_scale; + ++span; + --len; + } + + // Ending part; checking for overflow. + // Typically it's 1-2 pixels, but may be more in some cases. + //------------------------- + while(len) + { + vv = v.y(); + va = a.y(); + if(vv < 0) vv = 0; if(vv > lim) vv = lim; + if(va < 0) va = 0; if(va > lim) va = lim; + span->v = (value_type)vv; + span->a = (value_type)va; + v += subpixel_scale; + a += subpixel_scale; + ++span; + --len; + } + } + + + private: + bool m_swap; + int m_y2; + gray_calc m_c1; + gray_calc m_c2; + gray_calc m_c3; + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_span_gouraud_rgba.h b/jni/desmume/src/android/agg/include/agg_span_gouraud_rgba.h new file mode 100755 index 0000000..3fab7ef --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_span_gouraud_rgba.h @@ -0,0 +1,286 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_GOURAUD_RGBA_INCLUDED +#define AGG_SPAN_GOURAUD_RGBA_INCLUDED + +#include "agg_basics.h" +#include "agg_color_rgba.h" +#include "agg_dda_line.h" +#include "agg_span_gouraud.h" + +namespace agg +{ + + //=======================================================span_gouraud_rgba + template<class ColorT> class span_gouraud_rgba : public span_gouraud<ColorT> + { + public: + typedef ColorT color_type; + typedef typename ColorT::value_type value_type; + typedef span_gouraud<color_type> base_type; + typedef typename base_type::coord_type coord_type; + enum subpixel_scale_e + { + subpixel_shift = 4, + subpixel_scale = 1 << subpixel_shift + }; + + private: + //-------------------------------------------------------------------- + struct rgba_calc + { + void init(const coord_type& c1, const coord_type& c2) + { + m_x1 = c1.x - 0.5; + m_y1 = c1.y - 0.5; + m_dx = c2.x - c1.x; + double dy = c2.y - c1.y; + m_1dy = (dy < 1e-5) ? 1e5 : 1.0 / dy; + m_r1 = c1.color.r; + m_g1 = c1.color.g; + m_b1 = c1.color.b; + m_a1 = c1.color.a; + m_dr = c2.color.r - m_r1; + m_dg = c2.color.g - m_g1; + m_db = c2.color.b - m_b1; + m_da = c2.color.a - m_a1; + } + + void calc(double y) + { + double k = (y - m_y1) * m_1dy; + if(k < 0.0) k = 0.0; + if(k > 1.0) k = 1.0; + m_r = m_r1 + iround(m_dr * k); + m_g = m_g1 + iround(m_dg * k); + m_b = m_b1 + iround(m_db * k); + m_a = m_a1 + iround(m_da * k); + m_x = iround((m_x1 + m_dx * k) * subpixel_scale); + } + + double m_x1; + double m_y1; + double m_dx; + double m_1dy; + int m_r1; + int m_g1; + int m_b1; + int m_a1; + int m_dr; + int m_dg; + int m_db; + int m_da; + int m_r; + int m_g; + int m_b; + int m_a; + int m_x; + }; + + public: + + //-------------------------------------------------------------------- + span_gouraud_rgba() {} + span_gouraud_rgba(const color_type& c1, + const color_type& c2, + const color_type& c3, + double x1, double y1, + double x2, double y2, + double x3, double y3, + double d = 0) : + base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d) + {} + + //-------------------------------------------------------------------- + void prepare() + { + coord_type coord[3]; + base_type::arrange_vertices(coord); + + m_y2 = int(coord[1].y); + + m_swap = cross_product(coord[0].x, coord[0].y, + coord[2].x, coord[2].y, + coord[1].x, coord[1].y) < 0.0; + + m_rgba1.init(coord[0], coord[2]); + m_rgba2.init(coord[0], coord[1]); + m_rgba3.init(coord[1], coord[2]); + } + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + m_rgba1.calc(y);//(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y); + const rgba_calc* pc1 = &m_rgba1; + const rgba_calc* pc2 = &m_rgba2; + + if(y <= m_y2) + { + // Bottom part of the triangle (first subtriangle) + //------------------------- + m_rgba2.calc(y + m_rgba2.m_1dy); + } + else + { + // Upper part (second subtriangle) + m_rgba3.calc(y - m_rgba3.m_1dy); + //------------------------- + pc2 = &m_rgba3; + } + + if(m_swap) + { + // It means that the triangle is oriented clockwise, + // so that we need to swap the controlling structures + //------------------------- + const rgba_calc* t = pc2; + pc2 = pc1; + pc1 = t; + } + + // Get the horizontal length with subpixel accuracy + // and protect it from division by zero + //------------------------- + int nlen = abs(pc2->m_x - pc1->m_x); + if(nlen <= 0) nlen = 1; + + dda_line_interpolator<14> r(pc1->m_r, pc2->m_r, nlen); + dda_line_interpolator<14> g(pc1->m_g, pc2->m_g, nlen); + dda_line_interpolator<14> b(pc1->m_b, pc2->m_b, nlen); + dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen); + + // Calculate the starting point of the gradient with subpixel + // accuracy and correct (roll back) the interpolators. + // This operation will also clip the beginning of the span + // if necessary. + //------------------------- + int start = pc1->m_x - (x << subpixel_shift); + r -= start; + g -= start; + b -= start; + a -= start; + nlen += start; + + int vr, vg, vb, va; + enum lim_e { lim = color_type::base_mask }; + + // Beginning part of the span. Since we rolled back the + // interpolators, the color values may have overflow. + // So that, we render the beginning part with checking + // for overflow. It lasts until "start" is positive; + // typically it's 1-2 pixels, but may be more in some cases. + //------------------------- + while(len && start > 0) + { + vr = r.y(); + vg = g.y(); + vb = b.y(); + va = a.y(); + if(vr < 0) vr = 0; if(vr > lim) vr = lim; + if(vg < 0) vg = 0; if(vg > lim) vg = lim; + if(vb < 0) vb = 0; if(vb > lim) vb = lim; + if(va < 0) va = 0; if(va > lim) va = lim; + span->r = (value_type)vr; + span->g = (value_type)vg; + span->b = (value_type)vb; + span->a = (value_type)va; + r += subpixel_scale; + g += subpixel_scale; + b += subpixel_scale; + a += subpixel_scale; + nlen -= subpixel_scale; + start -= subpixel_scale; + ++span; + --len; + } + + // Middle part, no checking for overflow. + // Actual spans can be longer than the calculated length + // because of anti-aliasing, thus, the interpolators can + // overflow. But while "nlen" is positive we are safe. + //------------------------- + while(len && nlen > 0) + { + span->r = (value_type)r.y(); + span->g = (value_type)g.y(); + span->b = (value_type)b.y(); + span->a = (value_type)a.y(); + r += subpixel_scale; + g += subpixel_scale; + b += subpixel_scale; + a += subpixel_scale; + nlen -= subpixel_scale; + ++span; + --len; + } + + // Ending part; checking for overflow. + // Typically it's 1-2 pixels, but may be more in some cases. + //------------------------- + while(len) + { + vr = r.y(); + vg = g.y(); + vb = b.y(); + va = a.y(); + if(vr < 0) vr = 0; if(vr > lim) vr = lim; + if(vg < 0) vg = 0; if(vg > lim) vg = lim; + if(vb < 0) vb = 0; if(vb > lim) vb = lim; + if(va < 0) va = 0; if(va > lim) va = lim; + span->r = (value_type)vr; + span->g = (value_type)vg; + span->b = (value_type)vb; + span->a = (value_type)va; + r += subpixel_scale; + g += subpixel_scale; + b += subpixel_scale; + a += subpixel_scale; + ++span; + --len; + } + } + + private: + bool m_swap; + int m_y2; + rgba_calc m_rgba1; + rgba_calc m_rgba2; + rgba_calc m_rgba3; + }; + + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_span_gradient.h b/jni/desmume/src/android/agg/include/agg_span_gradient.h new file mode 100755 index 0000000..1270281 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_span_gradient.h @@ -0,0 +1,373 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_GRADIENT_INCLUDED +#define AGG_SPAN_GRADIENT_INCLUDED + +#include <math.h> +#include <stdlib.h> +#include <string.h> +#include "agg_basics.h" +#include "agg_math.h" +#include "agg_array.h" + + +namespace agg +{ + + enum gradient_subpixel_scale_e + { + gradient_subpixel_shift = 4, //-----gradient_subpixel_shift + gradient_subpixel_scale = 1 << gradient_subpixel_shift, //-----gradient_subpixel_scale + gradient_subpixel_mask = gradient_subpixel_scale - 1 //-----gradient_subpixel_mask + }; + + + + //==========================================================span_gradient + template<class ColorT, + class Interpolator, + class GradientF, + class ColorF> + class span_gradient + { + public: + typedef Interpolator interpolator_type; + typedef ColorT color_type; + + enum downscale_shift_e + { + downscale_shift = interpolator_type::subpixel_shift - + gradient_subpixel_shift + }; + + //-------------------------------------------------------------------- + span_gradient() {} + + //-------------------------------------------------------------------- + span_gradient(interpolator_type& inter, + const GradientF& gradient_function, + const ColorF& color_function, + double d1, double d2) : + m_interpolator(&inter), + m_gradient_function(&gradient_function), + m_color_function(&color_function), + m_d1(iround(d1 * gradient_subpixel_scale)), + m_d2(iround(d2 * gradient_subpixel_scale)) + {} + + //-------------------------------------------------------------------- + interpolator_type& interpolator() { return *m_interpolator; } + const GradientF& gradient_function() const { return *m_gradient_function; } + const ColorF& color_function() const { return *m_color_function; } + double d1() const { return double(m_d1) / gradient_subpixel_scale; } + double d2() const { return double(m_d2) / gradient_subpixel_scale; } + + //-------------------------------------------------------------------- + void interpolator(interpolator_type& i) { m_interpolator = &i; } + void gradient_function(const GradientF& gf) { m_gradient_function = &gf; } + void color_function(const ColorF& cf) { m_color_function = &cf; } + void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); } + void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + int dd = m_d2 - m_d1; + if(dd < 1) dd = 1; + m_interpolator->begin(x+0.5, y+0.5, len); + do + { + m_interpolator->coordinates(&x, &y); + int d = m_gradient_function->calculate(x >> downscale_shift, + y >> downscale_shift, m_d2); + d = ((d - m_d1) * (int)m_color_function->size()) / dd; + if(d < 0) d = 0; + if(d >= (int)m_color_function->size()) d = m_color_function->size() - 1; + *span++ = (*m_color_function)[d]; + ++(*m_interpolator); + } + while(--len); + } + + private: + interpolator_type* m_interpolator; + const GradientF* m_gradient_function; + const ColorF* m_color_function; + int m_d1; + int m_d2; + }; + + + + + //=====================================================gradient_linear_color + template<class ColorT> + struct gradient_linear_color + { + typedef ColorT color_type; + + gradient_linear_color() {} + gradient_linear_color(const color_type& c1, const color_type& c2, + unsigned size = 256) : + m_c1(c1), m_c2(c2), m_size(size) {} + + unsigned size() const { return m_size; } + color_type operator [] (unsigned v) const + { + return m_c1.gradient(m_c2, double(v) / double(m_size - 1)); + } + + void colors(const color_type& c1, const color_type& c2, unsigned size = 256) + { + m_c1 = c1; + m_c2 = c2; + m_size = size; + } + + color_type m_c1; + color_type m_c2; + unsigned m_size; + }; + + + + + + + //==========================================================gradient_circle + class gradient_circle + { + // Actually the same as radial. Just for compatibility + public: + static AGG_INLINE int calculate(int x, int y, int) + { + return int(fast_sqrt(x*x + y*y)); + } + }; + + + //==========================================================gradient_radial + class gradient_radial + { + public: + static AGG_INLINE int calculate(int x, int y, int) + { + return int(fast_sqrt(x*x + y*y)); + } + }; + + //========================================================gradient_radial_d + class gradient_radial_d + { + public: + static AGG_INLINE int calculate(int x, int y, int) + { + return uround(sqrt(double(x)*double(x) + double(y)*double(y))); + } + }; + + //====================================================gradient_radial_focus + class gradient_radial_focus + { + public: + //--------------------------------------------------------------------- + gradient_radial_focus() : + m_r(100 * gradient_subpixel_scale), + m_fx(0), + m_fy(0) + { + update_values(); + } + + //--------------------------------------------------------------------- + gradient_radial_focus(double r, double fx, double fy) : + m_r (iround(r * gradient_subpixel_scale)), + m_fx(iround(fx * gradient_subpixel_scale)), + m_fy(iround(fy * gradient_subpixel_scale)) + { + update_values(); + } + + //--------------------------------------------------------------------- + void init(double r, double fx, double fy) + { + m_r = iround(r * gradient_subpixel_scale); + m_fx = iround(fx * gradient_subpixel_scale); + m_fy = iround(fy * gradient_subpixel_scale); + update_values(); + } + + //--------------------------------------------------------------------- + double radius() const { return double(m_r) / gradient_subpixel_scale; } + double focus_x() const { return double(m_fx) / gradient_subpixel_scale; } + double focus_y() const { return double(m_fy) / gradient_subpixel_scale; } + + //--------------------------------------------------------------------- + int calculate(int x, int y, int) const + { + double dx = x - m_fx; + double dy = y - m_fy; + double d2 = dx * m_fy - dy * m_fx; + double d3 = m_r2 * (dx * dx + dy * dy) - d2 * d2; + return iround((dx * m_fx + dy * m_fy + sqrt(fabs(d3))) * m_mul); + } + + private: + //--------------------------------------------------------------------- + void update_values() + { + // Calculate the invariant values. In case the focal center + // lies exactly on the gradient circle the divisor degenerates + // into zero. In this case we just move the focal center by + // one subpixel unit possibly in the direction to the origin (0,0) + // and calculate the values again. + //------------------------- + m_r2 = double(m_r) * double(m_r); + m_fx2 = double(m_fx) * double(m_fx); + m_fy2 = double(m_fy) * double(m_fy); + double d = (m_r2 - (m_fx2 + m_fy2)); + if(d == 0) + { + if(m_fx) { if(m_fx < 0) ++m_fx; else --m_fx; } + if(m_fy) { if(m_fy < 0) ++m_fy; else --m_fy; } + m_fx2 = double(m_fx) * double(m_fx); + m_fy2 = double(m_fy) * double(m_fy); + d = (m_r2 - (m_fx2 + m_fy2)); + } + m_mul = m_r / d; + } + + int m_r; + int m_fx; + int m_fy; + double m_r2; + double m_fx2; + double m_fy2; + double m_mul; + }; + + + //==============================================================gradient_x + class gradient_x + { + public: + static int calculate(int x, int, int) { return x; } + }; + + + //==============================================================gradient_y + class gradient_y + { + public: + static int calculate(int, int y, int) { return y; } + }; + + //========================================================gradient_diamond + class gradient_diamond + { + public: + static AGG_INLINE int calculate(int x, int y, int) + { + int ax = abs(x); + int ay = abs(y); + return ax > ay ? ax : ay; + } + }; + + //=============================================================gradient_xy + class gradient_xy + { + public: + static AGG_INLINE int calculate(int x, int y, int d) + { + return abs(x) * abs(y) / d; + } + }; + + //========================================================gradient_sqrt_xy + class gradient_sqrt_xy + { + public: + static AGG_INLINE int calculate(int x, int y, int) + { + return fast_sqrt(abs(x) * abs(y)); + } + }; + + //==========================================================gradient_conic + class gradient_conic + { + public: + static AGG_INLINE int calculate(int x, int y, int d) + { + return uround(fabs(atan2(double(y), double(x))) * double(d) / pi); + } + }; + + //=================================================gradient_repeat_adaptor + template<class GradientF> class gradient_repeat_adaptor + { + public: + gradient_repeat_adaptor(const GradientF& gradient) : + m_gradient(&gradient) {} + + AGG_INLINE int calculate(int x, int y, int d) const + { + int ret = m_gradient->calculate(x, y, d) % d; + if(ret < 0) ret += d; + return ret; + } + + private: + const GradientF* m_gradient; + }; + + //================================================gradient_reflect_adaptor + template<class GradientF> class gradient_reflect_adaptor + { + public: + gradient_reflect_adaptor(const GradientF& gradient) : + m_gradient(&gradient) {} + + AGG_INLINE int calculate(int x, int y, int d) const + { + int d2 = d << 1; + int ret = m_gradient->calculate(x, y, d) % d2; + if(ret < 0) ret += d2; + if(ret >= d) ret = d2 - ret; + return ret; + } + + private: + const GradientF* m_gradient; + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_span_gradient_alpha.h b/jni/desmume/src/android/agg/include/agg_span_gradient_alpha.h new file mode 100755 index 0000000..2cc5cb1 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_span_gradient_alpha.h @@ -0,0 +1,135 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_GRADIENT_ALPHA_INCLUDED +#define AGG_SPAN_GRADIENT_ALPHA_INCLUDED + +#include "agg_span_gradient.h" + +namespace agg +{ + //======================================================span_gradient_alpha + template<class ColorT, + class Interpolator, + class GradientF, + class AlphaF> + class span_gradient_alpha + { + public: + typedef Interpolator interpolator_type; + typedef ColorT color_type; + typedef typename color_type::value_type alpha_type; + + enum downscale_shift_e + { + downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift + }; + + + //-------------------------------------------------------------------- + span_gradient_alpha() {} + + //-------------------------------------------------------------------- + span_gradient_alpha(interpolator_type& inter, + const GradientF& gradient_function, + const AlphaF& alpha_function, + double d1, double d2) : + m_interpolator(&inter), + m_gradient_function(&gradient_function), + m_alpha_function(&alpha_function), + m_d1(iround(d1 * gradient_subpixel_scale)), + m_d2(iround(d2 * gradient_subpixel_scale)) + {} + + //-------------------------------------------------------------------- + interpolator_type& interpolator() { return *m_interpolator; } + const GradientF& gradient_function() const { return *m_gradient_function; } + const AlphaF& alpha_function() const { return *m_alpha_function; } + double d1() const { return double(m_d1) / gradient_subpixel_scale; } + double d2() const { return double(m_d2) / gradient_subpixel_scale; } + + //-------------------------------------------------------------------- + void interpolator(interpolator_type& i) { m_interpolator = &i; } + void gradient_function(const GradientF& gf) { m_gradient_function = &gf; } + void alpha_function(const AlphaF& af) { m_alpha_function = ⁡ } + void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); } + void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + int dd = m_d2 - m_d1; + if(dd < 1) dd = 1; + m_interpolator->begin(x+0.5, y+0.5, len); + do + { + m_interpolator->coordinates(&x, &y); + int d = m_gradient_function->calculate(x >> downscale_shift, + y >> downscale_shift, m_d2); + d = ((d - m_d1) * (int)m_alpha_function->size()) / dd; + if(d < 0) d = 0; + if(d >= (int)m_alpha_function->size()) d = m_alpha_function->size() - 1; + span->a = (*m_alpha_function)[d]; + ++span; + ++(*m_interpolator); + } + while(--len); + } + + private: + interpolator_type* m_interpolator; + const GradientF* m_gradient_function; + const AlphaF* m_alpha_function; + int m_d1; + int m_d2; + }; + + + //=======================================================gradient_alpha_x + template<class ColorT> struct gradient_alpha_x + { + typedef typename ColorT::value_type alpha_type; + alpha_type operator [] (alpha_type x) const { return x; } + }; + + //====================================================gradient_alpha_x_u8 + struct gradient_alpha_x_u8 + { + typedef int8u alpha_type; + alpha_type operator [] (alpha_type x) const { return x; } + }; + + //==========================================gradient_alpha_one_munus_x_u8 + struct gradient_alpha_one_munus_x_u8 + { + typedef int8u alpha_type; + alpha_type operator [] (alpha_type x) const { return 255-x; } + }; + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_span_image_filter.h b/jni/desmume/src/android/agg/include/agg_span_image_filter.h new file mode 100755 index 0000000..f104299 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_span_image_filter.h @@ -0,0 +1,252 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_IMAGE_FILTER_INCLUDED +#define AGG_SPAN_IMAGE_FILTER_INCLUDED + +#include "agg_basics.h" +#include "agg_image_filters.h" +#include "agg_span_interpolator_linear.h" + +namespace agg +{ + + //-------------------------------------------------------span_image_filter + template<class Source, class Interpolator> class span_image_filter + { + public: + typedef Source source_type; + typedef Interpolator interpolator_type; + + //-------------------------------------------------------------------- + span_image_filter() {} + span_image_filter(source_type& src, + interpolator_type& interpolator, + const image_filter_lut* filter) : + m_src(&src), + m_interpolator(&interpolator), + m_filter(filter), + m_dx_dbl(0.5), + m_dy_dbl(0.5), + m_dx_int(image_subpixel_scale / 2), + m_dy_int(image_subpixel_scale / 2) + {} + void attach(source_type& v) { m_src = &v; } + + //-------------------------------------------------------------------- + source_type& source() { return *m_src; } + const source_type& source() const { return *m_src; } + const image_filter_lut& filter() const { return *m_filter; } + int filter_dx_int() const { return m_dx_int; } + int filter_dy_int() const { return m_dy_int; } + double filter_dx_dbl() const { return m_dx_dbl; } + double filter_dy_dbl() const { return m_dy_dbl; } + + //-------------------------------------------------------------------- + void interpolator(interpolator_type& v) { m_interpolator = &v; } + void filter(const image_filter_lut& v) { m_filter = &v; } + void filter_offset(double dx, double dy) + { + m_dx_dbl = dx; + m_dy_dbl = dy; + m_dx_int = iround(dx * image_subpixel_scale); + m_dy_int = iround(dy * image_subpixel_scale); + } + void filter_offset(double d) { filter_offset(d, d); } + + //-------------------------------------------------------------------- + interpolator_type& interpolator() { return *m_interpolator; } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + private: + source_type* m_src; + interpolator_type* m_interpolator; + const image_filter_lut* m_filter; + double m_dx_dbl; + double m_dy_dbl; + unsigned m_dx_int; + unsigned m_dy_int; + }; + + + + + //==============================================span_image_resample_affine + template<class Source> + class span_image_resample_affine : + public span_image_filter<Source, span_interpolator_linear<trans_affine> > + { + public: + typedef Source source_type; + typedef span_interpolator_linear<trans_affine> interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + + //-------------------------------------------------------------------- + span_image_resample_affine() : + m_scale_limit(200.0), + m_blur_x(1.0), + m_blur_y(1.0) + {} + + //-------------------------------------------------------------------- + span_image_resample_affine(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, &filter), + m_scale_limit(200.0), + m_blur_x(1.0), + m_blur_y(1.0) + {} + + + //-------------------------------------------------------------------- + int scale_limit() const { return uround(m_scale_limit); } + void scale_limit(int v) { m_scale_limit = v; } + + //-------------------------------------------------------------------- + double blur_x() const { return m_blur_x; } + double blur_y() const { return m_blur_y; } + void blur_x(double v) { m_blur_x = v; } + void blur_y(double v) { m_blur_y = v; } + void blur(double v) { m_blur_x = m_blur_y = v; } + + //-------------------------------------------------------------------- + void prepare() + { + double scale_x; + double scale_y; + + base_type::interpolator().transformer().scaling_abs(&scale_x, &scale_y); + + if(scale_x * scale_y > m_scale_limit) + { + scale_x = scale_x * m_scale_limit / (scale_x * scale_y); + scale_y = scale_y * m_scale_limit / (scale_x * scale_y); + } + + if(scale_x < 1) scale_x = 1; + if(scale_y < 1) scale_y = 1; + + if(scale_x > m_scale_limit) scale_x = m_scale_limit; + if(scale_y > m_scale_limit) scale_y = m_scale_limit; + + scale_x *= m_blur_x; + scale_y *= m_blur_y; + + if(scale_x < 1) scale_x = 1; + if(scale_y < 1) scale_y = 1; + + m_rx = uround( scale_x * double(image_subpixel_scale)); + m_rx_inv = uround(1.0/scale_x * double(image_subpixel_scale)); + + m_ry = uround( scale_y * double(image_subpixel_scale)); + m_ry_inv = uround(1.0/scale_y * double(image_subpixel_scale)); + } + + protected: + int m_rx; + int m_ry; + int m_rx_inv; + int m_ry_inv; + + private: + double m_scale_limit; + double m_blur_x; + double m_blur_y; + }; + + + + //=====================================================span_image_resample + template<class Source, class Interpolator> + class span_image_resample : + public span_image_filter<Source, Interpolator> + { + public: + typedef Source source_type; + typedef Interpolator interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + + //-------------------------------------------------------------------- + span_image_resample() : + m_scale_limit(20), + m_blur_x(image_subpixel_scale), + m_blur_y(image_subpixel_scale) + {} + + //-------------------------------------------------------------------- + span_image_resample(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, &filter), + m_scale_limit(20), + m_blur_x(image_subpixel_scale), + m_blur_y(image_subpixel_scale) + {} + + //-------------------------------------------------------------------- + int scale_limit() const { return m_scale_limit; } + void scale_limit(int v) { m_scale_limit = v; } + + //-------------------------------------------------------------------- + double blur_x() const { return double(m_blur_x) / double(image_subpixel_scale); } + double blur_y() const { return double(m_blur_y) / double(image_subpixel_scale); } + void blur_x(double v) { m_blur_x = uround(v * double(image_subpixel_scale)); } + void blur_y(double v) { m_blur_y = uround(v * double(image_subpixel_scale)); } + void blur(double v) { m_blur_x = + m_blur_y = uround(v * double(image_subpixel_scale)); } + + protected: + AGG_INLINE void adjust_scale(int* rx, int* ry) + { + if(*rx < image_subpixel_scale) *rx = image_subpixel_scale; + if(*ry < image_subpixel_scale) *ry = image_subpixel_scale; + if(*rx > image_subpixel_scale * m_scale_limit) + { + *rx = image_subpixel_scale * m_scale_limit; + } + if(*ry > image_subpixel_scale * m_scale_limit) + { + *ry = image_subpixel_scale * m_scale_limit; + } + *rx = (*rx * m_blur_x) >> image_subpixel_shift; + *ry = (*ry * m_blur_y) >> image_subpixel_shift; + if(*rx < image_subpixel_scale) *rx = image_subpixel_scale; + if(*ry < image_subpixel_scale) *ry = image_subpixel_scale; + } + + int m_scale_limit; + int m_blur_x; + int m_blur_y; + }; + + + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_span_image_filter_gray.h b/jni/desmume/src/android/agg/include/agg_span_image_filter_gray.h new file mode 100755 index 0000000..4a312d0 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_span_image_filter_gray.h @@ -0,0 +1,757 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- +#ifndef AGG_SPAN_IMAGE_FILTER_GRAY_INCLUDED +#define AGG_SPAN_IMAGE_FILTER_GRAY_INCLUDED + +#include "agg_basics.h" +#include "agg_color_gray.h" +#include "agg_span_image_filter.h" + + +namespace agg +{ + + //==============================================span_image_filter_gray_nn + template<class Source, class Interpolator> + class span_image_filter_gray_nn : + public span_image_filter<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef Interpolator interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + span_image_filter_gray_nn() {} + span_image_filter_gray_nn(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + do + { + base_type::interpolator().coordinates(&x, &y); + span->v = *(const value_type*) + base_type::source().span(x >> image_subpixel_shift, + y >> image_subpixel_shift, + 1); + span->a = base_mask; + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + + + //=========================================span_image_filter_gray_bilinear + template<class Source, class Interpolator> + class span_image_filter_gray_bilinear : + public span_image_filter<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef Interpolator interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + span_image_filter_gray_bilinear() {} + span_image_filter_gray_bilinear(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + calc_type fg; + const value_type *fg_ptr; + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + fg = image_subpixel_scale * image_subpixel_scale / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + fg += *fg_ptr * (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); + + fg_ptr = (const value_type*)base_type::source().next_x(); + fg += *fg_ptr * x_hr * (image_subpixel_scale - y_hr); + + fg_ptr = (const value_type*)base_type::source().next_y(); + fg += *fg_ptr * (image_subpixel_scale - x_hr) * y_hr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + fg += *fg_ptr * x_hr * y_hr; + + span->v = value_type(fg >> (image_subpixel_shift * 2)); + span->a = base_mask; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + //====================================span_image_filter_gray_bilinear_clip + template<class Source, class Interpolator> + class span_image_filter_gray_bilinear_clip : + public span_image_filter<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef Interpolator interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + span_image_filter_gray_bilinear_clip() {} + span_image_filter_gray_bilinear_clip(source_type& src, + const color_type& back_color, + interpolator_type& inter) : + base_type(src, inter, 0), + m_back_color(back_color) + {} + const color_type& background_color() const { return m_back_color; } + void background_color(const color_type& v) { m_back_color = v; } + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + calc_type fg; + calc_type src_alpha; + value_type back_v = m_back_color.v; + value_type back_a = m_back_color.a; + + const value_type *fg_ptr; + + int maxx = base_type::source().width() - 1; + int maxy = base_type::source().height() - 1; + + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + if(x_lr >= 0 && y_lr >= 0 && + x_lr < maxx && y_lr < maxy) + { + fg = image_subpixel_scale * image_subpixel_scale / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + fg_ptr = (const value_type*)base_type::source().row_ptr(y_lr) + x_lr; + + fg += *fg_ptr++ * (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); + fg += *fg_ptr++ * (image_subpixel_scale - y_hr) * x_hr; + + ++y_lr; + fg_ptr = (const value_type*)base_type::source().row_ptr(y_lr) + x_lr; + + fg += *fg_ptr++ * (image_subpixel_scale - x_hr) * y_hr; + fg += *fg_ptr++ * x_hr * y_hr; + + fg >>= image_subpixel_shift * 2; + src_alpha = base_mask; + } + else + { + unsigned weight; + if(x_lr < -1 || y_lr < -1 || + x_lr > maxx || y_lr > maxy) + { + fg = back_v; + src_alpha = back_a; + } + else + { + fg = + src_alpha = image_subpixel_scale * image_subpixel_scale / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg += weight * + *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); + src_alpha += weight * base_mask; + } + else + { + fg += back_v * weight; + src_alpha += back_a * weight; + } + + x_lr++; + + weight = x_hr * (image_subpixel_scale - y_hr); + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg += weight * + *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); + src_alpha += weight * base_mask; + } + else + { + fg += back_v * weight; + src_alpha += back_a * weight; + } + + x_lr--; + y_lr++; + + weight = (image_subpixel_scale - x_hr) * y_hr; + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg += weight * + *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); + src_alpha += weight * base_mask; + } + else + { + fg += back_v * weight; + src_alpha += back_a * weight; + } + + x_lr++; + + weight = x_hr * y_hr; + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg += weight * + *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); + src_alpha += weight * base_mask; + } + else + { + fg += back_v * weight; + src_alpha += back_a * weight; + } + + fg >>= image_subpixel_shift * 2; + src_alpha >>= image_subpixel_shift * 2; + } + } + + span->v = (value_type)fg; + span->a = (value_type)src_alpha; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + private: + color_type m_back_color; + }; + + + + //==============================================span_image_filter_gray_2x2 + template<class Source, class Interpolator> + class span_image_filter_gray_2x2 : + public span_image_filter<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef Interpolator interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + span_image_filter_gray_2x2() {} + span_image_filter_gray_2x2(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, &filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + calc_type fg; + + const value_type *fg_ptr; + const int16* weight_array = base_type::filter().weight_array() + + ((base_type::filter().diameter()/2 - 1) << + image_subpixel_shift); + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + unsigned weight; + fg = image_filter_scale / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_y(); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg += weight * *fg_ptr; + + fg >>= image_filter_shift; + if(fg > base_mask) fg = base_mask; + + span->v = (value_type)fg; + span->a = base_mask; + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + + + //==================================================span_image_filter_gray + template<class Source, class Interpolator> + class span_image_filter_gray : + public span_image_filter<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef Interpolator interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + span_image_filter_gray() {} + span_image_filter_gray(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, &filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + int fg; + const value_type *fg_ptr; + + unsigned diameter = base_type::filter().diameter(); + int start = base_type::filter().start(); + const int16* weight_array = base_type::filter().weight_array(); + + int x_count; + int weight_y; + + do + { + base_type::interpolator().coordinates(&x, &y); + + x -= base_type::filter_dx_int(); + y -= base_type::filter_dy_int(); + + int x_hr = x; + int y_hr = y; + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + fg = image_filter_scale / 2; + + int x_fract = x_hr & image_subpixel_mask; + unsigned y_count = diameter; + + y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); + fg_ptr = (const value_type*)base_type::source().span(x_lr + start, + y_lr + start, + diameter); + for(;;) + { + x_count = diameter; + weight_y = weight_array[y_hr]; + x_hr = image_subpixel_mask - x_fract; + for(;;) + { + fg += *fg_ptr * + ((weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + image_filter_shift); + if(--x_count == 0) break; + x_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + + if(--y_count == 0) break; + y_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg >>= image_filter_shift; + if(fg < 0) fg = 0; + if(fg > base_mask) fg = base_mask; + span->v = (value_type)fg; + span->a = base_mask; + + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //=========================================span_image_resample_gray_affine + template<class Source> + class span_image_resample_gray_affine : + public span_image_resample_affine<Source> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef span_image_resample_affine<source_type> base_type; + typedef typename base_type::interpolator_type interpolator_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask, + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_gray_affine() {} + span_image_resample_gray_affine(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + int radius_x = (diameter * base_type::m_rx) >> 1; + int radius_y = (diameter * base_type::m_ry) >> 1; + int len_x_lr = + (diameter * base_type::m_rx + image_subpixel_mask) >> + image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + + do + { + base_type::interpolator().coordinates(&x, &y); + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg = image_filter_scale / 2; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + base_type::m_ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + base_type::m_rx_inv) >> + image_subpixel_shift; + + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + + fg += *fg_ptr * weight; + total_weight += weight; + x_hr += base_type::m_rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + y_hr += base_type::m_ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg /= total_weight; + if(fg < 0) fg = 0; + if(fg > base_mask) fg = base_mask; + + span->v = (value_type)fg; + span->a = base_mask; + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + + + //================================================span_image_resample_gray + template<class Source, class Interpolator> + class span_image_resample_gray : + public span_image_resample<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef Interpolator interpolator_type; + typedef span_image_resample<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask, + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_gray() {} + span_image_resample_gray(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + long_type fg; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + do + { + int rx; + int ry; + int rx_inv = image_subpixel_scale; + int ry_inv = image_subpixel_scale; + base_type::interpolator().coordinates(&x, &y); + base_type::interpolator().local_scale(&rx, &ry); + base_type::adjust_scale(&rx, &ry); + + rx_inv = image_subpixel_scale * image_subpixel_scale / rx; + ry_inv = image_subpixel_scale * image_subpixel_scale / ry; + + int radius_x = (diameter * rx) >> 1; + int radius_y = (diameter * ry) >> 1; + int len_x_lr = + (diameter * rx + image_subpixel_mask) >> + image_subpixel_shift; + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg = image_filter_scale / 2; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + rx_inv) >> + image_subpixel_shift; + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + fg += *fg_ptr * weight; + total_weight += weight; + x_hr += rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + y_hr += ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg /= total_weight; + if(fg < 0) fg = 0; + if(fg > base_mask) fg = base_mask; + + span->v = (value_type)fg; + span->a = base_mask; + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + +} + + +#endif + + + diff --git a/jni/desmume/src/android/agg/include/agg_span_image_filter_rgb.h b/jni/desmume/src/android/agg/include/agg_span_image_filter_rgb.h new file mode 100755 index 0000000..dfead43 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_span_image_filter_rgb.h @@ -0,0 +1,901 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- +#ifndef AGG_SPAN_IMAGE_FILTER_RGB_INCLUDED +#define AGG_SPAN_IMAGE_FILTER_RGB_INCLUDED + +#include "agg_basics.h" +#include "agg_color_rgba.h" +#include "agg_span_image_filter.h" + + +namespace agg +{ + + //===============================================span_image_filter_rgb_nn + template<class Source, class Interpolator> + class span_image_filter_rgb_nn : + public span_image_filter<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + span_image_filter_rgb_nn() {} + span_image_filter_rgb_nn(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + do + { + base_type::interpolator().coordinates(&x, &y); + const value_type* fg_ptr = (const value_type*) + base_type::source().span(x >> image_subpixel_shift, + y >> image_subpixel_shift, + 1); + span->r = fg_ptr[order_type::R]; + span->g = fg_ptr[order_type::G]; + span->b = fg_ptr[order_type::B]; + span->a = base_mask; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //==========================================span_image_filter_rgb_bilinear + template<class Source, class Interpolator> + class span_image_filter_rgb_bilinear : + public span_image_filter<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + span_image_filter_rgb_bilinear() {} + span_image_filter_rgb_bilinear(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + calc_type fg[3]; + const value_type *fg_ptr; + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + unsigned weight; + + fg[0] = + fg[1] = + fg[2] = image_subpixel_scale * image_subpixel_scale / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = x_hr * (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_y(); + weight = (image_subpixel_scale - x_hr) * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = x_hr * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + span->r = value_type(fg[order_type::R] >> (image_subpixel_shift * 2)); + span->g = value_type(fg[order_type::G] >> (image_subpixel_shift * 2)); + span->b = value_type(fg[order_type::B] >> (image_subpixel_shift * 2)); + span->a = base_mask; + + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //=====================================span_image_filter_rgb_bilinear_clip + template<class Source, class Interpolator> + class span_image_filter_rgb_bilinear_clip : + public span_image_filter<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + span_image_filter_rgb_bilinear_clip() {} + span_image_filter_rgb_bilinear_clip(source_type& src, + const color_type& back_color, + interpolator_type& inter) : + base_type(src, inter, 0), + m_back_color(back_color) + {} + const color_type& background_color() const { return m_back_color; } + void background_color(const color_type& v) { m_back_color = v; } + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + calc_type fg[3]; + calc_type src_alpha; + value_type back_r = m_back_color.r; + value_type back_g = m_back_color.g; + value_type back_b = m_back_color.b; + value_type back_a = m_back_color.a; + + const value_type *fg_ptr; + + int maxx = base_type::source().width() - 1; + int maxy = base_type::source().height() - 1; + + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + unsigned weight; + + if(x_lr >= 0 && y_lr >= 0 && + x_lr < maxx && y_lr < maxy) + { + fg[0] = + fg[1] = + fg[2] = image_subpixel_scale * image_subpixel_scale / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + + weight = x_hr * (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + + ++y_lr; + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + + weight = (image_subpixel_scale - x_hr) * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + + weight = x_hr * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + + fg[0] >>= image_subpixel_shift * 2; + fg[1] >>= image_subpixel_shift * 2; + fg[2] >>= image_subpixel_shift * 2; + src_alpha = base_mask; + } + else + { + if(x_lr < -1 || y_lr < -1 || + x_lr > maxx || y_lr > maxy) + { + fg[order_type::R] = back_r; + fg[order_type::G] = back_g; + fg[order_type::B] = back_b; + src_alpha = back_a; + } + else + { + fg[0] = + fg[1] = + fg[2] = + src_alpha = image_subpixel_scale * image_subpixel_scale / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + src_alpha += weight * base_mask; + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + src_alpha += back_a * weight; + } + + x_lr++; + + weight = x_hr * (image_subpixel_scale - y_hr); + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + src_alpha += weight * base_mask; + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + src_alpha += back_a * weight; + } + + x_lr--; + y_lr++; + + weight = (image_subpixel_scale - x_hr) * y_hr; + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + src_alpha += weight * base_mask; + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + src_alpha += back_a * weight; + } + + x_lr++; + + weight = x_hr * y_hr; + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + src_alpha += weight * base_mask; + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + src_alpha += back_a * weight; + } + + fg[0] >>= image_subpixel_shift * 2; + fg[1] >>= image_subpixel_shift * 2; + fg[2] >>= image_subpixel_shift * 2; + src_alpha >>= image_subpixel_shift * 2; + } + } + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)src_alpha; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + private: + color_type m_back_color; + }; + + + + //===============================================span_image_filter_rgb_2x2 + template<class Source, class Interpolator> + class span_image_filter_rgb_2x2 : + public span_image_filter<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + span_image_filter_rgb_2x2() {} + span_image_filter_rgb_2x2(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, &filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + calc_type fg[3]; + + const value_type *fg_ptr; + const int16* weight_array = base_type::filter().weight_array() + + ((base_type::filter().diameter()/2 - 1) << + image_subpixel_shift); + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + unsigned weight; + fg[0] = fg[1] = fg[2] = image_filter_scale / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_y(); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg[0] >>= image_filter_shift; + fg[1] >>= image_filter_shift; + fg[2] >>= image_filter_shift; + + if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; + if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; + if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = base_mask; + + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //===================================================span_image_filter_rgb + template<class Source, class Interpolator> + class span_image_filter_rgb : + public span_image_filter<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + span_image_filter_rgb() {} + span_image_filter_rgb(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, &filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + int fg[3]; + const value_type *fg_ptr; + + unsigned diameter = base_type::filter().diameter(); + int start = base_type::filter().start(); + const int16* weight_array = base_type::filter().weight_array(); + + int x_count; + int weight_y; + + do + { + base_type::interpolator().coordinates(&x, &y); + + x -= base_type::filter_dx_int(); + y -= base_type::filter_dy_int(); + + int x_hr = x; + int y_hr = y; + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + fg[0] = fg[1] = fg[2] = image_filter_scale / 2; + + int x_fract = x_hr & image_subpixel_mask; + unsigned y_count = diameter; + + y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); + fg_ptr = (const value_type*)base_type::source().span(x_lr + start, + y_lr + start, + diameter); + for(;;) + { + x_count = diameter; + weight_y = weight_array[y_hr]; + x_hr = image_subpixel_mask - x_fract; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + image_filter_shift; + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + if(--x_count == 0) break; + x_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + + if(--y_count == 0) break; + y_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg[0] >>= image_filter_shift; + fg[1] >>= image_filter_shift; + fg[2] >>= image_filter_shift; + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + + if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; + if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; + if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = base_mask; + + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //==========================================span_image_resample_rgb_affine + template<class Source> + class span_image_resample_rgb_affine : + public span_image_resample_affine<Source> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef span_image_resample_affine<source_type> base_type; + typedef typename base_type::interpolator_type interpolator_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask, + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_rgb_affine() {} + span_image_resample_rgb_affine(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg[3]; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + int radius_x = (diameter * base_type::m_rx) >> 1; + int radius_y = (diameter * base_type::m_ry) >> 1; + int len_x_lr = + (diameter * base_type::m_rx + image_subpixel_mask) >> + image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + + do + { + base_type::interpolator().coordinates(&x, &y); + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg[0] = fg[1] = fg[2] = image_filter_scale / 2; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + base_type::m_ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + base_type::m_rx_inv) >> + image_subpixel_shift; + + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + + fg[0] += *fg_ptr++ * weight; + fg[1] += *fg_ptr++ * weight; + fg[2] += *fg_ptr * weight; + total_weight += weight; + x_hr += base_type::m_rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + y_hr += base_type::m_ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg[0] /= total_weight; + fg[1] /= total_weight; + fg[2] /= total_weight; + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + + if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; + if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; + if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = base_mask; + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + + + //=================================================span_image_resample_rgb + template<class Source, class Interpolator> + class span_image_resample_rgb : + public span_image_resample<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_resample<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask, + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_rgb() {} + span_image_resample_rgb(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + long_type fg[3]; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + do + { + int rx; + int ry; + int rx_inv = image_subpixel_scale; + int ry_inv = image_subpixel_scale; + base_type::interpolator().coordinates(&x, &y); + base_type::interpolator().local_scale(&rx, &ry); + base_type::adjust_scale(&rx, &ry); + + rx_inv = image_subpixel_scale * image_subpixel_scale / rx; + ry_inv = image_subpixel_scale * image_subpixel_scale / ry; + + int radius_x = (diameter * rx) >> 1; + int radius_y = (diameter * ry) >> 1; + int len_x_lr = + (diameter * rx + image_subpixel_mask) >> + image_subpixel_shift; + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg[0] = fg[1] = fg[2] = image_filter_scale / 2; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + rx_inv) >> + image_subpixel_shift; + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + fg[0] += *fg_ptr++ * weight; + fg[1] += *fg_ptr++ * weight; + fg[2] += *fg_ptr * weight; + total_weight += weight; + x_hr += rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + y_hr += ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg[0] /= total_weight; + fg[1] /= total_weight; + fg[2] /= total_weight; + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + + if(fg[order_type::R] > base_mask) fg[order_type::R] = base_mask; + if(fg[order_type::G] > base_mask) fg[order_type::G] = base_mask; + if(fg[order_type::B] > base_mask) fg[order_type::B] = base_mask; + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = base_mask; + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + +} + + +#endif + + + diff --git a/jni/desmume/src/android/agg/include/agg_span_image_filter_rgba.h b/jni/desmume/src/android/agg/include/agg_span_image_filter_rgba.h new file mode 100755 index 0000000..fcf2c37 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_span_image_filter_rgba.h @@ -0,0 +1,929 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- +#ifndef AGG_SPAN_IMAGE_FILTER_RGBA_INCLUDED +#define AGG_SPAN_IMAGE_FILTER_RGBA_INCLUDED + +#include "agg_basics.h" +#include "agg_color_rgba.h" +#include "agg_span_image_filter.h" + + +namespace agg +{ + + //==============================================span_image_filter_rgba_nn + template<class Source, class Interpolator> + class span_image_filter_rgba_nn : + public span_image_filter<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + span_image_filter_rgba_nn() {} + span_image_filter_rgba_nn(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + do + { + base_type::interpolator().coordinates(&x, &y); + const value_type* fg_ptr = (const value_type*) + base_type::source().span(x >> image_subpixel_shift, + y >> image_subpixel_shift, + 1); + span->r = fg_ptr[order_type::R]; + span->g = fg_ptr[order_type::G]; + span->b = fg_ptr[order_type::B]; + span->a = fg_ptr[order_type::A]; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //=========================================span_image_filter_rgba_bilinear + template<class Source, class Interpolator> + class span_image_filter_rgba_bilinear : + public span_image_filter<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + span_image_filter_rgba_bilinear() {} + span_image_filter_rgba_bilinear(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + calc_type fg[4]; + const value_type *fg_ptr; + + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + unsigned weight; + + fg[0] = + fg[1] = + fg[2] = + fg[3] = image_subpixel_scale * image_subpixel_scale / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = x_hr * (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_y(); + weight = (image_subpixel_scale - x_hr) * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = x_hr * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + span->r = value_type(fg[order_type::R] >> (image_subpixel_shift * 2)); + span->g = value_type(fg[order_type::G] >> (image_subpixel_shift * 2)); + span->b = value_type(fg[order_type::B] >> (image_subpixel_shift * 2)); + span->a = value_type(fg[order_type::A] >> (image_subpixel_shift * 2)); + + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + //====================================span_image_filter_rgba_bilinear_clip + template<class Source, class Interpolator> + class span_image_filter_rgba_bilinear_clip : + public span_image_filter<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + span_image_filter_rgba_bilinear_clip() {} + span_image_filter_rgba_bilinear_clip(source_type& src, + const color_type& back_color, + interpolator_type& inter) : + base_type(src, inter, 0), + m_back_color(back_color) + {} + const color_type& background_color() const { return m_back_color; } + void background_color(const color_type& v) { m_back_color = v; } + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + calc_type fg[4]; + value_type back_r = m_back_color.r; + value_type back_g = m_back_color.g; + value_type back_b = m_back_color.b; + value_type back_a = m_back_color.a; + + const value_type *fg_ptr; + int maxx = base_type::source().width() - 1; + int maxy = base_type::source().height() - 1; + + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + unsigned weight; + + if(x_lr >= 0 && y_lr >= 0 && + x_lr < maxx && y_lr < maxy) + { + fg[0] = + fg[1] = + fg[2] = + fg[3] = image_subpixel_scale * image_subpixel_scale / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + + weight = x_hr * (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + + ++y_lr; + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + + weight = (image_subpixel_scale - x_hr) * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + + weight = x_hr * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + + fg[0] >>= image_subpixel_shift * 2; + fg[1] >>= image_subpixel_shift * 2; + fg[2] >>= image_subpixel_shift * 2; + fg[3] >>= image_subpixel_shift * 2; + } + else + { + if(x_lr < -1 || y_lr < -1 || + x_lr > maxx || y_lr > maxy) + { + fg[order_type::R] = back_r; + fg[order_type::G] = back_g; + fg[order_type::B] = back_b; + fg[order_type::A] = back_a; + } + else + { + fg[0] = + fg[1] = + fg[2] = + fg[3] = image_subpixel_scale * image_subpixel_scale / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + fg[order_type::A] += back_a * weight; + } + + x_lr++; + + weight = x_hr * (image_subpixel_scale - y_hr); + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + fg[order_type::A] += back_a * weight; + } + + x_lr--; + y_lr++; + + weight = (image_subpixel_scale - x_hr) * y_hr; + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + fg[order_type::A] += back_a * weight; + } + + x_lr++; + + weight = x_hr * y_hr; + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + fg[order_type::A] += back_a * weight; + } + + fg[0] >>= image_subpixel_shift * 2; + fg[1] >>= image_subpixel_shift * 2; + fg[2] >>= image_subpixel_shift * 2; + fg[3] >>= image_subpixel_shift * 2; + } + } + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)fg[order_type::A]; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + private: + color_type m_back_color; + }; + + + //==============================================span_image_filter_rgba_2x2 + template<class Source, class Interpolator> + class span_image_filter_rgba_2x2 : + public span_image_filter<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + span_image_filter_rgba_2x2() {} + span_image_filter_rgba_2x2(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, &filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + calc_type fg[4]; + + const value_type *fg_ptr; + const int16* weight_array = base_type::filter().weight_array() + + ((base_type::filter().diameter()/2 - 1) << + image_subpixel_shift); + + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + unsigned weight; + fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_y(); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg[0] >>= image_filter_shift; + fg[1] >>= image_filter_shift; + fg[2] >>= image_filter_shift; + fg[3] >>= image_filter_shift; + + if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; + if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; + if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; + if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)fg[order_type::A]; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //==================================================span_image_filter_rgba + template<class Source, class Interpolator> + class span_image_filter_rgba : + public span_image_filter<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + span_image_filter_rgba() {} + span_image_filter_rgba(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, &filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + int fg[4]; + const value_type *fg_ptr; + + unsigned diameter = base_type::filter().diameter(); + int start = base_type::filter().start(); + const int16* weight_array = base_type::filter().weight_array(); + + int x_count; + int weight_y; + + do + { + base_type::interpolator().coordinates(&x, &y); + + x -= base_type::filter_dx_int(); + y -= base_type::filter_dy_int(); + + int x_hr = x; + int y_hr = y; + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2; + + int x_fract = x_hr & image_subpixel_mask; + unsigned y_count = diameter; + + y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); + fg_ptr = (const value_type*)base_type::source().span(x_lr + start, + y_lr + start, + diameter); + for(;;) + { + x_count = diameter; + weight_y = weight_array[y_hr]; + x_hr = image_subpixel_mask - x_fract; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + image_filter_shift; + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + if(--x_count == 0) break; + x_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + + if(--y_count == 0) break; + y_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg[0] >>= image_filter_shift; + fg[1] >>= image_filter_shift; + fg[2] >>= image_filter_shift; + fg[3] >>= image_filter_shift; + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + if(fg[3] < 0) fg[3] = 0; + + if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; + if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; + if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; + if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)fg[order_type::A]; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //========================================span_image_resample_rgba_affine + template<class Source> + class span_image_resample_rgba_affine : + public span_image_resample_affine<Source> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef span_image_resample_affine<source_type> base_type; + typedef typename base_type::interpolator_type interpolator_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask, + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_rgba_affine() {} + span_image_resample_rgba_affine(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg[4]; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + int radius_x = (diameter * base_type::m_rx) >> 1; + int radius_y = (diameter * base_type::m_ry) >> 1; + int len_x_lr = + (diameter * base_type::m_rx + image_subpixel_mask) >> + image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + + do + { + base_type::interpolator().coordinates(&x, &y); + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + base_type::m_ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + base_type::m_rx_inv) >> + image_subpixel_shift; + + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + + fg[0] += *fg_ptr++ * weight; + fg[1] += *fg_ptr++ * weight; + fg[2] += *fg_ptr++ * weight; + fg[3] += *fg_ptr++ * weight; + total_weight += weight; + x_hr += base_type::m_rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + y_hr += base_type::m_ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg[0] /= total_weight; + fg[1] /= total_weight; + fg[2] /= total_weight; + fg[3] /= total_weight; + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + if(fg[3] < 0) fg[3] = 0; + + if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; + if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; + if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; + if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)fg[order_type::A]; + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + + + //==============================================span_image_resample_rgba + template<class Source, class Interpolator> + class span_image_resample_rgba : + public span_image_resample<Source, Interpolator> + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_resample<source_type, interpolator_type> base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask, + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_rgba() {} + span_image_resample_rgba(source_type& src, + interpolator_type& inter, + const image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + long_type fg[4]; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + do + { + int rx; + int ry; + int rx_inv = image_subpixel_scale; + int ry_inv = image_subpixel_scale; + base_type::interpolator().coordinates(&x, &y); + base_type::interpolator().local_scale(&rx, &ry); + base_type::adjust_scale(&rx, &ry); + + rx_inv = image_subpixel_scale * image_subpixel_scale / rx; + ry_inv = image_subpixel_scale * image_subpixel_scale / ry; + + int radius_x = (diameter * rx) >> 1; + int radius_y = (diameter * ry) >> 1; + int len_x_lr = + (diameter * rx + image_subpixel_mask) >> + image_subpixel_shift; + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg[0] = fg[1] = fg[2] = fg[3] = image_filter_scale / 2; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + rx_inv) >> + image_subpixel_shift; + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + fg[0] += *fg_ptr++ * weight; + fg[1] += *fg_ptr++ * weight; + fg[2] += *fg_ptr++ * weight; + fg[3] += *fg_ptr++ * weight; + total_weight += weight; + x_hr += rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + y_hr += ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg[0] /= total_weight; + fg[1] /= total_weight; + fg[2] /= total_weight; + fg[3] /= total_weight; + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + if(fg[3] < 0) fg[3] = 0; + + if(fg[order_type::A] > base_mask) fg[order_type::A] = base_mask; + if(fg[order_type::R] > fg[order_type::R]) fg[order_type::R] = fg[order_type::R]; + if(fg[order_type::G] > fg[order_type::G]) fg[order_type::G] = fg[order_type::G]; + if(fg[order_type::B] > fg[order_type::B]) fg[order_type::B] = fg[order_type::B]; + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)fg[order_type::A]; + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + +} + + +#endif + + + diff --git a/jni/desmume/src/android/agg/include/agg_span_interpolator_adaptor.h b/jni/desmume/src/android/agg/include/agg_span_interpolator_adaptor.h new file mode 100755 index 0000000..97a10c4 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_span_interpolator_adaptor.h @@ -0,0 +1,86 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_INTERPOLATOR_ADAPTOR_INCLUDED +#define AGG_SPAN_INTERPOLATOR_ADAPTOR_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //===============================================span_interpolator_adaptor + template<class Interpolator, class Distortion> + class span_interpolator_adaptor : public Interpolator + { + public: + typedef Interpolator base_type; + typedef typename base_type::trans_type trans_type; + typedef Distortion distortion_type; + + //-------------------------------------------------------------------- + span_interpolator_adaptor() {} + span_interpolator_adaptor(const trans_type& trans, + const distortion_type& dist) : + base_type(trans), + m_distortion(&dist) + { + } + + //-------------------------------------------------------------------- + span_interpolator_adaptor(const trans_type& trans, + const distortion_type& dist, + double x, double y, unsigned len) : + base_type(trans, x, y, len), + m_distortion(&dist) + { + } + + //-------------------------------------------------------------------- + const distortion_type& distortion() const + { + return *m_distortion; + } + + //-------------------------------------------------------------------- + void distortion(const distortion_type& dist) + { + m_distortion = dist; + } + + //-------------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + base_type::coordinates(x, y); + m_distortion->calculate(x, y); + } + + private: + //-------------------------------------------------------------------- + const distortion_type* m_distortion; + }; +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_span_interpolator_linear.h b/jni/desmume/src/android/agg/include/agg_span_interpolator_linear.h new file mode 100755 index 0000000..f8bded5 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_span_interpolator_linear.h @@ -0,0 +1,241 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED +#define AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED + +#include "agg_basics.h" +#include "agg_dda_line.h" +#include "agg_trans_affine.h" + +namespace agg +{ + + //================================================span_interpolator_linear + template<class Transformer = trans_affine, unsigned SubpixelShift = 8> + class span_interpolator_linear + { + public: + typedef Transformer trans_type; + + enum subpixel_scale_e + { + subpixel_shift = SubpixelShift, + subpixel_scale = 1 << subpixel_shift + }; + + //-------------------------------------------------------------------- + span_interpolator_linear() {} + span_interpolator_linear(const trans_type& trans) : m_trans(&trans) {} + span_interpolator_linear(const trans_type& trans, + double x, double y, unsigned len) : + m_trans(&trans) + { + begin(x, y, len); + } + + //---------------------------------------------------------------- + const trans_type& transformer() const { return *m_trans; } + void transformer(const trans_type& trans) { m_trans = &trans; } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned len) + { + double tx; + double ty; + + tx = x; + ty = y; + m_trans->transform(&tx, &ty); + int x1 = iround(tx * subpixel_scale); + int y1 = iround(ty * subpixel_scale); + + tx = x + len; + ty = y; + m_trans->transform(&tx, &ty); + int x2 = iround(tx * subpixel_scale); + int y2 = iround(ty * subpixel_scale); + + m_li_x = dda2_line_interpolator(x1, x2, len); + m_li_y = dda2_line_interpolator(y1, y2, len); + } + + //---------------------------------------------------------------- + void resynchronize(double xe, double ye, unsigned len) + { + m_trans->transform(&xe, &ye); + m_li_x = dda2_line_interpolator(m_li_x.y(), iround(xe * subpixel_scale), len); + m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ye * subpixel_scale), len); + } + + //---------------------------------------------------------------- + void operator++() + { + ++m_li_x; + ++m_li_y; + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + *x = m_li_x.y(); + *y = m_li_y.y(); + } + + private: + const trans_type* m_trans; + dda2_line_interpolator m_li_x; + dda2_line_interpolator m_li_y; + }; + + + + + + + //=====================================span_interpolator_linear_subdiv + template<class Transformer = trans_affine, unsigned SubpixelShift = 8> + class span_interpolator_linear_subdiv + { + public: + typedef Transformer trans_type; + + enum subpixel_scale_e + { + subpixel_shift = SubpixelShift, + subpixel_scale = 1 << subpixel_shift + }; + + + //---------------------------------------------------------------- + span_interpolator_linear_subdiv() : + m_subdiv_shift(4), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1) {} + + span_interpolator_linear_subdiv(const trans_type& trans, + unsigned subdiv_shift = 4) : + m_subdiv_shift(subdiv_shift), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1), + m_trans(&trans) {} + + span_interpolator_linear_subdiv(const trans_type& trans, + double x, double y, unsigned len, + unsigned subdiv_shift = 4) : + m_subdiv_shift(subdiv_shift), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1), + m_trans(&trans) + { + begin(x, y, len); + } + + //---------------------------------------------------------------- + const trans_type& transformer() const { return *m_trans; } + void transformer(const trans_type& trans) { m_trans = &trans; } + + //---------------------------------------------------------------- + unsigned subdiv_shift() const { return m_subdiv_shift; } + void subdiv_shift(unsigned shift) + { + m_subdiv_shift = shift; + m_subdiv_size = 1 << m_subdiv_shift; + m_subdiv_mask = m_subdiv_size - 1; + } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned len) + { + double tx; + double ty; + m_pos = 1; + m_src_x = iround(x * subpixel_scale) + subpixel_scale; + m_src_y = y; + m_len = len; + + if(len > m_subdiv_size) len = m_subdiv_size; + tx = x; + ty = y; + m_trans->transform(&tx, &ty); + int x1 = iround(tx * subpixel_scale); + int y1 = iround(ty * subpixel_scale); + + tx = x + len; + ty = y; + m_trans->transform(&tx, &ty); + + m_li_x = dda2_line_interpolator(x1, iround(tx * subpixel_scale), len); + m_li_y = dda2_line_interpolator(y1, iround(ty * subpixel_scale), len); + } + + //---------------------------------------------------------------- + void operator++() + { + ++m_li_x; + ++m_li_y; + if(m_pos >= m_subdiv_size) + { + unsigned len = m_len; + if(len > m_subdiv_size) len = m_subdiv_size; + double tx = double(m_src_x) / double(subpixel_scale) + len; + double ty = m_src_y; + m_trans->transform(&tx, &ty); + m_li_x = dda2_line_interpolator(m_li_x.y(), iround(tx * subpixel_scale), len); + m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ty * subpixel_scale), len); + m_pos = 0; + } + m_src_x += subpixel_scale; + ++m_pos; + --m_len; + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + *x = m_li_x.y(); + *y = m_li_y.y(); + } + + private: + unsigned m_subdiv_shift; + unsigned m_subdiv_size; + unsigned m_subdiv_mask; + const trans_type* m_trans; + dda2_line_interpolator m_li_x; + dda2_line_interpolator m_li_y; + int m_src_x; + double m_src_y; + unsigned m_pos; + unsigned m_len; + }; + + +} + + + +#endif + + diff --git a/jni/desmume/src/android/agg/include/agg_span_interpolator_persp.h b/jni/desmume/src/android/agg/include/agg_span_interpolator_persp.h new file mode 100755 index 0000000..aea462b --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_span_interpolator_persp.h @@ -0,0 +1,472 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_INTERPOLATOR_PERSP_INCLUDED +#define AGG_SPAN_INTERPOLATOR_PERSP_INCLUDED + +#include "agg_trans_perspective.h" +#include "agg_dda_line.h" + +namespace agg +{ + + + + //===========================================span_interpolator_persp_exact + template<unsigned SubpixelShift = 8> + class span_interpolator_persp_exact + { + public: + typedef trans_perspective trans_type; + typedef trans_perspective::iterator_x iterator_type; + enum subpixel_scale_e + { + subpixel_shift = SubpixelShift, + subpixel_scale = 1 << subpixel_shift + }; + + //-------------------------------------------------------------------- + span_interpolator_persp_exact() {} + + //-------------------------------------------------------------------- + // Arbitrary quadrangle transformations + span_interpolator_persp_exact(const double* src, const double* dst) + { + quad_to_quad(src, dst); + } + + //-------------------------------------------------------------------- + // Direct transformations + span_interpolator_persp_exact(double x1, double y1, + double x2, double y2, + const double* quad) + { + rect_to_quad(x1, y1, x2, y2, quad); + } + + //-------------------------------------------------------------------- + // Reverse transformations + span_interpolator_persp_exact(const double* quad, + double x1, double y1, + double x2, double y2) + { + quad_to_rect(quad, x1, y1, x2, y2); + } + + //-------------------------------------------------------------------- + // Set the transformations using two arbitrary quadrangles. + void quad_to_quad(const double* src, const double* dst) + { + m_trans_dir.quad_to_quad(src, dst); + m_trans_inv.quad_to_quad(dst, src); + } + + //-------------------------------------------------------------------- + // Set the direct transformations, i.e., rectangle -> quadrangle + void rect_to_quad(double x1, double y1, double x2, double y2, + const double* quad) + { + double src[8]; + src[0] = src[6] = x1; + src[2] = src[4] = x2; + src[1] = src[3] = y1; + src[5] = src[7] = y2; + quad_to_quad(src, quad); + } + + + //-------------------------------------------------------------------- + // Set the reverse transformations, i.e., quadrangle -> rectangle + void quad_to_rect(const double* quad, + double x1, double y1, double x2, double y2) + { + double dst[8]; + dst[0] = dst[6] = x1; + dst[2] = dst[4] = x2; + dst[1] = dst[3] = y1; + dst[5] = dst[7] = y2; + quad_to_quad(quad, dst); + } + + //-------------------------------------------------------------------- + // Check if the equations were solved successfully + bool is_valid() const { return m_trans_dir.is_valid(); } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned len) + { + m_iterator = m_trans_dir.begin(x, y, 1.0); + double xt = m_iterator.x; + double yt = m_iterator.y; + + double dx; + double dy; + const double delta = 1/double(subpixel_scale); + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sx1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + dx = xt; + dy = yt + delta; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sy1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + x += len; + xt = x; + yt = y; + m_trans_dir.transform(&xt, &yt); + + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + dx = xt; + dy = yt + delta; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + m_scale_x = dda2_line_interpolator(sx1, sx2, len); + m_scale_y = dda2_line_interpolator(sy1, sy2, len); + } + + + //---------------------------------------------------------------- + void resynchronize(double xe, double ye, unsigned len) + { + // Assume x1,y1 are equal to the ones at the previous end point + int sx1 = m_scale_x.y(); + int sy1 = m_scale_y.y(); + + // Calculate transformed coordinates at x2,y2 + double xt = xe; + double yt = ye; + m_trans_dir.transform(&xt, &yt); + + const double delta = 1/double(subpixel_scale); + double dx; + double dy; + + // Calculate scale by X at x2,y2 + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= xe; + dy -= ye; + int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Calculate scale by Y at x2,y2 + dx = xt; + dy = yt + delta; + m_trans_inv.transform(&dx, &dy); + dx -= xe; + dy -= ye; + int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Initialize the interpolators + m_scale_x = dda2_line_interpolator(sx1, sx2, len); + m_scale_y = dda2_line_interpolator(sy1, sy2, len); + } + + + + //---------------------------------------------------------------- + void operator++() + { + ++m_iterator; + ++m_scale_x; + ++m_scale_y; + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + *x = iround(m_iterator.x * subpixel_scale); + *y = iround(m_iterator.y * subpixel_scale); + } + + //---------------------------------------------------------------- + void local_scale(int* x, int* y) + { + *x = m_scale_x.y(); + *y = m_scale_y.y(); + } + + //---------------------------------------------------------------- + void transform(double* x, double* y) const + { + m_trans_dir.transform(x, y); + } + + private: + trans_type m_trans_dir; + trans_type m_trans_inv; + iterator_type m_iterator; + dda2_line_interpolator m_scale_x; + dda2_line_interpolator m_scale_y; + }; + + + + + + + + + + + + //============================================span_interpolator_persp_lerp + template<unsigned SubpixelShift = 8> + class span_interpolator_persp_lerp + { + public: + typedef trans_perspective trans_type; + enum subpixel_scale_e + { + subpixel_shift = SubpixelShift, + subpixel_scale = 1 << subpixel_shift + }; + + //-------------------------------------------------------------------- + span_interpolator_persp_lerp() {} + + //-------------------------------------------------------------------- + // Arbitrary quadrangle transformations + span_interpolator_persp_lerp(const double* src, const double* dst) + { + quad_to_quad(src, dst); + } + + //-------------------------------------------------------------------- + // Direct transformations + span_interpolator_persp_lerp(double x1, double y1, + double x2, double y2, + const double* quad) + { + rect_to_quad(x1, y1, x2, y2, quad); + } + + //-------------------------------------------------------------------- + // Reverse transformations + span_interpolator_persp_lerp(const double* quad, + double x1, double y1, + double x2, double y2) + { + quad_to_rect(quad, x1, y1, x2, y2); + } + + //-------------------------------------------------------------------- + // Set the transformations using two arbitrary quadrangles. + void quad_to_quad(const double* src, const double* dst) + { + m_trans_dir.quad_to_quad(src, dst); + m_trans_inv.quad_to_quad(dst, src); + } + + //-------------------------------------------------------------------- + // Set the direct transformations, i.e., rectangle -> quadrangle + void rect_to_quad(double x1, double y1, double x2, double y2, + const double* quad) + { + double src[8]; + src[0] = src[6] = x1; + src[2] = src[4] = x2; + src[1] = src[3] = y1; + src[5] = src[7] = y2; + quad_to_quad(src, quad); + } + + + //-------------------------------------------------------------------- + // Set the reverse transformations, i.e., quadrangle -> rectangle + void quad_to_rect(const double* quad, + double x1, double y1, double x2, double y2) + { + double dst[8]; + dst[0] = dst[6] = x1; + dst[2] = dst[4] = x2; + dst[1] = dst[3] = y1; + dst[5] = dst[7] = y2; + quad_to_quad(quad, dst); + } + + //-------------------------------------------------------------------- + // Check if the equations were solved successfully + bool is_valid() const { return m_trans_dir.is_valid(); } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned len) + { + // Calculate transformed coordinates at x1,y1 + double xt = x; + double yt = y; + m_trans_dir.transform(&xt, &yt); + int x1 = iround(xt * subpixel_scale); + int y1 = iround(yt * subpixel_scale); + + double dx; + double dy; + const double delta = 1/double(subpixel_scale); + + // Calculate scale by X at x1,y1 + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sx1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Calculate scale by Y at x1,y1 + dx = xt; + dy = yt + delta; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sy1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Calculate transformed coordinates at x2,y2 + x += len; + xt = x; + yt = y; + m_trans_dir.transform(&xt, &yt); + int x2 = iround(xt * subpixel_scale); + int y2 = iround(yt * subpixel_scale); + + // Calculate scale by X at x2,y2 + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Calculate scale by Y at x2,y2 + dx = xt; + dy = yt + delta; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Initialize the interpolators + m_coord_x = dda2_line_interpolator(x1, x2, len); + m_coord_y = dda2_line_interpolator(y1, y2, len); + m_scale_x = dda2_line_interpolator(sx1, sx2, len); + m_scale_y = dda2_line_interpolator(sy1, sy2, len); + } + + + //---------------------------------------------------------------- + void resynchronize(double xe, double ye, unsigned len) + { + // Assume x1,y1 are equal to the ones at the previous end point + int x1 = m_coord_x.y(); + int y1 = m_coord_y.y(); + int sx1 = m_scale_x.y(); + int sy1 = m_scale_y.y(); + + // Calculate transformed coordinates at x2,y2 + double xt = xe; + double yt = ye; + m_trans_dir.transform(&xt, &yt); + int x2 = iround(xt * subpixel_scale); + int y2 = iround(yt * subpixel_scale); + + const double delta = 1/double(subpixel_scale); + double dx; + double dy; + + // Calculate scale by X at x2,y2 + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= xe; + dy -= ye; + int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Calculate scale by Y at x2,y2 + dx = xt; + dy = yt + delta; + m_trans_inv.transform(&dx, &dy); + dx -= xe; + dy -= ye; + int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Initialize the interpolators + m_coord_x = dda2_line_interpolator(x1, x2, len); + m_coord_y = dda2_line_interpolator(y1, y2, len); + m_scale_x = dda2_line_interpolator(sx1, sx2, len); + m_scale_y = dda2_line_interpolator(sy1, sy2, len); + } + + + //---------------------------------------------------------------- + void operator++() + { + ++m_coord_x; + ++m_coord_y; + ++m_scale_x; + ++m_scale_y; + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + *x = m_coord_x.y(); + *y = m_coord_y.y(); + } + + //---------------------------------------------------------------- + void local_scale(int* x, int* y) + { + *x = m_scale_x.y(); + *y = m_scale_y.y(); + } + + //---------------------------------------------------------------- + void transform(double* x, double* y) const + { + m_trans_dir.transform(x, y); + } + + private: + trans_type m_trans_dir; + trans_type m_trans_inv; + dda2_line_interpolator m_coord_x; + dda2_line_interpolator m_coord_y; + dda2_line_interpolator m_scale_x; + dda2_line_interpolator m_scale_y; + }; + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_span_interpolator_trans.h b/jni/desmume/src/android/agg/include/agg_span_interpolator_trans.h new file mode 100755 index 0000000..388ad6b --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_span_interpolator_trans.h @@ -0,0 +1,101 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Horizontal span interpolator for use with an arbitrary transformer +// The efficiency highly depends on the operations done in the transformer +// +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_INTERPOLATOR_TRANS_INCLUDED +#define AGG_SPAN_INTERPOLATOR_TRANS_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //=================================================span_interpolator_trans + template<class Transformer, unsigned SubpixelShift = 8> + class span_interpolator_trans + { + public: + typedef Transformer trans_type; + enum subpixel_scale_e + { + subpixel_shift = SubpixelShift, + subpixel_scale = 1 << subpixel_shift + }; + + //-------------------------------------------------------------------- + span_interpolator_trans() {} + span_interpolator_trans(const trans_type& trans) : m_trans(&trans) {} + span_interpolator_trans(const trans_type& trans, + double x, double y, unsigned) : + m_trans(&trans) + { + begin(x, y, 0); + } + + //---------------------------------------------------------------- + const trans_type& transformer() const { return *m_trans; } + void transformer(const trans_type& trans) { m_trans = &trans; } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned) + { + m_x = x; + m_y = y; + m_trans->transform(&x, &y); + m_ix = iround(x * subpixel_scale); + m_iy = iround(y * subpixel_scale); + } + + //---------------------------------------------------------------- + void operator++() + { + m_x += 1.0; + double x = m_x; + double y = m_y; + m_trans->transform(&x, &y); + m_ix = iround(x * subpixel_scale); + m_iy = iround(y * subpixel_scale); + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + *x = m_ix; + *y = m_iy; + } + + private: + const trans_type* m_trans; + double m_x; + double m_y; + int m_ix; + int m_iy; + }; + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_span_pattern_gray.h b/jni/desmume/src/android/agg/include/agg_span_pattern_gray.h new file mode 100755 index 0000000..d3910e8 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_span_pattern_gray.h @@ -0,0 +1,102 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + + +#ifndef AGG_SPAN_PATTERN_GRAY_INCLUDED +#define AGG_SPAN_PATTERN_GRAY_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //=======================================================span_pattern_gray + template<class Source> class span_pattern_gray + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + + //-------------------------------------------------------------------- + span_pattern_gray() {} + span_pattern_gray(source_type& src, + unsigned offset_x, unsigned offset_y) : + m_src(&src), + m_offset_x(offset_x), + m_offset_y(offset_y), + m_alpha(color_type::base_mask) + {} + + //-------------------------------------------------------------------- + void attach(source_type& v) { m_src = &v; } + source_type& source() { return *m_src; } + const source_type& source() const { return *m_src; } + + //-------------------------------------------------------------------- + void offset_x(unsigned v) { m_offset_x = v; } + void offset_y(unsigned v) { m_offset_y = v; } + unsigned offset_x() const { return m_offset_x; } + unsigned offset_y() const { return m_offset_y; } + void alpha(value_type v) { m_alpha = v; } + value_type alpha() const { return m_alpha; } + + //-------------------------------------------------------------------- + void prepare() {} + void generate(color_type* span, int x, int y, unsigned len) + { + x += m_offset_x; + y += m_offset_y; + const value_type* p = (const value_type*)m_src->span(x, y, len); + do + { + span->v = *p; + span->a = m_alpha; + p = m_src->next_x(); + ++span; + } + while(--len); + } + + private: + source_type* m_src; + unsigned m_offset_x; + unsigned m_offset_y; + value_type m_alpha; + + }; + +} + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_span_pattern_rgb.h b/jni/desmume/src/android/agg/include/agg_span_pattern_rgb.h new file mode 100755 index 0000000..b9a316b --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_span_pattern_rgb.h @@ -0,0 +1,105 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + + +#ifndef AGG_SPAN_PATTERN_RGB_INCLUDED +#define AGG_SPAN_PATTERN_RGB_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //========================================================span_pattern_rgb + template<class Source> class span_pattern_rgb + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + + //-------------------------------------------------------------------- + span_pattern_rgb() {} + span_pattern_rgb(source_type& src, + unsigned offset_x, unsigned offset_y) : + m_src(&src), + m_offset_x(offset_x), + m_offset_y(offset_y), + m_alpha(color_type::base_mask) + {} + + //-------------------------------------------------------------------- + void attach(source_type& v) { m_src = &v; } + source_type& source() { return *m_src; } + const source_type& source() const { return *m_src; } + + //-------------------------------------------------------------------- + void offset_x(unsigned v) { m_offset_x = v; } + void offset_y(unsigned v) { m_offset_y = v; } + unsigned offset_x() const { return m_offset_x; } + unsigned offset_y() const { return m_offset_y; } + void alpha(value_type v) { m_alpha = v; } + value_type alpha() const { return m_alpha; } + + //-------------------------------------------------------------------- + void prepare() {} + void generate(color_type* span, int x, int y, unsigned len) + { + x += m_offset_x; + y += m_offset_y; + const value_type* p = (const value_type*)m_src->span(x, y, len); + do + { + span->r = p[order_type::R]; + span->g = p[order_type::G]; + span->b = p[order_type::B]; + span->a = m_alpha; + p = m_src->next_x(); + ++span; + } + while(--len); + } + + private: + source_type* m_src; + unsigned m_offset_x; + unsigned m_offset_y; + value_type m_alpha; + + }; + +} + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_span_pattern_rgba.h b/jni/desmume/src/android/agg/include/agg_span_pattern_rgba.h new file mode 100755 index 0000000..88f6f22 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_span_pattern_rgba.h @@ -0,0 +1,103 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Adaptation for high precision colors has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- + + +#ifndef AGG_SPAN_PATTERN_RGBA_INCLUDED +#define AGG_SPAN_PATTERN_RGBA_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //======================================================span_pattern_rgba + template<class Source> class span_pattern_rgba + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + + //-------------------------------------------------------------------- + span_pattern_rgba() {} + span_pattern_rgba(source_type& src, + unsigned offset_x, unsigned offset_y) : + m_src(&src), + m_offset_x(offset_x), + m_offset_y(offset_y) + {} + + //-------------------------------------------------------------------- + void attach(source_type& v) { m_src = &v; } + source_type& source() { return *m_src; } + const source_type& source() const { return *m_src; } + + //-------------------------------------------------------------------- + void offset_x(unsigned v) { m_offset_x = v; } + void offset_y(unsigned v) { m_offset_y = v; } + unsigned offset_x() const { return m_offset_x; } + unsigned offset_y() const { return m_offset_y; } + void alpha(value_type) {} + value_type alpha() const { return 0; } + + //-------------------------------------------------------------------- + void prepare() {} + void generate(color_type* span, int x, int y, unsigned len) + { + x += m_offset_x; + y += m_offset_y; + const value_type* p = (const value_type*)m_src->span(x, y, len); + do + { + span->r = p[order_type::R]; + span->g = p[order_type::G]; + span->b = p[order_type::B]; + span->a = p[order_type::A]; + p = (const value_type*)m_src->next_x(); + ++span; + } + while(--len); + } + + private: + source_type* m_src; + unsigned m_offset_x; + unsigned m_offset_y; + + }; + +} + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_span_solid.h b/jni/desmume/src/android/agg/include/agg_span_solid.h new file mode 100755 index 0000000..7b29006 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_span_solid.h @@ -0,0 +1,58 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_SOLID_INCLUDED +#define AGG_SPAN_SOLID_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //--------------------------------------------------------------span_solid + template<class ColorT> class span_solid + { + public: + typedef ColorT color_type; + + //-------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + do { *span++ = m_color; } while(--len); + } + + private: + color_type m_color; + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_span_subdiv_adaptor.h b/jni/desmume/src/android/agg/include/agg_span_subdiv_adaptor.h new file mode 100755 index 0000000..9fd06e1 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_span_subdiv_adaptor.h @@ -0,0 +1,151 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_SUBDIV_ADAPTOR_INCLUDED +#define AGG_SPAN_SUBDIV_ADAPTOR_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //=================================================span_subdiv_adaptor + template<class Interpolator, unsigned SubpixelShift = 8> + class span_subdiv_adaptor + { + public: + typedef Interpolator interpolator_type; + typedef typename interpolator_type::trans_type trans_type; + + enum sublixel_scale_e + { + subpixel_shift = SubpixelShift, + subpixel_scale = 1 << subpixel_shift + }; + + + //---------------------------------------------------------------- + span_subdiv_adaptor() : + m_subdiv_shift(4), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1) {} + + span_subdiv_adaptor(interpolator_type& interpolator, + unsigned subdiv_shift = 4) : + m_subdiv_shift(subdiv_shift), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1), + m_interpolator(&interpolator) {} + + span_subdiv_adaptor(interpolator_type& interpolator, + double x, double y, unsigned len, + unsigned subdiv_shift = 4) : + m_subdiv_shift(subdiv_shift), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1), + m_interpolator(&interpolator) + { + begin(x, y, len); + } + + + //---------------------------------------------------------------- + const interpolator_type& interpolator() const { return *m_interpolator; } + void interpolator(interpolator_type& intr) { m_interpolator = &intr; } + + //---------------------------------------------------------------- + const trans_type& transformer() const + { + return *m_interpolator->transformer(); + } + void transformer(const trans_type& trans) + { + m_interpolator->transformer(trans); + } + + //---------------------------------------------------------------- + unsigned subdiv_shift() const { return m_subdiv_shift; } + void subdiv_shift(unsigned shift) + { + m_subdiv_shift = shift; + m_subdiv_size = 1 << m_subdiv_shift; + m_subdiv_mask = m_subdiv_size - 1; + } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned len) + { + m_pos = 1; + m_src_x = iround(x * subpixel_scale) + subpixel_scale; + m_src_y = y; + m_len = len; + if(len > m_subdiv_size) len = m_subdiv_size; + m_interpolator->begin(x, y, len); + } + + //---------------------------------------------------------------- + void operator++() + { + ++(*m_interpolator); + if(m_pos >= m_subdiv_size) + { + unsigned len = m_len; + if(len > m_subdiv_size) len = m_subdiv_size; + m_interpolator->resynchronize(double(m_src_x) / double(subpixel_scale) + len, + m_src_y, + len); + m_pos = 0; + } + m_src_x += subpixel_scale; + ++m_pos; + --m_len; + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + m_interpolator->coordinates(x, y); + } + + //---------------------------------------------------------------- + void local_scale(int* x, int* y) const + { + m_interpolator->local_scale(x, y); + } + + + private: + unsigned m_subdiv_shift; + unsigned m_subdiv_size; + unsigned m_subdiv_mask; + interpolator_type* m_interpolator; + int m_src_x; + double m_src_y; + unsigned m_pos; + unsigned m_len; + }; + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_trans_affine.h b/jni/desmume/src/android/agg/include/agg_trans_affine.h new file mode 100755 index 0000000..a662099 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_trans_affine.h @@ -0,0 +1,524 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_TRANS_AFFINE_INCLUDED +#define AGG_TRANS_AFFINE_INCLUDED + +#include <math.h> +#include "agg_basics.h" + +namespace agg +{ + const double affine_epsilon = 1e-14; + + //============================================================trans_affine + // + // See Implementation agg_trans_affine.cpp + // + // Affine transformation are linear transformations in Cartesian coordinates + // (strictly speaking not only in Cartesian, but for the beginning we will + // think so). They are rotation, scaling, translation and skewing. + // After any affine transformation a line segment remains a line segment + // and it will never become a curve. + // + // There will be no math about matrix calculations, since it has been + // described many times. Ask yourself a very simple question: + // "why do we need to understand and use some matrix stuff instead of just + // rotating, scaling and so on". The answers are: + // + // 1. Any combination of transformations can be done by only 4 multiplications + // and 4 additions in floating point. + // 2. One matrix transformation is equivalent to the number of consecutive + // discrete transformations, i.e. the matrix "accumulates" all transformations + // in the order of their settings. Suppose we have 4 transformations: + // * rotate by 30 degrees, + // * scale X to 2.0, + // * scale Y to 1.5, + // * move to (100, 100). + // The result will depend on the order of these transformations, + // and the advantage of matrix is that the sequence of discret calls: + // rotate(30), scaleX(2.0), scaleY(1.5), move(100,100) + // will have exactly the same result as the following matrix transformations: + // + // affine_matrix m; + // m *= rotate_matrix(30); + // m *= scaleX_matrix(2.0); + // m *= scaleY_matrix(1.5); + // m *= move_matrix(100,100); + // + // m.transform_my_point_at_last(x, y); + // + // What is the good of it? In real life we will set-up the matrix only once + // and then transform many points, let alone the convenience to set any + // combination of transformations. + // + // So, how to use it? Very easy - literally as it's shown above. Not quite, + // let us write a correct example: + // + // agg::trans_affine m; + // m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0); + // m *= agg::trans_affine_scaling(2.0, 1.5); + // m *= agg::trans_affine_translation(100.0, 100.0); + // m.transform(&x, &y); + // + // The affine matrix is all you need to perform any linear transformation, + // but all transformations have origin point (0,0). It means that we need to + // use 2 translations if we want to rotate someting around (100,100): + // + // m *= agg::trans_affine_translation(-100.0, -100.0); // move to (0,0) + // m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0); // rotate + // m *= agg::trans_affine_translation(100.0, 100.0); // move back to (100,100) + //---------------------------------------------------------------------- + struct trans_affine + { + double sx, shy, shx, sy, tx, ty; + + //------------------------------------------ Construction + // Identity matrix + trans_affine() : + sx(1.0), shy(0.0), shx(0.0), sy(1.0), tx(0.0), ty(0.0) + {} + + // Custom matrix. Usually used in derived classes + trans_affine(double v0, double v1, double v2, + double v3, double v4, double v5) : + sx(v0), shy(v1), shx(v2), sy(v3), tx(v4), ty(v5) + {} + + // Custom matrix from m[6] + explicit trans_affine(const double* m) : + sx(m[0]), shy(m[1]), shx(m[2]), sy(m[3]), tx(m[4]), ty(m[5]) + {} + + // Rectangle to a parallelogram. + trans_affine(double x1, double y1, double x2, double y2, + const double* parl) + { + rect_to_parl(x1, y1, x2, y2, parl); + } + + // Parallelogram to a rectangle. + trans_affine(const double* parl, + double x1, double y1, double x2, double y2) + { + parl_to_rect(parl, x1, y1, x2, y2); + } + + // Arbitrary parallelogram transformation. + trans_affine(const double* src, const double* dst) + { + parl_to_parl(src, dst); + } + + //---------------------------------- Parellelogram transformations + // transform a parallelogram to another one. Src and dst are + // pointers to arrays of three points (double[6], x1,y1,...) that + // identify three corners of the parallelograms assuming implicit + // fourth point. The arguments are arrays of double[6] mapped + // to x1,y1, x2,y2, x3,y3 where the coordinates are: + // *-----------------* + // / (x3,y3)/ + // / / + // /(x1,y1) (x2,y2)/ + // *-----------------* + const trans_affine& parl_to_parl(const double* src, + const double* dst); + + const trans_affine& rect_to_parl(double x1, double y1, + double x2, double y2, + const double* parl); + + const trans_affine& parl_to_rect(const double* parl, + double x1, double y1, + double x2, double y2); + + + //------------------------------------------ Operations + // Reset - load an identity matrix + const trans_affine& reset(); + + // Direct transformations operations + const trans_affine& translate(double x, double y); + const trans_affine& rotate(double a); + const trans_affine& scale(double s); + const trans_affine& scale(double x, double y); + + // Multiply matrix to another one + const trans_affine& multiply(const trans_affine& m); + + // Multiply "m" to "this" and assign the result to "this" + const trans_affine& premultiply(const trans_affine& m); + + // Multiply matrix to inverse of another one + const trans_affine& multiply_inv(const trans_affine& m); + + // Multiply inverse of "m" to "this" and assign the result to "this" + const trans_affine& premultiply_inv(const trans_affine& m); + + // Invert matrix. Do not try to invert degenerate matrices, + // there's no check for validity. If you set scale to 0 and + // then try to invert matrix, expect unpredictable result. + const trans_affine& invert(); + + // Mirroring around X + const trans_affine& flip_x(); + + // Mirroring around Y + const trans_affine& flip_y(); + + //------------------------------------------- Load/Store + // Store matrix to an array [6] of double + void store_to(double* m) const + { + *m++ = sx; *m++ = shy; *m++ = shx; *m++ = sy; *m++ = tx; *m++ = ty; + } + + // Load matrix from an array [6] of double + const trans_affine& load_from(const double* m) + { + sx = *m++; shy = *m++; shx = *m++; sy = *m++; tx = *m++; ty = *m++; + return *this; + } + + //------------------------------------------- Operators + + // Multiply the matrix by another one + const trans_affine& operator *= (const trans_affine& m) + { + return multiply(m); + } + + // Multiply the matrix by inverse of another one + const trans_affine& operator /= (const trans_affine& m) + { + return multiply_inv(m); + } + + // Multiply the matrix by another one and return + // the result in a separete matrix. + trans_affine operator * (const trans_affine& m) + { + return trans_affine(*this).multiply(m); + } + + // Multiply the matrix by inverse of another one + // and return the result in a separete matrix. + trans_affine operator / (const trans_affine& m) + { + return trans_affine(*this).multiply_inv(m); + } + + // Calculate and return the inverse matrix + trans_affine operator ~ () const + { + trans_affine ret = *this; + return ret.invert(); + } + + // Equal operator with default epsilon + bool operator == (const trans_affine& m) const + { + return is_equal(m, affine_epsilon); + } + + // Not Equal operator with default epsilon + bool operator != (const trans_affine& m) const + { + return !is_equal(m, affine_epsilon); + } + + //-------------------------------------------- Transformations + // Direct transformation of x and y + void transform(double* x, double* y) const; + + // Direct transformation of x and y, 2x2 matrix only, no translation + void transform_2x2(double* x, double* y) const; + + // Inverse transformation of x and y. It works slower than the + // direct transformation. For massive operations it's better to + // invert() the matrix and then use direct transformations. + void inverse_transform(double* x, double* y) const; + + //-------------------------------------------- Auxiliary + // Calculate the determinant of matrix + double determinant() const + { + return sx * sy - shy * shx; + } + + // Calculate the reciprocal of the determinant + double determinant_reciprocal() const + { + return 1.0 / (sx * sy - shy * shx); + } + + // Get the average scale (by X and Y). + // Basically used to calculate the approximation_scale when + // decomposinting curves into line segments. + double scale() const; + + // Check to see if the matrix is not degenerate + bool is_valid(double epsilon = affine_epsilon) const; + + // Check to see if it's an identity matrix + bool is_identity(double epsilon = affine_epsilon) const; + + // Check to see if two matrices are equal + bool is_equal(const trans_affine& m, double epsilon = affine_epsilon) const; + + // Determine the major parameters. Use with caution considering + // possible degenerate cases. + double rotation() const; + void translation(double* dx, double* dy) const; + void scaling(double* x, double* y) const; + void scaling_abs(double* x, double* y) const; + }; + + //------------------------------------------------------------------------ + inline void trans_affine::transform(double* x, double* y) const + { + register double tmp = *x; + *x = tmp * sx + *y * shx + tx; + *y = tmp * shy + *y * sy + ty; + } + + //------------------------------------------------------------------------ + inline void trans_affine::transform_2x2(double* x, double* y) const + { + register double tmp = *x; + *x = tmp * sx + *y * shx; + *y = tmp * shy + *y * sy; + } + + //------------------------------------------------------------------------ + inline void trans_affine::inverse_transform(double* x, double* y) const + { + register double d = determinant_reciprocal(); + register double a = (*x - tx) * d; + register double b = (*y - ty) * d; + *x = a * sy - b * shx; + *y = b * sx - a * shy; + } + + //------------------------------------------------------------------------ + inline double trans_affine::scale() const + { + double x = 0.707106781 * sx + 0.707106781 * shx; + double y = 0.707106781 * shy + 0.707106781 * sy; + return sqrt(x*x + y*y); + } + + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::translate(double x, double y) + { + tx += x; + ty += y; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::rotate(double a) + { + double ca = cos(a); + double sa = sin(a); + double t0 = sx * ca - shy * sa; + double t2 = shx * ca - sy * sa; + double t4 = tx * ca - ty * sa; + shy = sx * sa + shy * ca; + sy = shx * sa + sy * ca; + ty = tx * sa + ty * ca; + sx = t0; + shx = t2; + tx = t4; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::scale(double x, double y) + { + double mm0 = x; // Possible hint for the optimizer + double mm3 = y; + sx *= mm0; + shx *= mm0; + tx *= mm0; + shy *= mm3; + sy *= mm3; + ty *= mm3; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::scale(double s) + { + double m = s; // Possible hint for the optimizer + sx *= m; + shx *= m; + tx *= m; + shy *= m; + sy *= m; + ty *= m; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::premultiply(const trans_affine& m) + { + trans_affine t = m; + return *this = t.multiply(*this); + } + + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::multiply_inv(const trans_affine& m) + { + trans_affine t = m; + t.invert(); + return multiply(t); + } + + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::premultiply_inv(const trans_affine& m) + { + trans_affine t = m; + t.invert(); + return *this = t.multiply(*this); + } + + //------------------------------------------------------------------------ + inline void trans_affine::scaling_abs(double* x, double* y) const + { + // Used to calculate scaling coefficients in image resampling. + // When there is considerable shear this method gives us much + // better estimation than just sx, sy. + *x = sqrt(sx * sx + shx * shx); + *y = sqrt(shy * shy + sy * sy); + } + + //====================================================trans_affine_rotation + // Rotation matrix. sin() and cos() are calculated twice for the same angle. + // There's no harm because the performance of sin()/cos() is very good on all + // modern processors. Besides, this operation is not going to be invoked too + // often. + class trans_affine_rotation : public trans_affine + { + public: + trans_affine_rotation(double a) : + trans_affine(cos(a), sin(a), -sin(a), cos(a), 0.0, 0.0) + {} + }; + + //====================================================trans_affine_scaling + // Scaling matrix. x, y - scale coefficients by X and Y respectively + class trans_affine_scaling : public trans_affine + { + public: + trans_affine_scaling(double x, double y) : + trans_affine(x, 0.0, 0.0, y, 0.0, 0.0) + {} + + trans_affine_scaling(double s) : + trans_affine(s, 0.0, 0.0, s, 0.0, 0.0) + {} + }; + + //================================================trans_affine_translation + // Translation matrix + class trans_affine_translation : public trans_affine + { + public: + trans_affine_translation(double x, double y) : + trans_affine(1.0, 0.0, 0.0, 1.0, x, y) + {} + }; + + //====================================================trans_affine_skewing + // Sckewing (shear) matrix + class trans_affine_skewing : public trans_affine + { + public: + trans_affine_skewing(double x, double y) : + trans_affine(1.0, tan(y), tan(x), 1.0, 0.0, 0.0) + {} + }; + + + //===============================================trans_affine_line_segment + // Rotate, Scale and Translate, associating 0...dist with line segment + // x1,y1,x2,y2 + class trans_affine_line_segment : public trans_affine + { + public: + trans_affine_line_segment(double x1, double y1, double x2, double y2, + double dist) + { + double dx = x2 - x1; + double dy = y2 - y1; + if(dist > 0.0) + { + multiply(trans_affine_scaling(sqrt(dx * dx + dy * dy) / dist)); + } + multiply(trans_affine_rotation(atan2(dy, dx))); + multiply(trans_affine_translation(x1, y1)); + } + }; + + + //============================================trans_affine_reflection_unit + // Reflection matrix. Reflect coordinates across the line through + // the origin containing the unit vector (ux, uy). + // Contributed by John Horigan + class trans_affine_reflection_unit : public trans_affine + { + public: + trans_affine_reflection_unit(double ux, double uy) : + trans_affine(2.0 * ux * ux - 1.0, + 2.0 * ux * uy, + 2.0 * ux * uy, + 2.0 * uy * uy - 1.0, + 0.0, 0.0) + {} + }; + + + //=================================================trans_affine_reflection + // Reflection matrix. Reflect coordinates across the line through + // the origin at the angle a or containing the non-unit vector (x, y). + // Contributed by John Horigan + class trans_affine_reflection : public trans_affine_reflection_unit + { + public: + trans_affine_reflection(double a) : + trans_affine_reflection_unit(cos(a), sin(a)) + {} + + + trans_affine_reflection(double x, double y) : + trans_affine_reflection_unit(x / sqrt(x * x + y * y), y / sqrt(x * x + y * y)) + {} + }; + +} + + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_trans_bilinear.h b/jni/desmume/src/android/agg/include/agg_trans_bilinear.h new file mode 100755 index 0000000..26315ec --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_trans_bilinear.h @@ -0,0 +1,172 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_TRANS_BILINEAR_INCLUDED +#define AGG_TRANS_BILINEAR_INCLUDED + +#include "agg_basics.h" +#include "agg_simul_eq.h" + +namespace agg +{ + + //==========================================================trans_bilinear + class trans_bilinear + { + public: + //-------------------------------------------------------------------- + trans_bilinear() : m_valid(false) {} + + //-------------------------------------------------------------------- + // Arbitrary quadrangle transformations + trans_bilinear(const double* src, const double* dst) + { + quad_to_quad(src, dst); + } + + + //-------------------------------------------------------------------- + // Direct transformations + trans_bilinear(double x1, double y1, double x2, double y2, + const double* quad) + { + rect_to_quad(x1, y1, x2, y2, quad); + } + + + //-------------------------------------------------------------------- + // Reverse transformations + trans_bilinear(const double* quad, + double x1, double y1, double x2, double y2) + { + quad_to_rect(quad, x1, y1, x2, y2); + } + + + //-------------------------------------------------------------------- + // Set the transformations using two arbitrary quadrangles. + void quad_to_quad(const double* src, const double* dst) + { + double left[4][4]; + double right[4][2]; + + unsigned i; + for(i = 0; i < 4; i++) + { + unsigned ix = i * 2; + unsigned iy = ix + 1; + left[i][0] = 1.0; + left[i][1] = src[ix] * src[iy]; + left[i][2] = src[ix]; + left[i][3] = src[iy]; + + right[i][0] = dst[ix]; + right[i][1] = dst[iy]; + } + m_valid = simul_eq<4, 2>::solve(left, right, m_mtx); + } + + + //-------------------------------------------------------------------- + // Set the direct transformations, i.e., rectangle -> quadrangle + void rect_to_quad(double x1, double y1, double x2, double y2, + const double* quad) + { + double src[8]; + src[0] = src[6] = x1; + src[2] = src[4] = x2; + src[1] = src[3] = y1; + src[5] = src[7] = y2; + quad_to_quad(src, quad); + } + + + //-------------------------------------------------------------------- + // Set the reverse transformations, i.e., quadrangle -> rectangle + void quad_to_rect(const double* quad, + double x1, double y1, double x2, double y2) + { + double dst[8]; + dst[0] = dst[6] = x1; + dst[2] = dst[4] = x2; + dst[1] = dst[3] = y1; + dst[5] = dst[7] = y2; + quad_to_quad(quad, dst); + } + + //-------------------------------------------------------------------- + // Check if the equations were solved successfully + bool is_valid() const { return m_valid; } + + //-------------------------------------------------------------------- + // Transform a point (x, y) + void transform(double* x, double* y) const + { + double tx = *x; + double ty = *y; + double xy = tx * ty; + *x = m_mtx[0][0] + m_mtx[1][0] * xy + m_mtx[2][0] * tx + m_mtx[3][0] * ty; + *y = m_mtx[0][1] + m_mtx[1][1] * xy + m_mtx[2][1] * tx + m_mtx[3][1] * ty; + } + + + //-------------------------------------------------------------------- + class iterator_x + { + double inc_x; + double inc_y; + + public: + double x; + double y; + + iterator_x() {} + iterator_x(double tx, double ty, double step, const double m[4][2]) : + inc_x(m[1][0] * step * ty + m[2][0] * step), + inc_y(m[1][1] * step * ty + m[2][1] * step), + x(m[0][0] + m[1][0] * tx * ty + m[2][0] * tx + m[3][0] * ty), + y(m[0][1] + m[1][1] * tx * ty + m[2][1] * tx + m[3][1] * ty) + { + } + + void operator ++ () + { + x += inc_x; + y += inc_y; + } + }; + + iterator_x begin(double x, double y, double step) const + { + return iterator_x(x, y, step, m_mtx); + } + + private: + double m_mtx[4][2]; + bool m_valid; + }; + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_trans_double_path.h b/jni/desmume/src/android/agg/include/agg_trans_double_path.h new file mode 100755 index 0000000..90fe63a --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_trans_double_path.h @@ -0,0 +1,140 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_TRANS_DOUBLE_PATH_INCLUDED +#define AGG_TRANS_DOUBLE_PATH_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + + // See also: agg_trans_double_path.cpp + // + //-------------------------------------------------------trans_double_path + class trans_double_path + { + enum status_e + { + initial, + making_path, + ready + }; + + public: + typedef vertex_sequence<vertex_dist, 6> vertex_storage; + + trans_double_path(); + + //-------------------------------------------------------------------- + void base_length(double v) { m_base_length = v; } + double base_length() const { return m_base_length; } + + //-------------------------------------------------------------------- + void base_height(double v) { m_base_height = v; } + double base_height() const { return m_base_height; } + + //-------------------------------------------------------------------- + void preserve_x_scale(bool f) { m_preserve_x_scale = f; } + bool preserve_x_scale() const { return m_preserve_x_scale; } + + //-------------------------------------------------------------------- + void reset(); + void move_to1(double x, double y); + void line_to1(double x, double y); + void move_to2(double x, double y); + void line_to2(double x, double y); + void finalize_paths(); + + //-------------------------------------------------------------------- + template<class VertexSource1, class VertexSource2> + void add_paths(VertexSource1& vs1, VertexSource2& vs2, + unsigned path1_id=0, unsigned path2_id=0) + { + double x; + double y; + + unsigned cmd; + + vs1.rewind(path1_id); + while(!is_stop(cmd = vs1.vertex(&x, &y))) + { + if(is_move_to(cmd)) + { + move_to1(x, y); + } + else + { + if(is_vertex(cmd)) + { + line_to1(x, y); + } + } + } + + vs2.rewind(path2_id); + while(!is_stop(cmd = vs2.vertex(&x, &y))) + { + if(is_move_to(cmd)) + { + move_to2(x, y); + } + else + { + if(is_vertex(cmd)) + { + line_to2(x, y); + } + } + } + finalize_paths(); + } + + //-------------------------------------------------------------------- + double total_length1() const; + double total_length2() const; + void transform(double *x, double *y) const; + + private: + double finalize_path(vertex_storage& vertices); + void transform1(const vertex_storage& vertices, + double kindex, double kx, + double *x, double* y) const; + + vertex_storage m_src_vertices1; + vertex_storage m_src_vertices2; + double m_base_length; + double m_base_height; + double m_kindex1; + double m_kindex2; + status_e m_status1; + status_e m_status2; + bool m_preserve_x_scale; + }; + +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_trans_perspective.h b/jni/desmume/src/android/agg/include/agg_trans_perspective.h new file mode 100755 index 0000000..5476eb4 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_trans_perspective.h @@ -0,0 +1,737 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_TRANS_PERSPECTIVE_INCLUDED +#define AGG_TRANS_PERSPECTIVE_INCLUDED + +#include "agg_trans_affine.h" + +namespace agg +{ + //=======================================================trans_perspective + struct trans_perspective + { + double sx, shy, w0, shx, sy, w1, tx, ty, w2; + + //------------------------------------------------------- Construction + // Identity matrix + trans_perspective() : + sx (1), shy(0), w0(0), + shx(0), sy (1), w1(0), + tx (0), ty (0), w2(1) {} + + // Custom matrix + trans_perspective(double v0, double v1, double v2, + double v3, double v4, double v5, + double v6, double v7, double v8) : + sx (v0), shy(v1), w0(v2), + shx(v3), sy (v4), w1(v5), + tx (v6), ty (v7), w2(v8) {} + + // Custom matrix from m[9] + explicit trans_perspective(const double* m) : + sx (m[0]), shy(m[1]), w0(m[2]), + shx(m[3]), sy (m[4]), w1(m[5]), + tx (m[6]), ty (m[7]), w2(m[8]) {} + + // From affine + explicit trans_perspective(const trans_affine& a) : + sx (a.sx ), shy(a.shy), w0(0), + shx(a.shx), sy (a.sy ), w1(0), + tx (a.tx ), ty (a.ty ), w2(1) {} + + // Rectangle to quadrilateral + trans_perspective(double x1, double y1, double x2, double y2, + const double* quad); + + // Quadrilateral to rectangle + trans_perspective(const double* quad, + double x1, double y1, double x2, double y2); + + // Arbitrary quadrilateral transformations + trans_perspective(const double* src, const double* dst); + + //-------------------------------------- Quadrilateral transformations + // The arguments are double[8] that are mapped to quadrilaterals: + // x1,y1, x2,y2, x3,y3, x4,y4 + bool quad_to_quad(const double* qs, const double* qd); + + bool rect_to_quad(double x1, double y1, + double x2, double y2, + const double* q); + + bool quad_to_rect(const double* q, + double x1, double y1, + double x2, double y2); + + // Map square (0,0,1,1) to the quadrilateral and vice versa + bool square_to_quad(const double* q); + bool quad_to_square(const double* q); + + + //--------------------------------------------------------- Operations + // Reset - load an identity matrix + const trans_perspective& reset(); + + // Invert matrix. Returns false in degenerate case + bool invert(); + + // Direct transformations operations + const trans_perspective& translate(double x, double y); + const trans_perspective& rotate(double a); + const trans_perspective& scale(double s); + const trans_perspective& scale(double x, double y); + + // Multiply the matrix by another one + const trans_perspective& multiply(const trans_perspective& m); + + // Multiply "m" by "this" and assign the result to "this" + const trans_perspective& premultiply(const trans_perspective& m); + + // Multiply matrix to inverse of another one + const trans_perspective& multiply_inv(const trans_perspective& m); + + // Multiply inverse of "m" by "this" and assign the result to "this" + const trans_perspective& premultiply_inv(const trans_perspective& m); + + // Multiply the matrix by another one + const trans_perspective& multiply(const trans_affine& m); + + // Multiply "m" by "this" and assign the result to "this" + const trans_perspective& premultiply(const trans_affine& m); + + // Multiply the matrix by inverse of another one + const trans_perspective& multiply_inv(const trans_affine& m); + + // Multiply inverse of "m" by "this" and assign the result to "this" + const trans_perspective& premultiply_inv(const trans_affine& m); + + //--------------------------------------------------------- Load/Store + void store_to(double* m) const; + const trans_perspective& load_from(const double* m); + + //---------------------------------------------------------- Operators + // Multiply the matrix by another one + const trans_perspective& operator *= (const trans_perspective& m) + { + return multiply(m); + } + const trans_perspective& operator *= (const trans_affine& m) + { + return multiply(m); + } + + // Multiply the matrix by inverse of another one + const trans_perspective& operator /= (const trans_perspective& m) + { + return multiply_inv(m); + } + const trans_perspective& operator /= (const trans_affine& m) + { + return multiply_inv(m); + } + + // Multiply the matrix by another one and return + // the result in a separete matrix. + trans_perspective operator * (const trans_perspective& m) + { + return trans_perspective(*this).multiply(m); + } + trans_perspective operator * (const trans_affine& m) + { + return trans_perspective(*this).multiply(m); + } + + // Multiply the matrix by inverse of another one + // and return the result in a separete matrix. + trans_perspective operator / (const trans_perspective& m) + { + return trans_perspective(*this).multiply_inv(m); + } + trans_perspective operator / (const trans_affine& m) + { + return trans_perspective(*this).multiply_inv(m); + } + + // Calculate and return the inverse matrix + trans_perspective operator ~ () const + { + trans_perspective ret = *this; + ret.invert(); + return ret; + } + + // Equal operator with default epsilon + bool operator == (const trans_perspective& m) const + { + return is_equal(m, affine_epsilon); + } + + // Not Equal operator with default epsilon + bool operator != (const trans_perspective& m) const + { + return !is_equal(m, affine_epsilon); + } + + //---------------------------------------------------- Transformations + // Direct transformation of x and y + void transform(double* x, double* y) const; + + // Direct transformation of x and y, affine part only + void transform_affine(double* x, double* y) const; + + // Direct transformation of x and y, 2x2 matrix only, no translation + void transform_2x2(double* x, double* y) const; + + // Inverse transformation of x and y. It works slow because + // it explicitly inverts the matrix on every call. For massive + // operations it's better to invert() the matrix and then use + // direct transformations. + void inverse_transform(double* x, double* y) const; + + + //---------------------------------------------------------- Auxiliary + const trans_perspective& from_affine(const trans_affine& a); + double determinant() const; + double determinant_reciprocal() const; + + bool is_valid(double epsilon = affine_epsilon) const; + bool is_identity(double epsilon = affine_epsilon) const; + bool is_equal(const trans_perspective& m, + double epsilon = affine_epsilon) const; + + // Determine the major affine parameters. Use with caution + // considering possible degenerate cases. + double scale() const; + double rotation() const; + void translation(double* dx, double* dy) const; + void scaling(double* x, double* y) const; + void scaling_abs(double* x, double* y) const; + + + + //-------------------------------------------------------------------- + class iterator_x + { + double den; + double den_step; + double nom_x; + double nom_x_step; + double nom_y; + double nom_y_step; + + public: + double x; + double y; + + iterator_x() {} + iterator_x(double px, double py, double step, const trans_perspective& m) : + den(px * m.w0 + py * m.w1 + m.w2), + den_step(m.w0 * step), + nom_x(px * m.sx + py * m.shx + m.tx), + nom_x_step(step * m.sx), + nom_y(px * m.shy + py * m.sy + m.ty), + nom_y_step(step * m.shy), + x(nom_x / den), + y(nom_y / den) + {} + + void operator ++ () + { + den += den_step; + nom_x += nom_x_step; + nom_y += nom_y_step; + double d = 1.0 / den; + x = nom_x * d; + y = nom_y * d; + } + }; + + //-------------------------------------------------------------------- + iterator_x begin(double x, double y, double step) const + { + return iterator_x(x, y, step, *this); + } + }; + + + + + + + + + + + + + + + //------------------------------------------------------------------------ + inline bool trans_perspective::square_to_quad(const double* q) + { + double dx = q[0] - q[2] + q[4] - q[6]; + double dy = q[1] - q[3] + q[5] - q[7]; + if(dx == 0.0 && dy == 0.0) + { + // Affine case (parallelogram) + //--------------- + sx = q[2] - q[0]; + shy = q[3] - q[1]; + w0 = 0.0; + shx = q[4] - q[2]; + sy = q[5] - q[3]; + w1 = 0.0; + tx = q[0]; + ty = q[1]; + w2 = 1.0; + } + else + { + double dx1 = q[2] - q[4]; + double dy1 = q[3] - q[5]; + double dx2 = q[6] - q[4]; + double dy2 = q[7] - q[5]; + double den = dx1 * dy2 - dx2 * dy1; + if(den == 0.0) + { + // Singular case + //--------------- + sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0; + return false; + } + // General case + //--------------- + double u = (dx * dy2 - dy * dx2) / den; + double v = (dy * dx1 - dx * dy1) / den; + sx = q[2] - q[0] + u * q[2]; + shy = q[3] - q[1] + u * q[3]; + w0 = u; + shx = q[6] - q[0] + v * q[6]; + sy = q[7] - q[1] + v * q[7]; + w1 = v; + tx = q[0]; + ty = q[1]; + w2 = 1.0; + } + return true; + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::invert() + { + double d0 = sy * w2 - w1 * ty; + double d1 = w0 * ty - shy * w2; + double d2 = shy * w1 - w0 * sy; + double d = sx * d0 + shx * d1 + tx * d2; + if(d == 0.0) + { + sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0; + return false; + } + d = 1.0 / d; + trans_perspective a = *this; + sx = d * d0; + shy = d * d1; + w0 = d * d2; + shx = d * (a.w1 *a.tx - a.shx*a.w2); + sy = d * (a.sx *a.w2 - a.w0 *a.tx); + w1 = d * (a.w0 *a.shx - a.sx *a.w1); + tx = d * (a.shx*a.ty - a.sy *a.tx); + ty = d * (a.shy*a.tx - a.sx *a.ty); + w2 = d * (a.sx *a.sy - a.shy*a.shx); + return true; + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::quad_to_square(const double* q) + { + if(!square_to_quad(q)) return false; + invert(); + return true; + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::quad_to_quad(const double* qs, + const double* qd) + { + trans_perspective p; + if(! quad_to_square(qs)) return false; + if(!p.square_to_quad(qd)) return false; + multiply(p); + return true; + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::rect_to_quad(double x1, double y1, + double x2, double y2, + const double* q) + { + double r[8]; + r[0] = r[6] = x1; + r[2] = r[4] = x2; + r[1] = r[3] = y1; + r[5] = r[7] = y2; + return quad_to_quad(r, q); + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::quad_to_rect(const double* q, + double x1, double y1, + double x2, double y2) + { + double r[8]; + r[0] = r[6] = x1; + r[2] = r[4] = x2; + r[1] = r[3] = y1; + r[5] = r[7] = y2; + return quad_to_quad(q, r); + } + + //------------------------------------------------------------------------ + inline trans_perspective::trans_perspective(double x1, double y1, + double x2, double y2, + const double* quad) + { + rect_to_quad(x1, y1, x2, y2, quad); + } + + //------------------------------------------------------------------------ + inline trans_perspective::trans_perspective(const double* quad, + double x1, double y1, + double x2, double y2) + { + quad_to_rect(quad, x1, y1, x2, y2); + } + + //------------------------------------------------------------------------ + inline trans_perspective::trans_perspective(const double* src, + const double* dst) + { + quad_to_quad(src, dst); + } + + //------------------------------------------------------------------------ + inline const trans_perspective& trans_perspective::reset() + { + sx = 1; shy = 0; w0 = 0; + shx = 0; sy = 1; w1 = 0; + tx = 0; ty = 0; w2 = 1; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& + trans_perspective::multiply(const trans_perspective& a) + { + trans_perspective b = *this; + sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0; + shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1; + tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2; + shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0; + sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1; + ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2; + w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0; + w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1; + w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& + trans_perspective::multiply(const trans_affine& a) + { + trans_perspective b = *this; + sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0; + shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1; + tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2; + shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0; + sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1; + ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& + trans_perspective::premultiply(const trans_perspective& b) + { + trans_perspective a = *this; + sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0; + shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1; + tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2; + shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0; + sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1; + ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2; + w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0; + w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1; + w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& + trans_perspective::premultiply(const trans_affine& b) + { + trans_perspective a = *this; + sx = a.sx *b.sx + a.shx*b.shy; + shx = a.sx *b.shx + a.shx*b.sy; + tx = a.sx *b.tx + a.shx*b.ty + a.tx; + shy = a.shy*b.sx + a.sy *b.shy; + sy = a.shy*b.shx + a.sy *b.sy; + ty = a.shy*b.tx + a.sy *b.ty + a.ty; + w0 = a.w0 *b.sx + a.w1 *b.shy; + w1 = a.w0 *b.shx + a.w1 *b.sy; + w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2; + return *this; + } + + //------------------------------------------------------------------------ + const trans_perspective& + trans_perspective::multiply_inv(const trans_perspective& m) + { + trans_perspective t = m; + t.invert(); + return multiply(t); + } + + //------------------------------------------------------------------------ + const trans_perspective& + trans_perspective::multiply_inv(const trans_affine& m) + { + trans_affine t = m; + t.invert(); + return multiply(t); + } + + //------------------------------------------------------------------------ + const trans_perspective& + trans_perspective::premultiply_inv(const trans_perspective& m) + { + trans_perspective t = m; + t.invert(); + return *this = t.multiply(*this); + } + + //------------------------------------------------------------------------ + const trans_perspective& + trans_perspective::premultiply_inv(const trans_affine& m) + { + trans_perspective t(m); + t.invert(); + return *this = t.multiply(*this); + } + + //------------------------------------------------------------------------ + inline const trans_perspective& + trans_perspective::translate(double x, double y) + { + tx += x; + ty += y; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& trans_perspective::rotate(double a) + { + multiply(trans_affine_rotation(a)); + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& trans_perspective::scale(double s) + { + multiply(trans_affine_scaling(s)); + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& trans_perspective::scale(double x, double y) + { + multiply(trans_affine_scaling(x, y)); + return *this; + } + + //------------------------------------------------------------------------ + inline void trans_perspective::transform(double* px, double* py) const + { + double x = *px; + double y = *py; + double m = 1.0 / (x*w0 + y*w1 + w2); + *px = m * (x*sx + y*shx + tx); + *py = m * (x*shy + y*sy + ty); + } + + //------------------------------------------------------------------------ + inline void trans_perspective::transform_affine(double* x, double* y) const + { + double tmp = *x; + *x = tmp * sx + *y * shx + tx; + *y = tmp * shy + *y * sy + ty; + } + + //------------------------------------------------------------------------ + inline void trans_perspective::transform_2x2(double* x, double* y) const + { + double tmp = *x; + *x = tmp * sx + *y * shx; + *y = tmp * shy + *y * sy; + } + + //------------------------------------------------------------------------ + inline void trans_perspective::inverse_transform(double* x, double* y) const + { + trans_perspective t(*this); + if(t.invert()) t.transform(x, y); + } + + //------------------------------------------------------------------------ + inline void trans_perspective::store_to(double* m) const + { + *m++ = sx; *m++ = shy; *m++ = w0; + *m++ = shx; *m++ = sy; *m++ = w1; + *m++ = tx; *m++ = ty; *m++ = w2; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& trans_perspective::load_from(const double* m) + { + sx = *m++; shy = *m++; w0 = *m++; + shx = *m++; sy = *m++; w1 = *m++; + tx = *m++; ty = *m++; w2 = *m++; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& + trans_perspective::from_affine(const trans_affine& a) + { + sx = a.sx; shy = a.shy; w0 = 0; + shx = a.shx; sy = a.sy; w1 = 0; + tx = a.tx; ty = a.ty; w2 = 1; + return *this; + } + + //------------------------------------------------------------------------ + inline double trans_perspective::determinant() const + { + return sx * (sy * w2 - ty * w1) + + shx * (ty * w0 - shy * w2) + + tx * (shy * w1 - sy * w0); + } + + //------------------------------------------------------------------------ + inline double trans_perspective::determinant_reciprocal() const + { + return 1.0 / determinant(); + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::is_valid(double epsilon) const + { + return fabs(sx) > epsilon && fabs(sy) > epsilon && fabs(w2) > epsilon; + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::is_identity(double epsilon) const + { + return is_equal_eps(sx, 1.0, epsilon) && + is_equal_eps(shy, 0.0, epsilon) && + is_equal_eps(w0, 0.0, epsilon) && + is_equal_eps(shx, 0.0, epsilon) && + is_equal_eps(sy, 1.0, epsilon) && + is_equal_eps(w1, 0.0, epsilon) && + is_equal_eps(tx, 0.0, epsilon) && + is_equal_eps(ty, 0.0, epsilon) && + is_equal_eps(w2, 1.0, epsilon); + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::is_equal(const trans_perspective& m, + double epsilon) const + { + return is_equal_eps(sx, m.sx, epsilon) && + is_equal_eps(shy, m.shy, epsilon) && + is_equal_eps(w0, m.w0, epsilon) && + is_equal_eps(shx, m.shx, epsilon) && + is_equal_eps(sy, m.sy, epsilon) && + is_equal_eps(w1, m.w1, epsilon) && + is_equal_eps(tx, m.tx, epsilon) && + is_equal_eps(ty, m.ty, epsilon) && + is_equal_eps(w2, m.w2, epsilon); + } + + //------------------------------------------------------------------------ + inline double trans_perspective::scale() const + { + double x = 0.707106781 * sx + 0.707106781 * shx; + double y = 0.707106781 * shy + 0.707106781 * sy; + return sqrt(x*x + y*y); + } + + //------------------------------------------------------------------------ + inline double trans_perspective::rotation() const + { + double x1 = 0.0; + double y1 = 0.0; + double x2 = 1.0; + double y2 = 0.0; + transform(&x1, &y1); + transform(&x2, &y2); + return atan2(y2-y1, x2-x1); + } + + //------------------------------------------------------------------------ + void trans_perspective::translation(double* dx, double* dy) const + { + *dx = tx; + *dy = ty; + } + + //------------------------------------------------------------------------ + void trans_perspective::scaling(double* x, double* y) const + { + double x1 = 0.0; + double y1 = 0.0; + double x2 = 1.0; + double y2 = 1.0; + trans_perspective t(*this); + t *= trans_affine_rotation(-rotation()); + t.transform(&x1, &y1); + t.transform(&x2, &y2); + *x = x2 - x1; + *y = y2 - y1; + } + + //------------------------------------------------------------------------ + void trans_perspective::scaling_abs(double* x, double* y) const + { + *x = sqrt(sx * sx + shx * shx); + *y = sqrt(shy * shy + sy * sy); + } + + +} + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_trans_single_path.h b/jni/desmume/src/android/agg/include/agg_trans_single_path.h new file mode 100755 index 0000000..08e7adf --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_trans_single_path.h @@ -0,0 +1,106 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_TRANS_SINGLE_PATH_INCLUDED +#define AGG_TRANS_SINGLE_PATH_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + + // See also: agg_trans_single_path.cpp + // + //-------------------------------------------------------trans_single_path + class trans_single_path + { + enum status_e + { + initial, + making_path, + ready + }; + + public: + typedef vertex_sequence<vertex_dist, 6> vertex_storage; + + trans_single_path(); + + //-------------------------------------------------------------------- + void base_length(double v) { m_base_length = v; } + double base_length() const { return m_base_length; } + + //-------------------------------------------------------------------- + void preserve_x_scale(bool f) { m_preserve_x_scale = f; } + bool preserve_x_scale() const { return m_preserve_x_scale; } + + //-------------------------------------------------------------------- + void reset(); + void move_to(double x, double y); + void line_to(double x, double y); + void finalize_path(); + + //-------------------------------------------------------------------- + template<class VertexSource> + void add_path(VertexSource& vs, unsigned path_id=0) + { + double x; + double y; + + unsigned cmd; + vs.rewind(path_id); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + if(is_move_to(cmd)) + { + move_to(x, y); + } + else + { + if(is_vertex(cmd)) + { + line_to(x, y); + } + } + } + finalize_path(); + } + + //-------------------------------------------------------------------- + double total_length() const; + void transform(double *x, double *y) const; + + private: + vertex_storage m_src_vertices; + double m_base_length; + double m_kindex; + status_e m_status; + bool m_preserve_x_scale; + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_trans_viewport.h b/jni/desmume/src/android/agg/include/agg_trans_viewport.h new file mode 100755 index 0000000..7f02668 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_trans_viewport.h @@ -0,0 +1,312 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Viewport transformer - simple orthogonal conversions from world coordinates +// to screen (device) ones. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_TRANS_VIEWPORT_INCLUDED +#define AGG_TRANS_VIEWPORT_INCLUDED + +#include <string.h> +#include "agg_trans_affine.h" + + +namespace agg +{ + + enum aspect_ratio_e + { + aspect_ratio_stretch, + aspect_ratio_meet, + aspect_ratio_slice + }; + + + //----------------------------------------------------------trans_viewport + class trans_viewport + { + public: + //------------------------------------------------------------------- + trans_viewport() : + m_world_x1(0.0), + m_world_y1(0.0), + m_world_x2(1.0), + m_world_y2(1.0), + m_device_x1(0.0), + m_device_y1(0.0), + m_device_x2(1.0), + m_device_y2(1.0), + m_aspect(aspect_ratio_stretch), + m_is_valid(true), + m_align_x(0.5), + m_align_y(0.5), + m_wx1(0.0), + m_wy1(0.0), + m_wx2(1.0), + m_wy2(1.0), + m_dx1(0.0), + m_dy1(0.0), + m_kx(1.0), + m_ky(1.0) + {} + + //------------------------------------------------------------------- + void preserve_aspect_ratio(double alignx, + double aligny, + aspect_ratio_e aspect) + { + m_align_x = alignx; + m_align_y = aligny; + m_aspect = aspect; + update(); + } + + //------------------------------------------------------------------- + void device_viewport(double x1, double y1, double x2, double y2) + { + m_device_x1 = x1; + m_device_y1 = y1; + m_device_x2 = x2; + m_device_y2 = y2; + update(); + } + + //------------------------------------------------------------------- + void world_viewport(double x1, double y1, double x2, double y2) + { + m_world_x1 = x1; + m_world_y1 = y1; + m_world_x2 = x2; + m_world_y2 = y2; + update(); + } + + //------------------------------------------------------------------- + void device_viewport(double* x1, double* y1, double* x2, double* y2) const + { + *x1 = m_device_x1; + *y1 = m_device_y1; + *x2 = m_device_x2; + *y2 = m_device_y2; + } + + //------------------------------------------------------------------- + void world_viewport(double* x1, double* y1, double* x2, double* y2) const + { + *x1 = m_world_x1; + *y1 = m_world_y1; + *x2 = m_world_x2; + *y2 = m_world_y2; + } + + //------------------------------------------------------------------- + void world_viewport_actual(double* x1, double* y1, + double* x2, double* y2) const + { + *x1 = m_wx1; + *y1 = m_wy1; + *x2 = m_wx2; + *y2 = m_wy2; + } + + //------------------------------------------------------------------- + bool is_valid() const { return m_is_valid; } + double align_x() const { return m_align_x; } + double align_y() const { return m_align_y; } + aspect_ratio_e aspect_ratio() const { return m_aspect; } + + //------------------------------------------------------------------- + void transform(double* x, double* y) const + { + *x = (*x - m_wx1) * m_kx + m_dx1; + *y = (*y - m_wy1) * m_ky + m_dy1; + } + + //------------------------------------------------------------------- + void transform_scale_only(double* x, double* y) const + { + *x *= m_kx; + *y *= m_ky; + } + + //------------------------------------------------------------------- + void inverse_transform(double* x, double* y) const + { + *x = (*x - m_dx1) / m_kx + m_wx1; + *y = (*y - m_dy1) / m_ky + m_wy1; + } + + //------------------------------------------------------------------- + void inverse_transform_scale_only(double* x, double* y) const + { + *x /= m_kx; + *y /= m_ky; + } + + //------------------------------------------------------------------- + double device_dx() const { return m_dx1 - m_wx1 * m_kx; } + double device_dy() const { return m_dy1 - m_wy1 * m_ky; } + + //------------------------------------------------------------------- + double scale_x() const + { + return m_kx; + } + + //------------------------------------------------------------------- + double scale_y() const + { + return m_ky; + } + + //------------------------------------------------------------------- + double scale() const + { + return (m_kx + m_ky) * 0.5; + } + + //------------------------------------------------------------------- + trans_affine to_affine() const + { + trans_affine mtx = trans_affine_translation(-m_wx1, -m_wy1); + mtx *= trans_affine_scaling(m_kx, m_ky); + mtx *= trans_affine_translation(m_dx1, m_dy1); + return mtx; + } + + //------------------------------------------------------------------- + trans_affine to_affine_scale_only() const + { + return trans_affine_scaling(m_kx, m_ky); + } + + //------------------------------------------------------------------- + unsigned byte_size() const + { + return sizeof(*this); + } + + void serialize(int8u* ptr) const + { + memcpy(ptr, this, sizeof(*this)); + } + + void deserialize(const int8u* ptr) + { + memcpy(this, ptr, sizeof(*this)); + } + + private: + void update(); + + double m_world_x1; + double m_world_y1; + double m_world_x2; + double m_world_y2; + double m_device_x1; + double m_device_y1; + double m_device_x2; + double m_device_y2; + aspect_ratio_e m_aspect; + bool m_is_valid; + double m_align_x; + double m_align_y; + double m_wx1; + double m_wy1; + double m_wx2; + double m_wy2; + double m_dx1; + double m_dy1; + double m_kx; + double m_ky; + }; + + + + //----------------------------------------------------------------------- + inline void trans_viewport::update() + { + const double epsilon = 1e-30; + if(fabs(m_world_x1 - m_world_x2) < epsilon || + fabs(m_world_y1 - m_world_y2) < epsilon || + fabs(m_device_x1 - m_device_x2) < epsilon || + fabs(m_device_y1 - m_device_y2) < epsilon) + { + m_wx1 = m_world_x1; + m_wy1 = m_world_y1; + m_wx2 = m_world_x1 + 1.0; + m_wy2 = m_world_y2 + 1.0; + m_dx1 = m_device_x1; + m_dy1 = m_device_y1; + m_kx = 1.0; + m_ky = 1.0; + m_is_valid = false; + return; + } + + double world_x1 = m_world_x1; + double world_y1 = m_world_y1; + double world_x2 = m_world_x2; + double world_y2 = m_world_y2; + double device_x1 = m_device_x1; + double device_y1 = m_device_y1; + double device_x2 = m_device_x2; + double device_y2 = m_device_y2; + if(m_aspect != aspect_ratio_stretch) + { + double d; + m_kx = (device_x2 - device_x1) / (world_x2 - world_x1); + m_ky = (device_y2 - device_y1) / (world_y2 - world_y1); + + if((m_aspect == aspect_ratio_meet) == (m_kx < m_ky)) + { + d = (world_y2 - world_y1) * m_ky / m_kx; + world_y1 += (world_y2 - world_y1 - d) * m_align_y; + world_y2 = world_y1 + d; + } + else + { + d = (world_x2 - world_x1) * m_kx / m_ky; + world_x1 += (world_x2 - world_x1 - d) * m_align_x; + world_x2 = world_x1 + d; + } + } + m_wx1 = world_x1; + m_wy1 = world_y1; + m_wx2 = world_x2; + m_wy2 = world_y2; + m_dx1 = device_x1; + m_dy1 = device_y1; + m_kx = (device_x2 - device_x1) / (world_x2 - world_x1); + m_ky = (device_y2 - device_y1) / (world_y2 - world_y1); + m_is_valid = true; + } + + +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_trans_warp_magnifier.h b/jni/desmume/src/android/agg/include/agg_trans_warp_magnifier.h new file mode 100755 index 0000000..526cc4f --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_trans_warp_magnifier.h @@ -0,0 +1,65 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_WARP_MAGNIFIER_INCLUDED +#define AGG_WARP_MAGNIFIER_INCLUDED + + +namespace agg +{ + + //----------------------------------------------------trans_warp_magnifier + // + // See Inmplementation agg_trans_warp_magnifier.cpp + // + class trans_warp_magnifier + { + public: + trans_warp_magnifier() : m_xc(0.0), m_yc(0.0), m_magn(1.0), m_radius(1.0) {} + + void center(double x, double y) { m_xc = x; m_yc = y; } + void magnification(double m) { m_magn = m; } + void radius(double r) { m_radius = r; } + + double xc() const { return m_xc; } + double yc() const { return m_yc; } + double magnification() const { return m_magn; } + double radius() const { return m_radius; } + + void transform(double* x, double* y) const; + void inverse_transform(double* x, double* y) const; + + private: + double m_xc; + double m_yc; + double m_magn; + double m_radius; + }; + + +} + + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_vcgen_bspline.h b/jni/desmume/src/android/agg/include/agg_vcgen_bspline.h new file mode 100755 index 0000000..75e9e80 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_vcgen_bspline.h @@ -0,0 +1,83 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_VCGEN_BSPLINE_INCLUDED +#define AGG_VCGEN_BSPLINE_INCLUDED + +#include "agg_basics.h" +#include "agg_array.h" +#include "agg_bspline.h" + + +namespace agg +{ + + //==========================================================vcgen_bspline + class vcgen_bspline + { + enum status_e + { + initial, + ready, + polygon, + end_poly, + stop + }; + + public: + typedef pod_bvector<point_d, 6> vertex_storage; + + vcgen_bspline(); + + void interpolation_step(double v) { m_interpolation_step = v; } + double interpolation_step() const { return m_interpolation_step; } + + // Vertex Generator Interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + vcgen_bspline(const vcgen_bspline&); + const vcgen_bspline& operator = (const vcgen_bspline&); + + vertex_storage m_src_vertices; + bspline m_spline_x; + bspline m_spline_y; + double m_interpolation_step; + unsigned m_closed; + status_e m_status; + unsigned m_src_vertex; + double m_cur_abscissa; + double m_max_abscissa; + }; + +} + + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_vcgen_contour.h b/jni/desmume/src/android/agg/include/agg_vcgen_contour.h new file mode 100755 index 0000000..1a3a4bc --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_vcgen_contour.h @@ -0,0 +1,103 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_VCGEN_CONTOUR_INCLUDED +#define AGG_VCGEN_CONTOUR_INCLUDED + +#include "agg_math_stroke.h" + +namespace agg +{ + + //----------------------------------------------------------vcgen_contour + // + // See Implementation agg_vcgen_contour.cpp + // + class vcgen_contour + { + enum status_e + { + initial, + ready, + outline, + out_vertices, + end_poly, + stop + }; + + public: + typedef vertex_sequence<vertex_dist, 6> vertex_storage; + typedef pod_bvector<point_d, 6> coord_storage; + + vcgen_contour(); + + void line_cap(line_cap_e lc) { m_stroker.line_cap(lc); } + void line_join(line_join_e lj) { m_stroker.line_join(lj); } + void inner_join(inner_join_e ij) { m_stroker.inner_join(ij); } + + line_cap_e line_cap() const { return m_stroker.line_cap(); } + line_join_e line_join() const { return m_stroker.line_join(); } + inner_join_e inner_join() const { return m_stroker.inner_join(); } + + void width(double w) { m_stroker.width(m_width = w); } + void miter_limit(double ml) { m_stroker.miter_limit(ml); } + void miter_limit_theta(double t) { m_stroker.miter_limit_theta(t); } + void inner_miter_limit(double ml) { m_stroker.inner_miter_limit(ml); } + void approximation_scale(double as) { m_stroker.approximation_scale(as); } + + double width() const { return m_width; } + double miter_limit() const { return m_stroker.miter_limit(); } + double inner_miter_limit() const { return m_stroker.inner_miter_limit(); } + double approximation_scale() const { return m_stroker.approximation_scale(); } + + void auto_detect_orientation(bool v) { m_auto_detect = v; } + bool auto_detect_orientation() const { return m_auto_detect; } + + // Generator interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + vcgen_contour(const vcgen_contour&); + const vcgen_contour& operator = (const vcgen_contour&); + + math_stroke<coord_storage> m_stroker; + double m_width; + vertex_storage m_src_vertices; + coord_storage m_out_vertices; + status_e m_status; + unsigned m_src_vertex; + unsigned m_out_vertex; + unsigned m_closed; + unsigned m_orientation; + bool m_auto_detect; + }; + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_vcgen_dash.h b/jni/desmume/src/android/agg/include/agg_vcgen_dash.h new file mode 100755 index 0000000..cb847e2 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_vcgen_dash.h @@ -0,0 +1,99 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_VCGEN_DASH_INCLUDED +#define AGG_VCGEN_DASH_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + + //---------------------------------------------------------------vcgen_dash + // + // See Implementation agg_vcgen_dash.cpp + // + class vcgen_dash + { + enum max_dashes_e + { + max_dashes = 32 + }; + + enum status_e + { + initial, + ready, + polyline, + stop + }; + + public: + typedef vertex_sequence<vertex_dist, 6> vertex_storage; + + vcgen_dash(); + + void remove_all_dashes(); + void add_dash(double dash_len, double gap_len); + void dash_start(double ds); + + void shorten(double s) { m_shorten = s; } + double shorten() const { return m_shorten; } + + // Vertex Generator Interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + vcgen_dash(const vcgen_dash&); + const vcgen_dash& operator = (const vcgen_dash&); + + void calc_dash_start(double ds); + + double m_dashes[max_dashes]; + double m_total_dash_len; + unsigned m_num_dashes; + double m_dash_start; + double m_shorten; + double m_curr_dash_start; + unsigned m_curr_dash; + double m_curr_rest; + const vertex_dist* m_v1; + const vertex_dist* m_v2; + + vertex_storage m_src_vertices; + unsigned m_closed; + status_e m_status; + unsigned m_src_vertex; + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_vcgen_markers_term.h b/jni/desmume/src/android/agg/include/agg_vcgen_markers_term.h new file mode 100755 index 0000000..08c384c --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_vcgen_markers_term.h @@ -0,0 +1,75 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_VCGEN_MARKERS_TERM_INCLUDED +#define AGG_VCGEN_MARKERS_TERM_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + + //======================================================vcgen_markers_term + // + // See Implemantation agg_vcgen_markers_term.cpp + // Terminal markers generator (arrowhead/arrowtail) + // + //------------------------------------------------------------------------ + class vcgen_markers_term + { + public: + vcgen_markers_term() : m_curr_id(0), m_curr_idx(0) {} + + // Vertex Generator Interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + vcgen_markers_term(const vcgen_markers_term&); + const vcgen_markers_term& operator = (const vcgen_markers_term&); + + struct coord_type + { + double x, y; + + coord_type() {} + coord_type(double x_, double y_) : x(x_), y(y_) {} + }; + + typedef pod_bvector<coord_type, 6> coord_storage; + + coord_storage m_markers; + unsigned m_curr_id; + unsigned m_curr_idx; + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_vcgen_smooth_poly1.h b/jni/desmume/src/android/agg/include/agg_vcgen_smooth_poly1.h new file mode 100755 index 0000000..b419b59 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_vcgen_smooth_poly1.h @@ -0,0 +1,96 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_VCGEN_SMOOTH_POLY1_INCLUDED +#define AGG_VCGEN_SMOOTH_POLY1_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" + + +namespace agg +{ + + //======================================================vcgen_smooth_poly1 + // + // See Implementation agg_vcgen_smooth_poly1.cpp + // Smooth polygon generator + // + //------------------------------------------------------------------------ + class vcgen_smooth_poly1 + { + enum status_e + { + initial, + ready, + polygon, + ctrl_b, + ctrl_e, + ctrl1, + ctrl2, + end_poly, + stop + }; + + public: + typedef vertex_sequence<vertex_dist, 6> vertex_storage; + + vcgen_smooth_poly1(); + + void smooth_value(double v) { m_smooth_value = v * 0.5; } + double smooth_value() const { return m_smooth_value * 2.0; } + + // Vertex Generator Interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + vcgen_smooth_poly1(const vcgen_smooth_poly1&); + const vcgen_smooth_poly1& operator = (const vcgen_smooth_poly1&); + + void calculate(const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + const vertex_dist& v3); + + vertex_storage m_src_vertices; + double m_smooth_value; + unsigned m_closed; + status_e m_status; + unsigned m_src_vertex; + double m_ctrl1_x; + double m_ctrl1_y; + double m_ctrl2_x; + double m_ctrl2_y; + }; + +} + + +#endif + diff --git a/jni/desmume/src/android/agg/include/agg_vcgen_stroke.h b/jni/desmume/src/android/agg/include/agg_vcgen_stroke.h new file mode 100755 index 0000000..4edba76 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_vcgen_stroke.h @@ -0,0 +1,111 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_VCGEN_STROKE_INCLUDED +#define AGG_VCGEN_STROKE_INCLUDED + +#include "agg_math_stroke.h" + + +namespace agg +{ + + //============================================================vcgen_stroke + // + // See Implementation agg_vcgen_stroke.cpp + // Stroke generator + // + //------------------------------------------------------------------------ + class vcgen_stroke + { + enum status_e + { + initial, + ready, + cap1, + cap2, + outline1, + close_first, + outline2, + out_vertices, + end_poly1, + end_poly2, + stop + }; + + public: + typedef vertex_sequence<vertex_dist, 6> vertex_storage; + typedef pod_bvector<point_d, 6> coord_storage; + + vcgen_stroke(); + + void line_cap(line_cap_e lc) { m_stroker.line_cap(lc); } + void line_join(line_join_e lj) { m_stroker.line_join(lj); } + void inner_join(inner_join_e ij) { m_stroker.inner_join(ij); } + + line_cap_e line_cap() const { return m_stroker.line_cap(); } + line_join_e line_join() const { return m_stroker.line_join(); } + inner_join_e inner_join() const { return m_stroker.inner_join(); } + + void width(double w) { m_stroker.width(w); } + void miter_limit(double ml) { m_stroker.miter_limit(ml); } + void miter_limit_theta(double t) { m_stroker.miter_limit_theta(t); } + void inner_miter_limit(double ml) { m_stroker.inner_miter_limit(ml); } + void approximation_scale(double as) { m_stroker.approximation_scale(as); } + + double width() const { return m_stroker.width(); } + double miter_limit() const { return m_stroker.miter_limit(); } + double inner_miter_limit() const { return m_stroker.inner_miter_limit(); } + double approximation_scale() const { return m_stroker.approximation_scale(); } + + void shorten(double s) { m_shorten = s; } + double shorten() const { return m_shorten; } + + // Vertex Generator Interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + vcgen_stroke(const vcgen_stroke&); + const vcgen_stroke& operator = (const vcgen_stroke&); + + math_stroke<coord_storage> m_stroker; + vertex_storage m_src_vertices; + coord_storage m_out_vertices; + double m_shorten; + unsigned m_closed; + status_e m_status; + status_e m_prev_status; + unsigned m_src_vertex; + unsigned m_out_vertex; + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_vcgen_vertex_sequence.h b/jni/desmume/src/android/agg/include/agg_vcgen_vertex_sequence.h new file mode 100755 index 0000000..120b02f --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_vcgen_vertex_sequence.h @@ -0,0 +1,144 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_VCGEN_VERTEX_SEQUENCE_INCLUDED +#define AGG_VCGEN_VERTEX_SEQUENCE_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" +#include "agg_shorten_path.h" + +namespace agg +{ + + //===================================================vcgen_vertex_sequence + class vcgen_vertex_sequence + { + public: + typedef vertex_dist_cmd vertex_type; + typedef vertex_sequence<vertex_type, 6> vertex_storage; + + vcgen_vertex_sequence() : + m_flags(0), + m_cur_vertex(0), + m_shorten(0.0), + m_ready(false) + { + } + + // Vertex Generator Interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + void shorten(double s) { m_shorten = s; } + double shorten() const { return m_shorten; } + + private: + vcgen_vertex_sequence(const vcgen_vertex_sequence&); + const vcgen_vertex_sequence& operator = (const vcgen_vertex_sequence&); + + vertex_storage m_src_vertices; + unsigned m_flags; + unsigned m_cur_vertex; + double m_shorten; + bool m_ready; + }; + + + //------------------------------------------------------------------------ + inline void vcgen_vertex_sequence::remove_all() + { + m_ready = false; + m_src_vertices.remove_all(); + m_cur_vertex = 0; + m_flags = 0; + } + + //------------------------------------------------------------------------ + inline void vcgen_vertex_sequence::add_vertex(double x, double y, unsigned cmd) + { + m_ready = false; + if(is_move_to(cmd)) + { + m_src_vertices.modify_last(vertex_dist_cmd(x, y, cmd)); + } + else + { + if(is_vertex(cmd)) + { + m_src_vertices.add(vertex_dist_cmd(x, y, cmd)); + } + else + { + m_flags = cmd & path_flags_mask; + } + } + } + + + //------------------------------------------------------------------------ + inline void vcgen_vertex_sequence::rewind(unsigned) + { + if(!m_ready) + { + m_src_vertices.close(is_closed(m_flags)); + shorten_path(m_src_vertices, m_shorten, get_close_flag(m_flags)); + } + m_ready = true; + m_cur_vertex = 0; + } + + //------------------------------------------------------------------------ + inline unsigned vcgen_vertex_sequence::vertex(double* x, double* y) + { + if(!m_ready) + { + rewind(0); + } + + if(m_cur_vertex == m_src_vertices.size()) + { + ++m_cur_vertex; + return path_cmd_end_poly | m_flags; + } + + if(m_cur_vertex > m_src_vertices.size()) + { + return path_cmd_stop; + } + + vertex_type& v = m_src_vertices[m_cur_vertex++]; + *x = v.x; + *y = v.y; + return v.cmd; + } + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_vertex_sequence.h b/jni/desmume/src/android/agg/include/agg_vertex_sequence.h new file mode 100755 index 0000000..f3ef35c --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_vertex_sequence.h @@ -0,0 +1,178 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_VERTEX_SEQUENCE_INCLUDED +#define AGG_VERTEX_SEQUENCE_INCLUDED + +#include "agg_basics.h" +#include "agg_array.h" +#include "agg_math.h" + +namespace agg +{ + + //----------------------------------------------------------vertex_sequence + // Modified agg::pod_bvector. The data is interpreted as a sequence + // of vertices. It means that the type T must expose: + // + // bool T::operator() (const T& val) + // + // that is called every time new vertex is being added. The main purpose + // of this operator is the possibility to calculate some values during + // adding and to return true if the vertex fits some criteria or false if + // it doesn't. In the last case the new vertex is not added. + // + // The simple example is filtering coinciding vertices with calculation + // of the distance between the current and previous ones: + // + // struct vertex_dist + // { + // double x; + // double y; + // double dist; + // + // vertex_dist() {} + // vertex_dist(double x_, double y_) : + // x(x_), + // y(y_), + // dist(0.0) + // { + // } + // + // bool operator () (const vertex_dist& val) + // { + // return (dist = calc_distance(x, y, val.x, val.y)) > EPSILON; + // } + // }; + // + // Function close() calls this operator and removes the last vertex if + // necessary. + //------------------------------------------------------------------------ + template<class T, unsigned S=6> + class vertex_sequence : public pod_bvector<T, S> + { + public: + typedef pod_bvector<T, S> base_type; + + void add(const T& val); + void modify_last(const T& val); + void close(bool remove_flag); + }; + + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + void vertex_sequence<T, S>::add(const T& val) + { + if(base_type::size() > 1) + { + if(!(*this)[base_type::size() - 2]((*this)[base_type::size() - 1])) + { + base_type::remove_last(); + } + } + base_type::add(val); + } + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + void vertex_sequence<T, S>::modify_last(const T& val) + { + base_type::remove_last(); + add(val); + } + + + + //------------------------------------------------------------------------ + template<class T, unsigned S> + void vertex_sequence<T, S>::close(bool closed) + { + while(base_type::size() > 1) + { + if((*this)[base_type::size() - 2]((*this)[base_type::size() - 1])) break; + T t = (*this)[base_type::size() - 1]; + base_type::remove_last(); + modify_last(t); + } + + if(closed) + { + while(base_type::size() > 1) + { + if((*this)[base_type::size() - 1]((*this)[0])) break; + base_type::remove_last(); + } + } + } + + + //-------------------------------------------------------------vertex_dist + // Vertex (x, y) with the distance to the next one. The last vertex has + // distance between the last and the first points if the polygon is closed + // and 0.0 if it's a polyline. + struct vertex_dist + { + double x; + double y; + double dist; + + vertex_dist() {} + vertex_dist(double x_, double y_) : + x(x_), + y(y_), + dist(0.0) + { + } + + bool operator () (const vertex_dist& val) + { + bool ret = (dist = calc_distance(x, y, val.x, val.y)) > vertex_dist_epsilon; + if(!ret) dist = 1.0 / vertex_dist_epsilon; + return ret; + } + }; + + + + //--------------------------------------------------------vertex_dist_cmd + // Save as the above but with additional "command" value + struct vertex_dist_cmd : public vertex_dist + { + unsigned cmd; + + vertex_dist_cmd() {} + vertex_dist_cmd(double x_, double y_, unsigned cmd_) : + vertex_dist(x_, y_), + cmd(cmd_) + { + } + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_vpgen_clip_polygon.h b/jni/desmume/src/android/agg/include/agg_vpgen_clip_polygon.h new file mode 100755 index 0000000..69cdd45 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_vpgen_clip_polygon.h @@ -0,0 +1,92 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_VPGEN_CLIP_POLYGON_INCLUDED +#define AGG_VPGEN_CLIP_POLYGON_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //======================================================vpgen_clip_polygon + // + // See Implementation agg_vpgen_clip_polygon.cpp + // + class vpgen_clip_polygon + { + public: + vpgen_clip_polygon() : + m_clip_box(0, 0, 1, 1), + m_x1(0), + m_y1(0), + m_clip_flags(0), + m_num_vertices(0), + m_vertex(0), + m_cmd(path_cmd_move_to) + { + } + + void clip_box(double x1, double y1, double x2, double y2) + { + m_clip_box.x1 = x1; + m_clip_box.y1 = y1; + m_clip_box.x2 = x2; + m_clip_box.y2 = y2; + m_clip_box.normalize(); + } + + + double x1() const { return m_clip_box.x1; } + double y1() const { return m_clip_box.y1; } + double x2() const { return m_clip_box.x2; } + double y2() const { return m_clip_box.y2; } + + static bool auto_close() { return true; } + static bool auto_unclose() { return false; } + + void reset(); + void move_to(double x, double y); + void line_to(double x, double y); + unsigned vertex(double* x, double* y); + + private: + unsigned clipping_flags(double x, double y); + + private: + rect_d m_clip_box; + double m_x1; + double m_y1; + unsigned m_clip_flags; + double m_x[4]; + double m_y[4]; + unsigned m_num_vertices; + unsigned m_vertex; + unsigned m_cmd; + }; + +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_vpgen_clip_polyline.h b/jni/desmume/src/android/agg/include/agg_vpgen_clip_polyline.h new file mode 100755 index 0000000..ba3484f --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_vpgen_clip_polyline.h @@ -0,0 +1,87 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_VPGEN_CLIP_POLYLINE_INCLUDED +#define AGG_VPGEN_CLIP_POLYLINE_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //======================================================vpgen_clip_polyline + // + // See Implementation agg_vpgen_clip_polyline.cpp + // + class vpgen_clip_polyline + { + public: + vpgen_clip_polyline() : + m_clip_box(0, 0, 1, 1), + m_x1(0), + m_y1(0), + m_num_vertices(0), + m_vertex(0), + m_move_to(false) + { + } + + void clip_box(double x1, double y1, double x2, double y2) + { + m_clip_box.x1 = x1; + m_clip_box.y1 = y1; + m_clip_box.x2 = x2; + m_clip_box.y2 = y2; + m_clip_box.normalize(); + } + + double x1() const { return m_clip_box.x1; } + double y1() const { return m_clip_box.y1; } + double x2() const { return m_clip_box.x2; } + double y2() const { return m_clip_box.y2; } + + static bool auto_close() { return false; } + static bool auto_unclose() { return true; } + + void reset(); + void move_to(double x, double y); + void line_to(double x, double y); + unsigned vertex(double* x, double* y); + + private: + rect_d m_clip_box; + double m_x1; + double m_y1; + double m_x[2]; + double m_y[2]; + unsigned m_cmd[2]; + unsigned m_num_vertices; + unsigned m_vertex; + bool m_move_to; + }; + +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/agg_vpgen_segmentator.h b/jni/desmume/src/android/agg/include/agg_vpgen_segmentator.h new file mode 100755 index 0000000..fd01a48 --- /dev/null +++ b/jni/desmume/src/android/agg/include/agg_vpgen_segmentator.h @@ -0,0 +1,70 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_VPGEN_SEGMENTATOR_INCLUDED +#define AGG_VPGEN_SEGMENTATOR_INCLUDED + +#include <math.h> +#include "agg_basics.h" + +namespace agg +{ + + //=======================================================vpgen_segmentator + // + // See Implementation agg_vpgen_segmentator.cpp + // + class vpgen_segmentator + { + public: + vpgen_segmentator() : m_approximation_scale(1.0) {} + + void approximation_scale(double s) { m_approximation_scale = s; } + double approximation_scale() const { return m_approximation_scale; } + + static bool auto_close() { return false; } + static bool auto_unclose() { return false; } + + void reset() { m_cmd = path_cmd_stop; } + void move_to(double x, double y); + void line_to(double x, double y); + unsigned vertex(double* x, double* y); + + private: + double m_approximation_scale; + double m_x1; + double m_y1; + double m_dx; + double m_dy; + double m_dl; + double m_ddl; + unsigned m_cmd; + }; + + + +} + +#endif + diff --git a/jni/desmume/src/android/agg/include/ctrl/Makefile.am b/jni/desmume/src/android/agg/include/ctrl/Makefile.am new file mode 100755 index 0000000..660c583 --- /dev/null +++ b/jni/desmume/src/android/agg/include/ctrl/Makefile.am @@ -0,0 +1,4 @@ +aggincludedir = $(includedir)/agg2/ctrl +agginclude_HEADERS = agg_ctrl.h agg_gamma_spline.h agg_scale_ctrl.h agg_spline_ctrl.h \ + agg_cbox_ctrl.h agg_gamma_ctrl.h agg_rbox_ctrl.h agg_slider_ctrl.h \ + agg_bezier_ctrl.h agg_polygon_ctrl.h diff --git a/jni/desmume/src/android/agg/include/ctrl/agg_bezier_ctrl.h b/jni/desmume/src/android/agg/include/ctrl/agg_bezier_ctrl.h new file mode 100755 index 0000000..7b11afd --- /dev/null +++ b/jni/desmume/src/android/agg/include/ctrl/agg_bezier_ctrl.h @@ -0,0 +1,201 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_BEZIER_CTRL_INCLUDED +#define AGG_BEZIER_CTRL_INCLUDED + +#include "agg_math.h" +#include "agg_ellipse.h" +#include "agg_trans_affine.h" +#include "agg_color_rgba.h" +#include "agg_conv_stroke.h" +#include "agg_conv_curve.h" +#include "agg_polygon_ctrl.h" + + +namespace agg +{ + + //--------------------------------------------------------bezier_ctrl_impl + class bezier_ctrl_impl : public ctrl + { + public: + bezier_ctrl_impl(); + + void curve(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4); + curve4& curve(); + + double x1() const { return m_poly.xn(0); } + double y1() const { return m_poly.yn(0); } + double x2() const { return m_poly.xn(1); } + double y2() const { return m_poly.yn(1); } + double x3() const { return m_poly.xn(2); } + double y3() const { return m_poly.yn(2); } + double x4() const { return m_poly.xn(3); } + double y4() const { return m_poly.yn(3); } + + void x1(double x) { m_poly.xn(0) = x; } + void y1(double y) { m_poly.yn(0) = y; } + void x2(double x) { m_poly.xn(1) = x; } + void y2(double y) { m_poly.yn(1) = y; } + void x3(double x) { m_poly.xn(2) = x; } + void y3(double y) { m_poly.yn(2) = y; } + void x4(double x) { m_poly.xn(3) = x; } + void y4(double y) { m_poly.yn(3) = y; } + + void line_width(double w) { m_stroke.width(w); } + double line_width() const { return m_stroke.width(); } + + void point_radius(double r) { m_poly.point_radius(r); } + double point_radius() const { return m_poly.point_radius(); } + + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + // Vertex source interface + unsigned num_paths() { return 7; }; + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + + private: + curve4 m_curve; + ellipse m_ellipse; + conv_stroke<curve4> m_stroke; + polygon_ctrl_impl m_poly; + unsigned m_idx; + }; + + + + //----------------------------------------------------------bezier_ctrl + template<class ColorT> class bezier_ctrl : public bezier_ctrl_impl + { + public: + bezier_ctrl() : + m_color(rgba(0.0, 0.0, 0.0)) + { + } + + void line_color(const ColorT& c) { m_color = c; } + const ColorT& color(unsigned i) const { return m_color; } + + private: + bezier_ctrl(const bezier_ctrl<ColorT>&); + const bezier_ctrl<ColorT>& operator = (const bezier_ctrl<ColorT>&); + + ColorT m_color; + }; + + + + + + //--------------------------------------------------------curve3_ctrl_impl + class curve3_ctrl_impl : public ctrl + { + public: + curve3_ctrl_impl(); + + void curve(double x1, double y1, + double x2, double y2, + double x3, double y3); + curve3& curve(); + + double x1() const { return m_poly.xn(0); } + double y1() const { return m_poly.yn(0); } + double x2() const { return m_poly.xn(1); } + double y2() const { return m_poly.yn(1); } + double x3() const { return m_poly.xn(2); } + double y3() const { return m_poly.yn(2); } + + void x1(double x) { m_poly.xn(0) = x; } + void y1(double y) { m_poly.yn(0) = y; } + void x2(double x) { m_poly.xn(1) = x; } + void y2(double y) { m_poly.yn(1) = y; } + void x3(double x) { m_poly.xn(2) = x; } + void y3(double y) { m_poly.yn(2) = y; } + + void line_width(double w) { m_stroke.width(w); } + double line_width() const { return m_stroke.width(); } + + void point_radius(double r) { m_poly.point_radius(r); } + double point_radius() const { return m_poly.point_radius(); } + + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + // Vertex source interface + unsigned num_paths() { return 6; }; + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + + private: + curve3 m_curve; + ellipse m_ellipse; + conv_stroke<curve3> m_stroke; + polygon_ctrl_impl m_poly; + unsigned m_idx; + }; + + + + //----------------------------------------------------------curve3_ctrl + template<class ColorT> class curve3_ctrl : public curve3_ctrl_impl + { + public: + curve3_ctrl() : + m_color(rgba(0.0, 0.0, 0.0)) + { + } + + void line_color(const ColorT& c) { m_color = c; } + const ColorT& color(unsigned i) const { return m_color; } + + private: + curve3_ctrl(const curve3_ctrl<ColorT>&); + const curve3_ctrl<ColorT>& operator = (const curve3_ctrl<ColorT>&); + + ColorT m_color; + }; + + + + +} + + + +#endif + diff --git a/jni/desmume/src/android/agg/include/ctrl/agg_cbox_ctrl.h b/jni/desmume/src/android/agg/include/ctrl/agg_cbox_ctrl.h new file mode 100755 index 0000000..d4174d5 --- /dev/null +++ b/jni/desmume/src/android/agg/include/ctrl/agg_cbox_ctrl.h @@ -0,0 +1,117 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_CBOX_CTRL_INCLUDED +#define AGG_CBOX_CTRL_INCLUDED + +#include "agg_basics.h" +#include "agg_conv_stroke.h" +#include "agg_gsv_text.h" +#include "agg_trans_affine.h" +#include "agg_color_rgba.h" +#include "agg_ctrl.h" + + + +namespace agg +{ + + //----------------------------------------------------------cbox_ctrl_impl + class cbox_ctrl_impl : public ctrl + { + public: + cbox_ctrl_impl(double x, double y, const char* label, bool flip_y=false); + + void text_thickness(double t) { m_text_thickness = t; } + void text_size(double h, double w=0.0); + + const char* label() { return m_label; } + void label(const char* l); + + bool status() const { return m_status; } + void status(bool st) { m_status = st; } + + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + // Vertex soutce interface + unsigned num_paths() { return 3; }; + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + double m_text_thickness; + double m_text_height; + double m_text_width; + char m_label[128]; + bool m_status; + double m_vx[32]; + double m_vy[32]; + + gsv_text m_text; + conv_stroke<gsv_text> m_text_poly; + + unsigned m_idx; + unsigned m_vertex; + }; + + + //----------------------------------------------------------cbox_ctrl_impl + template<class ColorT> class cbox_ctrl : public cbox_ctrl_impl + { + public: + cbox_ctrl(double x, double y, const char* label, bool flip_y=false) : + cbox_ctrl_impl(x, y, label, flip_y), + m_text_color(rgba(0.0, 0.0, 0.0)), + m_inactive_color(rgba(0.0, 0.0, 0.0)), + m_active_color(rgba(0.4, 0.0, 0.0)) + { + m_colors[0] = &m_inactive_color; + m_colors[1] = &m_text_color; + m_colors[2] = &m_active_color; + } + + void text_color(const ColorT& c) { m_text_color = c; } + void inactive_color(const ColorT& c) { m_inactive_color = c; } + void active_color(const ColorT& c) { m_active_color = c; } + + const ColorT& color(unsigned i) const { return *m_colors[i]; } + + private: + cbox_ctrl(const cbox_ctrl<ColorT>&); + const cbox_ctrl<ColorT>& operator = (const cbox_ctrl<ColorT>&); + + ColorT m_text_color; + ColorT m_inactive_color; + ColorT m_active_color; + ColorT* m_colors[3]; + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/ctrl/agg_ctrl.h b/jni/desmume/src/android/agg/include/ctrl/agg_ctrl.h new file mode 100755 index 0000000..cf68c06 --- /dev/null +++ b/jni/desmume/src/android/agg/include/ctrl/agg_ctrl.h @@ -0,0 +1,123 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_CTRL_INCLUDED +#define AGG_CTRL_INCLUDED + +#include "agg_trans_affine.h" +#include "agg_renderer_scanline.h" + +namespace agg +{ + + //--------------------------------------------------------------------ctrl + class ctrl + { + public: + //-------------------------------------------------------------------- + virtual ~ctrl() {} + ctrl(double x1, double y1, double x2, double y2, bool flip_y) : + m_x1(x1), m_y1(y1), m_x2(x2), m_y2(y2), + m_flip_y(flip_y), + m_mtx(0) + { + } + + //-------------------------------------------------------------------- + virtual bool in_rect(double x, double y) const = 0; + virtual bool on_mouse_button_down(double x, double y) = 0; + virtual bool on_mouse_button_up(double x, double y) = 0; + virtual bool on_mouse_move(double x, double y, bool button_flag) = 0; + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up) = 0; + + //-------------------------------------------------------------------- + void transform(const trans_affine& mtx) { m_mtx = &mtx; } + void no_transform() { m_mtx = 0; } + + //-------------------------------------------------------------------- + void transform_xy(double* x, double* y) const + { + if(m_flip_y) *y = m_y1 + m_y2 - *y; + if(m_mtx) m_mtx->transform(x, y); + } + + //-------------------------------------------------------------------- + void inverse_transform_xy(double* x, double* y) const + { + if(m_mtx) m_mtx->inverse_transform(x, y); + if(m_flip_y) *y = m_y1 + m_y2 - *y; + } + + //-------------------------------------------------------------------- + double scale() const { return m_mtx ? m_mtx->scale() : 1.0; } + + private: + ctrl(const ctrl&); + const ctrl& operator = (const ctrl&); + + protected: + double m_x1; + double m_y1; + double m_x2; + double m_y2; + + private: + bool m_flip_y; + const trans_affine* m_mtx; + }; + + + //-------------------------------------------------------------------- + template<class Rasterizer, class Scanline, class Renderer, class Ctrl> + void render_ctrl(Rasterizer& ras, Scanline& sl, Renderer& r, Ctrl& c) + { + unsigned i; + for(i = 0; i < c.num_paths(); i++) + { + ras.reset(); + ras.add_path(c, i); + render_scanlines_aa_solid(ras, sl, r, c.color(i)); + } + } + + + //-------------------------------------------------------------------- + template<class Rasterizer, class Scanline, class Renderer, class Ctrl> + void render_ctrl_rs(Rasterizer& ras, Scanline& sl, Renderer& r, Ctrl& c) + { + unsigned i; + for(i = 0; i < c.num_paths(); i++) + { + ras.reset(); + ras.add_path(c, i); + r.color(c.color(i)); + render_scanlines(ras, sl, r); + } + } + + +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/ctrl/agg_gamma_ctrl.h b/jni/desmume/src/android/agg/include/ctrl/agg_gamma_ctrl.h new file mode 100755 index 0000000..158d730 --- /dev/null +++ b/jni/desmume/src/android/agg/include/ctrl/agg_gamma_ctrl.h @@ -0,0 +1,175 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_GAMMA_CTRL_INCLUDED +#define AGG_GAMMA_CTRL_INCLUDED + +#include "agg_basics.h" +#include "agg_gamma_spline.h" +#include "agg_ellipse.h" +#include "agg_conv_stroke.h" +#include "agg_gsv_text.h" +#include "agg_trans_affine.h" +#include "agg_color_rgba.h" +#include "agg_ctrl.h" + +namespace agg +{ + //------------------------------------------------------------------------ + // Class that can be used to create an interactive control to set up + // gamma arrays. + //------------------------------------------------------------------------ + class gamma_ctrl_impl : public ctrl + { + public: + gamma_ctrl_impl(double x1, double y1, double x2, double y2, bool flip_y=false); + + // Set other parameters + void border_width(double t, double extra=0.0); + void curve_width(double t) { m_curve_width = t; } + void grid_width(double t) { m_grid_width = t; } + void text_thickness(double t) { m_text_thickness = t; } + void text_size(double h, double w=0.0); + void point_size(double s) { m_point_size = s; } + + // Event handlers. Just call them if the respective events + // in your system occure. The functions return true if redrawing + // is required. + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + void change_active_point(); + + // A copy of agg::gamma_spline interface + void values(double kx1, double ky1, double kx2, double ky2); + void values(double* kx1, double* ky1, double* kx2, double* ky2) const; + const unsigned char* gamma() const { return m_gamma_spline.gamma(); } + double y(double x) const { return m_gamma_spline.y(x); } + double operator() (double x) const { return m_gamma_spline.y(x); } + const gamma_spline& get_gamma_spline() const { return m_gamma_spline; } + + // Vertex soutce interface + unsigned num_paths() { return 7; } + void rewind(unsigned idx); + unsigned vertex(double* x, double* y); + + private: + void calc_spline_box(); + void calc_points(); + void calc_values(); + + gamma_spline m_gamma_spline; + double m_border_width; + double m_border_extra; + double m_curve_width; + double m_grid_width; + double m_text_thickness; + double m_point_size; + double m_text_height; + double m_text_width; + double m_xc1; + double m_yc1; + double m_xc2; + double m_yc2; + double m_xs1; + double m_ys1; + double m_xs2; + double m_ys2; + double m_xt1; + double m_yt1; + double m_xt2; + double m_yt2; + conv_stroke<gamma_spline> m_curve_poly; + ellipse m_ellipse; + gsv_text m_text; + conv_stroke<gsv_text> m_text_poly; + unsigned m_idx; + unsigned m_vertex; + double m_vx[32]; + double m_vy[32]; + double m_xp1; + double m_yp1; + double m_xp2; + double m_yp2; + bool m_p1_active; + unsigned m_mouse_point; + double m_pdx; + double m_pdy; + }; + + + + template<class ColorT> class gamma_ctrl : public gamma_ctrl_impl + { + public: + gamma_ctrl(double x1, double y1, double x2, double y2, bool flip_y=false) : + gamma_ctrl_impl(x1, y1, x2, y2, flip_y), + m_background_color(rgba(1.0, 1.0, 0.9)), + m_border_color(rgba(0.0, 0.0, 0.0)), + m_curve_color(rgba(0.0, 0.0, 0.0)), + m_grid_color(rgba(0.2, 0.2, 0.0)), + m_inactive_pnt_color(rgba(0.0, 0.0, 0.0)), + m_active_pnt_color(rgba(1.0, 0.0, 0.0)), + m_text_color(rgba(0.0, 0.0, 0.0)) + { + m_colors[0] = &m_background_color; + m_colors[1] = &m_border_color; + m_colors[2] = &m_curve_color; + m_colors[3] = &m_grid_color; + m_colors[4] = &m_inactive_pnt_color; + m_colors[5] = &m_active_pnt_color; + m_colors[6] = &m_text_color; + } + + // Set colors + void background_color(const ColorT& c) { m_background_color = c; } + void border_color(const ColorT& c) { m_border_color = c; } + void curve_color(const ColorT& c) { m_curve_color = c; } + void grid_color(const ColorT& c) { m_grid_color = c; } + void inactive_pnt_color(const ColorT& c) { m_inactive_pnt_color = c; } + void active_pnt_color(const ColorT& c) { m_active_pnt_color = c; } + void text_color(const ColorT& c) { m_text_color = c; } + const ColorT& color(unsigned i) const { return *m_colors[i]; } + + private: + gamma_ctrl(const gamma_ctrl<ColorT>&); + const gamma_ctrl<ColorT>& operator = (const gamma_ctrl<ColorT>&); + + ColorT m_background_color; + ColorT m_border_color; + ColorT m_curve_color; + ColorT m_grid_color; + ColorT m_inactive_pnt_color; + ColorT m_active_pnt_color; + ColorT m_text_color; + ColorT* m_colors[7]; + }; + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/ctrl/agg_gamma_spline.h b/jni/desmume/src/android/agg/include/ctrl/agg_gamma_spline.h new file mode 100755 index 0000000..05b5a05 --- /dev/null +++ b/jni/desmume/src/android/agg/include/ctrl/agg_gamma_spline.h @@ -0,0 +1,100 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_GAMMA_SPLINE_INCLUDED +#define AGG_GAMMA_SPLINE_INCLUDED + +#include "agg_basics.h" +#include "agg_bspline.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + // Class-helper for calculation gamma-correction arrays. A gamma-correction + // array is an array of 256 unsigned chars that determine the actual values + // of Anti-Aliasing for each pixel coverage value from 0 to 255. If all the + // values in the array are equal to its index, i.e. 0,1,2,3,... there's + // no gamma-correction. Class agg::polyfill allows you to use custom + // gamma-correction arrays. You can calculate it using any approach, and + // class gamma_spline allows you to calculate almost any reasonable shape + // of the gamma-curve with using only 4 values - kx1, ky1, kx2, ky2. + // + // kx2 + // +----------------------------------+ + // | | | . | + // | | | . | ky2 + // | | . ------| + // | | . | + // | | . | + // |----------------.|----------------| + // | . | | + // | . | | + // |-------. | | + // ky1 | . | | | + // | . | | | + // +----------------------------------+ + // kx1 + // + // Each value can be in range [0...2]. Value 1.0 means one quarter of the + // bounding rectangle. Function values() calculates the curve by these + // 4 values. After calling it one can get the gamma-array with call gamma(). + // Class also supports the vertex source interface, i.e rewind() and + // vertex(). It's made for convinience and used in class gamma_ctrl. + // Before calling rewind/vertex one must set the bounding box + // box() using pixel coordinates. + //------------------------------------------------------------------------ + + class gamma_spline + { + public: + gamma_spline(); + + void values(double kx1, double ky1, double kx2, double ky2); + const unsigned char* gamma() const { return m_gamma; } + double y(double x) const; + void values(double* kx1, double* ky1, double* kx2, double* ky2) const; + void box(double x1, double y1, double x2, double y2); + + void rewind(unsigned); + unsigned vertex(double* x, double* y); + + private: + unsigned char m_gamma[256]; + double m_x[4]; + double m_y[4]; + bspline m_spline; + double m_x1; + double m_y1; + double m_x2; + double m_y2; + double m_cur_x; + }; + + + + +} + +#endif diff --git a/jni/desmume/src/android/agg/include/ctrl/agg_polygon_ctrl.h b/jni/desmume/src/android/agg/include/ctrl/agg_polygon_ctrl.h new file mode 100755 index 0000000..b1ce199 --- /dev/null +++ b/jni/desmume/src/android/agg/include/ctrl/agg_polygon_ctrl.h @@ -0,0 +1,171 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef POLYGON_CTRL_INCLUDED +#define POLYGON_CTRL_INCLUDED + +#include "agg_array.h" +#include "agg_conv_stroke.h" +#include "agg_ellipse.h" +#include "agg_color_rgba.h" +#include "agg_ctrl.h" + +namespace agg +{ + class simple_polygon_vertex_source + { + public: + simple_polygon_vertex_source(const double* polygon, unsigned np, + bool roundoff = false, + bool close = true) : + m_polygon(polygon), + m_num_points(np), + m_vertex(0), + m_roundoff(roundoff), + m_close(close) + { + } + + void close(bool f) { m_close = f; } + bool close() const { return m_close; } + + void rewind(unsigned) + { + m_vertex = 0; + } + + unsigned vertex(double* x, double* y) + { + if(m_vertex > m_num_points) return path_cmd_stop; + if(m_vertex == m_num_points) + { + ++m_vertex; + return path_cmd_end_poly | (m_close ? path_flags_close : 0); + } + *x = m_polygon[m_vertex * 2]; + *y = m_polygon[m_vertex * 2 + 1]; + if(m_roundoff) + { + *x = floor(*x) + 0.5; + *y = floor(*y) + 0.5; + } + ++m_vertex; + return (m_vertex == 1) ? path_cmd_move_to : path_cmd_line_to; + } + + private: + const double* m_polygon; + unsigned m_num_points; + unsigned m_vertex; + bool m_roundoff; + bool m_close; + }; + + + + + class polygon_ctrl_impl : public ctrl + { + public: + polygon_ctrl_impl(unsigned np, double point_radius=5); + + unsigned num_points() const { return m_num_points; } + double xn(unsigned n) const { return m_polygon[n * 2]; } + double yn(unsigned n) const { return m_polygon[n * 2 + 1]; } + double& xn(unsigned n) { return m_polygon[n * 2]; } + double& yn(unsigned n) { return m_polygon[n * 2 + 1]; } + + const double* polygon() const { return &m_polygon[0]; } + + void line_width(double w) { m_stroke.width(w); } + double line_width() const { return m_stroke.width(); } + + void point_radius(double r) { m_point_radius = r; } + double point_radius() const { return m_point_radius; } + + void in_polygon_check(bool f) { m_in_polygon_check = f; } + bool in_polygon_check() const { return m_in_polygon_check; } + + void close(bool f) { m_vs.close(f); } + bool close() const { return m_vs.close(); } + + // Vertex source interface + unsigned num_paths() { return 1; } + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + + private: + bool check_edge(unsigned i, double x, double y) const; + bool point_in_polygon(double x, double y) const; + + pod_array<double> m_polygon; + unsigned m_num_points; + int m_node; + int m_edge; + simple_polygon_vertex_source m_vs; + conv_stroke<simple_polygon_vertex_source> m_stroke; + ellipse m_ellipse; + double m_point_radius; + unsigned m_status; + double m_dx; + double m_dy; + bool m_in_polygon_check; + }; + + + + //----------------------------------------------------------polygon_ctrl + template<class ColorT> class polygon_ctrl : public polygon_ctrl_impl + { + public: + polygon_ctrl(unsigned np, double point_radius=5) : + polygon_ctrl_impl(np, point_radius), + m_color(rgba(0.0, 0.0, 0.0)) + { + } + + void line_color(const ColorT& c) { m_color = c; } + const ColorT& color(unsigned i) const { return m_color; } + + private: + polygon_ctrl(const polygon_ctrl<ColorT>&); + const polygon_ctrl<ColorT>& operator = (const polygon_ctrl<ColorT>&); + + ColorT m_color; + }; + + + + +} + +#endif + diff --git a/jni/desmume/src/android/agg/include/ctrl/agg_rbox_ctrl.h b/jni/desmume/src/android/agg/include/ctrl/agg_rbox_ctrl.h new file mode 100755 index 0000000..b5b8b3f --- /dev/null +++ b/jni/desmume/src/android/agg/include/ctrl/agg_rbox_ctrl.h @@ -0,0 +1,146 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_RBOX_CTRL_INCLUDED +#define AGG_RBOX_CTRL_INCLUDED + +#include "agg_array.h" +#include "agg_ellipse.h" +#include "agg_conv_stroke.h" +#include "agg_gsv_text.h" +#include "agg_trans_affine.h" +#include "agg_color_rgba.h" +#include "agg_ctrl.h" + + + +namespace agg +{ + + //------------------------------------------------------------------------ + class rbox_ctrl_impl : public ctrl + { + public: + rbox_ctrl_impl(double x1, double y1, double x2, double y2, bool flip_y=false); + + void border_width(double t, double extra=0.0); + void text_thickness(double t) { m_text_thickness = t; } + void text_size(double h, double w=0.0); + + void add_item(const char* text); + int cur_item() const { return m_cur_item; } + void cur_item(int i) { m_cur_item = i; } + + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + // Vertex soutce interface + unsigned num_paths() { return 5; }; + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + void calc_rbox(); + + double m_border_width; + double m_border_extra; + double m_text_thickness; + double m_text_height; + double m_text_width; + pod_array<char> m_items[32]; + unsigned m_num_items; + int m_cur_item; + + double m_xs1; + double m_ys1; + double m_xs2; + double m_ys2; + + double m_vx[32]; + double m_vy[32]; + unsigned m_draw_item; + double m_dy; + + ellipse m_ellipse; + conv_stroke<ellipse> m_ellipse_poly; + gsv_text m_text; + conv_stroke<gsv_text> m_text_poly; + + unsigned m_idx; + unsigned m_vertex; + }; + + + + //------------------------------------------------------------------------ + template<class ColorT> class rbox_ctrl : public rbox_ctrl_impl + { + public: + rbox_ctrl(double x1, double y1, double x2, double y2, bool flip_y=false) : + rbox_ctrl_impl(x1, y1, x2, y2, flip_y), + m_background_color(rgba(1.0, 1.0, 0.9)), + m_border_color(rgba(0.0, 0.0, 0.0)), + m_text_color(rgba(0.0, 0.0, 0.0)), + m_inactive_color(rgba(0.0, 0.0, 0.0)), + m_active_color(rgba(0.4, 0.0, 0.0)) + { + m_colors[0] = &m_background_color; + m_colors[1] = &m_border_color; + m_colors[2] = &m_text_color; + m_colors[3] = &m_inactive_color; + m_colors[4] = &m_active_color; + } + + + void background_color(const ColorT& c) { m_background_color = c; } + void border_color(const ColorT& c) { m_border_color = c; } + void text_color(const ColorT& c) { m_text_color = c; } + void inactive_color(const ColorT& c) { m_inactive_color = c; } + void active_color(const ColorT& c) { m_active_color = c; } + + const ColorT& color(unsigned i) const { return *m_colors[i]; } + + private: + rbox_ctrl(const rbox_ctrl<ColorT>&); + const rbox_ctrl<ColorT>& operator = (const rbox_ctrl<ColorT>&); + + ColorT m_background_color; + ColorT m_border_color; + ColorT m_text_color; + ColorT m_inactive_color; + ColorT m_active_color; + ColorT* m_colors[5]; + }; + + + +} + + + +#endif + diff --git a/jni/desmume/src/android/agg/include/ctrl/agg_scale_ctrl.h b/jni/desmume/src/android/agg/include/ctrl/agg_scale_ctrl.h new file mode 100755 index 0000000..953a12c --- /dev/null +++ b/jni/desmume/src/android/agg/include/ctrl/agg_scale_ctrl.h @@ -0,0 +1,151 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_SCALE_CTRL_INCLUDED +#define AGG_SCALE_CTRL_INCLUDED + +#include "agg_basics.h" +#include "agg_math.h" +#include "agg_ellipse.h" +#include "agg_trans_affine.h" +#include "agg_color_rgba.h" +#include "agg_ctrl.h" + + +namespace agg +{ + + //------------------------------------------------------------------------ + class scale_ctrl_impl : public ctrl + { + enum move_e + { + move_nothing, + move_value1, + move_value2, + move_slider + }; + + public: + scale_ctrl_impl(double x1, double y1, double x2, double y2, bool flip_y=false); + + void border_thickness(double t, double extra=0.0); + void resize(double x1, double y1, double x2, double y2); + + double min_delta() const { return m_min_d; } + void min_delta(double d) { m_min_d = d; } + + double value1() const { return m_value1; } + void value1(double value); + + double value2() const { return m_value2; } + void value2(double value); + + void move(double d); + + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + // Vertex soutce interface + unsigned num_paths() { return 5; }; + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + void calc_box(); + + double m_border_thickness; + double m_border_extra; + double m_value1; + double m_value2; + double m_min_d; + double m_xs1; + double m_ys1; + double m_xs2; + double m_ys2; + double m_pdx; + double m_pdy; + move_e m_move_what; + double m_vx[32]; + double m_vy[32]; + + ellipse m_ellipse; + + unsigned m_idx; + unsigned m_vertex; + + }; + + + + //------------------------------------------------------------------------ + template<class ColorT> class scale_ctrl : public scale_ctrl_impl + { + public: + scale_ctrl(double x1, double y1, double x2, double y2, bool flip_y=false) : + scale_ctrl_impl(x1, y1, x2, y2, flip_y), + m_background_color(rgba(1.0, 0.9, 0.8)), + m_border_color(rgba(0.0, 0.0, 0.0)), + m_pointers_color(rgba(0.8, 0.0, 0.0, 0.8)), + m_slider_color(rgba(0.2, 0.1, 0.0, 0.6)) + { + m_colors[0] = &m_background_color; + m_colors[1] = &m_border_color; + m_colors[2] = &m_pointers_color; + m_colors[3] = &m_pointers_color; + m_colors[4] = &m_slider_color; + } + + + void background_color(const ColorT& c) { m_background_color = c; } + void border_color(const ColorT& c) { m_border_color = c; } + void pointers_color(const ColorT& c) { m_pointers_color = c; } + void slider_color(const ColorT& c) { m_slider_color = c; } + + const ColorT& color(unsigned i) const { return *m_colors[i]; } + + private: + scale_ctrl(const scale_ctrl<ColorT>&); + const scale_ctrl<ColorT>& operator = (const scale_ctrl<ColorT>&); + + ColorT m_background_color; + ColorT m_border_color; + ColorT m_pointers_color; + ColorT m_slider_color; + ColorT* m_colors[5]; + }; + + + + + +} + + + +#endif + diff --git a/jni/desmume/src/android/agg/include/ctrl/agg_slider_ctrl.h b/jni/desmume/src/android/agg/include/ctrl/agg_slider_ctrl.h new file mode 100755 index 0000000..d2fbcde --- /dev/null +++ b/jni/desmume/src/android/agg/include/ctrl/agg_slider_ctrl.h @@ -0,0 +1,155 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_SLIDER_CTRL_INCLUDED +#define AGG_SLIDER_CTRL_INCLUDED + +#include "agg_basics.h" +#include "agg_math.h" +#include "agg_ellipse.h" +#include "agg_trans_affine.h" +#include "agg_color_rgba.h" +#include "agg_gsv_text.h" +#include "agg_conv_stroke.h" +#include "agg_path_storage.h" +#include "agg_ctrl.h" + + +namespace agg +{ + + //--------------------------------------------------------slider_ctrl_impl + class slider_ctrl_impl : public ctrl + { + public: + slider_ctrl_impl(double x1, double y1, double x2, double y2, bool flip_y=false); + + void border_width(double t, double extra=0.0); + + void range(double min, double max) { m_min = min; m_max = max; } + void num_steps(unsigned num) { m_num_steps = num; } + void label(const char* fmt); + void text_thickness(double t) { m_text_thickness = t; } + + bool descending() const { return m_descending; } + void descending(bool v) { m_descending = v; } + + double value() const { return m_value * (m_max - m_min) + m_min; } + void value(double value); + + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + // Vertex source interface + unsigned num_paths() { return 6; }; + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + void calc_box(); + bool normalize_value(bool preview_value_flag); + + double m_border_width; + double m_border_extra; + double m_text_thickness; + double m_value; + double m_preview_value; + double m_min; + double m_max; + unsigned m_num_steps; + bool m_descending; + char m_label[64]; + double m_xs1; + double m_ys1; + double m_xs2; + double m_ys2; + double m_pdx; + bool m_mouse_move; + double m_vx[32]; + double m_vy[32]; + + ellipse m_ellipse; + + unsigned m_idx; + unsigned m_vertex; + + gsv_text m_text; + conv_stroke<gsv_text> m_text_poly; + path_storage m_storage; + + }; + + + + //----------------------------------------------------------slider_ctrl + template<class ColorT> class slider_ctrl : public slider_ctrl_impl + { + public: + slider_ctrl(double x1, double y1, double x2, double y2, bool flip_y=false) : + slider_ctrl_impl(x1, y1, x2, y2, flip_y), + m_background_color(rgba(1.0, 0.9, 0.8)), + m_triangle_color(rgba(0.7, 0.6, 0.6)), + m_text_color(rgba(0.0, 0.0, 0.0)), + m_pointer_preview_color(rgba(0.6, 0.4, 0.4, 0.4)), + m_pointer_color(rgba(0.8, 0.0, 0.0, 0.6)) + { + m_colors[0] = &m_background_color; + m_colors[1] = &m_triangle_color; + m_colors[2] = &m_text_color; + m_colors[3] = &m_pointer_preview_color; + m_colors[4] = &m_pointer_color; + m_colors[5] = &m_text_color; + } + + + void background_color(const ColorT& c) { m_background_color = c; } + void pointer_color(const ColorT& c) { m_pointer_color = c; } + + const ColorT& color(unsigned i) const { return *m_colors[i]; } + + private: + slider_ctrl(const slider_ctrl<ColorT>&); + const slider_ctrl<ColorT>& operator = (const slider_ctrl<ColorT>&); + + ColorT m_background_color; + ColorT m_triangle_color; + ColorT m_text_color; + ColorT m_pointer_preview_color; + ColorT m_pointer_color; + ColorT* m_colors[6]; + }; + + + + + +} + + + +#endif + diff --git a/jni/desmume/src/android/agg/include/ctrl/agg_spline_ctrl.h b/jni/desmume/src/android/agg/include/ctrl/agg_spline_ctrl.h new file mode 100755 index 0000000..b55360e --- /dev/null +++ b/jni/desmume/src/android/agg/include/ctrl/agg_spline_ctrl.h @@ -0,0 +1,164 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_SPLINE_CTRL_INCLUDED +#define AGG_SPLINE_CTRL_INCLUDED + +#include "agg_basics.h" +#include "agg_ellipse.h" +#include "agg_bspline.h" +#include "agg_conv_stroke.h" +#include "agg_path_storage.h" +#include "agg_trans_affine.h" +#include "agg_color_rgba.h" +#include "agg_ctrl.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + // Class that can be used to create an interactive control to set up + // gamma arrays. + //------------------------------------------------------------------------ + class spline_ctrl_impl : public ctrl + { + public: + spline_ctrl_impl(double x1, double y1, double x2, double y2, + unsigned num_pnt, bool flip_y=false); + + // Set other parameters + void border_width(double t, double extra=0.0); + void curve_width(double t) { m_curve_width = t; } + void point_size(double s) { m_point_size = s; } + + // Event handlers. Just call them if the respective events + // in your system occure. The functions return true if redrawing + // is required. + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + void active_point(int i); + + const double* spline() const { return m_spline_values; } + const int8u* spline8() const { return m_spline_values8; } + double value(double x) const; + void value(unsigned idx, double y); + void point(unsigned idx, double x, double y); + void x(unsigned idx, double x) { m_xp[idx] = x; } + void y(unsigned idx, double y) { m_yp[idx] = y; } + double x(unsigned idx) const { return m_xp[idx]; } + double y(unsigned idx) const { return m_yp[idx]; } + void update_spline(); + + // Vertex soutce interface + unsigned num_paths() { return 5; } + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + void calc_spline_box(); + void calc_curve(); + double calc_xp(unsigned idx); + double calc_yp(unsigned idx); + void set_xp(unsigned idx, double val); + void set_yp(unsigned idx, double val); + + unsigned m_num_pnt; + double m_xp[32]; + double m_yp[32]; + bspline m_spline; + double m_spline_values[256]; + int8u m_spline_values8[256]; + double m_border_width; + double m_border_extra; + double m_curve_width; + double m_point_size; + double m_xs1; + double m_ys1; + double m_xs2; + double m_ys2; + path_storage m_curve_pnt; + conv_stroke<path_storage> m_curve_poly; + ellipse m_ellipse; + unsigned m_idx; + unsigned m_vertex; + double m_vx[32]; + double m_vy[32]; + int m_active_pnt; + int m_move_pnt; + double m_pdx; + double m_pdy; + const trans_affine* m_mtx; + }; + + + template<class ColorT> class spline_ctrl : public spline_ctrl_impl + { + public: + spline_ctrl(double x1, double y1, double x2, double y2, + unsigned num_pnt, bool flip_y=false) : + spline_ctrl_impl(x1, y1, x2, y2, num_pnt, flip_y), + m_background_color(rgba(1.0, 1.0, 0.9)), + m_border_color(rgba(0.0, 0.0, 0.0)), + m_curve_color(rgba(0.0, 0.0, 0.0)), + m_inactive_pnt_color(rgba(0.0, 0.0, 0.0)), + m_active_pnt_color(rgba(1.0, 0.0, 0.0)) + { + m_colors[0] = &m_background_color; + m_colors[1] = &m_border_color; + m_colors[2] = &m_curve_color; + m_colors[3] = &m_inactive_pnt_color; + m_colors[4] = &m_active_pnt_color; + } + + // Set colors + void background_color(const ColorT& c) { m_background_color = c; } + void border_color(const ColorT& c) { m_border_color = c; } + void curve_color(const ColorT& c) { m_curve_color = c; } + void inactive_pnt_color(const ColorT& c) { m_inactive_pnt_color = c; } + void active_pnt_color(const ColorT& c) { m_active_pnt_color = c; } + const ColorT& color(unsigned i) const { return *m_colors[i]; } + + private: + spline_ctrl(const spline_ctrl<ColorT>&); + const spline_ctrl<ColorT>& operator = (const spline_ctrl<ColorT>&); + + ColorT m_background_color; + ColorT m_border_color; + ColorT m_curve_color; + ColorT m_inactive_pnt_color; + ColorT m_active_pnt_color; + ColorT* m_colors[5]; + }; + + + + +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/platform/Makefile.am b/jni/desmume/src/android/agg/include/platform/Makefile.am new file mode 100755 index 0000000..0743d29 --- /dev/null +++ b/jni/desmume/src/android/agg/include/platform/Makefile.am @@ -0,0 +1,4 @@ +EXTRA_DIST=win32/agg_win32_bmp.h \ + mac/agg_mac_pmap.h +myincludedir = $(includedir)/agg2/platform +myinclude_HEADERS = agg_platform_support.h diff --git a/jni/desmume/src/android/agg/include/platform/agg_platform_support.h b/jni/desmume/src/android/agg/include/platform/agg_platform_support.h new file mode 100755 index 0000000..3b48d9d --- /dev/null +++ b/jni/desmume/src/android/agg/include/platform/agg_platform_support.h @@ -0,0 +1,680 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// class platform_support +// +// It's not a part of the AGG library, it's just a helper class to create +// interactive demo examples. Since the examples should not be too complex +// this class is provided to support some very basic interactive graphical +// funtionality, such as putting the rendered image to the window, simple +// keyboard and mouse input, window resizing, setting the window title, +// and catching the "idle" events. +// +// The idea is to have a single header file that does not depend on any +// platform (I hate these endless #ifdef/#elif/#elif.../#endif) and a number +// of different implementations depending on the concrete platform. +// The most popular platforms are: +// +// Windows-32 API +// X-Window API +// SDL library (see http://www.libsdl.org/) +// MacOS C/C++ API +// +// This file does not include any system dependent .h files such as +// windows.h or X11.h, so, your demo applications do not depend on the +// platform. The only file that can #include system dependend headers +// is the implementation file agg_platform_support.cpp. Different +// implementations are placed in different directories, such as +// ~/agg/src/platform/win32 +// ~/agg/src/platform/sdl +// ~/agg/src/platform/X11 +// and so on. +// +// All the system dependent stuff sits in the platform_specific +// class which is forward-declared here but not defined. +// The platform_support class has just a pointer to it and it's +// the responsibility of the implementation to create/delete it. +// This class being defined in the implementation file can have +// any platform dependent stuff such as HWND, X11 Window and so on. +// +//---------------------------------------------------------------------------- + + +#ifndef AGG_PLATFORM_SUPPORT_INCLUDED +#define AGG_PLATFORM_SUPPORT_INCLUDED + + +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_trans_viewport.h" +#include "ctrl/agg_ctrl.h" + +namespace agg +{ + + //----------------------------------------------------------window_flag_e + // These are flags used in method init(). Not all of them are + // applicable on different platforms, for example the win32_api + // cannot use a hardware buffer (window_hw_buffer). + // The implementation should simply ignore unsupported flags. + enum window_flag_e + { + window_resize = 1, + window_hw_buffer = 2, + window_keep_aspect_ratio = 4, + window_process_all_keys = 8 + }; + + //-----------------------------------------------------------pix_format_e + // Possible formats of the rendering buffer. Initially I thought that it's + // reasonable to create the buffer and the rendering functions in + // accordance with the native pixel format of the system because it + // would have no overhead for pixel format conersion. + // But eventually I came to a conclusion that having a possibility to + // convert pixel formats on demand is a good idea. First, it was X11 where + // there lots of different formats and visuals and it would be great to + // render everything in, say, RGB-24 and display it automatically without + // any additional efforts. The second reason is to have a possibility to + // debug renderers for different pixel formats and colorspaces having only + // one computer and one system. + // + // This stuff is not included into the basic AGG functionality because the + // number of supported pixel formats (and/or colorspaces) can be great and + // if one needs to add new format it would be good only to add new + // rendering files without having to modify any existing ones (a general + // principle of incapsulation and isolation). + // + // Using a particular pixel format doesn't obligatory mean the necessity + // of software conversion. For example, win32 API can natively display + // gray8, 15-bit RGB, 24-bit BGR, and 32-bit BGRA formats. + // This list can be (and will be!) extended in future. + enum pix_format_e + { + pix_format_undefined = 0, // By default. No conversions are applied + pix_format_bw, // 1 bit per color B/W + pix_format_gray8, // Simple 256 level grayscale + pix_format_gray16, // Simple 65535 level grayscale + pix_format_rgb555, // 15 bit rgb. Depends on the byte ordering! + pix_format_rgb565, // 16 bit rgb. Depends on the byte ordering! + pix_format_rgbAAA, // 30 bit rgb. Depends on the byte ordering! + pix_format_rgbBBA, // 32 bit rgb. Depends on the byte ordering! + pix_format_bgrAAA, // 30 bit bgr. Depends on the byte ordering! + pix_format_bgrABB, // 32 bit bgr. Depends on the byte ordering! + pix_format_rgb24, // R-G-B, one byte per color component + pix_format_bgr24, // B-G-R, native win32 BMP format. + pix_format_rgba32, // R-G-B-A, one byte per color component + pix_format_argb32, // A-R-G-B, native MAC format + pix_format_abgr32, // A-B-G-R, one byte per color component + pix_format_bgra32, // B-G-R-A, native win32 BMP format + pix_format_rgb48, // R-G-B, 16 bits per color component + pix_format_bgr48, // B-G-R, native win32 BMP format. + pix_format_rgba64, // R-G-B-A, 16 bits byte per color component + pix_format_argb64, // A-R-G-B, native MAC format + pix_format_abgr64, // A-B-G-R, one byte per color component + pix_format_bgra64, // B-G-R-A, native win32 BMP format + + end_of_pix_formats + }; + + //-------------------------------------------------------------input_flag_e + // Mouse and keyboard flags. They can be different on different platforms + // and the ways they are obtained are also different. But in any case + // the system dependent flags should be mapped into these ones. The meaning + // of that is as follows. For example, if kbd_ctrl is set it means that the + // ctrl key is pressed and being held at the moment. They are also used in + // the overridden methods such as on_mouse_move(), on_mouse_button_down(), + // on_mouse_button_dbl_click(), on_mouse_button_up(), on_key(). + // In the method on_mouse_button_up() the mouse flags have different + // meaning. They mean that the respective button is being released, but + // the meaning of the keyboard flags remains the same. + // There's absolut minimal set of flags is used because they'll be most + // probably supported on different platforms. Even the mouse_right flag + // is restricted because Mac's mice have only one button, but AFAIK + // it can be simulated with holding a special key on the keydoard. + enum input_flag_e + { + mouse_left = 1, + mouse_right = 2, + kbd_shift = 4, + kbd_ctrl = 8 + }; + + //--------------------------------------------------------------key_code_e + // Keyboard codes. There's also a restricted set of codes that are most + // probably supported on different platforms. Any platform dependent codes + // should be converted into these ones. There're only those codes are + // defined that cannot be represented as printable ASCII-characters. + // All printable ASCII-set can be used in a regular C/C++ manner: + // ' ', 'A', '0' '+' and so on. + // Since the class is used for creating very simple demo-applications + // we don't need very rich possibilities here, just basic ones. + // Actually the numeric key codes are taken from the SDL library, so, + // the implementation of the SDL support does not require any mapping. + enum key_code_e + { + // ASCII set. Should be supported everywhere + key_backspace = 8, + key_tab = 9, + key_clear = 12, + key_return = 13, + key_pause = 19, + key_escape = 27, + + // Keypad + key_delete = 127, + key_kp0 = 256, + key_kp1 = 257, + key_kp2 = 258, + key_kp3 = 259, + key_kp4 = 260, + key_kp5 = 261, + key_kp6 = 262, + key_kp7 = 263, + key_kp8 = 264, + key_kp9 = 265, + key_kp_period = 266, + key_kp_divide = 267, + key_kp_multiply = 268, + key_kp_minus = 269, + key_kp_plus = 270, + key_kp_enter = 271, + key_kp_equals = 272, + + // Arrow-keys and stuff + key_up = 273, + key_down = 274, + key_right = 275, + key_left = 276, + key_insert = 277, + key_home = 278, + key_end = 279, + key_page_up = 280, + key_page_down = 281, + + // Functional keys. You'd better avoid using + // f11...f15 in your applications if you want + // the applications to be portable + key_f1 = 282, + key_f2 = 283, + key_f3 = 284, + key_f4 = 285, + key_f5 = 286, + key_f6 = 287, + key_f7 = 288, + key_f8 = 289, + key_f9 = 290, + key_f10 = 291, + key_f11 = 292, + key_f12 = 293, + key_f13 = 294, + key_f14 = 295, + key_f15 = 296, + + // The possibility of using these keys is + // very restricted. Actually it's guaranteed + // only in win32_api and win32_sdl implementations + key_numlock = 300, + key_capslock = 301, + key_scrollock = 302, + + // Phew! + end_of_key_codes + }; + + + //------------------------------------------------------------------------ + // A predeclaration of the platform dependent class. Since we do not + // know anything here the only we can have is just a pointer to this + // class as a data member. It should be created and destroyed explicitly + // in the constructor/destructor of the platform_support class. + // Although the pointer to platform_specific is public the application + // cannot have access to its members or methods since it does not know + // anything about them and it's a perfect incapsulation :-) + class platform_specific; + + + //----------------------------------------------------------ctrl_container + // A helper class that contains pointers to a number of controls. + // This class is used to ease the event handling with controls. + // The implementation should simply call the appropriate methods + // of this class when appropriate events occur. + class ctrl_container + { + enum max_ctrl_e { max_ctrl = 64 }; + + public: + //-------------------------------------------------------------------- + ctrl_container() : m_num_ctrl(0), m_cur_ctrl(-1) {} + + //-------------------------------------------------------------------- + void add(ctrl& c) + { + if(m_num_ctrl < max_ctrl) + { + m_ctrl[m_num_ctrl++] = &c; + } + } + + //-------------------------------------------------------------------- + bool in_rect(double x, double y) + { + unsigned i; + for(i = 0; i < m_num_ctrl; i++) + { + if(m_ctrl[i]->in_rect(x, y)) return true; + } + return false; + } + + //-------------------------------------------------------------------- + bool on_mouse_button_down(double x, double y) + { + unsigned i; + for(i = 0; i < m_num_ctrl; i++) + { + if(m_ctrl[i]->on_mouse_button_down(x, y)) return true; + } + return false; + } + + //-------------------------------------------------------------------- + bool on_mouse_button_up(double x, double y) + { + unsigned i; + bool flag = false; + for(i = 0; i < m_num_ctrl; i++) + { + if(m_ctrl[i]->on_mouse_button_up(x, y)) flag = true; + } + return flag; + } + + //-------------------------------------------------------------------- + bool on_mouse_move(double x, double y, bool button_flag) + { + unsigned i; + for(i = 0; i < m_num_ctrl; i++) + { + if(m_ctrl[i]->on_mouse_move(x, y, button_flag)) return true; + } + return false; + } + + //-------------------------------------------------------------------- + bool on_arrow_keys(bool left, bool right, bool down, bool up) + { + if(m_cur_ctrl >= 0) + { + return m_ctrl[m_cur_ctrl]->on_arrow_keys(left, right, down, up); + } + return false; + } + + //-------------------------------------------------------------------- + bool set_cur(double x, double y) + { + unsigned i; + for(i = 0; i < m_num_ctrl; i++) + { + if(m_ctrl[i]->in_rect(x, y)) + { + if(m_cur_ctrl != int(i)) + { + m_cur_ctrl = i; + return true; + } + return false; + } + } + if(m_cur_ctrl != -1) + { + m_cur_ctrl = -1; + return true; + } + return false; + } + + private: + ctrl* m_ctrl[max_ctrl]; + unsigned m_num_ctrl; + int m_cur_ctrl; + }; + + + + //---------------------------------------------------------platform_support + // This class is a base one to the apllication classes. It can be used + // as follows: + // + // class the_application : public agg::platform_support + // { + // public: + // the_application(unsigned bpp, bool flip_y) : + // platform_support(bpp, flip_y) + // . . . + // + // //override stuff . . . + // virtual void on_init() + // { + // . . . + // } + // + // virtual void on_draw() + // { + // . . . + // } + // + // virtual void on_resize(int sx, int sy) + // { + // . . . + // } + // // . . . and so on, see virtual functions + // + // + // //any your own stuff . . . + // }; + // + // + // int agg_main(int argc, char* argv[]) + // { + // the_application app(pix_format_rgb24, true); + // app.caption("AGG Example. Lion"); + // + // if(app.init(500, 400, agg::window_resize)) + // { + // return app.run(); + // } + // return 1; + // } + // + // The reason to have agg_main() instead of just main() is that SDL + // for Windows requires including SDL.h if you define main(). Since + // the demo applications cannot rely on any platform/library specific + // stuff it's impossible to include SDL.h into the application files. + // The demo applications are simple and their use is restricted, so, + // this approach is quite reasonable. + // + class platform_support + { + public: + enum max_images_e { max_images = 16 }; + + // format - see enum pix_format_e {}; + // flip_y - true if you want to have the Y-axis flipped vertically. + platform_support(pix_format_e format, bool flip_y); + virtual ~platform_support(); + + // Setting the windows caption (title). Should be able + // to be called at least before calling init(). + // It's perfect if they can be called anytime. + void caption(const char* cap); + const char* caption() const { return m_caption; } + + //-------------------------------------------------------------------- + // These 3 methods handle working with images. The image + // formats are the simplest ones, such as .BMP in Windows or + // .ppm in Linux. In the applications the names of the files + // should not have any file extensions. Method load_img() can + // be called before init(), so, the application could be able + // to determine the initial size of the window depending on + // the size of the loaded image. + // The argument "idx" is the number of the image 0...max_images-1 + bool load_img(unsigned idx, const char* file); + bool save_img(unsigned idx, const char* file); + bool create_img(unsigned idx, unsigned width=0, unsigned height=0); + + //-------------------------------------------------------------------- + // init() and run(). See description before the class for details. + // The necessity of calling init() after creation is that it's + // impossible to call the overridden virtual function (on_init()) + // from the constructor. On the other hand it's very useful to have + // some on_init() event handler when the window is created but + // not yet displayed. The rbuf_window() method (see below) is + // accessible from on_init(). + bool init(unsigned width, unsigned height, unsigned flags); + int run(); + + //-------------------------------------------------------------------- + // The very same parameters that were used in the constructor + pix_format_e format() const { return m_format; } + bool flip_y() const { return m_flip_y; } + unsigned bpp() const { return m_bpp; } + + //-------------------------------------------------------------------- + // The following provides a very simple mechanism of doing someting + // in background. It's not multithreading. When wait_mode is true + // the class waits for the events and it does not ever call on_idle(). + // When it's false it calls on_idle() when the event queue is empty. + // The mode can be changed anytime. This mechanism is satisfactory + // to create very simple animations. + bool wait_mode() const { return m_wait_mode; } + void wait_mode(bool wait_mode) { m_wait_mode = wait_mode; } + + //-------------------------------------------------------------------- + // These two functions control updating of the window. + // force_redraw() is an analog of the Win32 InvalidateRect() function. + // Being called it sets a flag (or sends a message) which results + // in calling on_draw() and updating the content of the window + // when the next event cycle comes. + // update_window() results in just putting immediately the content + // of the currently rendered buffer to the window without calling + // on_draw(). + void force_redraw(); + void update_window(); + + //-------------------------------------------------------------------- + // So, finally, how to draw anythig with AGG? Very simple. + // rbuf_window() returns a reference to the main rendering + // buffer which can be attached to any rendering class. + // rbuf_img() returns a reference to the previously created + // or loaded image buffer (see load_img()). The image buffers + // are not displayed directly, they should be copied to or + // combined somehow with the rbuf_window(). rbuf_window() is + // the only buffer that can be actually displayed. + rendering_buffer& rbuf_window() { return m_rbuf_window; } + rendering_buffer& rbuf_img(unsigned idx) { return m_rbuf_img[idx]; } + + + //-------------------------------------------------------------------- + // Returns file extension used in the implementation for the particular + // system. + const char* img_ext() const; + + //-------------------------------------------------------------------- + void copy_img_to_window(unsigned idx) + { + if(idx < max_images && rbuf_img(idx).buf()) + { + rbuf_window().copy_from(rbuf_img(idx)); + } + } + + //-------------------------------------------------------------------- + void copy_window_to_img(unsigned idx) + { + if(idx < max_images) + { + create_img(idx, rbuf_window().width(), rbuf_window().height()); + rbuf_img(idx).copy_from(rbuf_window()); + } + } + + //-------------------------------------------------------------------- + void copy_img_to_img(unsigned idx_to, unsigned idx_from) + { + if(idx_from < max_images && + idx_to < max_images && + rbuf_img(idx_from).buf()) + { + create_img(idx_to, + rbuf_img(idx_from).width(), + rbuf_img(idx_from).height()); + rbuf_img(idx_to).copy_from(rbuf_img(idx_from)); + } + } + + //-------------------------------------------------------------------- + // Event handlers. They are not pure functions, so you don't have + // to override them all. + // In my demo applications these functions are defined inside + // the the_application class (implicit inlining) which is in general + // very bad practice, I mean vitual inline methods. At least it does + // not make sense. + // But in this case it's quite appropriate bacause we have the only + // instance of the the_application class and it is in the same file + // where this class is defined. + virtual void on_init(); + virtual void on_resize(int sx, int sy); + virtual void on_idle(); + virtual void on_mouse_move(int x, int y, unsigned flags); + virtual void on_mouse_button_down(int x, int y, unsigned flags); + virtual void on_mouse_button_up(int x, int y, unsigned flags); + virtual void on_key(int x, int y, unsigned key, unsigned flags); + virtual void on_ctrl_change(); + virtual void on_draw(); + virtual void on_post_draw(void* raw_handler); + + //-------------------------------------------------------------------- + // Adding control elements. A control element once added will be + // working and reacting to the mouse and keyboard events. Still, you + // will have to render them in the on_draw() using function + // render_ctrl() because platform_support doesn't know anything about + // renderers you use. The controls will be also scaled automatically + // if they provide a proper scaling mechanism (all the controls + // included into the basic AGG package do). + // If you don't need a particular control to be scaled automatically + // call ctrl::no_transform() after adding. + void add_ctrl(ctrl& c) { m_ctrls.add(c); c.transform(m_resize_mtx); } + + //-------------------------------------------------------------------- + // Auxiliary functions. trans_affine_resizing() modifier sets up the resizing + // matrix on the basis of the given width and height and the initial + // width and height of the window. The implementation should simply + // call this function every time when it catches the resizing event + // passing in the new values of width and height of the window. + // Nothing prevents you from "cheating" the scaling matrix if you + // call this function from somewhere with wrong arguments. + // trans_affine_resizing() accessor simply returns current resizing matrix + // which can be used to apply additional scaling of any of your + // stuff when the window is being resized. + // width(), height(), initial_width(), and initial_height() must be + // clear to understand with no comments :-) + void trans_affine_resizing(int width, int height) + { + if(m_window_flags & window_keep_aspect_ratio) + { + //double sx = double(width) / double(m_initial_width); + //double sy = double(height) / double(m_initial_height); + //if(sy < sx) sx = sy; + //m_resize_mtx = trans_affine_scaling(sx, sx); + trans_viewport vp; + vp.preserve_aspect_ratio(0.5, 0.5, aspect_ratio_meet); + vp.device_viewport(0, 0, width, height); + vp.world_viewport(0, 0, m_initial_width, m_initial_height); + m_resize_mtx = vp.to_affine(); + } + else + { + m_resize_mtx = trans_affine_scaling( + double(width) / double(m_initial_width), + double(height) / double(m_initial_height)); + } + } + const trans_affine& trans_affine_resizing() const { return m_resize_mtx; } + double width() const { return m_rbuf_window.width(); } + double height() const { return m_rbuf_window.height(); } + double initial_width() const { return m_initial_width; } + double initial_height() const { return m_initial_height; } + unsigned window_flags() const { return m_window_flags; } + + //-------------------------------------------------------------------- + // Get raw display handler depending on the system. + // For win32 its an HDC, for other systems it can be a pointer to some + // structure. See the implementation files for detals. + // It's provided "as is", so, first you should check if it's not null. + // If it's null the raw_display_handler is not supported. Also, there's + // no guarantee that this function is implemented, so, in some + // implementations you may have simply an unresolved symbol when linking. + void* raw_display_handler(); + + //-------------------------------------------------------------------- + // display message box or print the message to the console + // (depending on implementation) + void message(const char* msg); + + //-------------------------------------------------------------------- + // Stopwatch functions. Function elapsed_time() returns time elapsed + // since the latest start_timer() invocation in millisecods. + // The resolutoin depends on the implementation. + // In Win32 it uses QueryPerformanceFrequency() / QueryPerformanceCounter(). + void start_timer(); + double elapsed_time() const; + + //-------------------------------------------------------------------- + // Get the full file name. In most cases it simply returns + // file_name. As it's appropriate in many systems if you open + // a file by its name without specifying the path, it tries to + // open it in the current directory. The demos usually expect + // all the supplementary files to be placed in the current + // directory, that is usually coincides with the directory where + // the the executable is. However, in some systems (BeOS) it's not so. + // For those kinds of systems full_file_name() can help access files + // preserving commonly used policy. + // So, it's a good idea to use in the demos the following: + // FILE* fd = fopen(full_file_name("some.file"), "r"); + // instead of + // FILE* fd = fopen("some.file", "r"); + const char* full_file_name(const char* file_name); + + public: + platform_specific* m_specific; + ctrl_container m_ctrls; + + // Sorry, I'm too tired to describe the private + // data membders. See the implementations for different + // platforms for details. + private: + platform_support(const platform_support&); + const platform_support& operator = (const platform_support&); + + pix_format_e m_format; + unsigned m_bpp; + rendering_buffer m_rbuf_window; + rendering_buffer m_rbuf_img[max_images]; + unsigned m_window_flags; + bool m_wait_mode; + bool m_flip_y; + char m_caption[256]; + int m_initial_width; + int m_initial_height; + trans_affine m_resize_mtx; + }; + + +} + + + +#endif + diff --git a/jni/desmume/src/android/agg/include/platform/mac/agg_mac_pmap.h b/jni/desmume/src/android/agg/include/platform/mac/agg_mac_pmap.h new file mode 100755 index 0000000..7d52e28 --- /dev/null +++ b/jni/desmume/src/android/agg/include/platform/mac/agg_mac_pmap.h @@ -0,0 +1,92 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Copyright (C) 2002 Hansruedi Baer (MacOS support) +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_MAC_PMAP_INCLUDED +#define AGG_MAC_PMAP_INCLUDED + + +#include <stdio.h> +#include <Carbon.h> + + +namespace agg +{ + enum org_e + { + org_mono8 = 8, + org_color16 = 16, + org_color24 = 24, + org_color32 = 32 + }; + + class pixel_map + { + public: + ~pixel_map(); + pixel_map(); + + public: + void destroy(); + void create(unsigned width, + unsigned height, + org_e org, + unsigned clear_val=255); + + void clear(unsigned clear_val=255); + bool load_from_qt(const char* filename); + bool save_as_qt(const char* filename) const; + + void draw(WindowRef window, + const Rect* device_rect=0, + const Rect* bmp_rect=0) const; + void draw(WindowRef window, int x, int y, double scale=1.0) const; + void blend(WindowRef window, + const Rect* device_rect=0, + const Rect* bmp_rect=0) const; + void blend(WindowRef window, int x, int y, double scale=1.0) const; + + unsigned char* buf(); + unsigned width() const; + unsigned height() const; + int row_bytes() const; + unsigned bpp() const { return m_bpp; } + + //Auxiliary static functions + static unsigned calc_row_len(unsigned width, unsigned bits_per_pixel); + private: + pixel_map(const pixel_map&); + const pixel_map& operator = (const pixel_map&); + + private: + GWorldPtr m_pmap; + unsigned char* m_buf; + unsigned m_bpp; + unsigned m_img_size; + }; + +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/platform/win32/agg_win32_bmp.h b/jni/desmume/src/android/agg/include/platform/win32/agg_win32_bmp.h new file mode 100755 index 0000000..9b9cec6 --- /dev/null +++ b/jni/desmume/src/android/agg/include/platform/win32/agg_win32_bmp.h @@ -0,0 +1,123 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_WIN32_BMP_INCLUDED +#define AGG_WIN32_BMP_INCLUDED + + +#include <windows.h> +#include <stdio.h> + + +namespace agg +{ + enum org_e + { + org_mono8 = 8, + org_color16 = 16, + org_color24 = 24, + org_color32 = 32, + org_color48 = 48, + org_color64 = 64 + }; + + class pixel_map + { + public: + ~pixel_map(); + pixel_map(); + + public: + void destroy(); + void create(unsigned width, + unsigned height, + org_e org, + unsigned clear_val=256); + HBITMAP create_dib_section(HDC h_dc, + unsigned width, + unsigned height, + org_e org, + unsigned clear_val=256); + + void clear(unsigned clear_val=256); + void attach_to_bmp(BITMAPINFO* bmp); + BITMAPINFO* bitmap_info() { return m_bmp; } + bool load_from_bmp(FILE* fd); + bool save_as_bmp(FILE* fd) const; + bool load_from_bmp(const char* filename); + bool save_as_bmp(const char* filename) const; + + void draw(HDC h_dc, + const RECT* device_rect=0, + const RECT* bmp_rect=0) const; + void draw(HDC h_dc, int x, int y, double scale=1.0) const; + + void blend(HDC h_dc, + const RECT* device_rect=0, + const RECT* bmp_rect=0) const; + void blend(HDC h_dc, int x, int y, double scale=1.0) const; + + + unsigned char* buf(); + unsigned width() const; + unsigned height() const; + int stride() const; + unsigned bpp() const { return m_bpp; } + + //Auxiliary static functions + static unsigned calc_full_size(BITMAPINFO *bmp); + static unsigned calc_header_size(BITMAPINFO *bmp); + static unsigned calc_palette_size(unsigned clr_used, + unsigned bits_per_pixel); + static unsigned calc_palette_size(BITMAPINFO *bmp); + static unsigned char* calc_img_ptr(BITMAPINFO *bmp); + static BITMAPINFO* create_bitmap_info(unsigned width, + unsigned height, + unsigned bits_per_pixel); + static void create_gray_scale_palette(BITMAPINFO *bmp); + static unsigned calc_row_len(unsigned width, unsigned bits_per_pixel); + + private: + pixel_map(const pixel_map&); + const pixel_map& operator = (const pixel_map&); + void create_from_bmp(BITMAPINFO *bmp); + + HBITMAP create_dib_section_from_args(HDC h_dc, + unsigned width, + unsigned height, + unsigned bits_per_pixel); + + private: + BITMAPINFO* m_bmp; + unsigned char* m_buf; + unsigned m_bpp; + bool m_is_internal; + unsigned m_img_size; + unsigned m_full_size; + }; + +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/util/Makefile.am b/jni/desmume/src/android/agg/include/util/Makefile.am new file mode 100755 index 0000000..e197c3d --- /dev/null +++ b/jni/desmume/src/android/agg/include/util/Makefile.am @@ -0,0 +1,2 @@ +myincludedir = $(includedir)/agg2/util +myinclude_HEADERS = agg_color_conv.h agg_color_conv_rgb8.h agg_color_conv_rgb16.h diff --git a/jni/desmume/src/android/agg/include/util/agg_color_conv.h b/jni/desmume/src/android/agg/include/util/agg_color_conv.h new file mode 100755 index 0000000..8064977 --- /dev/null +++ b/jni/desmume/src/android/agg/include/util/agg_color_conv.h @@ -0,0 +1,89 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#ifndef AGG_COLOR_CONV_INCLUDED +#define AGG_COLOR_CONV_INCLUDED + +#include <string.h> +#include "agg_basics.h" +#include "agg_rendering_buffer.h" + + + + +namespace agg +{ + + //--------------------------------------------------------------color_conv + template<class RenBuf, class CopyRow> + void color_conv(RenBuf* dst, const RenBuf* src, CopyRow copy_row_functor) + { + unsigned width = src->width(); + unsigned height = src->height(); + + if(dst->width() < width) width = dst->width(); + if(dst->height() < height) height = dst->height(); + + if(width) + { + unsigned y; + for(y = 0; y < height; y++) + { + copy_row_functor(dst->row_ptr(0, y, width), + src->row_ptr(y), + width); + } + } + } + + + //---------------------------------------------------------color_conv_row + template<class CopyRow> + void color_conv_row(int8u* dst, + const int8u* src, + unsigned width, + CopyRow copy_row_functor) + { + copy_row_functor(dst, src, width); + } + + + //---------------------------------------------------------color_conv_same + template<int BPP> class color_conv_same + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + memmove(dst, src, width*BPP); + } + }; + + +} + + + +#endif diff --git a/jni/desmume/src/android/agg/include/util/agg_color_conv_rgb16.h b/jni/desmume/src/android/agg/include/util/agg_color_conv_rgb16.h new file mode 100755 index 0000000..da708bd --- /dev/null +++ b/jni/desmume/src/android/agg/include/util/agg_color_conv_rgb16.h @@ -0,0 +1,294 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// This part of the library has been sponsored by +// Liberty Technology Systems, Inc., visit http://lib-sys.com +// +// Liberty Technology Systems, Inc. is the provider of +// PostScript and PDF technology for software developers. +// +//---------------------------------------------------------------------------- +// +// A set of functors used with color_conv(). See file agg_color_conv.h +// These functors can convert images with up to 8 bits per component. +// Use convertors in the following way: +// +// agg::color_conv(dst, src, agg::color_conv_XXXX_to_YYYY()); +//---------------------------------------------------------------------------- + +#ifndef AGG_COLOR_CONV_RGB16_INCLUDED +#define AGG_COLOR_CONV_RGB16_INCLUDED + +#include "agg_basics.h" +#include "agg_color_conv.h" + +namespace agg +{ + + //-------------------------------------------------color_conv_gray16_to_gray8 + class color_conv_gray16_to_gray8 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + int16u* s = (int16u*)src; + do + { + *dst++ = *s++ >> 8; + } + while(--width); + } + }; + + + //-----------------------------------------------------color_conv_rgb24_rgb48 + template<int I1, int I3> class color_conv_rgb24_rgb48 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + int16u* d = (int16u*)dst; + do + { + *d++ = (src[I1] << 8) | src[I1]; + *d++ = (src[1] << 8) | src[1] ; + *d++ = (src[I3] << 8) | src[I3]; + src += 3; + } + while(--width); + } + }; + + typedef color_conv_rgb24_rgb48<0,2> color_conv_rgb24_to_rgb48; + typedef color_conv_rgb24_rgb48<0,2> color_conv_bgr24_to_bgr48; + typedef color_conv_rgb24_rgb48<2,0> color_conv_rgb24_to_bgr48; + typedef color_conv_rgb24_rgb48<2,0> color_conv_bgr24_to_rgb48; + + + //-----------------------------------------------------color_conv_rgb24_rgb48 + template<int I1, int I3> class color_conv_rgb48_rgb24 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + const int16u* s = (const int16u*)src; + do + { + *dst++ = s[I1] >> 8; + *dst++ = s[1] >> 8; + *dst++ = s[I3] >> 8; + s += 3; + } + while(--width); + } + }; + + typedef color_conv_rgb48_rgb24<0,2> color_conv_rgb48_to_rgb24; + typedef color_conv_rgb48_rgb24<0,2> color_conv_bgr48_to_bgr24; + typedef color_conv_rgb48_rgb24<2,0> color_conv_rgb48_to_bgr24; + typedef color_conv_rgb48_rgb24<2,0> color_conv_bgr48_to_rgb24; + + + //----------------------------------------------color_conv_rgbAAA_rgb24 + template<int R, int B> class color_conv_rgbAAA_rgb24 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + int32u rgb = *(int32u*)src; + dst[R] = int8u(rgb >> 22); + dst[1] = int8u(rgb >> 12); + dst[B] = int8u(rgb >> 2); + src += 4; + dst += 3; + } + while(--width); + } + }; + + typedef color_conv_rgbAAA_rgb24<0,2> color_conv_rgbAAA_to_rgb24; + typedef color_conv_rgbAAA_rgb24<2,0> color_conv_rgbAAA_to_bgr24; + typedef color_conv_rgbAAA_rgb24<2,0> color_conv_bgrAAA_to_rgb24; + typedef color_conv_rgbAAA_rgb24<0,2> color_conv_bgrAAA_to_bgr24; + + + //----------------------------------------------color_conv_rgbBBA_rgb24 + template<int R, int B> class color_conv_rgbBBA_rgb24 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + int32u rgb = *(int32u*)src; + dst[R] = int8u(rgb >> 24); + dst[1] = int8u(rgb >> 13); + dst[B] = int8u(rgb >> 2); + src += 4; + dst += 3; + } + while(--width); + } + }; + + typedef color_conv_rgbBBA_rgb24<0,2> color_conv_rgbBBA_to_rgb24; + typedef color_conv_rgbBBA_rgb24<2,0> color_conv_rgbBBA_to_bgr24; + + + //----------------------------------------------color_conv_bgrABB_rgb24 + template<int B, int R> class color_conv_bgrABB_rgb24 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + int32u bgr = *(int32u*)src; + dst[R] = int8u(bgr >> 3); + dst[1] = int8u(bgr >> 14); + dst[B] = int8u(bgr >> 24); + src += 4; + dst += 3; + } + while(--width); + } + }; + + typedef color_conv_bgrABB_rgb24<2,0> color_conv_bgrABB_to_rgb24; + typedef color_conv_bgrABB_rgb24<0,2> color_conv_bgrABB_to_bgr24; + + + //-------------------------------------------------color_conv_rgba64_rgba32 + template<int I1, int I2, int I3, int I4> class color_conv_rgba64_rgba32 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + *dst++ = int8u(((int16u*)src)[I1] >> 8); + *dst++ = int8u(((int16u*)src)[I2] >> 8); + *dst++ = int8u(((int16u*)src)[I3] >> 8); + *dst++ = int8u(((int16u*)src)[I4] >> 8); + src += 8; + } + while(--width); + } + }; + + //------------------------------------------------------------------------ + typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_rgba64_to_rgba32; //----color_conv_rgba64_to_rgba32 + typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_argb64_to_argb32; //----color_conv_argb64_to_argb32 + typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_bgra64_to_bgra32; //----color_conv_bgra64_to_bgra32 + typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_abgr64_to_abgr32; //----color_conv_abgr64_to_abgr32 + typedef color_conv_rgba64_rgba32<0,3,2,1> color_conv_argb64_to_abgr32; //----color_conv_argb64_to_abgr32 + typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_argb64_to_bgra32; //----color_conv_argb64_to_bgra32 + typedef color_conv_rgba64_rgba32<1,2,3,0> color_conv_argb64_to_rgba32; //----color_conv_argb64_to_rgba32 + typedef color_conv_rgba64_rgba32<3,0,1,2> color_conv_bgra64_to_abgr32; //----color_conv_bgra64_to_abgr32 + typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_bgra64_to_argb32; //----color_conv_bgra64_to_argb32 + typedef color_conv_rgba64_rgba32<2,1,0,3> color_conv_bgra64_to_rgba32; //----color_conv_bgra64_to_rgba32 + typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_rgba64_to_abgr32; //----color_conv_rgba64_to_abgr32 + typedef color_conv_rgba64_rgba32<3,0,1,2> color_conv_rgba64_to_argb32; //----color_conv_rgba64_to_argb32 + typedef color_conv_rgba64_rgba32<2,1,0,3> color_conv_rgba64_to_bgra32; //----color_conv_rgba64_to_bgra32 + typedef color_conv_rgba64_rgba32<0,3,2,1> color_conv_abgr64_to_argb32; //----color_conv_abgr64_to_argb32 + typedef color_conv_rgba64_rgba32<1,2,3,0> color_conv_abgr64_to_bgra32; //----color_conv_abgr64_to_bgra32 + typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_abgr64_to_rgba32; //----color_conv_abgr64_to_rgba32 + + + + //--------------------------------------------color_conv_rgb24_rgba64 + template<int I1, int I2, int I3, int A> class color_conv_rgb24_rgba64 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + int16u* d = (int16u*)dst; + do + { + d[I1] = (src[0] << 8) | src[0]; + d[I2] = (src[1] << 8) | src[1]; + d[I3] = (src[2] << 8) | src[2]; + d[A] = 65535; + d += 4; + src += 3; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgb24_rgba64<1,2,3,0> color_conv_rgb24_to_argb64; //----color_conv_rgb24_to_argb64 + typedef color_conv_rgb24_rgba64<3,2,1,0> color_conv_rgb24_to_abgr64; //----color_conv_rgb24_to_abgr64 + typedef color_conv_rgb24_rgba64<2,1,0,3> color_conv_rgb24_to_bgra64; //----color_conv_rgb24_to_bgra64 + typedef color_conv_rgb24_rgba64<0,1,2,3> color_conv_rgb24_to_rgba64; //----color_conv_rgb24_to_rgba64 + typedef color_conv_rgb24_rgba64<3,2,1,0> color_conv_bgr24_to_argb64; //----color_conv_bgr24_to_argb64 + typedef color_conv_rgb24_rgba64<1,2,3,0> color_conv_bgr24_to_abgr64; //----color_conv_bgr24_to_abgr64 + typedef color_conv_rgb24_rgba64<0,1,2,3> color_conv_bgr24_to_bgra64; //----color_conv_bgr24_to_bgra64 + typedef color_conv_rgb24_rgba64<2,1,0,3> color_conv_bgr24_to_rgba64; //----color_conv_bgr24_to_rgba64 + + + template<int R, int B> class color_conv_rgb24_gray16 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + int16u* d = (int16u*)dst; + do + { + *d++ = src[R]*77 + src[1]*150 + src[B]*29; + src += 3; + } + while(--width); + } + }; + + typedef color_conv_rgb24_gray16<0,2> color_conv_rgb24_to_gray16; + typedef color_conv_rgb24_gray16<2,0> color_conv_bgr24_to_gray16; + + +} + + +#endif diff --git a/jni/desmume/src/android/agg/include/util/agg_color_conv_rgb8.h b/jni/desmume/src/android/agg/include/util/agg_color_conv_rgb8.h new file mode 100755 index 0000000..c09ea7d --- /dev/null +++ b/jni/desmume/src/android/agg/include/util/agg_color_conv_rgb8.h @@ -0,0 +1,478 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// A set of functors used with color_conv(). See file agg_color_conv.h +// These functors can convert images with up to 8 bits per component. +// Use convertors in the following way: +// +// agg::color_conv(dst, src, agg::color_conv_XXXX_to_YYYY()); +// whare XXXX and YYYY can be any of: +// rgb24 +// bgr24 +// rgba32 +// abgr32 +// argb32 +// bgra32 +// rgb555 +// rgb565 +//---------------------------------------------------------------------------- + +#ifndef AGG_COLOR_CONV_RGB8_INCLUDED +#define AGG_COLOR_CONV_RGB8_INCLUDED + +#include "agg_basics.h" +#include "agg_color_conv.h" + +namespace agg +{ + + //-----------------------------------------------------color_conv_rgb24 + class color_conv_rgb24 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + *dst++ = src[2]; + *dst++ = src[1]; + *dst++ = src[0]; + src += 3; + } + while(--width); + } + }; + + typedef color_conv_rgb24 color_conv_rgb24_to_bgr24; + typedef color_conv_rgb24 color_conv_bgr24_to_rgb24; + + typedef color_conv_same<3> color_conv_bgr24_to_bgr24; + typedef color_conv_same<3> color_conv_rgb24_to_rgb24; + + + + //------------------------------------------------------color_conv_rgba32 + template<int I1, int I2, int I3, int I4> class color_conv_rgba32 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + *dst++ = src[I1]; + *dst++ = src[I2]; + *dst++ = src[I3]; + *dst++ = src[I4]; + src += 4; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgba32<0,3,2,1> color_conv_argb32_to_abgr32; //----color_conv_argb32_to_abgr32 + typedef color_conv_rgba32<3,2,1,0> color_conv_argb32_to_bgra32; //----color_conv_argb32_to_bgra32 + typedef color_conv_rgba32<1,2,3,0> color_conv_argb32_to_rgba32; //----color_conv_argb32_to_rgba32 + typedef color_conv_rgba32<3,0,1,2> color_conv_bgra32_to_abgr32; //----color_conv_bgra32_to_abgr32 + typedef color_conv_rgba32<3,2,1,0> color_conv_bgra32_to_argb32; //----color_conv_bgra32_to_argb32 + typedef color_conv_rgba32<2,1,0,3> color_conv_bgra32_to_rgba32; //----color_conv_bgra32_to_rgba32 + typedef color_conv_rgba32<3,2,1,0> color_conv_rgba32_to_abgr32; //----color_conv_rgba32_to_abgr32 + typedef color_conv_rgba32<3,0,1,2> color_conv_rgba32_to_argb32; //----color_conv_rgba32_to_argb32 + typedef color_conv_rgba32<2,1,0,3> color_conv_rgba32_to_bgra32; //----color_conv_rgba32_to_bgra32 + typedef color_conv_rgba32<0,3,2,1> color_conv_abgr32_to_argb32; //----color_conv_abgr32_to_argb32 + typedef color_conv_rgba32<1,2,3,0> color_conv_abgr32_to_bgra32; //----color_conv_abgr32_to_bgra32 + typedef color_conv_rgba32<3,2,1,0> color_conv_abgr32_to_rgba32; //----color_conv_abgr32_to_rgba32 + + //------------------------------------------------------------------------ + typedef color_conv_same<4> color_conv_rgba32_to_rgba32; //----color_conv_rgba32_to_rgba32 + typedef color_conv_same<4> color_conv_argb32_to_argb32; //----color_conv_argb32_to_argb32 + typedef color_conv_same<4> color_conv_bgra32_to_bgra32; //----color_conv_bgra32_to_bgra32 + typedef color_conv_same<4> color_conv_abgr32_to_abgr32; //----color_conv_abgr32_to_abgr32 + + + //--------------------------------------------color_conv_rgb24_rgba32 + template<int I1, int I2, int I3, int A> class color_conv_rgb24_rgba32 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + dst[I1] = *src++; + dst[I2] = *src++; + dst[I3] = *src++; + dst[A] = 255; + dst += 4; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgb24_rgba32<1,2,3,0> color_conv_rgb24_to_argb32; //----color_conv_rgb24_to_argb32 + typedef color_conv_rgb24_rgba32<3,2,1,0> color_conv_rgb24_to_abgr32; //----color_conv_rgb24_to_abgr32 + typedef color_conv_rgb24_rgba32<2,1,0,3> color_conv_rgb24_to_bgra32; //----color_conv_rgb24_to_bgra32 + typedef color_conv_rgb24_rgba32<0,1,2,3> color_conv_rgb24_to_rgba32; //----color_conv_rgb24_to_rgba32 + typedef color_conv_rgb24_rgba32<3,2,1,0> color_conv_bgr24_to_argb32; //----color_conv_bgr24_to_argb32 + typedef color_conv_rgb24_rgba32<1,2,3,0> color_conv_bgr24_to_abgr32; //----color_conv_bgr24_to_abgr32 + typedef color_conv_rgb24_rgba32<0,1,2,3> color_conv_bgr24_to_bgra32; //----color_conv_bgr24_to_bgra32 + typedef color_conv_rgb24_rgba32<2,1,0,3> color_conv_bgr24_to_rgba32; //----color_conv_bgr24_to_rgba32 + + + + //-------------------------------------------------color_conv_rgba32_rgb24 + template<int I1, int I2, int I3> class color_conv_rgba32_rgb24 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + *dst++ = src[I1]; + *dst++ = src[I2]; + *dst++ = src[I3]; + src += 4; + } + while(--width); + } + }; + + + + //------------------------------------------------------------------------ + typedef color_conv_rgba32_rgb24<1,2,3> color_conv_argb32_to_rgb24; //----color_conv_argb32_to_rgb24 + typedef color_conv_rgba32_rgb24<3,2,1> color_conv_abgr32_to_rgb24; //----color_conv_abgr32_to_rgb24 + typedef color_conv_rgba32_rgb24<2,1,0> color_conv_bgra32_to_rgb24; //----color_conv_bgra32_to_rgb24 + typedef color_conv_rgba32_rgb24<0,1,2> color_conv_rgba32_to_rgb24; //----color_conv_rgba32_to_rgb24 + typedef color_conv_rgba32_rgb24<3,2,1> color_conv_argb32_to_bgr24; //----color_conv_argb32_to_bgr24 + typedef color_conv_rgba32_rgb24<1,2,3> color_conv_abgr32_to_bgr24; //----color_conv_abgr32_to_bgr24 + typedef color_conv_rgba32_rgb24<0,1,2> color_conv_bgra32_to_bgr24; //----color_conv_bgra32_to_bgr24 + typedef color_conv_rgba32_rgb24<2,1,0> color_conv_rgba32_to_bgr24; //----color_conv_rgba32_to_bgr24 + + + //------------------------------------------------color_conv_rgb555_rgb24 + template<int R, int B> class color_conv_rgb555_rgb24 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + unsigned rgb = *(int16u*)src; + dst[R] = (int8u)((rgb >> 7) & 0xF8); + dst[1] = (int8u)((rgb >> 2) & 0xF8); + dst[B] = (int8u)((rgb << 3) & 0xF8); + src += 2; + dst += 3; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgb555_rgb24<2,0> color_conv_rgb555_to_bgr24; //----color_conv_rgb555_to_bgr24 + typedef color_conv_rgb555_rgb24<0,2> color_conv_rgb555_to_rgb24; //----color_conv_rgb555_to_rgb24 + + + //-------------------------------------------------color_conv_rgb24_rgb555 + template<int R, int B> class color_conv_rgb24_rgb555 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + *(int16u*)dst = (int16u)(((unsigned(src[R]) << 7) & 0x7C00) | + ((unsigned(src[1]) << 2) & 0x3E0) | + ((unsigned(src[B]) >> 3))); + src += 3; + dst += 2; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgb24_rgb555<2,0> color_conv_bgr24_to_rgb555; //----color_conv_bgr24_to_rgb555 + typedef color_conv_rgb24_rgb555<0,2> color_conv_rgb24_to_rgb555; //----color_conv_rgb24_to_rgb555 + + + //-------------------------------------------------color_conv_rgb565_rgb24 + template<int R, int B> class color_conv_rgb565_rgb24 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + unsigned rgb = *(int16u*)src; + dst[R] = (rgb >> 8) & 0xF8; + dst[1] = (rgb >> 3) & 0xFC; + dst[B] = (rgb << 3) & 0xF8; + src += 2; + dst += 3; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgb565_rgb24<2,0> color_conv_rgb565_to_bgr24; //----color_conv_rgb565_to_bgr24 + typedef color_conv_rgb565_rgb24<0,2> color_conv_rgb565_to_rgb24; //----color_conv_rgb565_to_rgb24 + + + //-------------------------------------------------color_conv_rgb24_rgb565 + template<int R, int B> class color_conv_rgb24_rgb565 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + *(int16u*)dst = (int16u)(((unsigned(src[R]) << 8) & 0xF800) | + ((unsigned(src[1]) << 3) & 0x7E0) | + ((unsigned(src[B]) >> 3))); + src += 3; + dst += 2; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgb24_rgb565<2,0> color_conv_bgr24_to_rgb565; //----color_conv_bgr24_to_rgb565 + typedef color_conv_rgb24_rgb565<0,2> color_conv_rgb24_to_rgb565; //----color_conv_rgb24_to_rgb565 + + + + //-------------------------------------------------color_conv_rgb555_rgba32 + template<int R, int G, int B, int A> class color_conv_rgb555_rgba32 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + int rgb = *(int16*)src; + dst[R] = (int8u)((rgb >> 7) & 0xF8); + dst[G] = (int8u)((rgb >> 2) & 0xF8); + dst[B] = (int8u)((rgb << 3) & 0xF8); + dst[A] = (int8u)(rgb >> 15); + src += 2; + dst += 4; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgb555_rgba32<1,2,3,0> color_conv_rgb555_to_argb32; //----color_conv_rgb555_to_argb32 + typedef color_conv_rgb555_rgba32<3,2,1,0> color_conv_rgb555_to_abgr32; //----color_conv_rgb555_to_abgr32 + typedef color_conv_rgb555_rgba32<2,1,0,3> color_conv_rgb555_to_bgra32; //----color_conv_rgb555_to_bgra32 + typedef color_conv_rgb555_rgba32<0,1,2,3> color_conv_rgb555_to_rgba32; //----color_conv_rgb555_to_rgba32 + + + //------------------------------------------------color_conv_rgba32_rgb555 + template<int R, int G, int B, int A> class color_conv_rgba32_rgb555 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + *(int16u*)dst = (int16u)(((unsigned(src[R]) << 7) & 0x7C00) | + ((unsigned(src[G]) << 2) & 0x3E0) | + ((unsigned(src[B]) >> 3)) | + ((unsigned(src[A]) << 8) & 0x8000)); + src += 4; + dst += 2; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgba32_rgb555<1,2,3,0> color_conv_argb32_to_rgb555; //----color_conv_argb32_to_rgb555 + typedef color_conv_rgba32_rgb555<3,2,1,0> color_conv_abgr32_to_rgb555; //----color_conv_abgr32_to_rgb555 + typedef color_conv_rgba32_rgb555<2,1,0,3> color_conv_bgra32_to_rgb555; //----color_conv_bgra32_to_rgb555 + typedef color_conv_rgba32_rgb555<0,1,2,3> color_conv_rgba32_to_rgb555; //----color_conv_rgba32_to_rgb555 + + + + //------------------------------------------------color_conv_rgb565_rgba32 + template<int R, int G, int B, int A> class color_conv_rgb565_rgba32 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + int rgb = *(int16*)src; + dst[R] = (rgb >> 8) & 0xF8; + dst[G] = (rgb >> 3) & 0xFC; + dst[B] = (rgb << 3) & 0xF8; + dst[A] = 255; + src += 2; + dst += 4; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgb565_rgba32<1,2,3,0> color_conv_rgb565_to_argb32; //----color_conv_rgb565_to_argb32 + typedef color_conv_rgb565_rgba32<3,2,1,0> color_conv_rgb565_to_abgr32; //----color_conv_rgb565_to_abgr32 + typedef color_conv_rgb565_rgba32<2,1,0,3> color_conv_rgb565_to_bgra32; //----color_conv_rgb565_to_bgra32 + typedef color_conv_rgb565_rgba32<0,1,2,3> color_conv_rgb565_to_rgba32; //----color_conv_rgb565_to_rgba32 + + + //------------------------------------------------color_conv_rgba32_rgb565 + template<int R, int G, int B> class color_conv_rgba32_rgb565 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + *(int16u*)dst = (int16u)(((unsigned(src[R]) << 8) & 0xF800) | + ((unsigned(src[G]) << 3) & 0x7E0) | + ((unsigned(src[B]) >> 3))); + src += 4; + dst += 2; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgba32_rgb565<1,2,3> color_conv_argb32_to_rgb565; //----color_conv_argb32_to_rgb565 + typedef color_conv_rgba32_rgb565<3,2,1> color_conv_abgr32_to_rgb565; //----color_conv_abgr32_to_rgb565 + typedef color_conv_rgba32_rgb565<2,1,0> color_conv_bgra32_to_rgb565; //----color_conv_bgra32_to_rgb565 + typedef color_conv_rgba32_rgb565<0,1,2> color_conv_rgba32_to_rgb565; //----color_conv_rgba32_to_rgb565 + + + //---------------------------------------------color_conv_rgb555_to_rgb565 + class color_conv_rgb555_to_rgb565 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + unsigned rgb = *(int16u*)src; + *(int16u*)dst = (int16u)(((rgb << 1) & 0xFFC0) | (rgb & 0x1F)); + src += 2; + dst += 2; + } + while(--width); + } + }; + + + //----------------------------------------------color_conv_rgb565_to_rgb555 + class color_conv_rgb565_to_rgb555 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + unsigned rgb = *(int16u*)src; + *(int16u*)dst = (int16u)(((rgb >> 1) & 0x7FE0) | (rgb & 0x1F)); + src += 2; + dst += 2; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_same<2> color_conv_rgb555_to_rgb555; //----color_conv_rgb555_to_rgb555 + typedef color_conv_same<2> color_conv_rgb565_to_rgb565; //----color_conv_rgb565_to_rgb565 + + + template<int R, int B> class color_conv_rgb24_gray8 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + *dst++ = (src[R]*77 + src[1]*150 + src[B]*29) >> 8; + src += 3; + } + while(--width); + } + }; + + typedef color_conv_rgb24_gray8<0,2> color_conv_rgb24_to_gray8; //----color_conv_rgb24_to_gray8 + typedef color_conv_rgb24_gray8<2,0> color_conv_bgr24_to_gray8; //----color_conv_bgr24_to_gray8 + + +} + + + +#endif diff --git a/jni/desmume/src/android/agg/install b/jni/desmume/src/android/agg/install new file mode 100755 index 0000000..917f846 --- /dev/null +++ b/jni/desmume/src/android/agg/install @@ -0,0 +1,38 @@ +Anti-Grain Geometry is a C++ library distributed in sources +and does not require any installation procedure. The source code +is platform independent and does not have any dependencies on +system APIs (except for very standard C runtime library). +You just take source files and include them into +your project. The sources are maintained to be highly compatible +with most popular C++ compilers, including poor ones, like +Microsoft Visual C++ V6.0. + +On Unix/Linux/MacOS/BeOS/AmigaOS systems you can type "make" to +build src/libagg.a There must be GNU Make utility installed. +Makefiles are very simple, so that if something goes wrong +you could easily fix it. There are no "include files" +dependency suppoeted. +Also note that there's no "make install" option either; +basically the original Makefiles are needed only to build +the examples. + +After building the library you do "cd examples/<YourOS>" and build +the examples in a similar way. + +On most Linux platforms the "automake" environment should work. +It's generously provided by Nikolas Zimmermann, aka WildFox, +who is a key developer of KDE and KSVG. +This process will replace the original Makefiles. + +On Windows there's no library or a DLL created at all. You just +add source files into your project or create a preoject to build +a LIB/DLL if you wish. The problem is that it's very tedious to +maintain building environments for all possible configurations. +I'm sorry for not automating it, but the compensation is that +AGG compiles fine without any hidden problems, nor the neccesity +to configure. +All examples have building environments for Microsoft Visual C++ 6.0 +(.dsp/.dsw) and they are self-sufficient. The newer versions +of the studio can easily convert the projects. + +Also, see "readme" for more details. \ No newline at end of file diff --git a/jni/desmume/src/android/agg/libagg.m4 b/jni/desmume/src/android/agg/libagg.m4 new file mode 100755 index 0000000..d09893d --- /dev/null +++ b/jni/desmume/src/android/agg/libagg.m4 @@ -0,0 +1,34 @@ +# Configure paths for libagg +# Kirill Smelkov 2005-10-23, based on freetype2.m4 by Marcelo Magallon + +# AC_CHECK_LIBAGG([MINIMUM-VERSION [, ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]]]) +# Test for libagg, and define LIBAGG_CFLAGS and LIBAGG_LIBS +# +AC_DEFUN([AC_CHECK_LIBAGG], +[ + # Get the cflags and libraries from pkg-config libagg ... + AC_ARG_WITH([libagg], + AS_HELP_STRING([--with-libagg=PREFIX], + [Prefix where libagg is installed (optional)]), + [libagg_prefix="$withval"], + [libagg_prefix=""]) + + libagg_name=libagg + if test "x$libagg_prefix" != "x"; then + libagg_name="$libagg_prefix/lib/pkgconfig/libagg.pc" + fi + + PKG_CHECK_MODULES([LIBAGG], "$libagg_name", success=yes, success=no) + + if test "x$success" = xyes; then + ifelse([$2], , :, [$2]) + + AC_SUBST([LIBAGG_CFLAGS]) + AC_SUBST([LIBAGG_LIBS]) + else + ifelse([$3], , :, [$3]) + fi +]) + +# end of libagg.m4 + diff --git a/jni/desmume/src/android/agg/libagg.pc.in b/jni/desmume/src/android/agg/libagg.pc.in new file mode 100755 index 0000000..5d465e3 --- /dev/null +++ b/jni/desmume/src/android/agg/libagg.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/agg2 + +Name: libagg +Description: Anti Grain Geometry - A High Quality Rendering Engine for C++ +Version: @VERSION@ +Libs: -L${libdir} -Wl,-rpath,${exec_prefix}/lib -lagg +Cflags: -I${includedir} diff --git a/jni/desmume/src/android/agg/news b/jni/desmume/src/android/agg/news new file mode 100755 index 0000000..9bc083f --- /dev/null +++ b/jni/desmume/src/android/agg/news @@ -0,0 +1 @@ +Visit http://antigrain.com/news \ No newline at end of file diff --git a/jni/desmume/src/android/agg/readme b/jni/desmume/src/android/agg/readme new file mode 100755 index 0000000..ba298b7 --- /dev/null +++ b/jni/desmume/src/android/agg/readme @@ -0,0 +1,75 @@ +Anti-Grain Geometry (AGG) - Version 2.5 +A high quality rendering engine for C++ +Copyright (C) 2002-2006 Maxim Shemanarev +Contact: mcseem@antigrain.com + mcseemagg@yahoo.com + http://antigrain.com + +AGG 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. + +AGG 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 AGG; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +MA 02110-1301, USA. + + + +--------------------------------- + +Use automake to build the library. + +If automake is not available you still can use the old make. +There is a very simple Makefile that can be used. Note that +if you use automake it will overwrite Makefile. + +--------------------------------- + +If building on AmigaOS 4.0 or higher type the following for +instructions on what targets are available. + make -f Makefile.AmigaOS + +To just build and install AGG into the standard AmigaOS SDK +ready for use type: + make -f Makefile.AmigaOS install + +If you just want to build one demo (e.g. lion) use: + make -f Makefile.AmigaOS bin/lion + +If you have any questions about the AmigaOS port please +contact Steven Solie (ssolie@telus.net) for help. + +--------------------------------- + +To build all examples using SDL (Mac or Linux) just type: + +cd /examples/sdl +make + +Individual examples can be built with + +make aa_test + +In the same way the native Carbon examples can be built with + +cd /examples/macosx_carbon +make + +In both cases the static library will be built (if it was not already) +from the existing global Makefile in /src/. + +The Makefiles for both SDL and Carbon will also attempt to download the +required .bmp files if they are not found in the system for a given +example. If the files could not be fetched (wget) the user will receive +a message explaining where to download the samples from (sphere.bmp, +etc.) Since all programs reside in the same directory there is no need +to duplicate the .bmp files for each program that needs to use them. + +--------------------------------- diff --git a/jni/desmume/src/android/agg/src/ChangeLog b/jni/desmume/src/android/agg/src/ChangeLog new file mode 100755 index 0000000..e69de29 diff --git a/jni/desmume/src/android/agg/src/Makefile b/jni/desmume/src/android/agg/src/Makefile new file mode 100755 index 0000000..271bbd0 --- /dev/null +++ b/jni/desmume/src/android/agg/src/Makefile @@ -0,0 +1,59 @@ +include ../Makefile.in.$(shell uname) + +CXXFLAGS= $(AGGCXXFLAGS) -I../include -L./ + +SRC_CXX=\ +agg_arc.cpp \ +agg_arrowhead.cpp \ +agg_bezier_arc.cpp \ +agg_bspline.cpp \ +agg_curves.cpp \ +agg_vcgen_contour.cpp \ +agg_vcgen_dash.cpp \ +agg_vcgen_markers_term.cpp \ +agg_vcgen_smooth_poly1.cpp \ +agg_vcgen_stroke.cpp \ +agg_vcgen_bspline.cpp \ +agg_gsv_text.cpp \ +agg_image_filters.cpp \ +agg_line_aa_basics.cpp \ +agg_line_profile_aa.cpp \ +agg_rounded_rect.cpp \ +agg_sqrt_tables.cpp \ +agg_embedded_raster_fonts.cpp \ +agg_trans_affine.cpp \ +agg_trans_warp_magnifier.cpp \ +agg_trans_single_path.cpp \ +agg_trans_double_path.cpp \ +agg_vpgen_clip_polygon.cpp \ +agg_vpgen_clip_polyline.cpp \ +agg_vpgen_segmentator.cpp \ +ctrl/agg_cbox_ctrl.cpp \ +ctrl/agg_gamma_ctrl.cpp \ +ctrl/agg_gamma_spline.cpp \ +ctrl/agg_rbox_ctrl.cpp \ +ctrl/agg_slider_ctrl.cpp \ +ctrl/agg_spline_ctrl.cpp \ +ctrl/agg_scale_ctrl.cpp \ +ctrl/agg_polygon_ctrl.cpp \ +ctrl/agg_bezier_ctrl.cpp + +SRC_C=\ +../gpc/gpc.c + + +OBJ=$(SRC_CXX:.cpp=.o) $(SRC_C:.c=.o) + +all: $(OBJ) + $(LIB) libagg.a $(OBJ) + +clean: + rm -f *.o *.a ctrl/*.o ../gpc/*.o + rm -rf SunWS_cache + rm -rf ctrl/SunWS_cache + +%.o: %.cpp + $(CXX) -c $(CXXFLAGS) $*.cpp -o $@ + +%.o: %.c + $(C) -c $(CXXFLAGS) $*.c -o $@ diff --git a/jni/desmume/src/android/agg/src/Makefile.am b/jni/desmume/src/android/agg/src/Makefile.am new file mode 100755 index 0000000..0492034 --- /dev/null +++ b/jni/desmume/src/android/agg/src/Makefile.am @@ -0,0 +1,47 @@ +SUBDIRS = ctrl . platform + +INCLUDES = -I$(top_srcdir)/include + +lib_LTLIBRARIES = libagg.la + +libagg_la_LDFLAGS = -no-undefined -version-info @AGG_LIB_VERSION@ +libagg_la_SOURCES = agg_arc.cpp \ + agg_arrowhead.cpp \ + agg_bezier_arc.cpp \ + agg_bspline.cpp \ + agg_curves.cpp \ + agg_embedded_raster_fonts.cpp \ + agg_gsv_text.cpp \ + agg_image_filters.cpp \ + agg_line_aa_basics.cpp \ + agg_line_profile_aa.cpp \ + agg_rounded_rect.cpp \ + agg_sqrt_tables.cpp \ + agg_trans_affine.cpp \ + agg_trans_double_path.cpp \ + agg_trans_single_path.cpp \ + agg_trans_warp_magnifier.cpp \ + agg_vcgen_bspline.cpp \ + agg_vcgen_contour.cpp \ + agg_vcgen_dash.cpp \ + agg_vcgen_markers_term.cpp \ + agg_vcgen_smooth_poly1.cpp \ + agg_vcgen_stroke.cpp \ + agg_vpgen_clip_polygon.cpp \ + agg_vpgen_clip_polyline.cpp \ + agg_vpgen_segmentator.cpp + +if ENABLE_GPC +GPCLD=$(top_builddir)/gpc/libagggpc.la +else +GPCLD= +endif + +if ENABLE_CTRL +CTRLLD=$(top_builddir)/src/ctrl/libaggctrl.la +else +CTRLLD= +endif + +libagg_la_LIBADD = $(GPCLD) $(CTRLLD) + diff --git a/jni/desmume/src/android/agg/src/agg_arc.cpp b/jni/desmume/src/android/agg/src/agg_arc.cpp new file mode 100755 index 0000000..b710d30 --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_arc.cpp @@ -0,0 +1,111 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <math.h> +#include "agg_arc.h" + + +namespace agg +{ + //------------------------------------------------------------------------ + arc::arc(double x, double y, + double rx, double ry, + double a1, double a2, + bool ccw) : + m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_scale(1.0) + { + normalize(a1, a2, ccw); + } + + //------------------------------------------------------------------------ + void arc::init(double x, double y, + double rx, double ry, + double a1, double a2, + bool ccw) + { + m_x = x; m_y = y; + m_rx = rx; m_ry = ry; + normalize(a1, a2, ccw); + } + + //------------------------------------------------------------------------ + void arc::approximation_scale(double s) + { + m_scale = s; + if(m_initialized) + { + normalize(m_start, m_end, m_ccw); + } + } + + //------------------------------------------------------------------------ + void arc::rewind(unsigned) + { + m_path_cmd = path_cmd_move_to; + m_angle = m_start; + } + + //------------------------------------------------------------------------ + unsigned arc::vertex(double* x, double* y) + { + if(is_stop(m_path_cmd)) return path_cmd_stop; + if((m_angle < m_end - m_da/4) != m_ccw) + { + *x = m_x + cos(m_end) * m_rx; + *y = m_y + sin(m_end) * m_ry; + m_path_cmd = path_cmd_stop; + return path_cmd_line_to; + } + + *x = m_x + cos(m_angle) * m_rx; + *y = m_y + sin(m_angle) * m_ry; + + m_angle += m_da; + + unsigned pf = m_path_cmd; + m_path_cmd = path_cmd_line_to; + return pf; + } + + //------------------------------------------------------------------------ + void arc::normalize(double a1, double a2, bool ccw) + { + double ra = (fabs(m_rx) + fabs(m_ry)) / 2; + m_da = acos(ra / (ra + 0.125 / m_scale)) * 2; + if(ccw) + { + while(a2 < a1) a2 += pi * 2.0; + } + else + { + while(a1 < a2) a1 += pi * 2.0; + m_da = -m_da; + } + m_ccw = ccw; + m_start = a1; + m_end = a2; + m_initialized = true; + } + +} diff --git a/jni/desmume/src/android/agg/src/agg_arrowhead.cpp b/jni/desmume/src/android/agg/src/agg_arrowhead.cpp new file mode 100755 index 0000000..1eea004 --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_arrowhead.cpp @@ -0,0 +1,115 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include "agg_arrowhead.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + arrowhead::arrowhead() : + m_head_d1(1.0), + m_head_d2(1.0), + m_head_d3(1.0), + m_head_d4(0.0), + m_tail_d1(1.0), + m_tail_d2(1.0), + m_tail_d3(1.0), + m_tail_d4(0.0), + m_head_flag(false), + m_tail_flag(false), + m_curr_id(0), + m_curr_coord(0) + { + } + + + + //------------------------------------------------------------------------ + void arrowhead::rewind(unsigned path_id) + { + m_curr_id = path_id; + m_curr_coord = 0; + if(path_id == 0) + { + if(!m_tail_flag) + { + m_cmd[0] = path_cmd_stop; + return; + } + m_coord[0] = m_tail_d1; m_coord[1] = 0.0; + m_coord[2] = m_tail_d1 - m_tail_d4; m_coord[3] = m_tail_d3; + m_coord[4] = -m_tail_d2 - m_tail_d4; m_coord[5] = m_tail_d3; + m_coord[6] = -m_tail_d2; m_coord[7] = 0.0; + m_coord[8] = -m_tail_d2 - m_tail_d4; m_coord[9] = -m_tail_d3; + m_coord[10] = m_tail_d1 - m_tail_d4; m_coord[11] = -m_tail_d3; + + m_cmd[0] = path_cmd_move_to; + m_cmd[1] = path_cmd_line_to; + m_cmd[2] = path_cmd_line_to; + m_cmd[3] = path_cmd_line_to; + m_cmd[4] = path_cmd_line_to; + m_cmd[5] = path_cmd_line_to; + m_cmd[7] = path_cmd_end_poly | path_flags_close | path_flags_ccw; + m_cmd[6] = path_cmd_stop; + return; + } + + if(path_id == 1) + { + if(!m_head_flag) + { + m_cmd[0] = path_cmd_stop; + return; + } + m_coord[0] = -m_head_d1; m_coord[1] = 0.0; + m_coord[2] = m_head_d2 + m_head_d4; m_coord[3] = -m_head_d3; + m_coord[4] = m_head_d2; m_coord[5] = 0.0; + m_coord[6] = m_head_d2 + m_head_d4; m_coord[7] = m_head_d3; + + m_cmd[0] = path_cmd_move_to; + m_cmd[1] = path_cmd_line_to; + m_cmd[2] = path_cmd_line_to; + m_cmd[3] = path_cmd_line_to; + m_cmd[4] = path_cmd_end_poly | path_flags_close | path_flags_ccw; + m_cmd[5] = path_cmd_stop; + return; + } + } + + + //------------------------------------------------------------------------ + unsigned arrowhead::vertex(double* x, double* y) + { + if(m_curr_id < 2) + { + unsigned curr_idx = m_curr_coord * 2; + *x = m_coord[curr_idx]; + *y = m_coord[curr_idx + 1]; + return m_cmd[m_curr_coord++]; + } + return path_cmd_stop; + } + +} diff --git a/jni/desmume/src/android/agg/src/agg_bezier_arc.cpp b/jni/desmume/src/android/agg/src/agg_bezier_arc.cpp new file mode 100755 index 0000000..8d5425a --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_bezier_arc.cpp @@ -0,0 +1,261 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <math.h> +#include "agg_bezier_arc.h" + + +namespace agg +{ + + // This epsilon is used to prevent us from adding degenerate curves + // (converging to a single point). + // The value isn't very critical. Function arc_to_bezier() has a limit + // of the sweep_angle. If fabs(sweep_angle) exceeds pi/2 the curve + // becomes inaccurate. But slight exceeding is quite appropriate. + //-------------------------------------------------bezier_arc_angle_epsilon + const double bezier_arc_angle_epsilon = 0.01; + + //------------------------------------------------------------arc_to_bezier + void arc_to_bezier(double cx, double cy, double rx, double ry, + double start_angle, double sweep_angle, + double* curve) + { + double x0 = cos(sweep_angle / 2.0); + double y0 = sin(sweep_angle / 2.0); + double tx = (1.0 - x0) * 4.0 / 3.0; + double ty = y0 - tx * x0 / y0; + double px[4]; + double py[4]; + px[0] = x0; + py[0] = -y0; + px[1] = x0 + tx; + py[1] = -ty; + px[2] = x0 + tx; + py[2] = ty; + px[3] = x0; + py[3] = y0; + + double sn = sin(start_angle + sweep_angle / 2.0); + double cs = cos(start_angle + sweep_angle / 2.0); + + unsigned i; + for(i = 0; i < 4; i++) + { + curve[i * 2] = cx + rx * (px[i] * cs - py[i] * sn); + curve[i * 2 + 1] = cy + ry * (px[i] * sn + py[i] * cs); + } + } + + + + //------------------------------------------------------------------------ + void bezier_arc::init(double x, double y, + double rx, double ry, + double start_angle, + double sweep_angle) + { + start_angle = fmod(start_angle, 2.0 * pi); + if(sweep_angle >= 2.0 * pi) sweep_angle = 2.0 * pi; + if(sweep_angle <= -2.0 * pi) sweep_angle = -2.0 * pi; + + if(fabs(sweep_angle) < 1e-10) + { + m_num_vertices = 4; + m_cmd = path_cmd_line_to; + m_vertices[0] = x + rx * cos(start_angle); + m_vertices[1] = y + ry * sin(start_angle); + m_vertices[2] = x + rx * cos(start_angle + sweep_angle); + m_vertices[3] = y + ry * sin(start_angle + sweep_angle); + return; + } + + double total_sweep = 0.0; + double local_sweep = 0.0; + double prev_sweep; + m_num_vertices = 2; + m_cmd = path_cmd_curve4; + bool done = false; + do + { + if(sweep_angle < 0.0) + { + prev_sweep = total_sweep; + local_sweep = -pi * 0.5; + total_sweep -= pi * 0.5; + if(total_sweep <= sweep_angle + bezier_arc_angle_epsilon) + { + local_sweep = sweep_angle - prev_sweep; + done = true; + } + } + else + { + prev_sweep = total_sweep; + local_sweep = pi * 0.5; + total_sweep += pi * 0.5; + if(total_sweep >= sweep_angle - bezier_arc_angle_epsilon) + { + local_sweep = sweep_angle - prev_sweep; + done = true; + } + } + + arc_to_bezier(x, y, rx, ry, + start_angle, + local_sweep, + m_vertices + m_num_vertices - 2); + + m_num_vertices += 6; + start_angle += local_sweep; + } + while(!done && m_num_vertices < 26); + } + + + + + //-------------------------------------------------------------------- + void bezier_arc_svg::init(double x0, double y0, + double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double x2, double y2) + { + m_radii_ok = true; + + if(rx < 0.0) rx = -rx; + if(ry < 0.0) ry = -rx; + + // Calculate the middle point between + // the current and the final points + //------------------------ + double dx2 = (x0 - x2) / 2.0; + double dy2 = (y0 - y2) / 2.0; + + double cos_a = cos(angle); + double sin_a = sin(angle); + + // Calculate (x1, y1) + //------------------------ + double x1 = cos_a * dx2 + sin_a * dy2; + double y1 = -sin_a * dx2 + cos_a * dy2; + + // Ensure radii are large enough + //------------------------ + double prx = rx * rx; + double pry = ry * ry; + double px1 = x1 * x1; + double py1 = y1 * y1; + + // Check that radii are large enough + //------------------------ + double radii_check = px1/prx + py1/pry; + if(radii_check > 1.0) + { + rx = sqrt(radii_check) * rx; + ry = sqrt(radii_check) * ry; + prx = rx * rx; + pry = ry * ry; + if(radii_check > 10.0) m_radii_ok = false; + } + + // Calculate (cx1, cy1) + //------------------------ + double sign = (large_arc_flag == sweep_flag) ? -1.0 : 1.0; + double sq = (prx*pry - prx*py1 - pry*px1) / (prx*py1 + pry*px1); + double coef = sign * sqrt((sq < 0) ? 0 : sq); + double cx1 = coef * ((rx * y1) / ry); + double cy1 = coef * -((ry * x1) / rx); + + // + // Calculate (cx, cy) from (cx1, cy1) + //------------------------ + double sx2 = (x0 + x2) / 2.0; + double sy2 = (y0 + y2) / 2.0; + double cx = sx2 + (cos_a * cx1 - sin_a * cy1); + double cy = sy2 + (sin_a * cx1 + cos_a * cy1); + + // Calculate the start_angle (angle1) and the sweep_angle (dangle) + //------------------------ + double ux = (x1 - cx1) / rx; + double uy = (y1 - cy1) / ry; + double vx = (-x1 - cx1) / rx; + double vy = (-y1 - cy1) / ry; + double p, n; + + // Calculate the angle start + //------------------------ + n = sqrt(ux*ux + uy*uy); + p = ux; // (1 * ux) + (0 * uy) + sign = (uy < 0) ? -1.0 : 1.0; + double v = p / n; + if(v < -1.0) v = -1.0; + if(v > 1.0) v = 1.0; + double start_angle = sign * acos(v); + + // Calculate the sweep angle + //------------------------ + n = sqrt((ux*ux + uy*uy) * (vx*vx + vy*vy)); + p = ux * vx + uy * vy; + sign = (ux * vy - uy * vx < 0) ? -1.0 : 1.0; + v = p / n; + if(v < -1.0) v = -1.0; + if(v > 1.0) v = 1.0; + double sweep_angle = sign * acos(v); + if(!sweep_flag && sweep_angle > 0) + { + sweep_angle -= pi * 2.0; + } + else + if (sweep_flag && sweep_angle < 0) + { + sweep_angle += pi * 2.0; + } + + // We can now build and transform the resulting arc + //------------------------ + m_arc.init(0.0, 0.0, rx, ry, start_angle, sweep_angle); + trans_affine mtx = trans_affine_rotation(angle); + mtx *= trans_affine_translation(cx, cy); + + for(unsigned i = 2; i < m_arc.num_vertices()-2; i += 2) + { + mtx.transform(m_arc.vertices() + i, m_arc.vertices() + i + 1); + } + + // We must make sure that the starting and ending points + // exactly coincide with the initial (x0,y0) and (x2,y2) + m_arc.vertices()[0] = x0; + m_arc.vertices()[1] = y0; + if(m_arc.num_vertices() > 2) + { + m_arc.vertices()[m_arc.num_vertices() - 2] = x2; + m_arc.vertices()[m_arc.num_vertices() - 1] = y2; + } + } + + +} diff --git a/jni/desmume/src/android/agg/src/agg_bspline.cpp b/jni/desmume/src/android/agg/src/agg_bspline.cpp new file mode 100755 index 0000000..48b7038 --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_bspline.cpp @@ -0,0 +1,289 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include "agg_bspline.h" + +namespace agg +{ + //------------------------------------------------------------------------ + bspline::bspline() : + m_max(0), + m_num(0), + m_x(0), + m_y(0), + m_last_idx(-1) + { + } + + //------------------------------------------------------------------------ + bspline::bspline(int num) : + m_max(0), + m_num(0), + m_x(0), + m_y(0), + m_last_idx(-1) + { + init(num); + } + + //------------------------------------------------------------------------ + bspline::bspline(int num, const double* x, const double* y) : + m_max(0), + m_num(0), + m_x(0), + m_y(0), + m_last_idx(-1) + { + init(num, x, y); + } + + + //------------------------------------------------------------------------ + void bspline::init(int max) + { + if(max > 2 && max > m_max) + { + m_am.resize(max * 3); + m_max = max; + m_x = &m_am[m_max]; + m_y = &m_am[m_max * 2]; + } + m_num = 0; + m_last_idx = -1; + } + + + //------------------------------------------------------------------------ + void bspline::add_point(double x, double y) + { + if(m_num < m_max) + { + m_x[m_num] = x; + m_y[m_num] = y; + ++m_num; + } + } + + + //------------------------------------------------------------------------ + void bspline::prepare() + { + if(m_num > 2) + { + int i, k, n1; + double* temp; + double* r; + double* s; + double h, p, d, f, e; + + for(k = 0; k < m_num; k++) + { + m_am[k] = 0.0; + } + + n1 = 3 * m_num; + + pod_array<double> al(n1); + temp = &al[0]; + + for(k = 0; k < n1; k++) + { + temp[k] = 0.0; + } + + r = temp + m_num; + s = temp + m_num * 2; + + n1 = m_num - 1; + d = m_x[1] - m_x[0]; + e = (m_y[1] - m_y[0]) / d; + + for(k = 1; k < n1; k++) + { + h = d; + d = m_x[k + 1] - m_x[k]; + f = e; + e = (m_y[k + 1] - m_y[k]) / d; + al[k] = d / (d + h); + r[k] = 1.0 - al[k]; + s[k] = 6.0 * (e - f) / (h + d); + } + + for(k = 1; k < n1; k++) + { + p = 1.0 / (r[k] * al[k - 1] + 2.0); + al[k] *= -p; + s[k] = (s[k] - r[k] * s[k - 1]) * p; + } + + m_am[n1] = 0.0; + al[n1 - 1] = s[n1 - 1]; + m_am[n1 - 1] = al[n1 - 1]; + + for(k = n1 - 2, i = 0; i < m_num - 2; i++, k--) + { + al[k] = al[k] * al[k + 1] + s[k]; + m_am[k] = al[k]; + } + } + m_last_idx = -1; + } + + + + //------------------------------------------------------------------------ + void bspline::init(int num, const double* x, const double* y) + { + if(num > 2) + { + init(num); + int i; + for(i = 0; i < num; i++) + { + add_point(*x++, *y++); + } + prepare(); + } + m_last_idx = -1; + } + + + //------------------------------------------------------------------------ + void bspline::bsearch(int n, const double *x, double x0, int *i) + { + int j = n - 1; + int k; + + for(*i = 0; (j - *i) > 1; ) + { + if(x0 < x[k = (*i + j) >> 1]) j = k; + else *i = k; + } + } + + + + //------------------------------------------------------------------------ + double bspline::interpolation(double x, int i) const + { + int j = i + 1; + double d = m_x[i] - m_x[j]; + double h = x - m_x[j]; + double r = m_x[i] - x; + double p = d * d / 6.0; + return (m_am[j] * r * r * r + m_am[i] * h * h * h) / 6.0 / d + + ((m_y[j] - m_am[j] * p) * r + (m_y[i] - m_am[i] * p) * h) / d; + } + + + //------------------------------------------------------------------------ + double bspline::extrapolation_left(double x) const + { + double d = m_x[1] - m_x[0]; + return (-d * m_am[1] / 6 + (m_y[1] - m_y[0]) / d) * + (x - m_x[0]) + + m_y[0]; + } + + //------------------------------------------------------------------------ + double bspline::extrapolation_right(double x) const + { + double d = m_x[m_num - 1] - m_x[m_num - 2]; + return (d * m_am[m_num - 2] / 6 + (m_y[m_num - 1] - m_y[m_num - 2]) / d) * + (x - m_x[m_num - 1]) + + m_y[m_num - 1]; + } + + //------------------------------------------------------------------------ + double bspline::get(double x) const + { + if(m_num > 2) + { + int i; + + // Extrapolation on the left + if(x < m_x[0]) return extrapolation_left(x); + + // Extrapolation on the right + if(x >= m_x[m_num - 1]) return extrapolation_right(x); + + // Interpolation + bsearch(m_num, m_x, x, &i); + return interpolation(x, i); + } + return 0.0; + } + + + //------------------------------------------------------------------------ + double bspline::get_stateful(double x) const + { + if(m_num > 2) + { + // Extrapolation on the left + if(x < m_x[0]) return extrapolation_left(x); + + // Extrapolation on the right + if(x >= m_x[m_num - 1]) return extrapolation_right(x); + + if(m_last_idx >= 0) + { + // Check if x is not in current range + if(x < m_x[m_last_idx] || x > m_x[m_last_idx + 1]) + { + // Check if x between next points (most probably) + if(m_last_idx < m_num - 2 && + x >= m_x[m_last_idx + 1] && + x <= m_x[m_last_idx + 2]) + { + ++m_last_idx; + } + else + if(m_last_idx > 0 && + x >= m_x[m_last_idx - 1] && + x <= m_x[m_last_idx]) + { + // x is between pevious points + --m_last_idx; + } + else + { + // Else perform full search + bsearch(m_num, m_x, x, &m_last_idx); + } + } + return interpolation(x, m_last_idx); + } + else + { + // Interpolation + bsearch(m_num, m_x, x, &m_last_idx); + return interpolation(x, m_last_idx); + } + } + return 0.0; + } + +} + diff --git a/jni/desmume/src/android/agg/src/agg_curves.cpp b/jni/desmume/src/android/agg/src/agg_curves.cpp new file mode 100755 index 0000000..5d4a9eb --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_curves.cpp @@ -0,0 +1,620 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <math.h> +#include "agg_curves.h" +#include "agg_math.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + const double curve_distance_epsilon = 1e-30; + const double curve_collinearity_epsilon = 1e-30; + const double curve_angle_tolerance_epsilon = 0.01; + enum curve_recursion_limit_e { curve_recursion_limit = 32 }; + + + + //------------------------------------------------------------------------ + void curve3_inc::approximation_scale(double s) + { + m_scale = s; + } + + //------------------------------------------------------------------------ + double curve3_inc::approximation_scale() const + { + return m_scale; + } + + //------------------------------------------------------------------------ + void curve3_inc::init(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + m_start_x = x1; + m_start_y = y1; + m_end_x = x3; + m_end_y = y3; + + double dx1 = x2 - x1; + double dy1 = y2 - y1; + double dx2 = x3 - x2; + double dy2 = y3 - y2; + + double len = sqrt(dx1 * dx1 + dy1 * dy1) + sqrt(dx2 * dx2 + dy2 * dy2); + + m_num_steps = uround(len * 0.25 * m_scale); + + if(m_num_steps < 4) + { + m_num_steps = 4; + } + + double subdivide_step = 1.0 / m_num_steps; + double subdivide_step2 = subdivide_step * subdivide_step; + + double tmpx = (x1 - x2 * 2.0 + x3) * subdivide_step2; + double tmpy = (y1 - y2 * 2.0 + y3) * subdivide_step2; + + m_saved_fx = m_fx = x1; + m_saved_fy = m_fy = y1; + + m_saved_dfx = m_dfx = tmpx + (x2 - x1) * (2.0 * subdivide_step); + m_saved_dfy = m_dfy = tmpy + (y2 - y1) * (2.0 * subdivide_step); + + m_ddfx = tmpx * 2.0; + m_ddfy = tmpy * 2.0; + + m_step = m_num_steps; + } + + //------------------------------------------------------------------------ + void curve3_inc::rewind(unsigned) + { + if(m_num_steps == 0) + { + m_step = -1; + return; + } + m_step = m_num_steps; + m_fx = m_saved_fx; + m_fy = m_saved_fy; + m_dfx = m_saved_dfx; + m_dfy = m_saved_dfy; + } + + //------------------------------------------------------------------------ + unsigned curve3_inc::vertex(double* x, double* y) + { + if(m_step < 0) return path_cmd_stop; + if(m_step == m_num_steps) + { + *x = m_start_x; + *y = m_start_y; + --m_step; + return path_cmd_move_to; + } + if(m_step == 0) + { + *x = m_end_x; + *y = m_end_y; + --m_step; + return path_cmd_line_to; + } + m_fx += m_dfx; + m_fy += m_dfy; + m_dfx += m_ddfx; + m_dfy += m_ddfy; + *x = m_fx; + *y = m_fy; + --m_step; + return path_cmd_line_to; + } + + //------------------------------------------------------------------------ + void curve3_div::init(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + m_points.remove_all(); + m_distance_tolerance_square = 0.5 / m_approximation_scale; + m_distance_tolerance_square *= m_distance_tolerance_square; + bezier(x1, y1, x2, y2, x3, y3); + m_count = 0; + } + + //------------------------------------------------------------------------ + void curve3_div::recursive_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + unsigned level) + { + if(level > curve_recursion_limit) + { + return; + } + + // Calculate all the mid-points of the line segments + //---------------------- + double x12 = (x1 + x2) / 2; + double y12 = (y1 + y2) / 2; + double x23 = (x2 + x3) / 2; + double y23 = (y2 + y3) / 2; + double x123 = (x12 + x23) / 2; + double y123 = (y12 + y23) / 2; + + double dx = x3-x1; + double dy = y3-y1; + double d = fabs(((x2 - x3) * dy - (y2 - y3) * dx)); + double da; + + if(d > curve_collinearity_epsilon) + { + // Regular case + //----------------- + if(d * d <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + // If the curvature doesn't exceed the distance_tolerance value + // we tend to finish subdivisions. + //---------------------- + if(m_angle_tolerance < curve_angle_tolerance_epsilon) + { + m_points.add(point_d(x123, y123)); + return; + } + + // Angle & Cusp Condition + //---------------------- + da = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1)); + if(da >= pi) da = 2*pi - da; + + if(da < m_angle_tolerance) + { + // Finally we can stop the recursion + //---------------------- + m_points.add(point_d(x123, y123)); + return; + } + } + } + else + { + // Collinear case + //------------------ + da = dx*dx + dy*dy; + if(da == 0) + { + d = calc_sq_distance(x1, y1, x2, y2); + } + else + { + d = ((x2 - x1)*dx + (y2 - y1)*dy) / da; + if(d > 0 && d < 1) + { + // Simple collinear case, 1---2---3 + // We can leave just two endpoints + return; + } + if(d <= 0) d = calc_sq_distance(x2, y2, x1, y1); + else if(d >= 1) d = calc_sq_distance(x2, y2, x3, y3); + else d = calc_sq_distance(x2, y2, x1 + d*dx, y1 + d*dy); + } + if(d < m_distance_tolerance_square) + { + m_points.add(point_d(x2, y2)); + return; + } + } + + // Continue subdivision + //---------------------- + recursive_bezier(x1, y1, x12, y12, x123, y123, level + 1); + recursive_bezier(x123, y123, x23, y23, x3, y3, level + 1); + } + + //------------------------------------------------------------------------ + void curve3_div::bezier(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + m_points.add(point_d(x1, y1)); + recursive_bezier(x1, y1, x2, y2, x3, y3, 0); + m_points.add(point_d(x3, y3)); + } + + + + + + //------------------------------------------------------------------------ + void curve4_inc::approximation_scale(double s) + { + m_scale = s; + } + + //------------------------------------------------------------------------ + double curve4_inc::approximation_scale() const + { + return m_scale; + } + + //------------------------------------------------------------------------ + static double MSC60_fix_ICE(double v) { return v; } + + //------------------------------------------------------------------------ + void curve4_inc::init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + m_start_x = x1; + m_start_y = y1; + m_end_x = x4; + m_end_y = y4; + + double dx1 = x2 - x1; + double dy1 = y2 - y1; + double dx2 = x3 - x2; + double dy2 = y3 - y2; + double dx3 = x4 - x3; + double dy3 = y4 - y3; + + double len = (sqrt(dx1 * dx1 + dy1 * dy1) + + sqrt(dx2 * dx2 + dy2 * dy2) + + sqrt(dx3 * dx3 + dy3 * dy3)) * 0.25 * m_scale; + +#if defined(_MSC_VER) && _MSC_VER <= 1200 + m_num_steps = uround(MSC60_fix_ICE(len)); +#else + m_num_steps = uround(len); +#endif + + if(m_num_steps < 4) + { + m_num_steps = 4; + } + + double subdivide_step = 1.0 / m_num_steps; + double subdivide_step2 = subdivide_step * subdivide_step; + double subdivide_step3 = subdivide_step * subdivide_step * subdivide_step; + + double pre1 = 3.0 * subdivide_step; + double pre2 = 3.0 * subdivide_step2; + double pre4 = 6.0 * subdivide_step2; + double pre5 = 6.0 * subdivide_step3; + + double tmp1x = x1 - x2 * 2.0 + x3; + double tmp1y = y1 - y2 * 2.0 + y3; + + double tmp2x = (x2 - x3) * 3.0 - x1 + x4; + double tmp2y = (y2 - y3) * 3.0 - y1 + y4; + + m_saved_fx = m_fx = x1; + m_saved_fy = m_fy = y1; + + m_saved_dfx = m_dfx = (x2 - x1) * pre1 + tmp1x * pre2 + tmp2x * subdivide_step3; + m_saved_dfy = m_dfy = (y2 - y1) * pre1 + tmp1y * pre2 + tmp2y * subdivide_step3; + + m_saved_ddfx = m_ddfx = tmp1x * pre4 + tmp2x * pre5; + m_saved_ddfy = m_ddfy = tmp1y * pre4 + tmp2y * pre5; + + m_dddfx = tmp2x * pre5; + m_dddfy = tmp2y * pre5; + + m_step = m_num_steps; + } + + //------------------------------------------------------------------------ + void curve4_inc::rewind(unsigned) + { + if(m_num_steps == 0) + { + m_step = -1; + return; + } + m_step = m_num_steps; + m_fx = m_saved_fx; + m_fy = m_saved_fy; + m_dfx = m_saved_dfx; + m_dfy = m_saved_dfy; + m_ddfx = m_saved_ddfx; + m_ddfy = m_saved_ddfy; + } + + //------------------------------------------------------------------------ + unsigned curve4_inc::vertex(double* x, double* y) + { + if(m_step < 0) return path_cmd_stop; + if(m_step == m_num_steps) + { + *x = m_start_x; + *y = m_start_y; + --m_step; + return path_cmd_move_to; + } + + if(m_step == 0) + { + *x = m_end_x; + *y = m_end_y; + --m_step; + return path_cmd_line_to; + } + + m_fx += m_dfx; + m_fy += m_dfy; + m_dfx += m_ddfx; + m_dfy += m_ddfy; + m_ddfx += m_dddfx; + m_ddfy += m_dddfy; + + *x = m_fx; + *y = m_fy; + --m_step; + return path_cmd_line_to; + } + + + + + //------------------------------------------------------------------------ + void curve4_div::init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + m_points.remove_all(); + m_distance_tolerance_square = 0.5 / m_approximation_scale; + m_distance_tolerance_square *= m_distance_tolerance_square; + bezier(x1, y1, x2, y2, x3, y3, x4, y4); + m_count = 0; + } + + //------------------------------------------------------------------------ + void curve4_div::recursive_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4, + unsigned level) + { + if(level > curve_recursion_limit) + { + return; + } + + // Calculate all the mid-points of the line segments + //---------------------- + double x12 = (x1 + x2) / 2; + double y12 = (y1 + y2) / 2; + double x23 = (x2 + x3) / 2; + double y23 = (y2 + y3) / 2; + double x34 = (x3 + x4) / 2; + double y34 = (y3 + y4) / 2; + double x123 = (x12 + x23) / 2; + double y123 = (y12 + y23) / 2; + double x234 = (x23 + x34) / 2; + double y234 = (y23 + y34) / 2; + double x1234 = (x123 + x234) / 2; + double y1234 = (y123 + y234) / 2; + + + // Try to approximate the full cubic curve by a single straight line + //------------------ + double dx = x4-x1; + double dy = y4-y1; + + double d2 = fabs(((x2 - x4) * dy - (y2 - y4) * dx)); + double d3 = fabs(((x3 - x4) * dy - (y3 - y4) * dx)); + double da1, da2, k; + + switch((int(d2 > curve_collinearity_epsilon) << 1) + + int(d3 > curve_collinearity_epsilon)) + { + case 0: + // All collinear OR p1==p4 + //---------------------- + k = dx*dx + dy*dy; + if(k == 0) + { + d2 = calc_sq_distance(x1, y1, x2, y2); + d3 = calc_sq_distance(x4, y4, x3, y3); + } + else + { + k = 1 / k; + da1 = x2 - x1; + da2 = y2 - y1; + d2 = k * (da1*dx + da2*dy); + da1 = x3 - x1; + da2 = y3 - y1; + d3 = k * (da1*dx + da2*dy); + if(d2 > 0 && d2 < 1 && d3 > 0 && d3 < 1) + { + // Simple collinear case, 1---2---3---4 + // We can leave just two endpoints + return; + } + if(d2 <= 0) d2 = calc_sq_distance(x2, y2, x1, y1); + else if(d2 >= 1) d2 = calc_sq_distance(x2, y2, x4, y4); + else d2 = calc_sq_distance(x2, y2, x1 + d2*dx, y1 + d2*dy); + + if(d3 <= 0) d3 = calc_sq_distance(x3, y3, x1, y1); + else if(d3 >= 1) d3 = calc_sq_distance(x3, y3, x4, y4); + else d3 = calc_sq_distance(x3, y3, x1 + d3*dx, y1 + d3*dy); + } + if(d2 > d3) + { + if(d2 < m_distance_tolerance_square) + { + m_points.add(point_d(x2, y2)); + return; + } + } + else + { + if(d3 < m_distance_tolerance_square) + { + m_points.add(point_d(x3, y3)); + return; + } + } + break; + + case 1: + // p1,p2,p4 are collinear, p3 is significant + //---------------------- + if(d3 * d3 <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + if(m_angle_tolerance < curve_angle_tolerance_epsilon) + { + m_points.add(point_d(x23, y23)); + return; + } + + // Angle Condition + //---------------------- + da1 = fabs(atan2(y4 - y3, x4 - x3) - atan2(y3 - y2, x3 - x2)); + if(da1 >= pi) da1 = 2*pi - da1; + + if(da1 < m_angle_tolerance) + { + m_points.add(point_d(x2, y2)); + m_points.add(point_d(x3, y3)); + return; + } + + if(m_cusp_limit != 0.0) + { + if(da1 > m_cusp_limit) + { + m_points.add(point_d(x3, y3)); + return; + } + } + } + break; + + case 2: + // p1,p3,p4 are collinear, p2 is significant + //---------------------- + if(d2 * d2 <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + if(m_angle_tolerance < curve_angle_tolerance_epsilon) + { + m_points.add(point_d(x23, y23)); + return; + } + + // Angle Condition + //---------------------- + da1 = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1)); + if(da1 >= pi) da1 = 2*pi - da1; + + if(da1 < m_angle_tolerance) + { + m_points.add(point_d(x2, y2)); + m_points.add(point_d(x3, y3)); + return; + } + + if(m_cusp_limit != 0.0) + { + if(da1 > m_cusp_limit) + { + m_points.add(point_d(x2, y2)); + return; + } + } + } + break; + + case 3: + // Regular case + //----------------- + if((d2 + d3)*(d2 + d3) <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + // If the curvature doesn't exceed the distance_tolerance value + // we tend to finish subdivisions. + //---------------------- + if(m_angle_tolerance < curve_angle_tolerance_epsilon) + { + m_points.add(point_d(x23, y23)); + return; + } + + // Angle & Cusp Condition + //---------------------- + k = atan2(y3 - y2, x3 - x2); + da1 = fabs(k - atan2(y2 - y1, x2 - x1)); + da2 = fabs(atan2(y4 - y3, x4 - x3) - k); + if(da1 >= pi) da1 = 2*pi - da1; + if(da2 >= pi) da2 = 2*pi - da2; + + if(da1 + da2 < m_angle_tolerance) + { + // Finally we can stop the recursion + //---------------------- + m_points.add(point_d(x23, y23)); + return; + } + + if(m_cusp_limit != 0.0) + { + if(da1 > m_cusp_limit) + { + m_points.add(point_d(x2, y2)); + return; + } + + if(da2 > m_cusp_limit) + { + m_points.add(point_d(x3, y3)); + return; + } + } + } + break; + } + + // Continue subdivision + //---------------------- + recursive_bezier(x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1); + recursive_bezier(x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1); + } + + //------------------------------------------------------------------------ + void curve4_div::bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + m_points.add(point_d(x1, y1)); + recursive_bezier(x1, y1, x2, y2, x3, y3, x4, y4, 0); + m_points.add(point_d(x4, y4)); + } + +} + diff --git a/jni/desmume/src/android/agg/src/agg_embedded_raster_fonts.cpp b/jni/desmume/src/android/agg/src/agg_embedded_raster_fonts.cpp new file mode 100755 index 0000000..4466597 --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_embedded_raster_fonts.cpp @@ -0,0 +1,10435 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include "agg_embedded_raster_fonts.h" + +namespace agg +{ + + const int8u gse4x6[] = + { + 6, 0, 32, 128-32, + + 0x00,0x00,0x07,0x00,0x0e,0x00,0x15,0x00,0x1c,0x00,0x23,0x00,0x2a,0x00,0x31,0x00,0x38,0x00, + 0x3f,0x00,0x46,0x00,0x4d,0x00,0x54,0x00,0x5b,0x00,0x62,0x00,0x69,0x00,0x70,0x00,0x77,0x00, + 0x7e,0x00,0x85,0x00,0x8c,0x00,0x93,0x00,0x9a,0x00,0xa1,0x00,0xa8,0x00,0xaf,0x00,0xb6,0x00, + 0xbd,0x00,0xc4,0x00,0xcb,0x00,0xd2,0x00,0xd9,0x00,0xe0,0x00,0xe7,0x00,0xee,0x00,0xf5,0x00, + 0xfc,0x00,0x03,0x01,0x0a,0x01,0x11,0x01,0x18,0x01,0x1f,0x01,0x26,0x01,0x2d,0x01,0x34,0x01, + 0x3b,0x01,0x42,0x01,0x49,0x01,0x50,0x01,0x57,0x01,0x5e,0x01,0x65,0x01,0x6c,0x01,0x73,0x01, + 0x7a,0x01,0x81,0x01,0x88,0x01,0x8f,0x01,0x96,0x01,0x9d,0x01,0xa4,0x01,0xab,0x01,0xb2,0x01, + 0xb9,0x01,0xc0,0x01,0xc7,0x01,0xce,0x01,0xd5,0x01,0xdc,0x01,0xe3,0x01,0xea,0x01,0xf1,0x01, + 0xf8,0x01,0xff,0x01,0x06,0x02,0x0d,0x02,0x14,0x02,0x1b,0x02,0x22,0x02,0x29,0x02,0x30,0x02, + 0x37,0x02,0x3e,0x02,0x45,0x02,0x4c,0x02,0x53,0x02,0x5a,0x02,0x61,0x02,0x68,0x02,0x6f,0x02, + 0x76,0x02,0x7d,0x02,0x84,0x02,0x8b,0x02,0x92,0x02,0x99,0x02, + + 4, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x21 '!' + 0x40,0x40,0x40,0x00,0x40,0x00, + + 4, // 0x22 '"' + 0xa0,0xa0,0x00,0x00,0x00,0x00, + + 4, // 0x23 '#' + 0x60,0xf0,0x60,0xf0,0x60,0x00, + + 4, // 0x24 '$' + 0x40,0x60,0xc0,0x60,0xc0,0x40, + + 4, // 0x25 '%' + 0xa0,0x20,0x40,0x80,0xa0,0x00, + + 4, // 0x26 '&' + 0xe0,0xa0,0x50,0xa0,0xd0,0x00, + + 4, // 0x27 ''' + 0x40,0x40,0x00,0x00,0x00,0x00, + + 4, // 0x28 '(' + 0x20,0x40,0x40,0x40,0x20,0x00, + + 4, // 0x29 ')' + 0x40,0x20,0x20,0x20,0x40,0x00, + + 4, // 0x2a '*' + 0xa0,0x40,0xe0,0x40,0xa0,0x00, + + 4, // 0x2b '+' + 0x40,0x40,0xe0,0x40,0x40,0x00, + + 4, // 0x2c ',' + 0x00,0x00,0x00,0x40,0x40,0x80, + + 4, // 0x2d '-' + 0x00,0x00,0xe0,0x00,0x00,0x00, + + 4, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x40,0x00, + + 4, // 0x2f '/' + 0x10,0x20,0x20,0x40,0x40,0x80, + + 4, // 0x30 '0' + 0xe0,0xa0,0xa0,0xa0,0xe0,0x00, + + 4, // 0x31 '1' + 0x40,0xc0,0x40,0x40,0xe0,0x00, + + 4, // 0x32 '2' + 0xe0,0xa0,0x20,0x40,0xe0,0x00, + + 4, // 0x33 '3' + 0xe0,0x20,0x40,0x20,0xe0,0x00, + + 4, // 0x34 '4' + 0xa0,0xa0,0xe0,0x20,0x20,0x00, + + 4, // 0x35 '5' + 0xe0,0x80,0xc0,0x20,0xc0,0x00, + + 4, // 0x36 '6' + 0x40,0x80,0xe0,0xa0,0xe0,0x00, + + 4, // 0x37 '7' + 0xe0,0xa0,0x20,0x40,0x40,0x00, + + 4, // 0x38 '8' + 0xe0,0xa0,0x40,0xa0,0xe0,0x00, + + 4, // 0x39 '9' + 0xe0,0xa0,0xe0,0x20,0xc0,0x00, + + 4, // 0x3a ':' + 0x00,0x40,0x00,0x40,0x00,0x00, + + 4, // 0x3b ';' + 0x00,0x40,0x00,0x40,0x40,0x80, + + 4, // 0x3c '<' + 0x20,0x40,0x80,0x40,0x20,0x00, + + 4, // 0x3d '=' + 0x00,0xe0,0x00,0xe0,0x00,0x00, + + 4, // 0x3e '>' + 0x80,0x40,0x20,0x40,0x80,0x00, + + 4, // 0x3f '?' + 0xc0,0x20,0x40,0x00,0x40,0x00, + + 4, // 0x40 '@' + 0x40,0xa0,0xe0,0xe0,0x80,0x60, + + 4, // 0x41 'A' + 0x40,0xa0,0xe0,0xa0,0xa0,0x00, + + 4, // 0x42 'B' + 0xc0,0xa0,0xc0,0xa0,0xc0,0x00, + + 4, // 0x43 'C' + 0x60,0x80,0x80,0x80,0x60,0x00, + + 4, // 0x44 'D' + 0xc0,0xa0,0xa0,0xa0,0xc0,0x00, + + 4, // 0x45 'E' + 0xe0,0x80,0xc0,0x80,0xe0,0x00, + + 4, // 0x46 'F' + 0xe0,0x80,0xc0,0x80,0x80,0x00, + + 4, // 0x47 'G' + 0x60,0x80,0xa0,0xa0,0x40,0x00, + + 4, // 0x48 'H' + 0xa0,0xa0,0xe0,0xa0,0xa0,0x00, + + 4, // 0x49 'I' + 0xe0,0x40,0x40,0x40,0xe0,0x00, + + 4, // 0x4a 'J' + 0x20,0x20,0x20,0x20,0xa0,0x40, + + 4, // 0x4b 'K' + 0xa0,0xa0,0xc0,0xc0,0xa0,0x00, + + 4, // 0x4c 'L' + 0x80,0x80,0x80,0x80,0xe0,0x00, + + 4, // 0x4d 'M' + 0xa0,0xe0,0xa0,0xa0,0xa0,0x00, + + 4, // 0x4e 'N' + 0x90,0xd0,0xb0,0x90,0x90,0x00, + + 4, // 0x4f 'O' + 0x40,0xa0,0xa0,0xa0,0x40,0x00, + + 4, // 0x50 'P' + 0xc0,0xa0,0xa0,0xc0,0x80,0x00, + + 4, // 0x51 'Q' + 0x40,0xa0,0xa0,0xa0,0x60,0x00, + + 4, // 0x52 'R' + 0xc0,0xa0,0xa0,0xc0,0xa0,0x00, + + 4, // 0x53 'S' + 0x60,0x80,0x40,0x20,0xc0,0x00, + + 4, // 0x54 'T' + 0xe0,0x40,0x40,0x40,0x40,0x00, + + 4, // 0x55 'U' + 0xa0,0xa0,0xa0,0xa0,0xe0,0x00, + + 4, // 0x56 'V' + 0xa0,0xa0,0xa0,0xa0,0x40,0x00, + + 4, // 0x57 'W' + 0xa0,0xa0,0xa0,0xe0,0xa0,0x00, + + 4, // 0x58 'X' + 0xa0,0xa0,0x40,0xa0,0xa0,0x00, + + 4, // 0x59 'Y' + 0xa0,0xa0,0x40,0x40,0x40,0x00, + + 4, // 0x5a 'Z' + 0xe0,0x20,0x40,0x80,0xe0,0x00, + + 4, // 0x5b '[' + 0xc0,0x80,0x80,0x80,0xc0,0x00, + + 4, // 0x5c '\' + 0x80,0x40,0x40,0x20,0x20,0x10, + + 4, // 0x5d ']' + 0xc0,0x40,0x40,0x40,0xc0,0x00, + + 4, // 0x5e '^' + 0x40,0xa0,0x00,0x00,0x00,0x00, + + 4, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0xf0, + + 4, // 0x60 '`' + 0x40,0x20,0x00,0x00,0x00,0x00, + + 4, // 0x61 'a' + 0x00,0x60,0xa0,0xa0,0x70,0x00, + + 4, // 0x62 'b' + 0x80,0x80,0xc0,0xa0,0xc0,0x00, + + 4, // 0x63 'c' + 0x00,0x60,0x80,0x80,0x60,0x00, + + 4, // 0x64 'd' + 0x20,0x20,0x60,0xa0,0x60,0x00, + + 4, // 0x65 'e' + 0x00,0x40,0xe0,0x80,0x60,0x00, + + 4, // 0x66 'f' + 0x20,0x40,0xe0,0x40,0x40,0x00, + + 4, // 0x67 'g' + 0x00,0x60,0xa0,0x60,0x20,0xc0, + + 4, // 0x68 'h' + 0x80,0x80,0xc0,0xa0,0xa0,0x00, + + 4, // 0x69 'i' + 0x40,0x00,0xc0,0x40,0xe0,0x00, + + 4, // 0x6a 'j' + 0x40,0x00,0xc0,0x40,0x40,0x80, + + 4, // 0x6b 'k' + 0x80,0x80,0xa0,0xc0,0xa0,0x00, + + 4, // 0x6c 'l' + 0xc0,0x40,0x40,0x40,0xe0,0x00, + + 4, // 0x6d 'm' + 0x00,0xa0,0xf0,0xf0,0x90,0x00, + + 4, // 0x6e 'n' + 0x00,0xc0,0xa0,0xa0,0xa0,0x00, + + 4, // 0x6f 'o' + 0x00,0x40,0xa0,0xa0,0x40,0x00, + + 4, // 0x70 'p' + 0x00,0xc0,0xa0,0xc0,0x80,0x80, + + 4, // 0x71 'q' + 0x00,0x60,0xa0,0x60,0x20,0x20, + + 4, // 0x72 'r' + 0x00,0xa0,0x50,0x40,0x40,0x00, + + 4, // 0x73 's' + 0x00,0x60,0xc0,0x20,0xc0,0x00, + + 4, // 0x74 't' + 0x40,0x40,0xe0,0x40,0x60,0x00, + + 4, // 0x75 'u' + 0x00,0xa0,0xa0,0xa0,0x60,0x00, + + 4, // 0x76 'v' + 0x00,0xa0,0xa0,0xa0,0x40,0x00, + + 4, // 0x77 'w' + 0x00,0xa0,0xa0,0xe0,0xa0,0x00, + + 4, // 0x78 'x' + 0x00,0xa0,0x40,0xa0,0xa0,0x00, + + 4, // 0x79 'y' + 0x00,0xa0,0xa0,0x60,0x20,0xc0, + + 4, // 0x7a 'z' + 0x00,0xe0,0x40,0x80,0xe0,0x00, + + 4, // 0x7b '{' + 0x30,0x20,0xc0,0x20,0x30,0x00, + + 4, // 0x7c '|' + 0x40,0x40,0x00,0x40,0x40,0x40, + + 4, // 0x7d '}' + 0xc0,0x40,0x30,0x40,0xc0,0x00, + + 4, // 0x7e '~' + 0x50,0xa0,0x00,0x00,0x00,0x00, + + 4, // 0x7f '' + 0x00,0x60,0x90,0xf0,0x00,0x00, + 0 + }; + + const int8u gse4x8[] = + { + 8, 0, 32, 128-32, + + 0x00,0x00,0x09,0x00,0x12,0x00,0x1b,0x00,0x24,0x00,0x2d,0x00,0x36,0x00,0x3f,0x00,0x48,0x00, + 0x51,0x00,0x5a,0x00,0x63,0x00,0x6c,0x00,0x75,0x00,0x7e,0x00,0x87,0x00,0x90,0x00,0x99,0x00, + 0xa2,0x00,0xab,0x00,0xb4,0x00,0xbd,0x00,0xc6,0x00,0xcf,0x00,0xd8,0x00,0xe1,0x00,0xea,0x00, + 0xf3,0x00,0xfc,0x00,0x05,0x01,0x0e,0x01,0x17,0x01,0x20,0x01,0x29,0x01,0x32,0x01,0x3b,0x01, + 0x44,0x01,0x4d,0x01,0x56,0x01,0x5f,0x01,0x68,0x01,0x71,0x01,0x7a,0x01,0x83,0x01,0x8c,0x01, + 0x95,0x01,0x9e,0x01,0xa7,0x01,0xb0,0x01,0xb9,0x01,0xc2,0x01,0xcb,0x01,0xd4,0x01,0xdd,0x01, + 0xe6,0x01,0xef,0x01,0xf8,0x01,0x01,0x02,0x0a,0x02,0x13,0x02,0x1c,0x02,0x25,0x02,0x2e,0x02, + 0x37,0x02,0x40,0x02,0x49,0x02,0x52,0x02,0x5b,0x02,0x64,0x02,0x6d,0x02,0x76,0x02,0x7f,0x02, + 0x88,0x02,0x91,0x02,0x9a,0x02,0xa3,0x02,0xac,0x02,0xb5,0x02,0xbe,0x02,0xc7,0x02,0xd0,0x02, + 0xd9,0x02,0xe2,0x02,0xeb,0x02,0xf4,0x02,0xfd,0x02,0x06,0x03,0x0f,0x03,0x18,0x03,0x21,0x03, + 0x2a,0x03,0x33,0x03,0x3c,0x03,0x45,0x03,0x4e,0x03,0x57,0x03, + + 4, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x21 '!' + 0x00,0x40,0x40,0x40,0x40,0x00,0x40,0x00, + + 4, // 0x22 '"' + 0x00,0xa0,0xa0,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x23 '#' + 0x60,0x60,0xf0,0x60,0x60,0xf0,0x60,0x60, + + 4, // 0x24 '$' + 0x40,0x60,0xc0,0xc0,0x60,0x60,0xc0,0x40, + + 4, // 0x25 '%' + 0x00,0xa0,0x20,0x40,0x40,0x80,0xa0,0x00, + + 4, // 0x26 '&' + 0x00,0x40,0xa0,0xa0,0x40,0xb0,0xa0,0x70, + + 4, // 0x27 ''' + 0x00,0x40,0x40,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x28 '(' + 0x20,0x40,0x80,0x80,0x80,0x80,0x40,0x20, + + 4, // 0x29 ')' + 0x80,0x40,0x20,0x20,0x20,0x20,0x40,0x80, + + 4, // 0x2a '*' + 0x00,0xa0,0x40,0xe0,0x40,0xa0,0x00,0x00, + + 4, // 0x2b '+' + 0x00,0x40,0x40,0xe0,0x40,0x40,0x00,0x00, + + 4, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x80, + + 4, // 0x2d '-' + 0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x00, + + 4, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00, + + 4, // 0x2f '/' + 0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80, + + 4, // 0x30 '0' + 0x00,0xe0,0xa0,0xa0,0xa0,0xa0,0xe0,0x00, + + 4, // 0x31 '1' + 0x00,0x40,0xc0,0x40,0x40,0x40,0xe0,0x00, + + 4, // 0x32 '2' + 0x00,0xe0,0xa0,0x20,0x40,0x80,0xe0,0x00, + + 4, // 0x33 '3' + 0x00,0xe0,0x20,0x40,0x20,0x20,0xe0,0x00, + + 4, // 0x34 '4' + 0x00,0x60,0xa0,0xa0,0xf0,0x20,0x20,0x00, + + 4, // 0x35 '5' + 0x00,0xe0,0x80,0xc0,0x20,0x20,0xc0,0x00, + + 4, // 0x36 '6' + 0x00,0x40,0x80,0xe0,0xa0,0xa0,0xe0,0x00, + + 4, // 0x37 '7' + 0x00,0xe0,0xa0,0x20,0x40,0x40,0x40,0x00, + + 4, // 0x38 '8' + 0x00,0xe0,0xa0,0x40,0xa0,0xa0,0xe0,0x00, + + 4, // 0x39 '9' + 0x00,0xe0,0xa0,0xe0,0x20,0x20,0x40,0x00, + + 4, // 0x3a ':' + 0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00, + + 4, // 0x3b ';' + 0x00,0x00,0x40,0x00,0x00,0x40,0x40,0x80, + + 4, // 0x3c '<' + 0x00,0x20,0x40,0x80,0x40,0x20,0x00,0x00, + + 4, // 0x3d '=' + 0x00,0x00,0xe0,0x00,0xe0,0x00,0x00,0x00, + + 4, // 0x3e '>' + 0x00,0x80,0x40,0x20,0x40,0x80,0x00,0x00, + + 4, // 0x3f '?' + 0x00,0x40,0xa0,0x20,0x40,0x00,0x40,0x00, + + 4, // 0x40 '@' + 0x00,0x40,0xa0,0xe0,0xe0,0x80,0x60,0x00, + + 4, // 0x41 'A' + 0x00,0x40,0xa0,0xa0,0xe0,0xa0,0xa0,0x00, + + 4, // 0x42 'B' + 0x00,0xc0,0xa0,0xc0,0xa0,0xa0,0xc0,0x00, + + 4, // 0x43 'C' + 0x00,0x40,0xa0,0x80,0x80,0xa0,0x40,0x00, + + 4, // 0x44 'D' + 0x00,0xc0,0xa0,0xa0,0xa0,0xa0,0xc0,0x00, + + 4, // 0x45 'E' + 0x00,0xe0,0x80,0xc0,0x80,0x80,0xe0,0x00, + + 4, // 0x46 'F' + 0x00,0xe0,0x80,0xc0,0x80,0x80,0x80,0x00, + + 4, // 0x47 'G' + 0x00,0x60,0x80,0xa0,0xa0,0xa0,0x40,0x00, + + 4, // 0x48 'H' + 0x00,0xa0,0xa0,0xe0,0xa0,0xa0,0xa0,0x00, + + 4, // 0x49 'I' + 0x00,0xe0,0x40,0x40,0x40,0x40,0xe0,0x00, + + 4, // 0x4a 'J' + 0x00,0x20,0x20,0x20,0x20,0xa0,0x40,0x00, + + 4, // 0x4b 'K' + 0x00,0xa0,0xa0,0xc0,0xc0,0xa0,0xa0,0x00, + + 4, // 0x4c 'L' + 0x00,0x80,0x80,0x80,0x80,0x80,0xe0,0x00, + + 4, // 0x4d 'M' + 0x00,0xa0,0xe0,0xa0,0xa0,0xa0,0xa0,0x00, + + 4, // 0x4e 'N' + 0x00,0x90,0x90,0xd0,0xb0,0x90,0x90,0x00, + + 4, // 0x4f 'O' + 0x00,0x40,0xa0,0xa0,0xa0,0xa0,0x40,0x00, + + 4, // 0x50 'P' + 0x00,0xc0,0xa0,0xa0,0xc0,0x80,0x80,0x00, + + 4, // 0x51 'Q' + 0x00,0x40,0xa0,0xa0,0xa0,0xa0,0x60,0x00, + + 4, // 0x52 'R' + 0x00,0xc0,0xa0,0xa0,0xc0,0xc0,0xa0,0x00, + + 4, // 0x53 'S' + 0x00,0x60,0x80,0x40,0x20,0x20,0xc0,0x00, + + 4, // 0x54 'T' + 0x00,0xe0,0x40,0x40,0x40,0x40,0x40,0x00, + + 4, // 0x55 'U' + 0x00,0xa0,0xa0,0xa0,0xa0,0xa0,0x40,0x00, + + 4, // 0x56 'V' + 0x00,0xa0,0xa0,0xa0,0xa0,0x40,0x40,0x00, + + 4, // 0x57 'W' + 0x00,0xa0,0xa0,0xa0,0xa0,0xe0,0xa0,0x00, + + 4, // 0x58 'X' + 0x00,0xa0,0xa0,0x40,0xa0,0xa0,0xa0,0x00, + + 4, // 0x59 'Y' + 0x00,0xa0,0xa0,0x40,0x40,0x40,0x40,0x00, + + 4, // 0x5a 'Z' + 0x00,0xe0,0x20,0x40,0x40,0x80,0xe0,0x00, + + 4, // 0x5b '[' + 0xc0,0x80,0x80,0x80,0x80,0x80,0x80,0xc0, + + 4, // 0x5c '\' + 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10, + + 4, // 0x5d ']' + 0xc0,0x40,0x40,0x40,0x40,0x40,0x40,0xc0, + + 4, // 0x5e '^' + 0x00,0x40,0xa0,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0, + + 4, // 0x60 '`' + 0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x61 'a' + 0x00,0x00,0x60,0xa0,0xa0,0xa0,0x70,0x00, + + 4, // 0x62 'b' + 0x00,0x80,0x80,0xc0,0xa0,0xa0,0xc0,0x00, + + 4, // 0x63 'c' + 0x00,0x00,0x40,0xa0,0x80,0xa0,0x40,0x00, + + 4, // 0x64 'd' + 0x00,0x20,0x20,0x60,0xa0,0xa0,0x60,0x00, + + 4, // 0x65 'e' + 0x00,0x00,0x40,0xa0,0xe0,0x80,0x60,0x00, + + 4, // 0x66 'f' + 0x00,0x20,0x40,0x40,0xe0,0x40,0x40,0x00, + + 4, // 0x67 'g' + 0x00,0x00,0x60,0xa0,0xa0,0x60,0x20,0xc0, + + 4, // 0x68 'h' + 0x00,0x80,0x80,0xc0,0xa0,0xa0,0xa0,0x00, + + 4, // 0x69 'i' + 0x00,0x40,0x00,0xc0,0x40,0x40,0xe0,0x00, + + 4, // 0x6a 'j' + 0x00,0x40,0x00,0xc0,0x40,0x40,0x40,0x80, + + 4, // 0x6b 'k' + 0x00,0x80,0x80,0xa0,0xc0,0xc0,0xa0,0x00, + + 4, // 0x6c 'l' + 0x00,0xc0,0x40,0x40,0x40,0x40,0xe0,0x00, + + 4, // 0x6d 'm' + 0x00,0x00,0xa0,0xf0,0xf0,0xf0,0x90,0x00, + + 4, // 0x6e 'n' + 0x00,0x00,0xc0,0xa0,0xa0,0xa0,0xa0,0x00, + + 4, // 0x6f 'o' + 0x00,0x00,0x40,0xa0,0xa0,0xa0,0x40,0x00, + + 4, // 0x70 'p' + 0x00,0x00,0xc0,0xa0,0xa0,0xc0,0x80,0x80, + + 4, // 0x71 'q' + 0x00,0x00,0x60,0xa0,0xa0,0x60,0x20,0x20, + + 4, // 0x72 'r' + 0x00,0x00,0xa0,0x50,0x40,0x40,0x40,0x00, + + 4, // 0x73 's' + 0x00,0x00,0x60,0x80,0x40,0x20,0xc0,0x00, + + 4, // 0x74 't' + 0x00,0x40,0x40,0xe0,0x40,0x40,0x20,0x00, + + 4, // 0x75 'u' + 0x00,0x00,0xa0,0xa0,0xa0,0xa0,0x60,0x00, + + 4, // 0x76 'v' + 0x00,0x00,0xa0,0xa0,0xa0,0x40,0x40,0x00, + + 4, // 0x77 'w' + 0x00,0x00,0xa0,0xa0,0xa0,0xe0,0xa0,0x00, + + 4, // 0x78 'x' + 0x00,0x00,0xa0,0xa0,0x40,0xa0,0xa0,0x00, + + 4, // 0x79 'y' + 0x00,0x00,0xa0,0xa0,0xa0,0x60,0x20,0xc0, + + 4, // 0x7a 'z' + 0x00,0x00,0xe0,0x20,0x40,0x80,0xe0,0x00, + + 4, // 0x7b '{' + 0x10,0x20,0x20,0xc0,0x20,0x20,0x10,0x00, + + 4, // 0x7c '|' + 0x00,0x40,0x40,0x40,0x00,0x40,0x40,0x40, + + 4, // 0x7d '}' + 0x80,0x40,0x40,0x30,0x40,0x40,0x80,0x00, + + 4, // 0x7e '~' + 0x00,0x50,0xa0,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x7f '' + 0x00,0x00,0x00,0x60,0x90,0xf0,0x00,0x00, + 0 + }; + + const int8u gse5x7[] = + { + 7, 0, 32, 128-32, + + 0x00,0x00,0x08,0x00,0x10,0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x38,0x00,0x40,0x00, + 0x48,0x00,0x50,0x00,0x58,0x00,0x60,0x00,0x68,0x00,0x70,0x00,0x78,0x00,0x80,0x00,0x88,0x00, + 0x90,0x00,0x98,0x00,0xa0,0x00,0xa8,0x00,0xb0,0x00,0xb8,0x00,0xc0,0x00,0xc8,0x00,0xd0,0x00, + 0xd8,0x00,0xe0,0x00,0xe8,0x00,0xf0,0x00,0xf8,0x00,0x00,0x01,0x08,0x01,0x10,0x01,0x18,0x01, + 0x20,0x01,0x28,0x01,0x30,0x01,0x38,0x01,0x40,0x01,0x48,0x01,0x50,0x01,0x58,0x01,0x60,0x01, + 0x68,0x01,0x70,0x01,0x78,0x01,0x80,0x01,0x88,0x01,0x90,0x01,0x98,0x01,0xa0,0x01,0xa8,0x01, + 0xb0,0x01,0xb8,0x01,0xc0,0x01,0xc8,0x01,0xd0,0x01,0xd8,0x01,0xe0,0x01,0xe8,0x01,0xf0,0x01, + 0xf8,0x01,0x00,0x02,0x08,0x02,0x10,0x02,0x18,0x02,0x20,0x02,0x28,0x02,0x30,0x02,0x38,0x02, + 0x40,0x02,0x48,0x02,0x50,0x02,0x58,0x02,0x60,0x02,0x68,0x02,0x70,0x02,0x78,0x02,0x80,0x02, + 0x88,0x02,0x90,0x02,0x98,0x02,0xa0,0x02,0xa8,0x02,0xb0,0x02,0xb8,0x02,0xc0,0x02,0xc8,0x02, + 0xd0,0x02,0xd8,0x02,0xe0,0x02,0xe8,0x02,0xf0,0x02,0xf8,0x02, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x21 '!' + 0x00,0x20,0x20,0x20,0x00,0x20,0x00, + + 5, // 0x22 '"' + 0x00,0x50,0x50,0x00,0x00,0x00,0x00, + + 5, // 0x23 '#' + 0x00,0x50,0xf8,0x50,0xf8,0x50,0x00, + + 5, // 0x24 '$' + 0x20,0x78,0xa0,0x70,0x28,0xf0,0x20, + + 5, // 0x25 '%' + 0x00,0x88,0x10,0x20,0x40,0x88,0x00, + + 5, // 0x26 '&' + 0x00,0x40,0xa0,0x68,0x90,0x68,0x00, + + 5, // 0x27 ''' + 0x00,0x20,0x20,0x00,0x00,0x00,0x00, + + 5, // 0x28 '(' + 0x10,0x20,0x40,0x40,0x40,0x20,0x10, + + 5, // 0x29 ')' + 0x80,0x40,0x20,0x20,0x20,0x40,0x80, + + 5, // 0x2a '*' + 0x00,0x20,0xa8,0x70,0xa8,0x20,0x00, + + 5, // 0x2b '+' + 0x00,0x20,0x20,0xf8,0x20,0x20,0x00, + + 5, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x20,0x20,0x40, + + 5, // 0x2d '-' + 0x00,0x00,0x00,0xf0,0x00,0x00,0x00, + + 5, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x40,0x00, + + 5, // 0x2f '/' + 0x00,0x08,0x10,0x20,0x40,0x80,0x00, + + 5, // 0x30 '0' + 0x00,0x60,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x31 '1' + 0x00,0x20,0x60,0x20,0x20,0x70,0x00, + + 5, // 0x32 '2' + 0x00,0x60,0x90,0x20,0x40,0xf0,0x00, + + 5, // 0x33 '3' + 0x00,0xf0,0x20,0x60,0x10,0xe0,0x00, + + 5, // 0x34 '4' + 0x00,0x30,0x50,0x90,0xf0,0x10,0x00, + + 5, // 0x35 '5' + 0x00,0xf0,0x80,0xe0,0x10,0xe0,0x00, + + 5, // 0x36 '6' + 0x00,0x60,0x80,0xe0,0x90,0x60,0x00, + + 5, // 0x37 '7' + 0x00,0xf0,0x90,0x20,0x40,0x40,0x00, + + 5, // 0x38 '8' + 0x00,0x60,0x90,0x60,0x90,0x60,0x00, + + 5, // 0x39 '9' + 0x00,0x60,0x90,0x70,0x10,0x60,0x00, + + 5, // 0x3a ':' + 0x00,0x00,0x20,0x00,0x20,0x00,0x00, + + 5, // 0x3b ';' + 0x00,0x00,0x20,0x00,0x20,0x20,0x40, + + 5, // 0x3c '<' + 0x00,0x10,0x20,0x40,0x20,0x10,0x00, + + 5, // 0x3d '=' + 0x00,0x00,0xf0,0x00,0xf0,0x00,0x00, + + 5, // 0x3e '>' + 0x00,0x80,0x40,0x20,0x40,0x80,0x00, + + 5, // 0x3f '?' + 0x00,0x60,0x90,0x20,0x00,0x20,0x00, + + 5, // 0x40 '@' + 0x00,0x60,0x90,0xb0,0x80,0x70,0x00, + + 5, // 0x41 'A' + 0x00,0x60,0x90,0xf0,0x90,0x90,0x00, + + 5, // 0x42 'B' + 0x00,0xe0,0x90,0xe0,0x90,0xe0,0x00, + + 5, // 0x43 'C' + 0x00,0x60,0x90,0x80,0x90,0x60,0x00, + + 5, // 0x44 'D' + 0x00,0xe0,0x90,0x90,0x90,0xe0,0x00, + + 5, // 0x45 'E' + 0x00,0xf0,0x80,0xe0,0x80,0xf0,0x00, + + 5, // 0x46 'F' + 0x00,0xf0,0x80,0xe0,0x80,0x80,0x00, + + 5, // 0x47 'G' + 0x00,0x70,0x80,0xb0,0x90,0x60,0x00, + + 5, // 0x48 'H' + 0x00,0x90,0x90,0xf0,0x90,0x90,0x00, + + 5, // 0x49 'I' + 0x00,0x70,0x20,0x20,0x20,0x70,0x00, + + 5, // 0x4a 'J' + 0x00,0x70,0x20,0x20,0xa0,0x40,0x00, + + 5, // 0x4b 'K' + 0x00,0x90,0xa0,0xc0,0xa0,0x90,0x00, + + 5, // 0x4c 'L' + 0x00,0x80,0x80,0x80,0x80,0xf0,0x00, + + 5, // 0x4d 'M' + 0x00,0x90,0xf0,0x90,0x90,0x90,0x00, + + 5, // 0x4e 'N' + 0x00,0x90,0xd0,0xb0,0x90,0x90,0x00, + + 5, // 0x4f 'O' + 0x00,0x60,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x50 'P' + 0x00,0xe0,0x90,0xe0,0x80,0x80,0x00, + + 5, // 0x51 'Q' + 0x00,0x60,0x90,0x90,0xa0,0x50,0x00, + + 5, // 0x52 'R' + 0x00,0xe0,0x90,0xe0,0xa0,0x90,0x00, + + 5, // 0x53 'S' + 0x00,0x70,0x80,0x60,0x10,0xe0,0x00, + + 5, // 0x54 'T' + 0x00,0x70,0x20,0x20,0x20,0x20,0x00, + + 5, // 0x55 'U' + 0x00,0x90,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x56 'V' + 0x00,0x50,0x50,0x50,0x20,0x20,0x00, + + 5, // 0x57 'W' + 0x00,0x90,0x90,0x90,0xf0,0x90,0x00, + + 5, // 0x58 'X' + 0x00,0x90,0x90,0x60,0x90,0x90,0x00, + + 5, // 0x59 'Y' + 0x00,0x50,0x50,0x20,0x20,0x20,0x00, + + 5, // 0x5a 'Z' + 0x00,0xf0,0x10,0x20,0x40,0xf0,0x00, + + 5, // 0x5b '[' + 0x70,0x40,0x40,0x40,0x40,0x40,0x70, + + 5, // 0x5c '\' + 0x00,0x80,0x40,0x20,0x10,0x08,0x00, + + 5, // 0x5d ']' + 0xe0,0x20,0x20,0x20,0x20,0x20,0xe0, + + 5, // 0x5e '^' + 0x00,0x20,0x50,0x00,0x00,0x00,0x00, + + 5, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0xf8,0x00, + + 5, // 0x60 '`' + 0x00,0x40,0x20,0x00,0x00,0x00,0x00, + + 5, // 0x61 'a' + 0x00,0x00,0x60,0xa0,0xa0,0x50,0x00, + + 5, // 0x62 'b' + 0x00,0x80,0x80,0xe0,0x90,0xe0,0x00, + + 5, // 0x63 'c' + 0x00,0x00,0x70,0x80,0x80,0x70,0x00, + + 5, // 0x64 'd' + 0x00,0x10,0x10,0x70,0x90,0x70,0x00, + + 5, // 0x65 'e' + 0x00,0x00,0x60,0xf0,0x80,0x70,0x00, + + 5, // 0x66 'f' + 0x00,0x30,0x40,0xe0,0x40,0x40,0x00, + + 5, // 0x67 'g' + 0x00,0x00,0x70,0x90,0x70,0x10,0x60, + + 5, // 0x68 'h' + 0x00,0x80,0x80,0xe0,0x90,0x90,0x00, + + 5, // 0x69 'i' + 0x20,0x00,0x60,0x20,0x20,0x70,0x00, + + 5, // 0x6a 'j' + 0x20,0x00,0x60,0x20,0x20,0xa0,0x40, + + 5, // 0x6b 'k' + 0x80,0x80,0x90,0xa0,0xe0,0x90,0x00, + + 5, // 0x6c 'l' + 0x00,0x60,0x20,0x20,0x20,0x70,0x00, + + 5, // 0x6d 'm' + 0x00,0x00,0xa0,0xf0,0xf0,0x90,0x00, + + 5, // 0x6e 'n' + 0x00,0x00,0xa0,0xd0,0x90,0x90,0x00, + + 5, // 0x6f 'o' + 0x00,0x00,0x60,0x90,0x90,0x60,0x00, + + 5, // 0x70 'p' + 0x00,0x00,0xe0,0x90,0xe0,0x80,0x80, + + 5, // 0x71 'q' + 0x00,0x00,0x70,0x90,0x70,0x10,0x10, + + 5, // 0x72 'r' + 0x00,0x00,0xe0,0x90,0x80,0x80,0x00, + + 5, // 0x73 's' + 0x00,0x00,0x70,0xe0,0x10,0xe0,0x00, + + 5, // 0x74 't' + 0x40,0x40,0xe0,0x40,0x40,0x70,0x00, + + 5, // 0x75 'u' + 0x00,0x00,0x90,0x90,0x90,0x70,0x00, + + 5, // 0x76 'v' + 0x00,0x00,0x50,0x50,0x50,0x20,0x00, + + 5, // 0x77 'w' + 0x00,0x00,0x90,0x90,0xf0,0x90,0x00, + + 5, // 0x78 'x' + 0x00,0x00,0x90,0x60,0x60,0x90,0x00, + + 5, // 0x79 'y' + 0x00,0x00,0x90,0x90,0x70,0x10,0x60, + + 5, // 0x7a 'z' + 0x00,0x00,0xf0,0x20,0x40,0xf0,0x00, + + 5, // 0x7b '{' + 0x10,0x20,0x20,0xc0,0x20,0x20,0x10, + + 5, // 0x7c '|' + 0x20,0x20,0x20,0x00,0x20,0x20,0x20, + + 5, // 0x7d '}' + 0x40,0x20,0x20,0x18,0x20,0x20,0x40, + + 5, // 0x7e '~' + 0x00,0x40,0xa8,0x10,0x00,0x00,0x00, + + 5, // 0x7f '' + 0x00,0x00,0x20,0x50,0x88,0xf8,0x00, + 0 + }; + + const int8u gse5x9[] = + { + 9, 0, 32, 128-32, + + 0x00,0x00,0x0a,0x00,0x14,0x00,0x1e,0x00,0x28,0x00,0x32,0x00,0x3c,0x00,0x46,0x00,0x50,0x00, + 0x5a,0x00,0x64,0x00,0x6e,0x00,0x78,0x00,0x82,0x00,0x8c,0x00,0x96,0x00,0xa0,0x00,0xaa,0x00, + 0xb4,0x00,0xbe,0x00,0xc8,0x00,0xd2,0x00,0xdc,0x00,0xe6,0x00,0xf0,0x00,0xfa,0x00,0x04,0x01, + 0x0e,0x01,0x18,0x01,0x22,0x01,0x2c,0x01,0x36,0x01,0x40,0x01,0x4a,0x01,0x54,0x01,0x5e,0x01, + 0x68,0x01,0x72,0x01,0x7c,0x01,0x86,0x01,0x90,0x01,0x9a,0x01,0xa4,0x01,0xae,0x01,0xb8,0x01, + 0xc2,0x01,0xcc,0x01,0xd6,0x01,0xe0,0x01,0xea,0x01,0xf4,0x01,0xfe,0x01,0x08,0x02,0x12,0x02, + 0x1c,0x02,0x26,0x02,0x30,0x02,0x3a,0x02,0x44,0x02,0x4e,0x02,0x58,0x02,0x62,0x02,0x6c,0x02, + 0x76,0x02,0x80,0x02,0x8a,0x02,0x94,0x02,0x9e,0x02,0xa8,0x02,0xb2,0x02,0xbc,0x02,0xc6,0x02, + 0xd0,0x02,0xda,0x02,0xe4,0x02,0xee,0x02,0xf8,0x02,0x02,0x03,0x0c,0x03,0x16,0x03,0x20,0x03, + 0x2a,0x03,0x34,0x03,0x3e,0x03,0x48,0x03,0x52,0x03,0x5c,0x03,0x66,0x03,0x70,0x03,0x7a,0x03, + 0x84,0x03,0x8e,0x03,0x98,0x03,0xa2,0x03,0xac,0x03,0xb6,0x03, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x21 '!' + 0x00,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00, + + 5, // 0x22 '"' + 0x00,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x23 '#' + 0x00,0x50,0x50,0xf8,0x50,0xf8,0x50,0x50,0x00, + + 5, // 0x24 '$' + 0x00,0x20,0x78,0xa0,0x70,0x28,0xf0,0x20,0x00, + + 5, // 0x25 '%' + 0x00,0xc8,0xc8,0x10,0x20,0x40,0x98,0x98,0x00, + + 5, // 0x26 '&' + 0x00,0x40,0xa0,0xa0,0x40,0xa8,0x90,0x68,0x00, + + 5, // 0x27 ''' + 0x00,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x28 '(' + 0x10,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x10, + + 5, // 0x29 ')' + 0x80,0x40,0x20,0x20,0x20,0x20,0x20,0x40,0x80, + + 5, // 0x2a '*' + 0x00,0x00,0x20,0xa8,0x70,0xa8,0x20,0x00,0x00, + + 5, // 0x2b '+' + 0x00,0x00,0x20,0x20,0xf8,0x20,0x20,0x00,0x00, + + 5, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x40, + + 5, // 0x2d '-' + 0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00, + + 5, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00, + + 5, // 0x2f '/' + 0x00,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80, + + 5, // 0x30 '0' + 0x00,0x60,0x90,0xb0,0xd0,0x90,0x90,0x60,0x00, + + 5, // 0x31 '1' + 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x70,0x00, + + 5, // 0x32 '2' + 0x00,0x60,0x90,0x10,0x20,0x40,0x80,0xf0,0x00, + + 5, // 0x33 '3' + 0x00,0xf0,0x10,0x20,0x60,0x10,0x90,0x60,0x00, + + 5, // 0x34 '4' + 0x00,0x30,0x50,0x90,0x90,0xf8,0x10,0x10,0x00, + + 5, // 0x35 '5' + 0x00,0xf0,0x80,0xe0,0x10,0x10,0x10,0xe0,0x00, + + 5, // 0x36 '6' + 0x00,0x60,0x80,0xe0,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x37 '7' + 0x00,0xf0,0x90,0x10,0x20,0x40,0x40,0x40,0x00, + + 5, // 0x38 '8' + 0x00,0x60,0x90,0x90,0x60,0x90,0x90,0x60,0x00, + + 5, // 0x39 '9' + 0x00,0x60,0x90,0x90,0x70,0x10,0x90,0x60,0x00, + + 5, // 0x3a ':' + 0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x00,0x00, + + 5, // 0x3b ';' + 0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x20,0x40, + + 5, // 0x3c '<' + 0x00,0x10,0x20,0x40,0x80,0x40,0x20,0x10,0x00, + + 5, // 0x3d '=' + 0x00,0x00,0x00,0xf0,0x00,0xf0,0x00,0x00,0x00, + + 5, // 0x3e '>' + 0x00,0x80,0x40,0x20,0x10,0x20,0x40,0x80,0x00, + + 5, // 0x3f '?' + 0x00,0x60,0x90,0x10,0x20,0x20,0x00,0x20,0x00, + + 5, // 0x40 '@' + 0x00,0x60,0x90,0xb0,0xb0,0xb0,0x80,0x70,0x00, + + 5, // 0x41 'A' + 0x00,0x60,0x90,0x90,0xf0,0x90,0x90,0x90,0x00, + + 5, // 0x42 'B' + 0x00,0xe0,0x90,0x90,0xe0,0x90,0x90,0xe0,0x00, + + 5, // 0x43 'C' + 0x00,0x60,0x90,0x80,0x80,0x80,0x90,0x60,0x00, + + 5, // 0x44 'D' + 0x00,0xe0,0x90,0x90,0x90,0x90,0x90,0xe0,0x00, + + 5, // 0x45 'E' + 0x00,0xf0,0x80,0x80,0xe0,0x80,0x80,0xf0,0x00, + + 5, // 0x46 'F' + 0x00,0xf0,0x80,0x80,0xe0,0x80,0x80,0x80,0x00, + + 5, // 0x47 'G' + 0x00,0x60,0x90,0x80,0xb0,0x90,0x90,0x60,0x00, + + 5, // 0x48 'H' + 0x00,0x90,0x90,0x90,0xf0,0x90,0x90,0x90,0x00, + + 5, // 0x49 'I' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00, + + 5, // 0x4a 'J' + 0x00,0x70,0x20,0x20,0x20,0x20,0xa0,0x40,0x00, + + 5, // 0x4b 'K' + 0x00,0x90,0x90,0xa0,0xc0,0xa0,0x90,0x90,0x00, + + 5, // 0x4c 'L' + 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0xf0,0x00, + + 5, // 0x4d 'M' + 0x00,0x90,0xf0,0x90,0x90,0x90,0x90,0x90,0x00, + + 5, // 0x4e 'N' + 0x00,0x90,0x90,0xd0,0xb0,0x90,0x90,0x90,0x00, + + 5, // 0x4f 'O' + 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x50 'P' + 0x00,0xe0,0x90,0x90,0xe0,0x80,0x80,0x80,0x00, + + 5, // 0x51 'Q' + 0x00,0x60,0x90,0x90,0x90,0x90,0xa0,0x50,0x00, + + 5, // 0x52 'R' + 0x00,0xe0,0x90,0x90,0xe0,0xa0,0x90,0x90,0x00, + + 5, // 0x53 'S' + 0x00,0x60,0x90,0x80,0x60,0x10,0x90,0x60,0x00, + + 5, // 0x54 'T' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x00, + + 5, // 0x55 'U' + 0x00,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x56 'V' + 0x00,0x50,0x50,0x50,0x50,0x50,0x20,0x20,0x00, + + 5, // 0x57 'W' + 0x00,0x90,0x90,0x90,0x90,0x90,0xf0,0x90,0x00, + + 5, // 0x58 'X' + 0x00,0x90,0x90,0x60,0x60,0x90,0x90,0x90,0x00, + + 5, // 0x59 'Y' + 0x00,0x50,0x50,0x50,0x20,0x20,0x20,0x20,0x00, + + 5, // 0x5a 'Z' + 0x00,0xf0,0x10,0x10,0x20,0x40,0x80,0xf0,0x00, + + 5, // 0x5b '[' + 0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x70,0x00, + + 5, // 0x5c '\' + 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x00, + + 5, // 0x5d ']' + 0xe0,0x20,0x20,0x20,0x20,0x20,0x20,0xe0,0x00, + + 5, // 0x5e '^' + 0x00,0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x00, + + 5, // 0x60 '`' + 0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x61 'a' + 0x00,0x00,0x60,0x10,0x70,0x90,0x90,0x70,0x00, + + 5, // 0x62 'b' + 0x00,0x80,0x80,0xe0,0x90,0x90,0x90,0xe0,0x00, + + 5, // 0x63 'c' + 0x00,0x00,0x60,0x90,0x80,0x80,0x90,0x60,0x00, + + 5, // 0x64 'd' + 0x00,0x10,0x10,0x70,0x90,0x90,0x90,0x70,0x00, + + 5, // 0x65 'e' + 0x00,0x00,0x60,0x90,0xf0,0x80,0x80,0x70,0x00, + + 5, // 0x66 'f' + 0x00,0x30,0x40,0x40,0xe0,0x40,0x40,0x40,0x00, + + 5, // 0x67 'g' + 0x00,0x00,0x70,0x90,0x90,0x70,0x10,0x90,0x60, + + 5, // 0x68 'h' + 0x00,0x80,0x80,0xe0,0x90,0x90,0x90,0x90,0x00, + + 5, // 0x69 'i' + 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x70,0x00, + + 5, // 0x6a 'j' + 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0xa0,0x40, + + 5, // 0x6b 'k' + 0x00,0x80,0x80,0x90,0xa0,0xc0,0xa0,0x90,0x00, + + 5, // 0x6c 'l' + 0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00, + + 5, // 0x6d 'm' + 0x00,0x00,0xa0,0xf0,0xf0,0xf0,0x90,0x90,0x00, + + 5, // 0x6e 'n' + 0x00,0x00,0xa0,0xd0,0x90,0x90,0x90,0x90,0x00, + + 5, // 0x6f 'o' + 0x00,0x00,0x60,0x90,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x70 'p' + 0x00,0x00,0xe0,0x90,0x90,0x90,0xe0,0x80,0x80, + + 5, // 0x71 'q' + 0x00,0x00,0x70,0x90,0x90,0x90,0x70,0x10,0x10, + + 5, // 0x72 'r' + 0x00,0x00,0xe0,0x90,0x80,0x80,0x80,0x80,0x00, + + 5, // 0x73 's' + 0x00,0x00,0x60,0x90,0x40,0x20,0x90,0x60,0x00, + + 5, // 0x74 't' + 0x00,0x40,0x40,0xe0,0x40,0x40,0x50,0x20,0x00, + + 5, // 0x75 'u' + 0x00,0x00,0x90,0x90,0x90,0x90,0x90,0x70,0x00, + + 5, // 0x76 'v' + 0x00,0x00,0x50,0x50,0x50,0x50,0x20,0x20,0x00, + + 5, // 0x77 'w' + 0x00,0x00,0x90,0x90,0x90,0x90,0xf0,0x90,0x00, + + 5, // 0x78 'x' + 0x00,0x00,0x90,0x90,0x60,0x60,0x90,0x90,0x00, + + 5, // 0x79 'y' + 0x00,0x00,0x90,0x90,0x90,0x90,0x70,0x10,0xe0, + + 5, // 0x7a 'z' + 0x00,0x00,0xf0,0x10,0x20,0x40,0x80,0xf0,0x00, + + 5, // 0x7b '{' + 0x10,0x20,0x20,0x20,0xc0,0x20,0x20,0x20,0x10, + + 5, // 0x7c '|' + 0x00,0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x00, + + 5, // 0x7d '}' + 0x80,0x40,0x40,0x40,0x30,0x40,0x40,0x40,0x80, + + 5, // 0x7e '~' + 0x00,0x40,0xa8,0x10,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x7f '' + 0x00,0x00,0x00,0x20,0x50,0x88,0xf8,0x00,0x00, + 0 + }; + + const int8u gse6x12[] = + { + 12, 0, 32, 128-32, + + 0x00,0x00,0x0d,0x00,0x1a,0x00,0x27,0x00,0x34,0x00,0x41,0x00,0x4e,0x00,0x5b,0x00,0x68,0x00, + 0x75,0x00,0x82,0x00,0x8f,0x00,0x9c,0x00,0xa9,0x00,0xb6,0x00,0xc3,0x00,0xd0,0x00,0xdd,0x00, + 0xea,0x00,0xf7,0x00,0x04,0x01,0x11,0x01,0x1e,0x01,0x2b,0x01,0x38,0x01,0x45,0x01,0x52,0x01, + 0x5f,0x01,0x6c,0x01,0x79,0x01,0x86,0x01,0x93,0x01,0xa0,0x01,0xad,0x01,0xba,0x01,0xc7,0x01, + 0xd4,0x01,0xe1,0x01,0xee,0x01,0xfb,0x01,0x08,0x02,0x15,0x02,0x22,0x02,0x2f,0x02,0x3c,0x02, + 0x49,0x02,0x56,0x02,0x63,0x02,0x70,0x02,0x7d,0x02,0x8a,0x02,0x97,0x02,0xa4,0x02,0xb1,0x02, + 0xbe,0x02,0xcb,0x02,0xd8,0x02,0xe5,0x02,0xf2,0x02,0xff,0x02,0x0c,0x03,0x19,0x03,0x26,0x03, + 0x33,0x03,0x40,0x03,0x4d,0x03,0x5a,0x03,0x67,0x03,0x74,0x03,0x81,0x03,0x8e,0x03,0x9b,0x03, + 0xa8,0x03,0xb5,0x03,0xc2,0x03,0xcf,0x03,0xdc,0x03,0xe9,0x03,0xf6,0x03,0x03,0x04,0x10,0x04, + 0x1d,0x04,0x2a,0x04,0x37,0x04,0x44,0x04,0x51,0x04,0x5e,0x04,0x6b,0x04,0x78,0x04,0x85,0x04, + 0x92,0x04,0x9f,0x04,0xac,0x04,0xb9,0x04,0xc6,0x04,0xd3,0x04, + + 6, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x21 '!' + 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, + + 6, // 0x22 '"' + 0x00,0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x23 '#' + 0x00,0x50,0x50,0xf8,0x50,0x50,0x50,0xf8,0x50,0x50,0x00,0x00, + + 6, // 0x24 '$' + 0x00,0x20,0x70,0xa8,0xa0,0x70,0x28,0xa8,0x70,0x20,0x00,0x00, + + 6, // 0x25 '%' + 0x00,0xc8,0xd8,0x10,0x30,0x20,0x60,0x40,0xd8,0x98,0x00,0x00, + + 6, // 0x26 '&' + 0x00,0x60,0x90,0x90,0x90,0x60,0xa8,0x90,0x90,0x68,0x00,0x00, + + 6, // 0x27 ''' + 0x00,0x20,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x28 '(' + 0x00,0x10,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x10,0x00,0x00, + + 6, // 0x29 ')' + 0x00,0x40,0x20,0x10,0x10,0x10,0x10,0x10,0x20,0x40,0x00,0x00, + + 6, // 0x2a '*' + 0x00,0x00,0x00,0x50,0x20,0xf8,0x20,0x50,0x00,0x00,0x00,0x00, + + 6, // 0x2b '+' + 0x00,0x00,0x20,0x20,0x20,0xf8,0x20,0x20,0x20,0x00,0x00,0x00, + + 6, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40, + + 6, // 0x2d '-' + 0x00,0x00,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00, + + 6, // 0x2f '/' + 0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80,0x00,0x00, + + 6, // 0x30 '0' + 0x00,0x70,0x88,0x88,0x98,0xa8,0xc8,0x88,0x88,0x70,0x00,0x00, + + 6, // 0x31 '1' + 0x00,0x20,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 6, // 0x32 '2' + 0x00,0x70,0x88,0x88,0x08,0x10,0x20,0x40,0x80,0xf8,0x00,0x00, + + 6, // 0x33 '3' + 0x00,0xf8,0x10,0x20,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00, + + 6, // 0x34 '4' + 0x00,0x10,0x20,0x40,0x90,0x90,0xf8,0x10,0x10,0x10,0x00,0x00, + + 6, // 0x35 '5' + 0x00,0xf8,0x80,0x80,0xf0,0x08,0x08,0x08,0x88,0x70,0x00,0x00, + + 6, // 0x36 '6' + 0x00,0x70,0x88,0x80,0x80,0xf0,0x88,0x88,0x88,0x70,0x00,0x00, + + 6, // 0x37 '7' + 0x00,0xf8,0x88,0x08,0x08,0x10,0x20,0x20,0x20,0x20,0x00,0x00, + + 6, // 0x38 '8' + 0x00,0x70,0x88,0x88,0x88,0x70,0x88,0x88,0x88,0x70,0x00,0x00, + + 6, // 0x39 '9' + 0x00,0x70,0x88,0x88,0x88,0x78,0x08,0x08,0x88,0x70,0x00,0x00, + + 6, // 0x3a ':' + 0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00, + + 6, // 0x3b ';' + 0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x20,0x20,0x40, + + 6, // 0x3c '<' + 0x00,0x08,0x10,0x20,0x40,0x80,0x40,0x20,0x10,0x08,0x00,0x00, + + 6, // 0x3d '=' + 0x00,0x00,0x00,0x00,0xf8,0x00,0xf8,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x3e '>' + 0x00,0x80,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x80,0x00,0x00, + + 6, // 0x3f '?' + 0x00,0x70,0x88,0x88,0x08,0x10,0x20,0x20,0x00,0x20,0x00,0x00, + + 6, // 0x40 '@' + 0x00,0x70,0x88,0x88,0xb8,0xb8,0xb0,0x80,0x88,0x70,0x00,0x00, + + 6, // 0x41 'A' + 0x00,0x20,0x50,0x88,0x88,0x88,0xf8,0x88,0x88,0x88,0x00,0x00, + + 6, // 0x42 'B' + 0x00,0xf0,0x88,0x88,0x88,0xf0,0x88,0x88,0x88,0xf0,0x00,0x00, + + 6, // 0x43 'C' + 0x00,0x70,0x88,0x88,0x80,0x80,0x80,0x88,0x88,0x70,0x00,0x00, + + 6, // 0x44 'D' + 0x00,0xe0,0x90,0x88,0x88,0x88,0x88,0x88,0x90,0xe0,0x00,0x00, + + 6, // 0x45 'E' + 0x00,0xf8,0x80,0x80,0x80,0xf0,0x80,0x80,0x80,0xf8,0x00,0x00, + + 6, // 0x46 'F' + 0x00,0xf8,0x80,0x80,0x80,0xf0,0x80,0x80,0x80,0x80,0x00,0x00, + + 6, // 0x47 'G' + 0x00,0x70,0x88,0x80,0x80,0xb8,0x88,0x88,0x88,0x70,0x00,0x00, + + 6, // 0x48 'H' + 0x00,0x88,0x88,0x88,0x88,0xf8,0x88,0x88,0x88,0x88,0x00,0x00, + + 6, // 0x49 'I' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 6, // 0x4a 'J' + 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x90,0x60,0x00,0x00, + + 6, // 0x4b 'K' + 0x00,0x88,0x88,0x90,0xa0,0xc0,0xa0,0x90,0x88,0x88,0x00,0x00, + + 6, // 0x4c 'L' + 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xf8,0x00,0x00, + + 6, // 0x4d 'M' + 0x00,0x88,0x88,0xd8,0xa8,0x88,0x88,0x88,0x88,0x88,0x00,0x00, + + 6, // 0x4e 'N' + 0x00,0x88,0x88,0xc8,0xa8,0x98,0x88,0x88,0x88,0x88,0x00,0x00, + + 6, // 0x4f 'O' + 0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, + + 6, // 0x50 'P' + 0x00,0xf0,0x88,0x88,0x88,0xf0,0x80,0x80,0x80,0x80,0x00,0x00, + + 6, // 0x51 'Q' + 0x00,0x70,0x88,0x88,0x88,0x88,0x88,0xa8,0x90,0x68,0x00,0x00, + + 6, // 0x52 'R' + 0x00,0xf0,0x88,0x88,0x88,0x88,0xf0,0xa0,0x90,0x88,0x00,0x00, + + 6, // 0x53 'S' + 0x00,0x70,0x88,0x80,0x80,0x70,0x08,0x08,0x88,0x70,0x00,0x00, + + 6, // 0x54 'T' + 0x00,0xf8,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00, + + 6, // 0x55 'U' + 0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, + + 6, // 0x56 'V' + 0x00,0x88,0x88,0x88,0x88,0x88,0x50,0x50,0x20,0x20,0x00,0x00, + + 6, // 0x57 'W' + 0x00,0x88,0x88,0x88,0x88,0x88,0xa8,0xa8,0xd8,0x88,0x00,0x00, + + 6, // 0x58 'X' + 0x00,0x88,0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x88,0x00,0x00, + + 6, // 0x59 'Y' + 0x00,0x88,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x20,0x00,0x00, + + 6, // 0x5a 'Z' + 0x00,0xf8,0x08,0x08,0x10,0x20,0x40,0x80,0x80,0xf8,0x00,0x00, + + 6, // 0x5b '[' + 0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x70,0x00, + + 6, // 0x5c '\' + 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00,0x00, + + 6, // 0x5d ']' + 0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70,0x00, + + 6, // 0x5e '^' + 0x00,0x00,0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x00,0x00, + + 6, // 0x60 '`' + 0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x61 'a' + 0x00,0x00,0x00,0x70,0x88,0x08,0x78,0x88,0x88,0x78,0x00,0x00, + + 6, // 0x62 'b' + 0x00,0x80,0x80,0x80,0xf0,0x88,0x88,0x88,0x88,0xf0,0x00,0x00, + + 6, // 0x63 'c' + 0x00,0x00,0x00,0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x00,0x00, + + 6, // 0x64 'd' + 0x00,0x08,0x08,0x08,0x78,0x88,0x88,0x88,0x88,0x78,0x00,0x00, + + 6, // 0x65 'e' + 0x00,0x00,0x00,0x70,0x88,0x88,0xf8,0x80,0x80,0x78,0x00,0x00, + + 6, // 0x66 'f' + 0x00,0x18,0x20,0x20,0xf8,0x20,0x20,0x20,0x20,0x20,0x00,0x00, + + 6, // 0x67 'g' + 0x00,0x00,0x00,0x78,0x88,0x88,0x88,0x88,0x78,0x08,0x08,0xf0, + + 6, // 0x68 'h' + 0x00,0x80,0x80,0x80,0xf0,0x88,0x88,0x88,0x88,0x88,0x00,0x00, + + 6, // 0x69 'i' + 0x00,0x20,0x00,0x00,0x60,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 6, // 0x6a 'j' + 0x00,0x10,0x00,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x90,0x60, + + 6, // 0x6b 'k' + 0x00,0x80,0x80,0x80,0x88,0x90,0xa0,0xd0,0x88,0x88,0x00,0x00, + + 6, // 0x6c 'l' + 0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 6, // 0x6d 'm' + 0x00,0x00,0x00,0xd0,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0x00,0x00, + + 6, // 0x6e 'n' + 0x00,0x00,0x00,0xb0,0xc8,0x88,0x88,0x88,0x88,0x88,0x00,0x00, + + 6, // 0x6f 'o' + 0x00,0x00,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, + + 6, // 0x70 'p' + 0x00,0x00,0x00,0xf0,0x88,0x88,0x88,0x88,0xf0,0x80,0x80,0x80, + + 6, // 0x71 'q' + 0x00,0x00,0x00,0x78,0x88,0x88,0x88,0x88,0x78,0x08,0x08,0x08, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0xb0,0xc8,0x88,0x80,0x80,0x80,0x80,0x00,0x00, + + 6, // 0x73 's' + 0x00,0x00,0x00,0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00,0x00, + + 6, // 0x74 't' + 0x00,0x40,0x40,0x40,0xe0,0x40,0x40,0x40,0x48,0x30,0x00,0x00, + + 6, // 0x75 'u' + 0x00,0x00,0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x78,0x00,0x00, + + 6, // 0x76 'v' + 0x00,0x00,0x00,0x88,0x88,0x88,0x50,0x50,0x20,0x20,0x00,0x00, + + 6, // 0x77 'w' + 0x00,0x00,0x00,0x88,0x88,0x88,0xa8,0xa8,0xd8,0x88,0x00,0x00, + + 6, // 0x78 'x' + 0x00,0x00,0x00,0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00,0x00, + + 6, // 0x79 'y' + 0x00,0x00,0x00,0x88,0x88,0x88,0x88,0x88,0x78,0x08,0x10,0xe0, + + 6, // 0x7a 'z' + 0x00,0x00,0x00,0xf8,0x08,0x10,0x20,0x40,0x80,0xf8,0x00,0x00, + + 6, // 0x7b '{' + 0x18,0x20,0x20,0x20,0x20,0xc0,0x20,0x20,0x20,0x20,0x18,0x00, + + 6, // 0x7c '|' + 0x00,0x20,0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x20,0x00,0x00, + + 6, // 0x7d '}' + 0xc0,0x20,0x20,0x20,0x20,0x18,0x20,0x20,0x20,0x20,0xc0,0x00, + + 6, // 0x7e '~' + 0x00,0x00,0x40,0xa8,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x7f '' + 0x00,0x00,0x00,0x00,0x20,0x50,0x88,0xf8,0x00,0x00,0x00,0x00, + 0 + }; + + const int8u gse6x9[] = + { + 9, 0, 32, 128-32, + + 0x00,0x00,0x0a,0x00,0x14,0x00,0x1e,0x00,0x28,0x00,0x32,0x00,0x3c,0x00,0x46,0x00,0x50,0x00, + 0x5a,0x00,0x64,0x00,0x6e,0x00,0x78,0x00,0x82,0x00,0x8c,0x00,0x96,0x00,0xa0,0x00,0xaa,0x00, + 0xb4,0x00,0xbe,0x00,0xc8,0x00,0xd2,0x00,0xdc,0x00,0xe6,0x00,0xf0,0x00,0xfa,0x00,0x04,0x01, + 0x0e,0x01,0x18,0x01,0x22,0x01,0x2c,0x01,0x36,0x01,0x40,0x01,0x4a,0x01,0x54,0x01,0x5e,0x01, + 0x68,0x01,0x72,0x01,0x7c,0x01,0x86,0x01,0x90,0x01,0x9a,0x01,0xa4,0x01,0xae,0x01,0xb8,0x01, + 0xc2,0x01,0xcc,0x01,0xd6,0x01,0xe0,0x01,0xea,0x01,0xf4,0x01,0xfe,0x01,0x08,0x02,0x12,0x02, + 0x1c,0x02,0x26,0x02,0x30,0x02,0x3a,0x02,0x44,0x02,0x4e,0x02,0x58,0x02,0x62,0x02,0x6c,0x02, + 0x76,0x02,0x80,0x02,0x8a,0x02,0x94,0x02,0x9e,0x02,0xa8,0x02,0xb2,0x02,0xbc,0x02,0xc6,0x02, + 0xd0,0x02,0xda,0x02,0xe4,0x02,0xee,0x02,0xf8,0x02,0x02,0x03,0x0c,0x03,0x16,0x03,0x20,0x03, + 0x2a,0x03,0x34,0x03,0x3e,0x03,0x48,0x03,0x52,0x03,0x5c,0x03,0x66,0x03,0x70,0x03,0x7a,0x03, + 0x84,0x03,0x8e,0x03,0x98,0x03,0xa2,0x03,0xac,0x03,0xb6,0x03, + + 6, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x21 '!' + 0x00,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00, + + 6, // 0x22 '"' + 0x00,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x23 '#' + 0x00,0x50,0x50,0xf8,0x50,0xf8,0x50,0x50,0x00, + + 6, // 0x24 '$' + 0x00,0x70,0xa8,0xa0,0x70,0x28,0xa8,0x70,0x00, + + 6, // 0x25 '%' + 0x00,0xc8,0xc8,0x10,0x20,0x40,0x98,0x98,0x00, + + 6, // 0x26 '&' + 0x00,0x60,0x90,0x90,0x60,0xa8,0x90,0x68,0x00, + + 6, // 0x27 ''' + 0x00,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x28 '(' + 0x10,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x10, + + 6, // 0x29 ')' + 0x40,0x20,0x10,0x10,0x10,0x10,0x10,0x20,0x40, + + 6, // 0x2a '*' + 0x00,0x00,0x20,0xa8,0x70,0xa8,0x20,0x00,0x00, + + 6, // 0x2b '+' + 0x00,0x00,0x20,0x20,0xf8,0x20,0x20,0x00,0x00, + + 6, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x40, + + 6, // 0x2d '-' + 0x00,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00, + + 6, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00, + + 6, // 0x2f '/' + 0x00,0x08,0x08,0x10,0x20,0x40,0x80,0x80,0x00, + + 6, // 0x30 '0' + 0x00,0x70,0x88,0x98,0xa8,0xc8,0x88,0x70,0x00, + + 6, // 0x31 '1' + 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x70,0x00, + + 6, // 0x32 '2' + 0x00,0x70,0x88,0x08,0x10,0x20,0x40,0xf8,0x00, + + 6, // 0x33 '3' + 0x00,0xf8,0x10,0x20,0x70,0x08,0x88,0x70,0x00, + + 6, // 0x34 '4' + 0x00,0x10,0x20,0x40,0x90,0xf8,0x10,0x10,0x00, + + 6, // 0x35 '5' + 0x00,0xf8,0x80,0xf0,0x08,0x08,0x88,0x70,0x00, + + 6, // 0x36 '6' + 0x00,0x70,0x88,0x80,0xf0,0x88,0x88,0x70,0x00, + + 6, // 0x37 '7' + 0x00,0xf8,0x08,0x08,0x10,0x20,0x40,0x40,0x00, + + 6, // 0x38 '8' + 0x00,0x70,0x88,0x88,0x70,0x88,0x88,0x70,0x00, + + 6, // 0x39 '9' + 0x00,0x70,0x88,0x88,0x78,0x08,0x88,0x70,0x00, + + 6, // 0x3a ':' + 0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x00,0x00, + + 6, // 0x3b ';' + 0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x20,0x40, + + 6, // 0x3c '<' + 0x00,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x00, + + 6, // 0x3d '=' + 0x00,0x00,0x00,0xf8,0x00,0xf8,0x00,0x00,0x00, + + 6, // 0x3e '>' + 0x00,0x80,0x40,0x20,0x10,0x20,0x40,0x80,0x00, + + 6, // 0x3f '?' + 0x00,0x70,0x88,0x08,0x10,0x20,0x00,0x20,0x00, + + 6, // 0x40 '@' + 0x00,0x70,0x88,0x88,0xb8,0xb8,0x80,0x70,0x00, + + 6, // 0x41 'A' + 0x00,0x20,0x50,0x88,0x88,0xf8,0x88,0x88,0x00, + + 6, // 0x42 'B' + 0x00,0xf0,0x88,0x88,0xf0,0x88,0x88,0xf0,0x00, + + 6, // 0x43 'C' + 0x00,0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x00, + + 6, // 0x44 'D' + 0x00,0xe0,0x90,0x88,0x88,0x88,0x90,0xe0,0x00, + + 6, // 0x45 'E' + 0x00,0xf8,0x80,0x80,0xf0,0x80,0x80,0xf8,0x00, + + 6, // 0x46 'F' + 0x00,0xf8,0x80,0x80,0xf0,0x80,0x80,0x80,0x00, + + 6, // 0x47 'G' + 0x00,0x70,0x88,0x80,0xb8,0x88,0x88,0x70,0x00, + + 6, // 0x48 'H' + 0x00,0x88,0x88,0x88,0xf8,0x88,0x88,0x88,0x00, + + 6, // 0x49 'I' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00, + + 6, // 0x4a 'J' + 0x00,0x38,0x10,0x10,0x10,0x10,0x90,0x60,0x00, + + 6, // 0x4b 'K' + 0x00,0x88,0x90,0xa0,0xc0,0xa0,0x90,0x88,0x00, + + 6, // 0x4c 'L' + 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0xf8,0x00, + + 6, // 0x4d 'M' + 0x00,0x88,0xd8,0xa8,0x88,0x88,0x88,0x88,0x00, + + 6, // 0x4e 'N' + 0x00,0x88,0x88,0xc8,0xa8,0x98,0x88,0x88,0x00, + + 6, // 0x4f 'O' + 0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00, + + 6, // 0x50 'P' + 0x00,0xf0,0x88,0x88,0xf0,0x80,0x80,0x80,0x00, + + 6, // 0x51 'Q' + 0x00,0x70,0x88,0x88,0x88,0xa8,0x90,0x68,0x00, + + 6, // 0x52 'R' + 0x00,0xf0,0x88,0x88,0x88,0xf0,0x90,0x88,0x00, + + 6, // 0x53 'S' + 0x00,0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00, + + 6, // 0x54 'T' + 0x00,0xf8,0x20,0x20,0x20,0x20,0x20,0x20,0x00, + + 6, // 0x55 'U' + 0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00, + + 6, // 0x56 'V' + 0x00,0x88,0x88,0x88,0x50,0x50,0x20,0x20,0x00, + + 6, // 0x57 'W' + 0x00,0x88,0x88,0x88,0xa8,0xa8,0xd8,0x88,0x00, + + 6, // 0x58 'X' + 0x00,0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00, + + 6, // 0x59 'Y' + 0x00,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00, + + 6, // 0x5a 'Z' + 0x00,0xf8,0x08,0x10,0x20,0x40,0x80,0xf8,0x00, + + 6, // 0x5b '[' + 0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x70, + + 6, // 0x5c '\' + 0x00,0x80,0x80,0x40,0x20,0x10,0x08,0x08,0x00, + + 6, // 0x5d ']' + 0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70, + + 6, // 0x5e '^' + 0x00,0x00,0x20,0x50,0x88,0x00,0x00,0x00,0x00, + + 6, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x00, + + 6, // 0x60 '`' + 0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x61 'a' + 0x00,0x00,0x00,0x70,0x08,0x78,0x88,0x78,0x00, + + 6, // 0x62 'b' + 0x00,0x80,0x80,0xf0,0x88,0x88,0x88,0xf0,0x00, + + 6, // 0x63 'c' + 0x00,0x00,0x00,0x70,0x88,0x80,0x88,0x70,0x00, + + 6, // 0x64 'd' + 0x00,0x08,0x08,0x78,0x88,0x88,0x88,0x78,0x00, + + 6, // 0x65 'e' + 0x00,0x00,0x00,0x70,0x88,0xf8,0x80,0x78,0x00, + + 6, // 0x66 'f' + 0x00,0x18,0x20,0x20,0xf8,0x20,0x20,0x20,0x00, + + 6, // 0x67 'g' + 0x00,0x00,0x00,0x78,0x88,0x88,0x78,0x08,0x70, + + 6, // 0x68 'h' + 0x00,0x80,0x80,0xf0,0x88,0x88,0x88,0x88,0x00, + + 6, // 0x69 'i' + 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x70,0x00, + + 6, // 0x6a 'j' + 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x90,0x60, + + 6, // 0x6b 'k' + 0x00,0x00,0x80,0x88,0x90,0xa0,0xd0,0x88,0x00, + + 6, // 0x6c 'l' + 0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00, + + 6, // 0x6d 'm' + 0x00,0x00,0x00,0xd0,0xa8,0xa8,0xa8,0xa8,0x00, + + 6, // 0x6e 'n' + 0x00,0x00,0x00,0xb0,0xc8,0x88,0x88,0x88,0x00, + + 6, // 0x6f 'o' + 0x00,0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00, + + 6, // 0x70 'p' + 0x00,0x00,0x00,0xf0,0x88,0x88,0xf0,0x80,0x80, + + 6, // 0x71 'q' + 0x00,0x00,0x00,0x78,0x88,0x88,0x78,0x08,0x08, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0xb8,0xc0,0x80,0x80,0x80,0x00, + + 6, // 0x73 's' + 0x00,0x00,0x00,0x78,0x80,0x70,0x08,0xf0,0x00, + + 6, // 0x74 't' + 0x00,0x40,0x40,0xe0,0x40,0x40,0x48,0x30,0x00, + + 6, // 0x75 'u' + 0x00,0x00,0x00,0x88,0x88,0x88,0x88,0x78,0x00, + + 6, // 0x76 'v' + 0x00,0x00,0x00,0x88,0x88,0x88,0x50,0x20,0x00, + + 6, // 0x77 'w' + 0x00,0x00,0x00,0x88,0x88,0xa8,0xd8,0x88,0x00, + + 6, // 0x78 'x' + 0x00,0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x00, + + 6, // 0x79 'y' + 0x00,0x00,0x00,0x88,0x88,0x88,0x78,0x08,0x70, + + 6, // 0x7a 'z' + 0x00,0x00,0x00,0xf8,0x10,0x20,0x40,0xf8,0x00, + + 6, // 0x7b '{' + 0x18,0x20,0x20,0x20,0xc0,0x20,0x20,0x20,0x18, + + 6, // 0x7c '|' + 0x00,0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x00, + + 6, // 0x7d '}' + 0xc0,0x20,0x20,0x20,0x18,0x20,0x20,0x20,0xc0, + + 6, // 0x7e '~' + 0x00,0x40,0xa8,0x10,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x7f '' + 0x00,0x00,0x00,0x20,0x50,0x88,0xf8,0x00,0x00, + 0 + }; + + const int8u gse7x11[] = + { + 11, 0, 32, 128-32, + + 0x00,0x00,0x0c,0x00,0x18,0x00,0x24,0x00,0x30,0x00,0x3c,0x00,0x48,0x00,0x54,0x00,0x60,0x00, + 0x6c,0x00,0x78,0x00,0x84,0x00,0x90,0x00,0x9c,0x00,0xa8,0x00,0xb4,0x00,0xc0,0x00,0xcc,0x00, + 0xd8,0x00,0xe4,0x00,0xf0,0x00,0xfc,0x00,0x08,0x01,0x14,0x01,0x20,0x01,0x2c,0x01,0x38,0x01, + 0x44,0x01,0x50,0x01,0x5c,0x01,0x68,0x01,0x74,0x01,0x80,0x01,0x8c,0x01,0x98,0x01,0xa4,0x01, + 0xb0,0x01,0xbc,0x01,0xc8,0x01,0xd4,0x01,0xe0,0x01,0xec,0x01,0xf8,0x01,0x04,0x02,0x10,0x02, + 0x1c,0x02,0x28,0x02,0x34,0x02,0x40,0x02,0x4c,0x02,0x58,0x02,0x64,0x02,0x70,0x02,0x7c,0x02, + 0x88,0x02,0x94,0x02,0xa0,0x02,0xac,0x02,0xb8,0x02,0xc4,0x02,0xd0,0x02,0xdc,0x02,0xe8,0x02, + 0xf4,0x02,0x00,0x03,0x0c,0x03,0x18,0x03,0x24,0x03,0x30,0x03,0x3c,0x03,0x48,0x03,0x54,0x03, + 0x60,0x03,0x6c,0x03,0x78,0x03,0x84,0x03,0x90,0x03,0x9c,0x03,0xa8,0x03,0xb4,0x03,0xc0,0x03, + 0xcc,0x03,0xd8,0x03,0xe4,0x03,0xf0,0x03,0xfc,0x03,0x08,0x04,0x14,0x04,0x20,0x04,0x2c,0x04, + 0x38,0x04,0x44,0x04,0x50,0x04,0x5c,0x04,0x68,0x04,0x74,0x04, + + 7, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x21 '!' + 0x00,0x10,0x38,0x38,0x38,0x10,0x10,0x00,0x10,0x00,0x00, + + 7, // 0x22 '"' + 0x00,0x00,0x24,0x24,0x24,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x23 '#' + 0x00,0x48,0x48,0xfc,0x48,0x48,0xfc,0x48,0x48,0x00,0x00, + + 7, // 0x24 '$' + 0x00,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x00, + + 7, // 0x25 '%' + 0x00,0x00,0x42,0xa4,0x48,0x10,0x24,0x4a,0x84,0x00,0x00, + + 7, // 0x26 '&' + 0x00,0x30,0x48,0x48,0x30,0x60,0x94,0x98,0x6c,0x00,0x00, + + 7, // 0x27 ''' + 0x00,0x20,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x28 '(' + 0x00,0x04,0x08,0x10,0x10,0x10,0x10,0x08,0x04,0x00,0x00, + + 7, // 0x29 ')' + 0x00,0x40,0x20,0x10,0x10,0x10,0x10,0x20,0x40,0x00,0x00, + + 7, // 0x2a '*' + 0x00,0x00,0x00,0x20,0xa8,0x70,0xa8,0x20,0x00,0x00,0x00, + + 7, // 0x2b '+' + 0x00,0x00,0x00,0x10,0x10,0x7c,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x60, + + 7, // 0x2d '-' + 0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00, + + 7, // 0x2f '/' + 0x00,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00,0x00, + + 7, // 0x30 '0' + 0x00,0x38,0x44,0x4c,0x54,0x64,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x31 '1' + 0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x7c,0x00,0x00, + + 7, // 0x32 '2' + 0x00,0x38,0x44,0x04,0x08,0x10,0x20,0x44,0x7c,0x00,0x00, + + 7, // 0x33 '3' + 0x00,0x7c,0x48,0x10,0x38,0x04,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x34 '4' + 0x00,0x08,0x10,0x20,0x48,0x48,0x7c,0x08,0x1c,0x00,0x00, + + 7, // 0x35 '5' + 0x00,0x7c,0x40,0x40,0x78,0x04,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x36 '6' + 0x00,0x18,0x20,0x40,0x78,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x37 '7' + 0x00,0x7c,0x44,0x04,0x08,0x10,0x10,0x10,0x10,0x00,0x00, + + 7, // 0x38 '8' + 0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x39 '9' + 0x00,0x38,0x44,0x44,0x44,0x3c,0x04,0x08,0x30,0x00,0x00, + + 7, // 0x3a ':' + 0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00, + + 7, // 0x3b ';' + 0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x30,0x60,0x00, + + 7, // 0x3c '<' + 0x00,0x00,0x04,0x08,0x10,0x20,0x10,0x08,0x04,0x00,0x00, + + 7, // 0x3d '=' + 0x00,0x00,0x00,0x00,0xfc,0x00,0xfc,0x00,0x00,0x00,0x00, + + 7, // 0x3e '>' + 0x00,0x00,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00,0x00, + + 7, // 0x3f '?' + 0x00,0x70,0x88,0x88,0x10,0x20,0x20,0x00,0x20,0x00,0x00, + + 7, // 0x40 '@' + 0x00,0x30,0x48,0x04,0x34,0x54,0x54,0x54,0x28,0x00,0x00, + + 7, // 0x41 'A' + 0x00,0x10,0x28,0x44,0x44,0x7c,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x42 'B' + 0x00,0x78,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00,0x00, + + 7, // 0x43 'C' + 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00, + + 7, // 0x44 'D' + 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00, + + 7, // 0x45 'E' + 0x00,0x7c,0x40,0x40,0x70,0x40,0x40,0x40,0x7c,0x00,0x00, + + 7, // 0x46 'F' + 0x00,0x7c,0x40,0x40,0x70,0x40,0x40,0x40,0x40,0x00,0x00, + + 7, // 0x47 'G' + 0x00,0x38,0x44,0x40,0x40,0x5c,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x48 'H' + 0x00,0x44,0x44,0x44,0x7c,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x49 'I' + 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 7, // 0x4a 'J' + 0x00,0x1c,0x08,0x08,0x08,0x08,0x08,0x48,0x30,0x00,0x00, + + 7, // 0x4b 'K' + 0x00,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x44,0x00,0x00, + + 7, // 0x4c 'L' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7c,0x00,0x00, + + 7, // 0x4d 'M' + 0x00,0x44,0x6c,0x54,0x54,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x4e 'N' + 0x00,0x44,0x44,0x64,0x54,0x4c,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x4f 'O' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00, + + 7, // 0x51 'Q' + 0x00,0x38,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00, + + 7, // 0x52 'R' + 0x00,0x78,0x44,0x44,0x44,0x78,0x50,0x48,0x44,0x00,0x00, + + 7, // 0x53 'S' + 0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x54 'T' + 0x00,0x7c,0x54,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 7, // 0x55 'U' + 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x56 'V' + 0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00, + + 7, // 0x57 'W' + 0x00,0x44,0x44,0x44,0x44,0x54,0x54,0x6c,0x44,0x00,0x00, + + 7, // 0x58 'X' + 0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x38,0x00,0x00, + + 7, // 0x5a 'Z' + 0x00,0x7c,0x04,0x08,0x10,0x20,0x40,0x44,0x7c,0x00,0x00, + + 7, // 0x5b '[' + 0x00,0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00,0x00, + + 7, // 0x5c '\' + 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00,0x00, + + 7, // 0x5d ']' + 0x00,0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x38,0x00,0x00, + + 7, // 0x5e '^' + 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00, + + 7, // 0x60 '`' + 0x00,0x20,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x61 'a' + 0x00,0x00,0x00,0x38,0x04,0x3c,0x44,0x44,0x3c,0x00,0x00, + + 7, // 0x62 'b' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x78,0x00,0x00, + + 7, // 0x63 'c' + 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x44,0x38,0x00,0x00, + + 7, // 0x64 'd' + 0x00,0x04,0x04,0x3c,0x44,0x44,0x44,0x44,0x3c,0x00,0x00, + + 7, // 0x65 'e' + 0x00,0x00,0x00,0x38,0x44,0x7c,0x40,0x44,0x38,0x00,0x00, + + 7, // 0x66 'f' + 0x00,0x18,0x24,0x20,0x70,0x20,0x20,0x20,0x70,0x00,0x00, + + 7, // 0x67 'g' + 0x00,0x00,0x00,0x3c,0x44,0x44,0x44,0x3c,0x04,0x44,0x38, + + 7, // 0x68 'h' + 0x00,0x40,0x40,0x40,0x58,0x64,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x69 'i' + 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 7, // 0x6a 'j' + 0x00,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x48,0x30,0x00, + + 7, // 0x6b 'k' + 0x00,0x40,0x40,0x44,0x48,0x50,0x68,0x44,0x44,0x00,0x00, + + 7, // 0x6c 'l' + 0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 7, // 0x6d 'm' + 0x00,0x00,0x00,0xa8,0x54,0x54,0x54,0x54,0x54,0x00,0x00, + + 7, // 0x6e 'n' + 0x00,0x00,0x00,0xb8,0x44,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x6f 'o' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x70 'p' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40, + + 7, // 0x71 'q' + 0x00,0x00,0x00,0x3c,0x44,0x44,0x44,0x44,0x3c,0x04,0x04, + + 7, // 0x72 'r' + 0x00,0x00,0x00,0x58,0x64,0x44,0x40,0x40,0x40,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x3c,0x40,0x38,0x04,0x04,0x78,0x00,0x00, + + 7, // 0x74 't' + 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x24,0x18,0x00,0x00, + + 7, // 0x75 'u' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x3a,0x00,0x00, + + 7, // 0x76 'v' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x28,0x10,0x00,0x00, + + 7, // 0x77 'w' + 0x00,0x00,0x00,0x44,0x44,0x54,0x54,0x6c,0x44,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, + + 7, // 0x79 'y' + 0x00,0x00,0x00,0x44,0x44,0x44,0x3c,0x04,0x08,0x30,0x00, + + 7, // 0x7a 'z' + 0x00,0x00,0x00,0x7c,0x08,0x10,0x20,0x44,0x7c,0x00,0x00, + + 7, // 0x7b '{' + 0x00,0x0c,0x10,0x10,0x10,0x60,0x10,0x10,0x0c,0x00,0x00, + + 7, // 0x7c '|' + 0x00,0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x20,0x00,0x00, + + 7, // 0x7d '}' + 0x00,0x60,0x10,0x10,0x10,0x0c,0x10,0x10,0x60,0x00,0x00, + + 7, // 0x7e '~' + 0x00,0x00,0x64,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x7f '' + 0x00,0x00,0x00,0x10,0x28,0x44,0x44,0x7c,0x00,0x00,0x00, + 0 + }; + + const int8u gse7x11_bold[] = + { + 11, 0, 32, 128-32, + + 0x00,0x00,0x0c,0x00,0x18,0x00,0x24,0x00,0x30,0x00,0x3c,0x00,0x48,0x00,0x54,0x00,0x60,0x00, + 0x6c,0x00,0x78,0x00,0x84,0x00,0x90,0x00,0x9c,0x00,0xa8,0x00,0xb4,0x00,0xc0,0x00,0xcc,0x00, + 0xd8,0x00,0xe4,0x00,0xf0,0x00,0xfc,0x00,0x08,0x01,0x14,0x01,0x20,0x01,0x2c,0x01,0x38,0x01, + 0x44,0x01,0x50,0x01,0x5c,0x01,0x68,0x01,0x74,0x01,0x80,0x01,0x8c,0x01,0x98,0x01,0xa4,0x01, + 0xb0,0x01,0xbc,0x01,0xc8,0x01,0xd4,0x01,0xe0,0x01,0xec,0x01,0xf8,0x01,0x04,0x02,0x10,0x02, + 0x1c,0x02,0x28,0x02,0x34,0x02,0x40,0x02,0x4c,0x02,0x58,0x02,0x64,0x02,0x70,0x02,0x7c,0x02, + 0x88,0x02,0x94,0x02,0xa0,0x02,0xac,0x02,0xb8,0x02,0xc4,0x02,0xd0,0x02,0xdc,0x02,0xe8,0x02, + 0xf4,0x02,0x00,0x03,0x0c,0x03,0x18,0x03,0x24,0x03,0x30,0x03,0x3c,0x03,0x48,0x03,0x54,0x03, + 0x60,0x03,0x6c,0x03,0x78,0x03,0x84,0x03,0x90,0x03,0x9c,0x03,0xa8,0x03,0xb4,0x03,0xc0,0x03, + 0xcc,0x03,0xd8,0x03,0xe4,0x03,0xf0,0x03,0xfc,0x03,0x08,0x04,0x14,0x04,0x20,0x04,0x2c,0x04, + 0x38,0x04,0x44,0x04,0x50,0x04,0x5c,0x04,0x68,0x04,0x74,0x04, + + 7, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x21 '!' + 0x00,0x30,0x30,0x30,0x30,0x30,0x00,0x30,0x30,0x00,0x00, + + 7, // 0x22 '"' + 0x00,0x6c,0x6c,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x23 '#' + 0x00,0x48,0x48,0xfc,0x48,0x48,0xfc,0x48,0x48,0x00,0x00, + + 7, // 0x24 '$' + 0x30,0x30,0x78,0xcc,0xc0,0x78,0x0c,0xcc,0x78,0x30,0x30, + + 7, // 0x25 '%' + 0x00,0x00,0xc4,0x0c,0x18,0x30,0x60,0xc0,0x8c,0x00,0x00, + + 7, // 0x26 '&' + 0x00,0x30,0x58,0x58,0x30,0x74,0xdc,0xd8,0x6c,0x00,0x00, + + 7, // 0x27 ''' + 0x00,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x28 '(' + 0x00,0x0c,0x18,0x30,0x30,0x30,0x30,0x18,0x0c,0x00,0x00, + + 7, // 0x29 ')' + 0x00,0xc0,0x60,0x30,0x30,0x30,0x30,0x60,0xc0,0x00,0x00, + + 7, // 0x2a '*' + 0x00,0x00,0x00,0x20,0xa8,0x70,0xa8,0x20,0x00,0x00,0x00, + + 7, // 0x2b '+' + 0x00,0x00,0x00,0x30,0x30,0xfc,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x60,0x00, + + 7, // 0x2d '-' + 0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00, + + 7, // 0x2f '/' + 0x00,0x0c,0x0c,0x18,0x18,0x30,0x30,0x60,0x60,0x00,0x00, + + 7, // 0x30 '0' + 0x00,0x78,0xcc,0xcc,0xdc,0xec,0xcc,0xcc,0x78,0x00,0x00, + + 7, // 0x31 '1' + 0x00,0x30,0x70,0xf0,0x30,0x30,0x30,0x30,0xfc,0x00,0x00, + + 7, // 0x32 '2' + 0x00,0x78,0xcc,0xcc,0x18,0x30,0x60,0xcc,0xfc,0x00,0x00, + + 7, // 0x33 '3' + 0x00,0xfc,0x98,0x30,0x78,0x0c,0x0c,0xcc,0x78,0x00,0x00, + + 7, // 0x34 '4' + 0x00,0x18,0x30,0x68,0xd8,0xd8,0xfc,0x18,0x3c,0x00,0x00, + + 7, // 0x35 '5' + 0x00,0xfc,0xc0,0xc0,0xf8,0x0c,0x0c,0xcc,0x78,0x00,0x00, + + 7, // 0x36 '6' + 0x00,0x38,0x60,0xc0,0xf8,0xcc,0xcc,0xcc,0x78,0x00,0x00, + + 7, // 0x37 '7' + 0x00,0xfc,0x8c,0x0c,0x18,0x30,0x30,0x30,0x30,0x00,0x00, + + 7, // 0x38 '8' + 0x00,0x78,0xcc,0xcc,0x78,0xcc,0xcc,0xcc,0x78,0x00,0x00, + + 7, // 0x39 '9' + 0x00,0x78,0xcc,0xcc,0xcc,0x7c,0x0c,0x18,0x70,0x00,0x00, + + 7, // 0x3a ':' + 0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x3b ';' + 0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x30,0x60,0x00, + + 7, // 0x3c '<' + 0x00,0x00,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x00,0x00, + + 7, // 0x3d '=' + 0x00,0x00,0x00,0x00,0xfc,0x00,0xfc,0x00,0x00,0x00,0x00, + + 7, // 0x3e '>' + 0x00,0x00,0x60,0x30,0x18,0x0c,0x18,0x30,0x60,0x00,0x00, + + 7, // 0x3f '?' + 0x00,0x78,0xcc,0xcc,0x18,0x30,0x30,0x00,0x30,0x00,0x00, + + 7, // 0x40 '@' + 0x00,0x70,0x88,0x04,0x74,0xb4,0xb4,0xb4,0x68,0x00,0x00, + + 7, // 0x41 'A' + 0x00,0x30,0x78,0xcc,0xcc,0xfc,0xcc,0xcc,0xcc,0x00,0x00, + + 7, // 0x42 'B' + 0x00,0xf8,0xcc,0xcc,0xf8,0xcc,0xcc,0xcc,0xf8,0x00,0x00, + + 7, // 0x43 'C' + 0x00,0x78,0xcc,0xc0,0xc0,0xc0,0xc0,0xcc,0x78,0x00,0x00, + + 7, // 0x44 'D' + 0x00,0xf0,0xd8,0xcc,0xcc,0xcc,0xcc,0xd8,0xf0,0x00,0x00, + + 7, // 0x45 'E' + 0x00,0xfc,0xc4,0xd0,0xf0,0xd0,0xc0,0xc4,0xfc,0x00,0x00, + + 7, // 0x46 'F' + 0x00,0xfc,0xc4,0xd0,0xf0,0xd0,0xc0,0xc0,0xc0,0x00,0x00, + + 7, // 0x47 'G' + 0x00,0x78,0xcc,0xc0,0xc0,0xdc,0xcc,0xcc,0x78,0x00,0x00, + + 7, // 0x48 'H' + 0x00,0xcc,0xcc,0xcc,0xfc,0xcc,0xcc,0xcc,0xcc,0x00,0x00, + + 7, // 0x49 'I' + 0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00, + + 7, // 0x4a 'J' + 0x00,0x3c,0x18,0x18,0x18,0x18,0xd8,0xd8,0x70,0x00,0x00, + + 7, // 0x4b 'K' + 0x00,0xcc,0xcc,0xd8,0xf0,0xd8,0xcc,0xcc,0xcc,0x00,0x00, + + 7, // 0x4c 'L' + 0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc4,0xfc,0x00,0x00, + + 7, // 0x4d 'M' + 0x00,0x84,0xcc,0xfc,0xb4,0xcc,0xcc,0xcc,0xcc,0x00,0x00, + + 7, // 0x4e 'N' + 0x00,0xcc,0xcc,0xec,0xfc,0xdc,0xcc,0xcc,0xcc,0x00,0x00, + + 7, // 0x4f 'O' + 0x00,0x78,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0xf8,0xcc,0xcc,0xcc,0xf8,0xc0,0xc0,0xc0,0x00,0x00, + + 7, // 0x51 'Q' + 0x00,0x78,0xcc,0xcc,0xcc,0xcc,0xdc,0x78,0x18,0x0c,0x00, + + 7, // 0x52 'R' + 0x00,0xf8,0xcc,0xcc,0xcc,0xf8,0xd8,0xcc,0xcc,0x00,0x00, + + 7, // 0x53 'S' + 0x00,0x78,0xcc,0xe0,0x70,0x38,0x1c,0xcc,0x78,0x00,0x00, + + 7, // 0x54 'T' + 0x00,0xfc,0xb4,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00, + + 7, // 0x55 'U' + 0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00, + + 7, // 0x56 'V' + 0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x30,0x00,0x00, + + 7, // 0x57 'W' + 0x00,0xcc,0xcc,0xcc,0xcc,0xb4,0xfc,0xcc,0x84,0x00,0x00, + + 7, // 0x58 'X' + 0x00,0xcc,0xcc,0x78,0x30,0x78,0xcc,0xcc,0xcc,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0xcc,0xcc,0xcc,0x78,0x30,0x30,0x30,0x78,0x00,0x00, + + 7, // 0x5a 'Z' + 0x00,0xfc,0x8c,0x18,0x30,0x60,0xc0,0xc4,0xfc,0x00,0x00, + + 7, // 0x5b '[' + 0x00,0x78,0x60,0x60,0x60,0x60,0x60,0x60,0x78,0x00,0x00, + + 7, // 0x5c '\' + 0x00,0x60,0x60,0x30,0x30,0x18,0x18,0x0c,0x0c,0x00,0x00, + + 7, // 0x5d ']' + 0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x78,0x00,0x00, + + 7, // 0x5e '^' + 0x00,0x10,0x38,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00, + + 7, // 0x60 '`' + 0x00,0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x61 'a' + 0x00,0x00,0x00,0x70,0x18,0x78,0xd8,0xd8,0x6c,0x00,0x00, + + 7, // 0x62 'b' + 0x00,0x60,0x60,0x60,0x78,0x6c,0x6c,0x6c,0x78,0x00,0x00, + + 7, // 0x63 'c' + 0x00,0x00,0x00,0x78,0xcc,0xc0,0xc0,0xcc,0x78,0x00,0x00, + + 7, // 0x64 'd' + 0x00,0x18,0x18,0x18,0x78,0xd8,0xd8,0xd8,0x6c,0x00,0x00, + + 7, // 0x65 'e' + 0x00,0x00,0x00,0x78,0xcc,0xfc,0xc0,0xcc,0x78,0x00,0x00, + + 7, // 0x66 'f' + 0x00,0x18,0x34,0x30,0x78,0x30,0x30,0x30,0x78,0x00,0x00, + + 7, // 0x67 'g' + 0x00,0x00,0x00,0x6c,0xd8,0xd8,0xd8,0x78,0x18,0xd8,0x70, + + 7, // 0x68 'h' + 0x00,0xc0,0xc0,0xd8,0xec,0xcc,0xcc,0xcc,0xcc,0x00,0x00, + + 7, // 0x69 'i' + 0x00,0x30,0x00,0x70,0x30,0x30,0x30,0x30,0x78,0x00,0x00, + + 7, // 0x6a 'j' + 0x00,0x0c,0x00,0x1c,0x0c,0x0c,0x0c,0x0c,0x6c,0x6c,0x38, + + 7, // 0x6b 'k' + 0x00,0xc0,0xc0,0xcc,0xcc,0xd8,0xf0,0xd8,0xcc,0x00,0x00, + + 7, // 0x6c 'l' + 0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00, + + 7, // 0x6d 'm' + 0x00,0x00,0x00,0xe8,0xfc,0xd4,0xd4,0xc4,0xc4,0x00,0x00, + + 7, // 0x6e 'n' + 0x00,0x00,0x00,0xd8,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00, + + 7, // 0x6f 'o' + 0x00,0x00,0x00,0x78,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00, + + 7, // 0x70 'p' + 0x00,0x00,0x00,0xf8,0xcc,0xcc,0xcc,0xf8,0xc0,0xc0,0xc0, + + 7, // 0x71 'q' + 0x00,0x00,0x00,0x7c,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x0c, + + 7, // 0x72 'r' + 0x00,0x00,0x00,0xd8,0xec,0xcc,0xc0,0xc0,0xc0,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x78,0xcc,0x60,0x18,0xcc,0x78,0x00,0x00, + + 7, // 0x74 't' + 0x00,0x20,0x60,0x60,0xf0,0x60,0x60,0x68,0x30,0x00,0x00, + + 7, // 0x75 'u' + 0x00,0x00,0x00,0xd8,0xd8,0xd8,0xd8,0xd8,0x6c,0x00,0x00, + + 7, // 0x76 'v' + 0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0x78,0x30,0x00,0x00, + + 7, // 0x77 'w' + 0x00,0x00,0x00,0xcc,0xcc,0xb4,0xfc,0xcc,0x84,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0xcc,0x78,0x30,0x78,0xcc,0xcc,0x00,0x00, + + 7, // 0x79 'y' + 0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x18,0xf0, + + 7, // 0x7a 'z' + 0x00,0x00,0x00,0xfc,0x98,0x30,0x60,0xc4,0xfc,0x00,0x00, + + 7, // 0x7b '{' + 0x1c,0x30,0x30,0x30,0xe0,0x30,0x30,0x30,0x1c,0x00,0x00, + + 7, // 0x7c '|' + 0x30,0x30,0x30,0x30,0x00,0x30,0x30,0x30,0x30,0x00,0x00, + + 7, // 0x7d '}' + 0xe0,0x30,0x30,0x30,0x1c,0x30,0x30,0x30,0xe0,0x00,0x00, + + 7, // 0x7e '~' + 0x00,0x34,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x7f '' + 0x00,0x00,0x00,0x30,0x78,0xcc,0xcc,0xfc,0x00,0x00,0x00, + 0 + }; + + const int8u gse7x15[] = + { + 15, 0, 32, 128-32, + + 0x00,0x00,0x10,0x00,0x20,0x00,0x30,0x00,0x40,0x00,0x50,0x00,0x60,0x00,0x70,0x00,0x80,0x00, + 0x90,0x00,0xa0,0x00,0xb0,0x00,0xc0,0x00,0xd0,0x00,0xe0,0x00,0xf0,0x00,0x00,0x01,0x10,0x01, + 0x20,0x01,0x30,0x01,0x40,0x01,0x50,0x01,0x60,0x01,0x70,0x01,0x80,0x01,0x90,0x01,0xa0,0x01, + 0xb0,0x01,0xc0,0x01,0xd0,0x01,0xe0,0x01,0xf0,0x01,0x00,0x02,0x10,0x02,0x20,0x02,0x30,0x02, + 0x40,0x02,0x50,0x02,0x60,0x02,0x70,0x02,0x80,0x02,0x90,0x02,0xa0,0x02,0xb0,0x02,0xc0,0x02, + 0xd0,0x02,0xe0,0x02,0xf0,0x02,0x00,0x03,0x10,0x03,0x20,0x03,0x30,0x03,0x40,0x03,0x50,0x03, + 0x60,0x03,0x70,0x03,0x80,0x03,0x90,0x03,0xa0,0x03,0xb0,0x03,0xc0,0x03,0xd0,0x03,0xe0,0x03, + 0xf0,0x03,0x00,0x04,0x10,0x04,0x20,0x04,0x30,0x04,0x40,0x04,0x50,0x04,0x60,0x04,0x70,0x04, + 0x80,0x04,0x90,0x04,0xa0,0x04,0xb0,0x04,0xc0,0x04,0xd0,0x04,0xe0,0x04,0xf0,0x04,0x00,0x05, + 0x10,0x05,0x20,0x05,0x30,0x05,0x40,0x05,0x50,0x05,0x60,0x05,0x70,0x05,0x80,0x05,0x90,0x05, + 0xa0,0x05,0xb0,0x05,0xc0,0x05,0xd0,0x05,0xe0,0x05,0xf0,0x05, + + 7, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x21 '!' + 0x00,0x00,0x10,0x38,0x38,0x38,0x38,0x10,0x10,0x00,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x22 '"' + 0x00,0x00,0x24,0x24,0x24,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x23 '#' + 0x00,0x00,0x48,0x48,0x48,0xfc,0x48,0x48,0xfc,0x48,0x48,0x48,0x00,0x00,0x00, + + 7, // 0x24 '$' + 0x00,0x00,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x54,0x38,0x10,0x00,0x00,0x00, + + 7, // 0x25 '%' + 0x00,0x00,0x44,0x44,0x08,0x08,0x10,0x10,0x20,0x20,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x26 '&' + 0x00,0x00,0x00,0x30,0x48,0x48,0x30,0x60,0x94,0x98,0x90,0x6c,0x00,0x00,0x00, + + 7, // 0x27 ''' + 0x00,0x00,0x20,0x20,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x28 '(' + 0x00,0x04,0x08,0x10,0x20,0x20,0x20,0x20,0x20,0x10,0x08,0x04,0x00,0x00,0x00, + + 7, // 0x29 ')' + 0x00,0x40,0x20,0x10,0x08,0x08,0x08,0x08,0x08,0x10,0x20,0x40,0x00,0x00,0x00, + + 7, // 0x2a '*' + 0x00,0x00,0x00,0x00,0x00,0x20,0xa8,0x70,0xa8,0x20,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x2b '+' + 0x00,0x00,0x00,0x00,0x10,0x10,0x10,0x7c,0x10,0x10,0x10,0x00,0x00,0x00,0x00, + + 7, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x60,0x00, + + 7, // 0x2d '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x2f '/' + 0x00,0x00,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00,0x00,0x00, + + 7, // 0x30 '0' + 0x00,0x00,0x38,0x44,0x44,0x4c,0x54,0x64,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x31 '1' + 0x00,0x00,0x10,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x7c,0x00,0x00,0x00, + + 7, // 0x32 '2' + 0x00,0x00,0x38,0x44,0x44,0x04,0x08,0x10,0x20,0x40,0x44,0x7c,0x00,0x00,0x00, + + 7, // 0x33 '3' + 0x00,0x00,0x7c,0x44,0x08,0x10,0x38,0x04,0x04,0x04,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x34 '4' + 0x00,0x00,0x08,0x10,0x20,0x40,0x48,0x48,0x7c,0x08,0x08,0x1c,0x00,0x00,0x00, + + 7, // 0x35 '5' + 0x00,0x00,0x7c,0x40,0x40,0x40,0x78,0x04,0x04,0x04,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x36 '6' + 0x00,0x00,0x18,0x20,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x37 '7' + 0x00,0x00,0x7c,0x44,0x04,0x04,0x08,0x08,0x10,0x10,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x38 '8' + 0x00,0x00,0x38,0x44,0x44,0x44,0x38,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x39 '9' + 0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x3c,0x04,0x04,0x08,0x30,0x00,0x00,0x00, + + 7, // 0x3a ':' + 0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00, + + 7, // 0x3b ';' + 0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x30,0x30,0x60,0x00,0x00, + + 7, // 0x3c '<' + 0x00,0x00,0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00,0x00,0x00, + + 7, // 0x3d '=' + 0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x3e '>' + 0x00,0x00,0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00,0x00,0x00, + + 7, // 0x3f '?' + 0x00,0x00,0x78,0x84,0x84,0x84,0x08,0x10,0x20,0x20,0x00,0x20,0x00,0x00,0x00, + + 7, // 0x40 '@' + 0x00,0x00,0x00,0x30,0x48,0x04,0x34,0x54,0x54,0x54,0x54,0x28,0x00,0x00,0x00, + + 7, // 0x41 'A' + 0x00,0x00,0x10,0x28,0x44,0x44,0x44,0x7c,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x42 'B' + 0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x44,0x44,0x44,0x44,0x78,0x00,0x00,0x00, + + 7, // 0x43 'C' + 0x00,0x00,0x38,0x44,0x44,0x40,0x40,0x40,0x40,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x44 'D' + 0x00,0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00,0x00, + + 7, // 0x45 'E' + 0x00,0x00,0x7c,0x40,0x40,0x40,0x70,0x40,0x40,0x40,0x40,0x7c,0x00,0x00,0x00, + + 7, // 0x46 'F' + 0x00,0x00,0x7c,0x40,0x40,0x40,0x70,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 7, // 0x47 'G' + 0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x5c,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x48 'H' + 0x00,0x00,0x44,0x44,0x44,0x44,0x7c,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x49 'I' + 0x00,0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, + + 7, // 0x4a 'J' + 0x00,0x00,0x1c,0x08,0x08,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00,0x00, + + 7, // 0x4b 'K' + 0x00,0x00,0x44,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x4c 'L' + 0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7c,0x00,0x00,0x00, + + 7, // 0x4d 'M' + 0x00,0x00,0x44,0x6c,0x54,0x54,0x44,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x4e 'N' + 0x00,0x00,0x44,0x44,0x44,0x64,0x54,0x4c,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x4f 'O' + 0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 7, // 0x51 'Q' + 0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00,0x00, + + 7, // 0x52 'R' + 0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x50,0x48,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x53 'S' + 0x00,0x00,0x38,0x44,0x44,0x40,0x38,0x04,0x04,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x54 'T' + 0x00,0x00,0x7c,0x54,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x55 'U' + 0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x56 'V' + 0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x57 'W' + 0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x54,0x54,0x6c,0x44,0x00,0x00,0x00, + + 7, // 0x58 'X' + 0x00,0x00,0x44,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x00,0x44,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, + + 7, // 0x5a 'Z' + 0x00,0x00,0x7c,0x04,0x04,0x08,0x10,0x20,0x40,0x40,0x40,0x7c,0x00,0x00,0x00, + + 7, // 0x5b '[' + 0x00,0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00,0x00, + + 7, // 0x5c '\' + 0x00,0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00,0x00,0x00, + + 7, // 0x5d ']' + 0x00,0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x38,0x00,0x00, + + 7, // 0x5e '^' + 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00, + + 7, // 0x60 '`' + 0x00,0x20,0x20,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x38,0x44,0x04,0x3c,0x44,0x44,0x44,0x3a,0x00,0x00,0x00, + + 7, // 0x62 'b' + 0x00,0x00,0x40,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00,0x00,0x00, + + 7, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x64 'd' + 0x00,0x00,0x04,0x04,0x04,0x3c,0x44,0x44,0x44,0x44,0x44,0x3a,0x00,0x00,0x00, + + 7, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x38,0x44,0x44,0x7c,0x40,0x40,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x66 'f' + 0x00,0x00,0x18,0x24,0x20,0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00,0x00, + + 7, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x3a,0x44,0x44,0x44,0x44,0x44,0x3c,0x04,0x44,0x38,0x00, + + 7, // 0x68 'h' + 0x00,0x00,0x40,0x40,0x40,0x58,0x64,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x69 'i' + 0x00,0x00,0x10,0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, + + 7, // 0x6a 'j' + 0x00,0x00,0x08,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00, + + 7, // 0x6b 'k' + 0x00,0x00,0x40,0x40,0x44,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00,0x00, + + 7, // 0x6c 'l' + 0x00,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, + + 7, // 0x6d 'm' + 0x00,0x00,0x00,0x00,0xa8,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x00,0x00,0x00, + + 7, // 0x6e 'n' + 0x00,0x00,0x00,0x00,0xb8,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x6f 'o' + 0x00,0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00, + + 7, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x3c,0x44,0x44,0x44,0x44,0x44,0x3c,0x04,0x04,0x04,0x00, + + 7, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x58,0x64,0x44,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x74 't' + 0x00,0x00,0x20,0x20,0x20,0x70,0x20,0x20,0x20,0x20,0x24,0x18,0x00,0x00,0x00, + + 7, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x3a,0x00,0x00,0x00, + + 7, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x54,0x54,0x6c,0x44,0x00,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x3c,0x04,0x08,0x70,0x00, + + 7, // 0x7a 'z' + 0x00,0x00,0x00,0x00,0x7c,0x04,0x08,0x10,0x20,0x40,0x40,0x7c,0x00,0x00,0x00, + + 7, // 0x7b '{' + 0x00,0x0c,0x10,0x10,0x10,0x10,0x10,0x60,0x10,0x10,0x10,0x10,0x0c,0x00,0x00, + + 7, // 0x7c '|' + 0x00,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x00,0x00, + + 7, // 0x7d '}' + 0x00,0x60,0x10,0x10,0x10,0x10,0x10,0x0c,0x10,0x10,0x10,0x10,0x60,0x00,0x00, + + 7, // 0x7e '~' + 0x00,0x00,0x64,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x7f '' + 0x00,0x00,0x00,0x00,0x00,0x10,0x28,0x44,0x44,0x7c,0x00,0x00,0x00,0x00,0x00, + 0 + }; + + const int8u gse7x15_bold[] = + { + 15, 0, 32, 128-32, + + 0x00,0x00,0x10,0x00,0x20,0x00,0x30,0x00,0x40,0x00,0x50,0x00,0x60,0x00,0x70,0x00,0x80,0x00, + 0x90,0x00,0xa0,0x00,0xb0,0x00,0xc0,0x00,0xd0,0x00,0xe0,0x00,0xf0,0x00,0x00,0x01,0x10,0x01, + 0x20,0x01,0x30,0x01,0x40,0x01,0x50,0x01,0x60,0x01,0x70,0x01,0x80,0x01,0x90,0x01,0xa0,0x01, + 0xb0,0x01,0xc0,0x01,0xd0,0x01,0xe0,0x01,0xf0,0x01,0x00,0x02,0x10,0x02,0x20,0x02,0x30,0x02, + 0x40,0x02,0x50,0x02,0x60,0x02,0x70,0x02,0x80,0x02,0x90,0x02,0xa0,0x02,0xb0,0x02,0xc0,0x02, + 0xd0,0x02,0xe0,0x02,0xf0,0x02,0x00,0x03,0x10,0x03,0x20,0x03,0x30,0x03,0x40,0x03,0x50,0x03, + 0x60,0x03,0x70,0x03,0x80,0x03,0x90,0x03,0xa0,0x03,0xb0,0x03,0xc0,0x03,0xd0,0x03,0xe0,0x03, + 0xf0,0x03,0x00,0x04,0x10,0x04,0x20,0x04,0x30,0x04,0x40,0x04,0x50,0x04,0x60,0x04,0x70,0x04, + 0x80,0x04,0x90,0x04,0xa0,0x04,0xb0,0x04,0xc0,0x04,0xd0,0x04,0xe0,0x04,0xf0,0x04,0x00,0x05, + 0x10,0x05,0x20,0x05,0x30,0x05,0x40,0x05,0x50,0x05,0x60,0x05,0x70,0x05,0x80,0x05,0x90,0x05, + 0xa0,0x05,0xb0,0x05,0xc0,0x05,0xd0,0x05,0xe0,0x05,0xf0,0x05, + + 7, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x21 '!' + 0x00,0x00,0x00,0x30,0x78,0x78,0x78,0x30,0x30,0x00,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x22 '"' + 0x00,0x00,0x6c,0x6c,0x6c,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x23 '#' + 0x00,0x00,0x48,0x48,0x48,0xfc,0x48,0x48,0xfc,0x48,0x48,0x48,0x00,0x00,0x00, + + 7, // 0x24 '$' + 0x00,0x30,0x30,0x78,0xcc,0xe0,0x70,0x38,0x1c,0xcc,0x78,0x30,0x30,0x00,0x00, + + 7, // 0x25 '%' + 0x00,0x00,0x00,0x64,0x6c,0x08,0x18,0x10,0x30,0x20,0x6c,0x4c,0x00,0x00,0x00, + + 7, // 0x26 '&' + 0x00,0x00,0x00,0x30,0x58,0x58,0x30,0x74,0xdc,0xd8,0xd8,0x6c,0x00,0x00,0x00, + + 7, // 0x27 ''' + 0x00,0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x28 '(' + 0x00,0x0c,0x18,0x30,0x60,0x60,0x60,0x60,0x60,0x30,0x18,0x0c,0x00,0x00,0x00, + + 7, // 0x29 ')' + 0x00,0xc0,0x60,0x30,0x18,0x18,0x18,0x18,0x18,0x30,0x60,0xc0,0x00,0x00,0x00, + + 7, // 0x2a '*' + 0x00,0x00,0x00,0x00,0x00,0x20,0xa8,0x70,0xa8,0x20,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x2b '+' + 0x00,0x00,0x00,0x00,0x00,0x30,0x30,0xfc,0x30,0x30,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x60,0x00, + + 7, // 0x2d '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x2f '/' + 0x00,0x00,0x0c,0x0c,0x18,0x18,0x30,0x30,0x60,0x60,0xc0,0xc0,0x00,0x00,0x00, + + 7, // 0x30 '0' + 0x00,0x00,0x78,0xcc,0xcc,0xcc,0xdc,0xec,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x31 '1' + 0x00,0x00,0x30,0x30,0x70,0xf0,0x30,0x30,0x30,0x30,0x30,0xfc,0x00,0x00,0x00, + + 7, // 0x32 '2' + 0x00,0x00,0x78,0xcc,0xcc,0x0c,0x18,0x30,0x60,0xc0,0xcc,0xfc,0x00,0x00,0x00, + + 7, // 0x33 '3' + 0x00,0x00,0xfc,0x8c,0x18,0x30,0x78,0x0c,0x0c,0x0c,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x34 '4' + 0x00,0x00,0x18,0x30,0x60,0xc8,0xd8,0xd8,0xfc,0x18,0x18,0x3c,0x00,0x00,0x00, + + 7, // 0x35 '5' + 0x00,0x00,0xfc,0xc0,0xc0,0xc0,0xf8,0x0c,0x0c,0x0c,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x36 '6' + 0x00,0x00,0x38,0x60,0xc0,0xc0,0xf8,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x37 '7' + 0x00,0x00,0xfc,0x8c,0x0c,0x0c,0x18,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x38 '8' + 0x00,0x00,0x78,0xcc,0xcc,0xcc,0x78,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x39 '9' + 0x00,0x00,0x78,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x18,0x70,0x00,0x00,0x00, + + 7, // 0x3a ':' + 0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00, + + 7, // 0x3b ';' + 0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x60,0x00, + + 7, // 0x3c '<' + 0x00,0x00,0x00,0x0c,0x18,0x30,0x60,0xc0,0x60,0x30,0x18,0x0c,0x00,0x00,0x00, + + 7, // 0x3d '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x3e '>' + 0x00,0x00,0x00,0xc0,0x60,0x30,0x18,0x0c,0x18,0x30,0x60,0xc0,0x00,0x00,0x00, + + 7, // 0x3f '?' + 0x00,0x00,0x78,0xcc,0xcc,0x18,0x30,0x30,0x30,0x00,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x40 '@' + 0x00,0x00,0x00,0x70,0x88,0x04,0x74,0xb4,0xb4,0xb4,0xb4,0x68,0x00,0x00,0x00, + + 7, // 0x41 'A' + 0x00,0x00,0x30,0x78,0xcc,0xcc,0xcc,0xfc,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0x00, + + 7, // 0x42 'B' + 0x00,0x00,0xf8,0xcc,0xcc,0xcc,0xf8,0xcc,0xcc,0xcc,0xcc,0xf8,0x00,0x00,0x00, + + 7, // 0x43 'C' + 0x00,0x00,0x78,0xcc,0xc4,0xc0,0xc0,0xc0,0xc0,0xc4,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x44 'D' + 0x00,0x00,0xf0,0xd8,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xd8,0xf0,0x00,0x00,0x00, + + 7, // 0x45 'E' + 0x00,0x00,0xfc,0xc4,0xc0,0xd0,0xf0,0xd0,0xc0,0xc0,0xc4,0xfc,0x00,0x00,0x00, + + 7, // 0x46 'F' + 0x00,0x00,0xfc,0xc4,0xc0,0xd0,0xf0,0xd0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00, + + 7, // 0x47 'G' + 0x00,0x00,0x78,0xcc,0xc0,0xc0,0xc0,0xdc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x48 'H' + 0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xfc,0xcc,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0x00, + + 7, // 0x49 'I' + 0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00, + + 7, // 0x4a 'J' + 0x00,0x00,0x3c,0x18,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0x70,0x00,0x00,0x00, + + 7, // 0x4b 'K' + 0x00,0x00,0xcc,0xcc,0xd8,0xd8,0xf0,0xd8,0xd8,0xcc,0xcc,0xcc,0x00,0x00,0x00, + + 7, // 0x4c 'L' + 0x00,0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc4,0xfc,0x00,0x00,0x00, + + 7, // 0x4d 'M' + 0x00,0x00,0x84,0xcc,0xfc,0xb4,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0x00, + + 7, // 0x4e 'N' + 0x00,0x00,0xcc,0xcc,0xcc,0xec,0xfc,0xdc,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0x00, + + 7, // 0x4f 'O' + 0x00,0x00,0x78,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0x00,0xf8,0xcc,0xcc,0xcc,0xcc,0xf8,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00, + + 7, // 0x51 'Q' + 0x00,0x00,0x78,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xdc,0x78,0x18,0x0c,0x00,0x00, + + 7, // 0x52 'R' + 0x00,0x00,0xf8,0xcc,0xcc,0xcc,0xcc,0xf8,0xd8,0xcc,0xcc,0xcc,0x00,0x00,0x00, + + 7, // 0x53 'S' + 0x00,0x00,0x78,0xcc,0xcc,0xe0,0x70,0x38,0x1c,0xcc,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x54 'T' + 0x00,0x00,0xfc,0xb4,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x55 'U' + 0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x56 'V' + 0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x30,0x00,0x00,0x00, + + 7, // 0x57 'W' + 0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xb4,0xfc,0xcc,0x84,0x00,0x00,0x00, + + 7, // 0x58 'X' + 0x00,0x00,0xcc,0xcc,0xcc,0x78,0x30,0x78,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x00,0xcc,0xcc,0xcc,0xcc,0x78,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00, + + 7, // 0x5a 'Z' + 0x00,0x00,0xfc,0x8c,0x0c,0x18,0x30,0x60,0xc0,0xc0,0xc4,0xfc,0x00,0x00,0x00, + + 7, // 0x5b '[' + 0x00,0x78,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x78,0x00,0x00, + + 7, // 0x5c '\' + 0x00,0x00,0xc0,0xc0,0x60,0x60,0x30,0x30,0x18,0x18,0x0c,0x0c,0x00,0x00,0x00, + + 7, // 0x5d ']' + 0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x78,0x00,0x00, + + 7, // 0x5e '^' + 0x00,0x10,0x38,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00, + + 7, // 0x60 '`' + 0x00,0x30,0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x70,0xd8,0x18,0x78,0xd8,0xd8,0xd8,0x6c,0x00,0x00,0x00, + + 7, // 0x62 'b' + 0x00,0x00,0x60,0x60,0x60,0x78,0x6c,0x6c,0x6c,0x6c,0x6c,0x78,0x00,0x00,0x00, + + 7, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x78,0xcc,0xc0,0xc0,0xc0,0xc0,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x64 'd' + 0x00,0x00,0x18,0x18,0x18,0x78,0xd8,0xd8,0xd8,0xd8,0xd8,0x6c,0x00,0x00,0x00, + + 7, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x78,0xcc,0xcc,0xfc,0xc0,0xc0,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x66 'f' + 0x00,0x00,0x30,0x68,0x60,0x60,0xf0,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00, + + 7, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x6c,0xd8,0xd8,0xd8,0xd8,0xd8,0x78,0x18,0xd8,0x70,0x00, + + 7, // 0x68 'h' + 0x00,0x00,0xc0,0xc0,0xc0,0xd8,0xec,0xcc,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0x00, + + 7, // 0x69 'i' + 0x00,0x00,0x30,0x30,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00, + + 7, // 0x6a 'j' + 0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0x70,0x00, + + 7, // 0x6b 'k' + 0x00,0x00,0xc0,0xc0,0xcc,0xcc,0xcc,0xd8,0xf0,0xd8,0xcc,0xcc,0x00,0x00,0x00, + + 7, // 0x6c 'l' + 0x00,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00, + + 7, // 0x6d 'm' + 0x00,0x00,0x00,0x00,0xe8,0xfc,0xd4,0xd4,0xd4,0xc4,0xc4,0xc4,0x00,0x00,0x00, + + 7, // 0x6e 'n' + 0x00,0x00,0x00,0x00,0xd8,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00, + + 7, // 0x6f 'o' + 0x00,0x00,0x00,0x00,0x78,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x70 'p' + 0x00,0x00,0x00,0x00,0xf8,0xcc,0xcc,0xcc,0xcc,0xcc,0xf8,0xc0,0xc0,0xc0,0x00, + + 7, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x7c,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x0c,0x00, + + 7, // 0x72 'r' + 0x00,0x00,0x00,0x00,0xd8,0xec,0xcc,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x00,0x78,0xcc,0xe0,0x70,0x38,0x1c,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x74 't' + 0x00,0x00,0x20,0x60,0x60,0xf0,0x60,0x60,0x60,0x60,0x6c,0x38,0x00,0x00,0x00, + + 7, // 0x75 'u' + 0x00,0x00,0x00,0x00,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0x6c,0x00,0x00,0x00, + + 7, // 0x76 'v' + 0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x30,0x00,0x00,0x00, + + 7, // 0x77 'w' + 0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xb4,0xfc,0xcc,0x84,0x00,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0x00,0xcc,0xcc,0x78,0x30,0x78,0xcc,0xcc,0xcc,0x00,0x00,0x00, + + 7, // 0x79 'y' + 0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x18,0xf0,0x00, + + 7, // 0x7a 'z' + 0x00,0x00,0x00,0x00,0xfc,0x8c,0x18,0x30,0x60,0xc0,0xc4,0xfc,0x00,0x00,0x00, + + 7, // 0x7b '{' + 0x00,0x1c,0x30,0x30,0x30,0x30,0x30,0xe0,0x30,0x30,0x30,0x30,0x1c,0x00,0x00, + + 7, // 0x7c '|' + 0x00,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x00,0x00, + + 7, // 0x7d '}' + 0x00,0xe0,0x30,0x30,0x30,0x30,0x30,0x1c,0x30,0x30,0x30,0x30,0xe0,0x00,0x00, + + 7, // 0x7e '~' + 0x00,0x00,0x34,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x7f '' + 0x00,0x00,0x00,0x00,0x00,0x30,0x78,0xcc,0xcc,0xfc,0x00,0x00,0x00,0x00,0x00, + 0 + }; + + const int8u gse8x16[] = + { + 16, 0, 32, 128-32, + + 0x00,0x00,0x11,0x00,0x22,0x00,0x33,0x00,0x44,0x00,0x55,0x00,0x66,0x00,0x77,0x00,0x88,0x00, + 0x99,0x00,0xaa,0x00,0xbb,0x00,0xcc,0x00,0xdd,0x00,0xee,0x00,0xff,0x00,0x10,0x01,0x21,0x01, + 0x32,0x01,0x43,0x01,0x54,0x01,0x65,0x01,0x76,0x01,0x87,0x01,0x98,0x01,0xa9,0x01,0xba,0x01, + 0xcb,0x01,0xdc,0x01,0xed,0x01,0xfe,0x01,0x0f,0x02,0x20,0x02,0x31,0x02,0x42,0x02,0x53,0x02, + 0x64,0x02,0x75,0x02,0x86,0x02,0x97,0x02,0xa8,0x02,0xb9,0x02,0xca,0x02,0xdb,0x02,0xec,0x02, + 0xfd,0x02,0x0e,0x03,0x1f,0x03,0x30,0x03,0x41,0x03,0x52,0x03,0x63,0x03,0x74,0x03,0x85,0x03, + 0x96,0x03,0xa7,0x03,0xb8,0x03,0xc9,0x03,0xda,0x03,0xeb,0x03,0xfc,0x03,0x0d,0x04,0x1e,0x04, + 0x2f,0x04,0x40,0x04,0x51,0x04,0x62,0x04,0x73,0x04,0x84,0x04,0x95,0x04,0xa6,0x04,0xb7,0x04, + 0xc8,0x04,0xd9,0x04,0xea,0x04,0xfb,0x04,0x0c,0x05,0x1d,0x05,0x2e,0x05,0x3f,0x05,0x50,0x05, + 0x61,0x05,0x72,0x05,0x83,0x05,0x94,0x05,0xa5,0x05,0xb6,0x05,0xc7,0x05,0xd8,0x05,0xe9,0x05, + 0xfa,0x05,0x0b,0x06,0x1c,0x06,0x2d,0x06,0x3e,0x06,0x4f,0x06, + + 8, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x21 '!' + 0x00,0x00,0x10,0x38,0x38,0x38,0x38,0x10,0x10,0x00,0x10,0x10,0x00,0x00,0x00,0x00, + + 8, // 0x22 '"' + 0x00,0x24,0x24,0x24,0x24,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x23 '#' + 0x00,0x00,0x24,0x24,0x24,0x7e,0x24,0x24,0x7e,0x24,0x24,0x24,0x00,0x00,0x00,0x00, + + 8, // 0x24 '$' + 0x00,0x14,0x14,0x3e,0x55,0x54,0x54,0x3e,0x15,0x15,0x55,0x3e,0x14,0x14,0x00,0x00, + + 8, // 0x25 '%' + 0x00,0x00,0x32,0x56,0x6c,0x04,0x08,0x08,0x10,0x13,0x25,0x26,0x00,0x00,0x00,0x00, + + 8, // 0x26 '&' + 0x00,0x00,0x18,0x24,0x24,0x24,0x18,0x28,0x45,0x46,0x44,0x3b,0x00,0x00,0x00,0x00, + + 8, // 0x27 ''' + 0x00,0x00,0x08,0x08,0x08,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x28 '(' + 0x00,0x04,0x08,0x10,0x10,0x20,0x20,0x20,0x20,0x10,0x10,0x08,0x04,0x00,0x00,0x00, + + 8, // 0x29 ')' + 0x00,0x10,0x08,0x04,0x04,0x02,0x02,0x02,0x02,0x04,0x04,0x08,0x10,0x00,0x00,0x00, + + 8, // 0x2a '*' + 0x00,0x00,0x00,0x00,0x66,0x24,0x18,0xff,0x18,0x24,0x66,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x2b '+' + 0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x7f,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x20,0x00, + + 8, // 0x2d '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, + + 8, // 0x2f '/' + 0x00,0x02,0x02,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00,0x00,0x00, + + 8, // 0x30 '0' + 0x00,0x00,0x3c,0x42,0x42,0x46,0x4a,0x52,0x62,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x31 '1' + 0x00,0x00,0x08,0x08,0x18,0x38,0x08,0x08,0x08,0x08,0x08,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x32 '2' + 0x00,0x00,0x3c,0x42,0x42,0x02,0x04,0x08,0x10,0x20,0x42,0x7e,0x00,0x00,0x00,0x00, + + 8, // 0x33 '3' + 0x00,0x00,0x7e,0x42,0x04,0x08,0x1c,0x02,0x02,0x02,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x34 '4' + 0x00,0x00,0x04,0x08,0x10,0x24,0x44,0x44,0x7e,0x04,0x04,0x0e,0x00,0x00,0x00,0x00, + + 8, // 0x35 '5' + 0x00,0x00,0x7e,0x42,0x40,0x40,0x7c,0x02,0x02,0x02,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x36 '6' + 0x00,0x00,0x1c,0x20,0x40,0x40,0x7c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x37 '7' + 0x00,0x00,0x7e,0x42,0x42,0x02,0x04,0x08,0x10,0x10,0x10,0x10,0x00,0x00,0x00,0x00, + + 8, // 0x38 '8' + 0x00,0x00,0x3c,0x42,0x42,0x42,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x39 '9' + 0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3e,0x02,0x02,0x04,0x38,0x00,0x00,0x00,0x00, + + 8, // 0x3a ':' + 0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x3b ';' + 0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x60,0x40,0x00, + + 8, // 0x3c '<' + 0x00,0x00,0x00,0x02,0x04,0x08,0x10,0x20,0x10,0x08,0x04,0x02,0x00,0x00,0x00,0x00, + + 8, // 0x3d '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x3e '>' + 0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x04,0x08,0x10,0x20,0x00,0x00,0x00,0x00, + + 8, // 0x3f '?' + 0x00,0x00,0x3c,0x42,0x42,0x42,0x04,0x08,0x08,0x00,0x08,0x08,0x00,0x00,0x00,0x00, + + 8, // 0x40 '@' + 0x00,0x00,0x3c,0x42,0x01,0x39,0x49,0x49,0x49,0x49,0x49,0x36,0x00,0x00,0x00,0x00, + + 8, // 0x41 'A' + 0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x7e,0x42,0x42,0x42,0x42,0x00,0x00,0x00,0x00, + + 8, // 0x42 'B' + 0x00,0x00,0x7c,0x22,0x22,0x22,0x3c,0x22,0x22,0x22,0x22,0x7c,0x00,0x00,0x00,0x00, + + 8, // 0x43 'C' + 0x00,0x00,0x3c,0x42,0x42,0x40,0x40,0x40,0x40,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x44 'D' + 0x00,0x00,0x7c,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x7c,0x00,0x00,0x00,0x00, + + 8, // 0x45 'E' + 0x00,0x00,0x7e,0x22,0x20,0x28,0x38,0x28,0x20,0x20,0x22,0x7e,0x00,0x00,0x00,0x00, + + 8, // 0x46 'F' + 0x00,0x00,0x7e,0x22,0x20,0x28,0x38,0x28,0x20,0x20,0x20,0x70,0x00,0x00,0x00,0x00, + + 8, // 0x47 'G' + 0x00,0x00,0x3c,0x42,0x42,0x40,0x40,0x4e,0x42,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x48 'H' + 0x00,0x00,0x42,0x42,0x42,0x42,0x7e,0x42,0x42,0x42,0x42,0x42,0x00,0x00,0x00,0x00, + + 8, // 0x49 'I' + 0x00,0x00,0x1c,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x1c,0x00,0x00,0x00,0x00, + + 8, // 0x4a 'J' + 0x00,0x00,0x0e,0x04,0x04,0x04,0x04,0x04,0x04,0x44,0x44,0x38,0x00,0x00,0x00,0x00, + + 8, // 0x4b 'K' + 0x00,0x00,0x62,0x22,0x24,0x28,0x30,0x28,0x24,0x22,0x22,0x62,0x00,0x00,0x00,0x00, + + 8, // 0x4c 'L' + 0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x22,0x7e,0x00,0x00,0x00,0x00, + + 8, // 0x4d 'M' + 0x00,0x00,0x41,0x63,0x55,0x49,0x41,0x41,0x41,0x41,0x41,0x41,0x00,0x00,0x00,0x00, + + 8, // 0x4e 'N' + 0x00,0x00,0x42,0x42,0x62,0x52,0x4a,0x46,0x42,0x42,0x42,0x42,0x00,0x00,0x00,0x00, + + 8, // 0x4f 'O' + 0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x50 'P' + 0x00,0x00,0x7c,0x22,0x22,0x22,0x22,0x3c,0x20,0x20,0x20,0x70,0x00,0x00,0x00,0x00, + + 8, // 0x51 'Q' + 0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x42,0x42,0x4a,0x44,0x3a,0x02,0x00,0x00,0x00, + + 8, // 0x52 'R' + 0x00,0x00,0x7c,0x22,0x22,0x22,0x22,0x3c,0x28,0x24,0x22,0x62,0x00,0x00,0x00,0x00, + + 8, // 0x53 'S' + 0x00,0x00,0x3c,0x42,0x42,0x40,0x30,0x0c,0x02,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x54 'T' + 0x00,0x00,0x7f,0x49,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x1c,0x00,0x00,0x00,0x00, + + 8, // 0x55 'U' + 0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x56 'V' + 0x00,0x00,0x41,0x41,0x41,0x41,0x22,0x22,0x14,0x14,0x08,0x08,0x00,0x00,0x00,0x00, + + 8, // 0x57 'W' + 0x00,0x00,0x41,0x41,0x41,0x41,0x41,0x49,0x49,0x55,0x63,0x41,0x00,0x00,0x00,0x00, + + 8, // 0x58 'X' + 0x00,0x00,0x42,0x42,0x42,0x24,0x18,0x18,0x24,0x42,0x42,0x42,0x00,0x00,0x00,0x00, + + 8, // 0x59 'Y' + 0x00,0x00,0x22,0x22,0x22,0x22,0x14,0x08,0x08,0x08,0x08,0x1c,0x00,0x00,0x00,0x00, + + 8, // 0x5a 'Z' + 0x00,0x00,0x7e,0x42,0x02,0x04,0x08,0x10,0x20,0x40,0x42,0x7e,0x00,0x00,0x00,0x00, + + 8, // 0x5b '[' + 0x00,0x1e,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x1e,0x00,0x00,0x00, + + 8, // 0x5c '\' + 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x02,0x02,0x00,0x00,0x00, + + 8, // 0x5d ']' + 0x00,0x3c,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x3c,0x00,0x00,0x00, + + 8, // 0x5e '^' + 0x00,0x00,0x08,0x14,0x22,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00, + + 8, // 0x60 '`' + 0x00,0x00,0x08,0x08,0x08,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x04,0x3c,0x44,0x44,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x62 'b' + 0x00,0x00,0x60,0x20,0x20,0x38,0x24,0x22,0x22,0x22,0x22,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x3c,0x42,0x40,0x40,0x40,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x64 'd' + 0x00,0x00,0x0c,0x04,0x04,0x1c,0x24,0x44,0x44,0x44,0x44,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x7e,0x40,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x66 'f' + 0x00,0x00,0x0c,0x12,0x10,0x10,0x38,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00,0x00, + + 8, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x3e,0x44,0x44,0x44,0x44,0x44,0x3c,0x04,0x44,0x38,0x00, + + 8, // 0x68 'h' + 0x00,0x00,0x60,0x20,0x20,0x2c,0x32,0x22,0x22,0x22,0x22,0x62,0x00,0x00,0x00,0x00, + + 8, // 0x69 'i' + 0x00,0x00,0x08,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x1c,0x00,0x00,0x00,0x00, + + 8, // 0x6a 'j' + 0x00,0x00,0x04,0x04,0x00,0x0c,0x04,0x04,0x04,0x04,0x04,0x44,0x44,0x38,0x00,0x00, + + 8, // 0x6b 'k' + 0x00,0x00,0x60,0x20,0x20,0x22,0x24,0x28,0x38,0x24,0x22,0x62,0x00,0x00,0x00,0x00, + + 8, // 0x6c 'l' + 0x00,0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x1c,0x00,0x00,0x00,0x00, + + 8, // 0x6d 'm' + 0x00,0x00,0x00,0x00,0x00,0x76,0x49,0x49,0x49,0x49,0x41,0x41,0x00,0x00,0x00,0x00, + + 8, // 0x6e 'n' + 0x00,0x00,0x00,0x00,0x00,0x5c,0x22,0x22,0x22,0x22,0x22,0x22,0x00,0x00,0x00,0x00, + + 8, // 0x6f 'o' + 0x00,0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x7c,0x22,0x22,0x22,0x22,0x22,0x3c,0x20,0x20,0x70,0x00, + + 8, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x3e,0x44,0x44,0x44,0x44,0x44,0x3c,0x04,0x04,0x0e,0x00, + + 8, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x7c,0x22,0x22,0x20,0x20,0x20,0x70,0x00,0x00,0x00,0x00, + + 8, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x3c,0x42,0x40,0x3c,0x02,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x74 't' + 0x00,0x00,0x10,0x10,0x10,0x7c,0x10,0x10,0x10,0x10,0x12,0x0c,0x00,0x00,0x00,0x00, + + 8, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x41,0x41,0x41,0x41,0x22,0x14,0x08,0x00,0x00,0x00,0x00, + + 8, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x41,0x41,0x41,0x49,0x49,0x55,0x22,0x00,0x00,0x00,0x00, + + 8, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x24,0x18,0x24,0x42,0x42,0x00,0x00,0x00,0x00, + + 8, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x3e,0x02,0x04,0x78,0x00, + + 8, // 0x7a 'z' + 0x00,0x00,0x00,0x00,0x00,0x7e,0x44,0x08,0x10,0x20,0x42,0x7e,0x00,0x00,0x00,0x00, + + 8, // 0x7b '{' + 0x00,0x06,0x08,0x08,0x08,0x08,0x08,0x30,0x08,0x08,0x08,0x08,0x08,0x06,0x00,0x00, + + 8, // 0x7c '|' + 0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x00, + + 8, // 0x7d '}' + 0x00,0x30,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x30,0x00,0x00, + + 8, // 0x7e '~' + 0x00,0x00,0x39,0x4e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x7f '' + 0x00,0x00,0x00,0x00,0x00,0x08,0x14,0x22,0x41,0x41,0x7f,0x00,0x00,0x00,0x00,0x00, + 0 + }; + + const int8u gse8x16_bold[] = + { + 16, 0, 32, 128-32, + + 0x00,0x00,0x11,0x00,0x22,0x00,0x33,0x00,0x44,0x00,0x55,0x00,0x66,0x00,0x77,0x00,0x88,0x00, + 0x99,0x00,0xaa,0x00,0xbb,0x00,0xcc,0x00,0xdd,0x00,0xee,0x00,0xff,0x00,0x10,0x01,0x21,0x01, + 0x32,0x01,0x43,0x01,0x54,0x01,0x65,0x01,0x76,0x01,0x87,0x01,0x98,0x01,0xa9,0x01,0xba,0x01, + 0xcb,0x01,0xdc,0x01,0xed,0x01,0xfe,0x01,0x0f,0x02,0x20,0x02,0x31,0x02,0x42,0x02,0x53,0x02, + 0x64,0x02,0x75,0x02,0x86,0x02,0x97,0x02,0xa8,0x02,0xb9,0x02,0xca,0x02,0xdb,0x02,0xec,0x02, + 0xfd,0x02,0x0e,0x03,0x1f,0x03,0x30,0x03,0x41,0x03,0x52,0x03,0x63,0x03,0x74,0x03,0x85,0x03, + 0x96,0x03,0xa7,0x03,0xb8,0x03,0xc9,0x03,0xda,0x03,0xeb,0x03,0xfc,0x03,0x0d,0x04,0x1e,0x04, + 0x2f,0x04,0x40,0x04,0x51,0x04,0x62,0x04,0x73,0x04,0x84,0x04,0x95,0x04,0xa6,0x04,0xb7,0x04, + 0xc8,0x04,0xd9,0x04,0xea,0x04,0xfb,0x04,0x0c,0x05,0x1d,0x05,0x2e,0x05,0x3f,0x05,0x50,0x05, + 0x61,0x05,0x72,0x05,0x83,0x05,0x94,0x05,0xa5,0x05,0xb6,0x05,0xc7,0x05,0xd8,0x05,0xe9,0x05, + 0xfa,0x05,0x0b,0x06,0x1c,0x06,0x2d,0x06,0x3e,0x06,0x4f,0x06, + + 8, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x21 '!' + 0x00,0x00,0x18,0x3c,0x3c,0x3c,0x3c,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, + + 8, // 0x22 '"' + 0x00,0x66,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x23 '#' + 0x00,0x00,0x66,0x66,0x66,0xff,0x66,0x66,0xff,0x66,0x66,0x66,0x00,0x00,0x00,0x00, + + 8, // 0x24 '$' + 0x00,0x08,0x08,0x3e,0x6b,0x6b,0x68,0x3e,0x0b,0x6b,0x6b,0x3e,0x08,0x08,0x00,0x00, + + 8, // 0x25 '%' + 0x00,0x00,0x66,0xbe,0xcc,0x0c,0x18,0x18,0x30,0x33,0x65,0x66,0x00,0x00,0x00,0x00, + + 8, // 0x26 '&' + 0x00,0x00,0x1c,0x36,0x36,0x36,0x1c,0x3b,0x6e,0x66,0x66,0x3b,0x00,0x00,0x00,0x00, + + 8, // 0x27 ''' + 0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x28 '(' + 0x00,0x06,0x0c,0x18,0x18,0x30,0x30,0x30,0x30,0x18,0x18,0x0c,0x06,0x00,0x00,0x00, + + 8, // 0x29 ')' + 0x00,0x30,0x18,0x0c,0x0c,0x06,0x06,0x06,0x06,0x0c,0x0c,0x18,0x30,0x00,0x00,0x00, + + 8, // 0x2a '*' + 0x00,0x00,0x00,0x00,0x66,0x24,0x18,0xff,0x18,0x24,0x66,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x2b '+' + 0x00,0x00,0x00,0x00,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x20,0x00, + + 8, // 0x2d '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, + + 8, // 0x2f '/' + 0x00,0x03,0x03,0x06,0x06,0x0c,0x0c,0x18,0x18,0x30,0x30,0x60,0x60,0x00,0x00,0x00, + + 8, // 0x30 '0' + 0x00,0x00,0x3e,0x63,0x63,0x67,0x6b,0x73,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x31 '1' + 0x00,0x00,0x0c,0x0c,0x1c,0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3f,0x00,0x00,0x00,0x00, + + 8, // 0x32 '2' + 0x00,0x00,0x3e,0x63,0x63,0x03,0x06,0x0c,0x18,0x30,0x61,0x7f,0x00,0x00,0x00,0x00, + + 8, // 0x33 '3' + 0x00,0x00,0x7f,0x43,0x06,0x0c,0x1e,0x03,0x03,0x03,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x34 '4' + 0x00,0x00,0x06,0x0c,0x18,0x32,0x66,0x66,0x7f,0x06,0x06,0x0f,0x00,0x00,0x00,0x00, + + 8, // 0x35 '5' + 0x00,0x00,0x7f,0x61,0x60,0x60,0x7e,0x03,0x03,0x03,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x36 '6' + 0x00,0x00,0x1e,0x30,0x60,0x60,0x7e,0x63,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x37 '7' + 0x00,0x00,0x7f,0x63,0x63,0x03,0x06,0x0c,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, + + 8, // 0x38 '8' + 0x00,0x00,0x3e,0x63,0x63,0x63,0x3e,0x63,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x39 '9' + 0x00,0x00,0x3e,0x63,0x63,0x63,0x63,0x3f,0x03,0x03,0x06,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x3a ':' + 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x3b ';' + 0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x60,0x40,0x00, + + 8, // 0x3c '<' + 0x00,0x00,0x00,0x06,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x06,0x00,0x00,0x00,0x00, + + 8, // 0x3d '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x3e '>' + 0x00,0x00,0x00,0x30,0x18,0x0c,0x06,0x03,0x06,0x0c,0x18,0x30,0x00,0x00,0x00,0x00, + + 8, // 0x3f '?' + 0x00,0x00,0x3e,0x63,0x63,0x63,0x06,0x0c,0x0c,0x00,0x0c,0x0c,0x00,0x00,0x00,0x00, + + 8, // 0x40 '@' + 0x00,0x00,0x7c,0x86,0x03,0x73,0xdb,0xdb,0xdb,0xdb,0xdb,0x6e,0x00,0x00,0x00,0x00, + + 8, // 0x41 'A' + 0x00,0x00,0x08,0x1c,0x36,0x63,0x63,0x63,0x7f,0x63,0x63,0x63,0x00,0x00,0x00,0x00, + + 8, // 0x42 'B' + 0x00,0x00,0x7e,0x33,0x33,0x33,0x3e,0x33,0x33,0x33,0x33,0x7e,0x00,0x00,0x00,0x00, + + 8, // 0x43 'C' + 0x00,0x00,0x1e,0x33,0x61,0x60,0x60,0x60,0x60,0x61,0x33,0x1e,0x00,0x00,0x00,0x00, + + 8, // 0x44 'D' + 0x00,0x00,0x7c,0x36,0x33,0x33,0x33,0x33,0x33,0x33,0x36,0x7c,0x00,0x00,0x00,0x00, + + 8, // 0x45 'E' + 0x00,0x00,0x7f,0x33,0x31,0x34,0x3c,0x34,0x30,0x31,0x33,0x7f,0x00,0x00,0x00,0x00, + + 8, // 0x46 'F' + 0x00,0x00,0x7f,0x33,0x31,0x34,0x3c,0x34,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00, + + 8, // 0x47 'G' + 0x00,0x00,0x1f,0x33,0x61,0x60,0x60,0x6f,0x63,0x63,0x33,0x1e,0x00,0x00,0x00,0x00, + + 8, // 0x48 'H' + 0x00,0x00,0x63,0x63,0x63,0x63,0x7f,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00, + + 8, // 0x49 'I' + 0x00,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, + + 8, // 0x4a 'J' + 0x00,0x00,0x0f,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x4b 'K' + 0x00,0x00,0x73,0x33,0x36,0x36,0x3c,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00, + + 8, // 0x4c 'L' + 0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x33,0x7f,0x00,0x00,0x00,0x00, + + 8, // 0x4d 'M' + 0x00,0x00,0x63,0x63,0x77,0x77,0x7f,0x6b,0x6b,0x63,0x63,0x63,0x00,0x00,0x00,0x00, + + 8, // 0x4e 'N' + 0x00,0x00,0x63,0x63,0x73,0x7b,0x6f,0x67,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00, + + 8, // 0x4f 'O' + 0x00,0x00,0x1c,0x36,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1c,0x00,0x00,0x00,0x00, + + 8, // 0x50 'P' + 0x00,0x00,0x7e,0x33,0x33,0x33,0x33,0x3e,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00, + + 8, // 0x51 'Q' + 0x00,0x00,0x1c,0x36,0x63,0x63,0x63,0x63,0x63,0x6f,0x36,0x1e,0x03,0x00,0x00,0x00, + + 8, // 0x52 'R' + 0x00,0x00,0x7e,0x33,0x33,0x33,0x33,0x3e,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00, + + 8, // 0x53 'S' + 0x00,0x00,0x3e,0x63,0x63,0x30,0x18,0x0c,0x06,0x63,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x54 'T' + 0x00,0x00,0x3f,0x3f,0x2d,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, + + 8, // 0x55 'U' + 0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x56 'V' + 0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1c,0x08,0x00,0x00,0x00,0x00, + + 8, // 0x57 'W' + 0x00,0x00,0x63,0x63,0x63,0x6b,0x6b,0x7f,0x77,0x77,0x63,0x63,0x00,0x00,0x00,0x00, + + 8, // 0x58 'X' + 0x00,0x00,0x63,0x63,0x63,0x36,0x1c,0x1c,0x36,0x63,0x63,0x63,0x00,0x00,0x00,0x00, + + 8, // 0x59 'Y' + 0x00,0x00,0x33,0x33,0x33,0x33,0x1e,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, + + 8, // 0x5a 'Z' + 0x00,0x00,0x7f,0x63,0x43,0x06,0x0c,0x18,0x30,0x61,0x63,0x7f,0x00,0x00,0x00,0x00, + + 8, // 0x5b '[' + 0x00,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00, + + 8, // 0x5c '\' + 0x00,0x60,0x60,0x30,0x30,0x18,0x18,0x0c,0x0c,0x06,0x06,0x03,0x03,0x00,0x00,0x00, + + 8, // 0x5d ']' + 0x00,0x7c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x7c,0x00,0x00,0x00, + + 8, // 0x5e '^' + 0x00,0x00,0x08,0x1c,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00, + + 8, // 0x60 '`' + 0x00,0x00,0x18,0x18,0x18,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x3c,0x66,0x06,0x3e,0x66,0x66,0x3b,0x00,0x00,0x00,0x00, + + 8, // 0x62 'b' + 0x00,0x00,0x70,0x30,0x30,0x3c,0x36,0x33,0x33,0x33,0x33,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x3e,0x63,0x63,0x60,0x60,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x64 'd' + 0x00,0x00,0x0e,0x06,0x06,0x1e,0x36,0x66,0x66,0x66,0x66,0x3b,0x00,0x00,0x00,0x00, + + 8, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x3e,0x63,0x63,0x7f,0x60,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x66 'f' + 0x00,0x00,0x0e,0x1b,0x1b,0x18,0x3c,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x3b,0x66,0x66,0x66,0x66,0x66,0x3e,0x06,0x66,0x3c,0x00, + + 8, // 0x68 'h' + 0x00,0x00,0x70,0x30,0x30,0x36,0x3b,0x33,0x33,0x33,0x33,0x73,0x00,0x00,0x00,0x00, + + 8, // 0x69 'i' + 0x00,0x00,0x0c,0x0c,0x00,0x1c,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, + + 8, // 0x6a 'j' + 0x00,0x00,0x06,0x06,0x00,0x0e,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3c,0x00,0x00, + + 8, // 0x6b 'k' + 0x00,0x00,0x70,0x30,0x30,0x33,0x33,0x36,0x3c,0x36,0x33,0x73,0x00,0x00,0x00,0x00, + + 8, // 0x6c 'l' + 0x00,0x00,0x1c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, + + 8, // 0x6d 'm' + 0x00,0x00,0x00,0x00,0x00,0x76,0x7f,0x6b,0x6b,0x6b,0x63,0x63,0x00,0x00,0x00,0x00, + + 8, // 0x6e 'n' + 0x00,0x00,0x00,0x00,0x00,0x6e,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x00, + + 8, // 0x6f 'o' + 0x00,0x00,0x00,0x00,0x00,0x3e,0x63,0x63,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x6e,0x33,0x33,0x33,0x33,0x33,0x3e,0x30,0x30,0x78,0x00, + + 8, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x3b,0x66,0x66,0x66,0x66,0x66,0x3e,0x06,0x06,0x0f,0x00, + + 8, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x6e,0x3b,0x33,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00, + + 8, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x3e,0x63,0x60,0x3e,0x03,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x74 't' + 0x00,0x00,0x08,0x18,0x18,0x7e,0x18,0x18,0x18,0x18,0x1b,0x0e,0x00,0x00,0x00,0x00, + + 8, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x3b,0x00,0x00,0x00,0x00, + + 8, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x36,0x1c,0x08,0x00,0x00,0x00,0x00, + + 8, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x6b,0x6b,0x7f,0x36,0x36,0x00,0x00,0x00,0x00, + + 8, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x36,0x1c,0x36,0x63,0x63,0x00,0x00,0x00,0x00, + + 8, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x3f,0x03,0x06,0x7c,0x00, + + 8, // 0x7a 'z' + 0x00,0x00,0x00,0x00,0x00,0x7f,0x63,0x06,0x0c,0x18,0x31,0x7f,0x00,0x00,0x00,0x00, + + 8, // 0x7b '{' + 0x00,0x03,0x04,0x0c,0x0c,0x0c,0x08,0x30,0x08,0x0c,0x0c,0x0c,0x04,0x03,0x00,0x00, + + 8, // 0x7c '|' + 0x00,0x00,0x0c,0x0c,0x0c,0x0c,0x0c,0x00,0x0c,0x0c,0x0c,0x0c,0x0c,0x00,0x00,0x00, + + 8, // 0x7d '}' + 0x00,0x60,0x10,0x18,0x18,0x18,0x08,0x06,0x08,0x18,0x18,0x18,0x10,0x60,0x00,0x00, + + 8, // 0x7e '~' + 0x00,0x00,0x3b,0x6e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x7f '' + 0x00,0x00,0x00,0x00,0x00,0x08,0x1c,0x36,0x63,0x63,0x7f,0x00,0x00,0x00,0x00,0x00, + 0 + }; + + const int8u mcs11_prop[] = + { + 11, 2, 32, 128-32, + 0x00,0x00,0x0C,0x00,0x18,0x00,0x24,0x00,0x30,0x00,0x3C,0x00,0x48,0x00,0x54,0x00,0x60,0x00, + 0x6C,0x00,0x78,0x00,0x84,0x00,0x90,0x00,0x9C,0x00,0xA8,0x00,0xB4,0x00,0xC0,0x00,0xCC,0x00, + 0xD8,0x00,0xE4,0x00,0xF0,0x00,0xFC,0x00,0x08,0x01,0x14,0x01,0x20,0x01,0x2C,0x01,0x38,0x01, + 0x44,0x01,0x50,0x01,0x5C,0x01,0x68,0x01,0x74,0x01,0x80,0x01,0x8C,0x01,0x98,0x01,0xA4,0x01, + 0xB0,0x01,0xBC,0x01,0xC8,0x01,0xD4,0x01,0xE0,0x01,0xEC,0x01,0xF8,0x01,0x04,0x02,0x10,0x02, + 0x1C,0x02,0x28,0x02,0x34,0x02,0x40,0x02,0x4C,0x02,0x58,0x02,0x64,0x02,0x70,0x02,0x7C,0x02, + 0x88,0x02,0x94,0x02,0xA0,0x02,0xAC,0x02,0xB8,0x02,0xC4,0x02,0xD0,0x02,0xDC,0x02,0xE8,0x02, + 0xF4,0x02,0x00,0x03,0x0C,0x03,0x18,0x03,0x24,0x03,0x30,0x03,0x3C,0x03,0x48,0x03,0x54,0x03, + 0x60,0x03,0x6C,0x03,0x78,0x03,0x84,0x03,0x90,0x03,0x9C,0x03,0xA8,0x03,0xB4,0x03,0xC0,0x03, + 0xCC,0x03,0xD8,0x03,0xE4,0x03,0xF0,0x03,0xFC,0x03,0x08,0x04,0x14,0x04,0x20,0x04,0x2C,0x04, + 0x38,0x04,0x44,0x04,0x50,0x04,0x5C,0x04,0x68,0x04,0x74,0x04, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x21 '!' + 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00, + + 4, // 0x22 '"' + 0x50,0x50,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x23 '#' + 0x00,0x28,0x28,0x7C,0x28,0x28,0x28,0x7C,0x28,0x28,0x00, + + 6, // 0x24 '$' + 0x10,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x10, + + 6, // 0x25 '%' + 0x00,0x00,0x68,0xA8,0xD0,0x10,0x20,0x2C,0x54,0x58,0x00, + + 6, // 0x26 '&' + 0x00,0x20,0x50,0x50,0x50,0x20,0x54,0x54,0x48,0x34,0x00, + + 3, // 0x27 ''' + 0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x28 '(' + 0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10, + + 5, // 0x29 ')' + 0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x20,0x20,0x40, + + 6, // 0x2A '*' + 0x00,0x00,0x28,0x7C,0x38,0x7C,0x28,0x00,0x00,0x00,0x00, + + 6, // 0x2B '+' + 0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, + + 4, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0xC0, + + 6, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00, + + 7, // 0x2F '/' + 0x00,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40, + + 6, // 0x30 '0' + 0x00,0x38,0x44,0x44,0x54,0x54,0x54,0x44,0x44,0x38,0x00, + + 4, // 0x31 '1' + 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00, + + 6, // 0x32 '2' + 0x00,0x38,0x44,0x44,0x04,0x08,0x10,0x20,0x40,0x7C,0x00, + + 6, // 0x33 '3' + 0x00,0x38,0x44,0x04,0x04,0x38,0x04,0x04,0x44,0x38,0x00, + + 6, // 0x34 '4' + 0x00,0x08,0x18,0x18,0x28,0x28,0x48,0x7C,0x08,0x08,0x00, + + 6, // 0x35 '5' + 0x00,0x7C,0x40,0x40,0x78,0x44,0x04,0x04,0x44,0x38,0x00, + + 6, // 0x36 '6' + 0x00,0x38,0x44,0x40,0x40,0x78,0x44,0x44,0x44,0x38,0x00, + + 6, // 0x37 '7' + 0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x20,0x00, + + 6, // 0x38 '8' + 0x00,0x38,0x44,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00, + + 6, // 0x39 '9' + 0x00,0x38,0x44,0x44,0x44,0x3C,0x04,0x04,0x44,0x38,0x00, + + 4, // 0x3A ':' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x00, + + 4, // 0x3B ';' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0xC0, + + 6, // 0x3C '<' + 0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00, + + 6, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00, + + 6, // 0x3E '>' + 0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00, + + 6, // 0x3F '?' + 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x10,0x00,0x10,0x00, + + 6, // 0x40 '@' + 0x00,0x38,0x44,0x44,0x5C,0x54,0x54,0x4C,0x40,0x38,0x00, + + 6, // 0x41 'A' + 0x00,0x38,0x44,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x00, + + 6, // 0x42 'B' + 0x00,0x78,0x44,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00, + + 6, // 0x43 'C' + 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x40,0x44,0x38,0x00, + + 6, // 0x44 'D' + 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x44,0x48,0x70,0x00, + + 6, // 0x45 'E' + 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x7C,0x00, + + 6, // 0x46 'F' + 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00, + + 6, // 0x47 'G' + 0x00,0x38,0x44,0x40,0x40,0x5C,0x44,0x44,0x4C,0x34,0x00, + + 6, // 0x48 'H' + 0x00,0x44,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00, + + 4, // 0x49 'I' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00, + + 6, // 0x4A 'J' + 0x00,0x1C,0x08,0x08,0x08,0x08,0x08,0x08,0x48,0x30,0x00, + + 6, // 0x4B 'K' + 0x00,0x44,0x48,0x50,0x60,0x60,0x50,0x48,0x44,0x44,0x00, + + 6, // 0x4C 'L' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00, + + 8, // 0x4D 'M' + 0x00,0x41,0x63,0x55,0x49,0x49,0x41,0x41,0x41,0x41,0x00, + + 7, // 0x4E 'N' + 0x00,0x42,0x42,0x62,0x52,0x4A,0x46,0x42,0x42,0x42,0x00, + + 6, // 0x4F 'O' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00, + + 6, // 0x50 'P' + 0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x40,0x00, + + 6, // 0x51 'Q' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00, + + 6, // 0x52 'R' + 0x00,0x78,0x44,0x44,0x44,0x78,0x44,0x44,0x44,0x44,0x00, + + 6, // 0x53 'S' + 0x00,0x38,0x44,0x40,0x40,0x38,0x04,0x04,0x44,0x38,0x00, + + 6, // 0x54 'T' + 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00, + + 6, // 0x55 'U' + 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00, + + 6, // 0x56 'V' + 0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00, + + 8, // 0x57 'W' + 0x00,0x41,0x41,0x41,0x41,0x49,0x49,0x49,0x55,0x22,0x00, + + 6, // 0x58 'X' + 0x00,0x44,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00, + + 6, // 0x59 'Y' + 0x00,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x10,0x00, + + 6, // 0x5A 'Z' + 0x00,0x7C,0x04,0x04,0x08,0x10,0x20,0x40,0x40,0x7C,0x00, + + 5, // 0x5B '[' + 0x30,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x30, + + 7, // 0x5C '\' + 0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00, + + 4, // 0x5D ']' + 0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x60, + + 6, // 0x5E '^' + 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00, + + 4, // 0x60 '`' + 0x00,0x40,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x61 'a' + 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x44,0x3C,0x00, + + 6, // 0x62 'b' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00, + + 6, // 0x63 'c' + 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00, + + 6, // 0x64 'd' + 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x00, + + 6, // 0x65 'e' + 0x00,0x00,0x00,0x38,0x44,0x44,0x7C,0x40,0x44,0x38,0x00, + + 4, // 0x66 'f' + 0x00,0x10,0x20,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x00, + + 6, // 0x67 'g' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x3C,0x04,0x44,0x38, + + 6, // 0x68 'h' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x44,0x00, + + 2, // 0x69 'i' + 0x00,0x40,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00, + + 3, // 0x6A 'j' + 0x00,0x20,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0xA0,0x40, + + 5, // 0x6B 'k' + 0x00,0x40,0x40,0x48,0x50,0x60,0x60,0x50,0x48,0x48,0x00, + + 2, // 0x6C 'l' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00, + + 8, // 0x6D 'm' + 0x00,0x00,0x00,0x76,0x49,0x49,0x49,0x49,0x41,0x41,0x00, + + 6, // 0x6E 'n' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x44,0x00, + + 6, // 0x6F 'o' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00, + + 6, // 0x70 'p' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40, + + 6, // 0x71 'q' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x04, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x20,0x20,0x20,0x00, + + 6, // 0x73 's' + 0x00,0x00,0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00, + + 5, // 0x74 't' + 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x20,0x28,0x10,0x00, + + 6, // 0x75 'u' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x4C,0x34,0x00, + + 6, // 0x76 'v' + 0x00,0x00,0x00,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00, + + 8, // 0x77 'w' + 0x00,0x00,0x00,0x41,0x41,0x41,0x41,0x49,0x49,0x36,0x00, + + 6, // 0x78 'x' + 0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00, + + 6, // 0x79 'y' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x3C,0x04,0x08,0x70, + + 6, // 0x7A 'z' + 0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00, + + 5, // 0x7B '{' + 0x18,0x20,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x20,0x18, + + 3, // 0x7C '|' + 0x00,0x40,0x40,0x40,0x40,0x00,0x40,0x40,0x40,0x40,0x00, + + 5, // 0x7D '}' + 0xC0,0x20,0x20,0x20,0x20,0x18,0x20,0x20,0x20,0x20,0xC0, + + 6, // 0x7E '~' + 0x00,0x24,0x54,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x7F '' + 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u mcs11_prop_condensed[] = + { + 11, 2, 32, 128-32, + 0x00,0x00,0x0C,0x00,0x18,0x00,0x24,0x00,0x30,0x00,0x3C,0x00,0x48,0x00,0x54,0x00,0x60,0x00, + 0x6C,0x00,0x78,0x00,0x84,0x00,0x90,0x00,0x9C,0x00,0xA8,0x00,0xB4,0x00,0xC0,0x00,0xCC,0x00, + 0xD8,0x00,0xE4,0x00,0xF0,0x00,0xFC,0x00,0x08,0x01,0x14,0x01,0x20,0x01,0x2C,0x01,0x38,0x01, + 0x44,0x01,0x50,0x01,0x5C,0x01,0x68,0x01,0x74,0x01,0x80,0x01,0x8C,0x01,0x98,0x01,0xA4,0x01, + 0xB0,0x01,0xBC,0x01,0xC8,0x01,0xD4,0x01,0xE0,0x01,0xEC,0x01,0xF8,0x01,0x04,0x02,0x10,0x02, + 0x1C,0x02,0x28,0x02,0x34,0x02,0x40,0x02,0x4C,0x02,0x58,0x02,0x64,0x02,0x70,0x02,0x7C,0x02, + 0x88,0x02,0x94,0x02,0xA0,0x02,0xAC,0x02,0xB8,0x02,0xC4,0x02,0xD0,0x02,0xDC,0x02,0xE8,0x02, + 0xF4,0x02,0x00,0x03,0x0C,0x03,0x18,0x03,0x24,0x03,0x30,0x03,0x3C,0x03,0x48,0x03,0x54,0x03, + 0x60,0x03,0x6C,0x03,0x78,0x03,0x84,0x03,0x90,0x03,0x9C,0x03,0xA8,0x03,0xB4,0x03,0xC0,0x03, + 0xCC,0x03,0xD8,0x03,0xE4,0x03,0xF0,0x03,0xFC,0x03,0x08,0x04,0x14,0x04,0x20,0x04,0x2C,0x04, + 0x38,0x04,0x44,0x04,0x50,0x04,0x5C,0x04,0x68,0x04,0x74,0x04, + + 3, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 3, // 0x21 '!' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x40,0x00, + + 4, // 0x22 '"' + 0x50,0x50,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x23 '#' + 0x00,0x50,0x50,0xF8,0x50,0x50,0x50,0xF8,0x50,0x50,0x00, + + 5, // 0x24 '$' + 0x00,0x40,0x60,0x90,0x80,0x60,0x10,0x90,0x60,0x20,0x00, + + 5, // 0x25 '%' + 0x00,0x00,0x90,0x90,0x20,0x20,0x40,0x40,0x90,0x90,0x00, + + 5, // 0x26 '&' + 0x00,0x40,0xA0,0xA0,0xA0,0x40,0xA8,0x90,0x90,0x68,0x00, + + 5, // 0x27 ''' + 0x00,0x00,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x28 '(' + 0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10, + + 4, // 0x29 ')' + 0x80,0x40,0x40,0x20,0x20,0x20,0x20,0x20,0x40,0x40,0x80, + + 5, // 0x2A '*' + 0x00,0x00,0x90,0x60,0xF0,0x60,0x90,0x00,0x00,0x00,0x00, + + 5, // 0x2B '+' + 0x00,0x00,0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00,0x00, + + 4, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0xC0, + + 5, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x00, + + 6, // 0x2F '/' + 0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80,0x00, + + 5, // 0x30 '0' + 0x00,0x70,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0xE0,0x00, + + 3, // 0x31 '1' + 0x00,0x40,0xC0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00, + + 5, // 0x32 '2' + 0x00,0x60,0x90,0x90,0x10,0x10,0x20,0x40,0x80,0xF0,0x00, + + 5, // 0x33 '3' + 0x00,0x60,0x90,0x10,0x10,0x60,0x10,0x10,0x90,0x60,0x00, + + 5, // 0x34 '4' + 0x00,0x10,0x30,0x30,0x50,0x50,0x90,0xF0,0x10,0x10,0x00, + + 5, // 0x35 '5' + 0x00,0xF0,0x80,0x80,0xE0,0x90,0x10,0x10,0x90,0x60,0x00, + + 5, // 0x36 '6' + 0x00,0x60,0x90,0x80,0x80,0xE0,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x37 '7' + 0x00,0xF0,0x10,0x10,0x10,0x20,0x20,0x40,0x40,0x40,0x00, + + 5, // 0x38 '8' + 0x00,0x60,0x90,0x90,0x90,0x60,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x39 '9' + 0x00,0x60,0x90,0x90,0x90,0x70,0x10,0x10,0x90,0x60,0x00, + + 4, // 0x3A ':' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x00, + + 4, // 0x3B ';' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0xC0, + + 6, // 0x3C '<' + 0x00,0x08,0x10,0x20,0x40,0x80,0x40,0x20,0x10,0x08,0x00, + + 5, // 0x3D '=' + 0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0xF0,0x00,0x00,0x00, + + 6, // 0x3E '>' + 0x00,0x80,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x80,0x00, + + 5, // 0x3F '?' + 0x00,0x60,0x90,0x10,0x10,0x20,0x40,0x00,0x40,0x00,0x00, + + 5, // 0x40 '@' + 0x00,0x60,0x90,0x90,0xB0,0xB0,0xB0,0x80,0x80,0x70,0x00, + + 5, // 0x41 'A' + 0x00,0x60,0x90,0x90,0x90,0xF0,0x90,0x90,0x90,0x90,0x00, + + 5, // 0x42 'B' + 0x00,0xE0,0x90,0x90,0x90,0xE0,0x90,0x90,0x90,0xE0,0x00, + + 5, // 0x43 'C' + 0x00,0x60,0x90,0x80,0x80,0x80,0x80,0x80,0x90,0x60,0x00, + + 5, // 0x44 'D' + 0x00,0xE0,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0xE0,0x00, + + 5, // 0x45 'E' + 0x00,0xF0,0x80,0x80,0x80,0xF0,0x80,0x80,0x80,0xF0,0x00, + + 5, // 0x46 'F' + 0x00,0xF0,0x80,0x80,0x80,0xF0,0x80,0x80,0x80,0x80,0x00, + + 5, // 0x47 'G' + 0x00,0x70,0x80,0x80,0x80,0xB0,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x48 'H' + 0x00,0x90,0x90,0x90,0x90,0xF0,0x90,0x90,0x90,0x90,0x00, + + 4, // 0x49 'I' + 0x00,0xE0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xE0,0x00, + + 5, // 0x4A 'J' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0xA0,0xA0,0x40,0x00, + + 5, // 0x4B 'K' + 0x00,0x90,0x90,0xA0,0xA0,0xC0,0xA0,0xA0,0x90,0x90,0x00, + + 5, // 0x4C 'L' + 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xF0,0x00, + + 6, // 0x4D 'M' + 0x00,0x88,0xD8,0xA8,0xA8,0xA8,0x88,0x88,0x88,0x88,0x00, + + 5, // 0x4E 'N' + 0x00,0x90,0x90,0xD0,0xD0,0xB0,0xB0,0x90,0x90,0x90,0x00, + + 5, // 0x4F 'O' + 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x50 'P' + 0x00,0xE0,0x90,0x90,0x90,0x90,0xE0,0x80,0x80,0x80,0x00, + + 5, // 0x51 'Q' + 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x30, + + 5, // 0x52 'R' + 0x00,0xE0,0x90,0x90,0x90,0x90,0xE0,0xA0,0x90,0x90,0x00, + + 5, // 0x53 'S' + 0x00,0x60,0x90,0x80,0x80,0x60,0x10,0x10,0x90,0x60,0x00, + + 6, // 0x54 'T' + 0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00, + + 5, // 0x55 'U' + 0x00,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00, + + 6, // 0x56 'V' + 0x00,0x88,0x88,0x88,0x88,0x50,0x50,0x50,0x20,0x20,0x00, + + 6, // 0x57 'W' + 0x00,0x88,0x88,0x88,0xA8,0xA8,0xA8,0xA8,0xA8,0x50,0x00, + + 5, // 0x58 'X' + 0x00,0x90,0x90,0x90,0x60,0x60,0x90,0x90,0x90,0x90,0x00, + + 6, // 0x59 'Y' + 0x00,0x88,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x20,0x00, + + 5, // 0x5A 'Z' + 0x00,0xF0,0x10,0x20,0x20,0x40,0x40,0x80,0x80,0xF0,0x00, + + 4, // 0x5B '[' + 0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x60,0x00, + + 6, // 0x5C '\' + 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00, + + 4, // 0x5D ']' + 0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x60,0x00, + + 5, // 0x5E '^' + 0x00,0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00, + + 5, // 0x60 '`' + 0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x61 'a' + 0x00,0x00,0x00,0x60,0x90,0x10,0x70,0x90,0x90,0x70,0x00, + + 5, // 0x62 'b' + 0x00,0x80,0x80,0x80,0xE0,0x90,0x90,0x90,0x90,0xE0,0x00, + + 5, // 0x63 'c' + 0x00,0x00,0x00,0x60,0x90,0x80,0x80,0x80,0x90,0x60,0x00, + + 5, // 0x64 'd' + 0x00,0x10,0x10,0x10,0x70,0x90,0x90,0x90,0x90,0x70,0x00, + + 5, // 0x65 'e' + 0x00,0x00,0x00,0x60,0x90,0x90,0xF0,0x80,0x90,0x60,0x00, + + 4, // 0x66 'f' + 0x00,0x20,0x40,0x40,0xE0,0x40,0x40,0x40,0x40,0x40,0x00, + + 5, // 0x67 'g' + 0x00,0x00,0x00,0x70,0x90,0x90,0x90,0x70,0x10,0x90,0x60, + + 5, // 0x68 'h' + 0x00,0x80,0x80,0x80,0xE0,0x90,0x90,0x90,0x90,0x90,0x00, + + 2, // 0x69 'i' + 0x00,0x80,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00, + + 4, // 0x6A 'j' + 0x00,0x20,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0xA0,0x40, + + 5, // 0x6B 'k' + 0x00,0x80,0x80,0x90,0x90,0xA0,0xC0,0xA0,0x90,0x90,0x00, + + 2, // 0x6C 'l' + 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00, + + 6, // 0x6D 'm' + 0x00,0x00,0x00,0xD0,0xA8,0xA8,0xA8,0x88,0x88,0x88,0x00, + + 5, // 0x6E 'n' + 0x00,0x00,0x00,0xA0,0xD0,0x90,0x90,0x90,0x90,0x90,0x00, + + 5, // 0x6F 'o' + 0x00,0x00,0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x70 'p' + 0x00,0x00,0x00,0xE0,0x90,0x90,0x90,0x90,0xE0,0x80,0x80, + + 5, // 0x71 'q' + 0x00,0x00,0x00,0x70,0x90,0x90,0x90,0x90,0x70,0x10,0x10, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0xB8,0x48,0x40,0x40,0x40,0x40,0x40,0x00, + + 5, // 0x73 's' + 0x00,0x00,0x00,0x60,0x90,0x40,0x20,0x10,0x90,0x60,0x00, + + 4, // 0x74 't' + 0x00,0x40,0x40,0xE0,0x40,0x40,0x40,0x40,0x40,0x20,0x00, + + 5, // 0x75 'u' + 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x90,0x90,0x70,0x00, + + 6, // 0x76 'v' + 0x00,0x00,0x00,0x88,0x88,0x88,0x50,0x50,0x20,0x20,0x00, + + 6, // 0x77 'w' + 0x00,0x00,0x00,0x88,0x88,0x88,0xA8,0xA8,0xA8,0x50,0x00, + + 5, // 0x78 'x' + 0x00,0x00,0x00,0x90,0x90,0x60,0x60,0x90,0x90,0x90,0x00, + + 5, // 0x79 'y' + 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x70,0x10,0x20,0xC0, + + 5, // 0x7A 'z' + 0x00,0x00,0x00,0xF0,0x10,0x20,0x40,0x80,0x80,0xF0,0x00, + + 5, // 0x7B '{' + 0x30,0x40,0x40,0x40,0x40,0x80,0x40,0x40,0x40,0x40,0x30, + + 3, // 0x7C '|' + 0x00,0x40,0x40,0x40,0x40,0x00,0x40,0x40,0x40,0x40,0x00, + + 5, // 0x7D '}' + 0xC0,0x20,0x20,0x20,0x20,0x10,0x20,0x20,0x20,0x20,0xC0, + + 5, // 0x7E '~' + 0x00,0x40,0xA8,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x7F '' + 0x00,0x20,0x70,0xD8,0x88,0x88,0xF8,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u mcs12_prop[] = + { + 12, 3, 32, 128-32, + 0x00,0x00,0x0D,0x00,0x1A,0x00,0x27,0x00,0x34,0x00,0x41,0x00,0x4E,0x00,0x5B,0x00,0x68,0x00, + 0x75,0x00,0x82,0x00,0x8F,0x00,0x9C,0x00,0xA9,0x00,0xB6,0x00,0xC3,0x00,0xD0,0x00,0xDD,0x00, + 0xEA,0x00,0xF7,0x00,0x04,0x01,0x11,0x01,0x1E,0x01,0x2B,0x01,0x38,0x01,0x45,0x01,0x52,0x01, + 0x5F,0x01,0x6C,0x01,0x79,0x01,0x86,0x01,0x93,0x01,0xA0,0x01,0xAD,0x01,0xBA,0x01,0xC7,0x01, + 0xD4,0x01,0xE1,0x01,0xEE,0x01,0xFB,0x01,0x08,0x02,0x15,0x02,0x22,0x02,0x2F,0x02,0x3C,0x02, + 0x49,0x02,0x62,0x02,0x6F,0x02,0x7C,0x02,0x89,0x02,0x96,0x02,0xA3,0x02,0xB0,0x02,0xBD,0x02, + 0xCA,0x02,0xD7,0x02,0xF0,0x02,0xFD,0x02,0x0A,0x03,0x17,0x03,0x24,0x03,0x31,0x03,0x3E,0x03, + 0x4B,0x03,0x58,0x03,0x65,0x03,0x72,0x03,0x7F,0x03,0x8C,0x03,0x99,0x03,0xA6,0x03,0xB3,0x03, + 0xC0,0x03,0xCD,0x03,0xDA,0x03,0xE7,0x03,0xF4,0x03,0x01,0x04,0x1A,0x04,0x27,0x04,0x34,0x04, + 0x41,0x04,0x4E,0x04,0x5B,0x04,0x68,0x04,0x75,0x04,0x82,0x04,0x8F,0x04,0xA8,0x04,0xB5,0x04, + 0xC2,0x04,0xCF,0x04,0xDC,0x04,0xE9,0x04,0xF6,0x04,0x03,0x05, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x21 '!' + 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, + + 4, // 0x22 '"' + 0x50,0x50,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x23 '#' + 0x28,0x28,0x28,0x7C,0x28,0x28,0x28,0x7C,0x28,0x28,0x28,0x00, + + 6, // 0x24 '$' + 0x10,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x10,0x00, + + 7, // 0x25 '%' + 0x32,0x54,0x64,0x08,0x08,0x10,0x10,0x26,0x2A,0x4C,0x00,0x00, + + 7, // 0x26 '&' + 0x00,0x30,0x48,0x48,0x48,0x30,0x4A,0x4A,0x44,0x3A,0x00,0x00, + + 3, // 0x27 ''' + 0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x28 '(' + 0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10,0x00, + + 5, // 0x29 ')' + 0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x20,0x20,0x40,0x00, + + 6, // 0x2A '*' + 0x00,0x00,0x10,0x54,0x38,0x7C,0x38,0x54,0x10,0x00,0x00,0x00, + + 6, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, + + 4, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x40,0x80, + + 6, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00, + + 7, // 0x2F '/' + 0x00,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00, + + 7, // 0x30 '0' + 0x00,0x38,0x44,0x44,0x54,0x54,0x54,0x44,0x44,0x38,0x00,0x00, + + 4, // 0x31 '1' + 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00, + + 7, // 0x32 '2' + 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, + + 7, // 0x33 '3' + 0x00,0x38,0x44,0x04,0x04,0x38,0x04,0x04,0x44,0x38,0x00,0x00, + + 6, // 0x34 '4' + 0x00,0x08,0x18,0x28,0x28,0x48,0x48,0x7C,0x08,0x08,0x00,0x00, + + 7, // 0x35 '5' + 0x00,0x7C,0x40,0x40,0x78,0x44,0x04,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x36 '6' + 0x00,0x38,0x44,0x40,0x78,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x37 '7' + 0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x20,0x00,0x00, + + 7, // 0x38 '8' + 0x00,0x38,0x44,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x39 '9' + 0x00,0x38,0x44,0x44,0x44,0x3C,0x04,0x04,0x44,0x38,0x00,0x00, + + 4, // 0x3A ':' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x00,0x00, + + 4, // 0x3B ';' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x40,0x80, + + 6, // 0x3C '<' + 0x00,0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00, + + 6, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00,0x00, + + 6, // 0x3E '>' + 0x00,0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00, + + 6, // 0x3F '?' + 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x10,0x00,0x10,0x00,0x00, + + 7, // 0x40 '@' + 0x00,0x38,0x44,0x44,0x5C,0x54,0x54,0x4C,0x40,0x38,0x00,0x00, + + 7, // 0x41 'A' + 0x00,0x38,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x42 'B' + 0x00,0x78,0x44,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00,0x00, + + 6, // 0x43 'C' + 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00, + + 7, // 0x44 'D' + 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00, + + 6, // 0x45 'E' + 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x7C,0x00,0x00, + + 6, // 0x46 'F' + 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00,0x00, + + 7, // 0x47 'G' + 0x00,0x38,0x44,0x40,0x40,0x5C,0x44,0x44,0x4C,0x34,0x00,0x00, + + 7, // 0x48 'H' + 0x00,0x44,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00, + + 5, // 0x49 'I' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 6, // 0x4A 'J' + 0x00,0x1C,0x08,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00, + + 6, // 0x4B 'K' + 0x00,0x44,0x48,0x50,0x60,0x60,0x50,0x48,0x44,0x44,0x00,0x00, + + 6, // 0x4C 'L' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00, + + 9, // 0x4D 'M' + 0x00,0x00,0x41,0x00,0x63,0x00,0x55,0x00,0x49,0x00,0x49,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x4E 'N' + 0x00,0x44,0x64,0x64,0x54,0x54,0x4C,0x4C,0x44,0x44,0x00,0x00, + + 7, // 0x4F 'O' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00, + + 7, // 0x51 'Q' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00, + + 7, // 0x52 'R' + 0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x48,0x44,0x44,0x00,0x00, + + 7, // 0x53 'S' + 0x00,0x38,0x44,0x40,0x40,0x38,0x04,0x04,0x44,0x38,0x00,0x00, + + 6, // 0x54 'T' + 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 7, // 0x55 'U' + 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x56 'V' + 0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00,0x00, + + 9, // 0x57 'W' + 0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x49,0x00,0x49,0x00,0x55,0x00,0x22,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x58 'X' + 0x00,0x44,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x44,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00,0x00, + + 6, // 0x5A 'Z' + 0x00,0x7C,0x04,0x04,0x08,0x10,0x20,0x40,0x40,0x7C,0x00,0x00, + + 4, // 0x5B '[' + 0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x70,0x00, + + 7, // 0x5C '\' + 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00, + + 4, // 0x5D ']' + 0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xE0,0x00, + + 6, // 0x5E '^' + 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00, + + 4, // 0x60 '`' + 0x00,0x40,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x61 'a' + 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x44,0x3C,0x00,0x00, + + 7, // 0x62 'b' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00,0x00, + + 6, // 0x63 'c' + 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00,0x00, + + 7, // 0x64 'd' + 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x00,0x00, + + 7, // 0x65 'e' + 0x00,0x00,0x00,0x38,0x44,0x44,0x7C,0x40,0x44,0x38,0x00,0x00, + + 4, // 0x66 'f' + 0x00,0x30,0x40,0xE0,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 7, // 0x67 'g' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x78, + + 7, // 0x68 'h' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x44,0x00,0x00, + + 3, // 0x69 'i' + 0x00,0x40,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 5, // 0x6A 'j' + 0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x90,0x60, + + 6, // 0x6B 'k' + 0x00,0x40,0x40,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00, + + 3, // 0x6C 'l' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 9, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x76,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x6E 'n' + 0x00,0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x6F 'o' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x70 'p' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x40,0x40, + + 7, // 0x71 'q' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x04, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00, + + 5, // 0x74 't' + 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x20,0x20,0x18,0x00,0x00, + + 7, // 0x75 'u' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x4C,0x34,0x00,0x00, + + 6, // 0x76 'v' + 0x00,0x00,0x00,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00, + + 9, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x36,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, + + 7, // 0x79 'y' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x3C,0x08,0x70, + + 6, // 0x7A 'z' + 0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, + + 5, // 0x7B '{' + 0x18,0x20,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x20,0x18,0x00, + + 3, // 0x7C '|' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00, + + 5, // 0x7D '}' + 0xC0,0x20,0x20,0x20,0x20,0x18,0x20,0x20,0x20,0x20,0xC0,0x00, + + 7, // 0x7E '~' + 0x00,0x60,0x92,0x92,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x7F '' + 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u mcs13_prop[] = + { + 13, 4, 32, 128-32, + 0x00,0x00,0x0E,0x00,0x1C,0x00,0x2A,0x00,0x38,0x00,0x46,0x00,0x54,0x00,0x62,0x00,0x70,0x00, + 0x7E,0x00,0x8C,0x00,0x9A,0x00,0xA8,0x00,0xB6,0x00,0xC4,0x00,0xD2,0x00,0xE0,0x00,0xEE,0x00, + 0xFC,0x00,0x0A,0x01,0x18,0x01,0x26,0x01,0x34,0x01,0x42,0x01,0x50,0x01,0x5E,0x01,0x6C,0x01, + 0x7A,0x01,0x88,0x01,0x96,0x01,0xA4,0x01,0xB2,0x01,0xC0,0x01,0xCE,0x01,0xDC,0x01,0xEA,0x01, + 0xF8,0x01,0x06,0x02,0x14,0x02,0x22,0x02,0x30,0x02,0x3E,0x02,0x4C,0x02,0x5A,0x02,0x68,0x02, + 0x76,0x02,0x91,0x02,0x9F,0x02,0xAD,0x02,0xBB,0x02,0xC9,0x02,0xD7,0x02,0xE5,0x02,0xF3,0x02, + 0x01,0x03,0x0F,0x03,0x2A,0x03,0x38,0x03,0x46,0x03,0x54,0x03,0x62,0x03,0x70,0x03,0x7E,0x03, + 0x8C,0x03,0x9A,0x03,0xA8,0x03,0xB6,0x03,0xC4,0x03,0xD2,0x03,0xE0,0x03,0xEE,0x03,0xFC,0x03, + 0x0A,0x04,0x18,0x04,0x26,0x04,0x34,0x04,0x42,0x04,0x50,0x04,0x6B,0x04,0x79,0x04,0x87,0x04, + 0x95,0x04,0xA3,0x04,0xB1,0x04,0xBF,0x04,0xCD,0x04,0xDB,0x04,0xE9,0x04,0x04,0x05,0x12,0x05, + 0x20,0x05,0x2E,0x05,0x3C,0x05,0x4A,0x05,0x58,0x05,0x66,0x05, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x21 '!' + 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, + + 4, // 0x22 '"' + 0x00,0x50,0x50,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x23 '#' + 0x00,0x28,0x28,0x28,0x7C,0x28,0x28,0x28,0x7C,0x28,0x28,0x28,0x00, + + 6, // 0x24 '$' + 0x00,0x10,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x10,0x00, + + 7, // 0x25 '%' + 0x00,0x32,0x54,0x64,0x08,0x08,0x10,0x10,0x26,0x2A,0x4C,0x00,0x00, + + 7, // 0x26 '&' + 0x00,0x30,0x48,0x48,0x48,0x30,0x4A,0x4A,0x44,0x3A,0x00,0x00,0x00, + + 3, // 0x27 ''' + 0x00,0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x28 '(' + 0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10,0x00,0x00, + + 5, // 0x29 ')' + 0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x20,0x20,0x40,0x00,0x00, + + 6, // 0x2A '*' + 0x00,0x00,0x10,0x54,0x38,0x7C,0x38,0x54,0x10,0x00,0x00,0x00,0x00, + + 6, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00,0x00, + + 4, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x20,0x40,0x80, + + 6, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00, + + 7, // 0x2F '/' + 0x00,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00,0x00, + + 7, // 0x30 '0' + 0x00,0x38,0x44,0x44,0x54,0x54,0x54,0x44,0x44,0x38,0x00,0x00,0x00, + + 4, // 0x31 '1' + 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x00, + + 7, // 0x32 '2' + 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00,0x00, + + 7, // 0x33 '3' + 0x00,0x38,0x44,0x04,0x04,0x38,0x04,0x04,0x44,0x38,0x00,0x00,0x00, + + 6, // 0x34 '4' + 0x00,0x08,0x18,0x28,0x28,0x48,0x48,0x7C,0x08,0x08,0x00,0x00,0x00, + + 7, // 0x35 '5' + 0x00,0x7C,0x40,0x40,0x78,0x44,0x04,0x04,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x36 '6' + 0x00,0x38,0x44,0x40,0x78,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 6, // 0x37 '7' + 0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x20,0x00,0x00,0x00, + + 7, // 0x38 '8' + 0x00,0x38,0x44,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x39 '9' + 0x00,0x38,0x44,0x44,0x44,0x3C,0x04,0x04,0x44,0x38,0x00,0x00,0x00, + + 4, // 0x3A ':' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00, + + 4, // 0x3B ';' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x20,0x40,0x80, + + 6, // 0x3C '<' + 0x00,0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00,0x00, + + 6, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x3E '>' + 0x00,0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00,0x00, + + 6, // 0x3F '?' + 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x10,0x00,0x10,0x00,0x00,0x00, + + 7, // 0x40 '@' + 0x00,0x38,0x44,0x44,0x5C,0x54,0x54,0x4C,0x40,0x38,0x00,0x00,0x00, + + 7, // 0x41 'A' + 0x00,0x38,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x42 'B' + 0x00,0x78,0x44,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00,0x00,0x00, + + 6, // 0x43 'C' + 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x44 'D' + 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00,0x00, + + 6, // 0x45 'E' + 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x7C,0x00,0x00,0x00, + + 6, // 0x46 'F' + 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 7, // 0x47 'G' + 0x00,0x38,0x44,0x40,0x40,0x5C,0x44,0x44,0x4C,0x34,0x00,0x00,0x00, + + 7, // 0x48 'H' + 0x00,0x44,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 5, // 0x49 'I' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00,0x00, + + 6, // 0x4A 'J' + 0x00,0x1C,0x08,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00,0x00, + + 6, // 0x4B 'K' + 0x00,0x44,0x48,0x50,0x60,0x60,0x50,0x48,0x44,0x44,0x00,0x00,0x00, + + 6, // 0x4C 'L' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00,0x00, + + 9, // 0x4D 'M' + 0x00,0x00,0x41,0x00,0x63,0x00,0x55,0x00,0x49,0x00,0x49,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x4E 'N' + 0x00,0x44,0x64,0x64,0x54,0x54,0x4C,0x4C,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x4F 'O' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00,0x00, + + 7, // 0x51 'Q' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00,0x00, + + 7, // 0x52 'R' + 0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x48,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x53 'S' + 0x00,0x38,0x44,0x40,0x40,0x38,0x04,0x04,0x44,0x38,0x00,0x00,0x00, + + 6, // 0x54 'T' + 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x55 'U' + 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 6, // 0x56 'V' + 0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00,0x00,0x00, + + 9, // 0x57 'W' + 0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x49,0x00,0x49,0x00,0x55,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x58 'X' + 0x00,0x44,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x44,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00,0x00,0x00, + + 6, // 0x5A 'Z' + 0x00,0x7C,0x04,0x04,0x08,0x10,0x20,0x40,0x40,0x7C,0x00,0x00,0x00, + + 4, // 0x5B '[' + 0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x70,0x00,0x00, + + 7, // 0x5C '\' + 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00,0x00, + + 4, // 0x5D ']' + 0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xE0,0x00,0x00, + + 6, // 0x5E '^' + 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00, + + 4, // 0x60 '`' + 0x00,0x40,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x61 'a' + 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x44,0x3C,0x00,0x00,0x00, + + 7, // 0x62 'b' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00,0x00,0x00, + + 6, // 0x63 'c' + 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x64 'd' + 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x00,0x00,0x00, + + 7, // 0x65 'e' + 0x00,0x00,0x00,0x38,0x44,0x44,0x7C,0x40,0x44,0x38,0x00,0x00,0x00, + + 4, // 0x66 'f' + 0x00,0x30,0x40,0xE0,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 7, // 0x67 'g' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x44,0x38, + + 7, // 0x68 'h' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 3, // 0x69 'i' + 0x00,0x40,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 5, // 0x6A 'j' + 0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x90,0x60,0x00, + + 6, // 0x6B 'k' + 0x00,0x40,0x40,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00,0x00, + + 3, // 0x6C 'l' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 9, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x76,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x6E 'n' + 0x00,0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x6F 'o' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x70 'p' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40, + + 7, // 0x71 'q' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x04,0x04, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x20,0x20,0x70,0x00,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00,0x00, + + 5, // 0x74 't' + 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x20,0x20,0x18,0x00,0x00,0x00, + + 7, // 0x75 'u' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x4C,0x34,0x00,0x00,0x00, + + 6, // 0x76 'v' + 0x00,0x00,0x00,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00,0x00, + + 9, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x79 'y' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x08,0x70, + + 6, // 0x7A 'z' + 0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00,0x00, + + 5, // 0x7B '{' + 0x18,0x20,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x20,0x18,0x00,0x00, + + 3, // 0x7C '|' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 5, // 0x7D '}' + 0xC0,0x20,0x20,0x20,0x20,0x18,0x20,0x20,0x20,0x20,0xC0,0x00,0x00, + + 7, // 0x7E '~' + 0x00,0x60,0x92,0x92,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x7F '' + 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u mcs5x10_mono[] = + { + 10, 2, 32, 128-32, + 0x00,0x00,0x0B,0x00,0x16,0x00,0x21,0x00,0x2C,0x00,0x37,0x00,0x42,0x00,0x4D,0x00,0x58,0x00, + 0x63,0x00,0x6E,0x00,0x79,0x00,0x84,0x00,0x8F,0x00,0x9A,0x00,0xA5,0x00,0xB0,0x00,0xBB,0x00, + 0xC6,0x00,0xD1,0x00,0xDC,0x00,0xE7,0x00,0xF2,0x00,0xFD,0x00,0x08,0x01,0x13,0x01,0x1E,0x01, + 0x29,0x01,0x34,0x01,0x3F,0x01,0x4A,0x01,0x55,0x01,0x60,0x01,0x6B,0x01,0x76,0x01,0x81,0x01, + 0x8C,0x01,0x97,0x01,0xA2,0x01,0xAD,0x01,0xB8,0x01,0xC3,0x01,0xCE,0x01,0xD9,0x01,0xE4,0x01, + 0xEF,0x01,0xFA,0x01,0x05,0x02,0x10,0x02,0x1B,0x02,0x26,0x02,0x31,0x02,0x3C,0x02,0x47,0x02, + 0x52,0x02,0x5D,0x02,0x68,0x02,0x73,0x02,0x7E,0x02,0x89,0x02,0x94,0x02,0x9F,0x02,0xAA,0x02, + 0xB5,0x02,0xC0,0x02,0xCB,0x02,0xD6,0x02,0xE1,0x02,0xEC,0x02,0xF7,0x02,0x02,0x03,0x0D,0x03, + 0x18,0x03,0x23,0x03,0x2E,0x03,0x39,0x03,0x44,0x03,0x4F,0x03,0x5A,0x03,0x65,0x03,0x70,0x03, + 0x7B,0x03,0x86,0x03,0x91,0x03,0x9C,0x03,0xA7,0x03,0xB2,0x03,0xBD,0x03,0xC8,0x03,0xD3,0x03, + 0xDE,0x03,0xE9,0x03,0xF4,0x03,0xFF,0x03,0x0A,0x04,0x15,0x04, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x21 '!' + 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00, + + 5, // 0x22 '"' + 0x00,0x50,0x50,0xA0,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x23 '#' + 0x00,0x50,0x50,0xF8,0x50,0x50,0x50,0xF8,0x50,0x50, + + 5, // 0x24 '$' + 0x00,0x40,0x60,0x90,0x80,0x60,0x10,0x90,0x60,0x20, + + 5, // 0x25 '%' + 0x00,0x00,0x90,0x90,0x20,0x20,0x40,0x40,0x90,0x90, + + 5, // 0x26 '&' + 0x00,0x40,0xA0,0xA0,0xA0,0x40,0xA8,0x90,0x90,0x68, + + 5, // 0x27 ''' + 0x00,0x20,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x28 '(' + 0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x20,0x20,0x10, + + 5, // 0x29 ')' + 0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x20,0x20,0x40, + + 5, // 0x2A '*' + 0x00,0x00,0x90,0x60,0xF0,0x60,0x90,0x00,0x00,0x00, + + 5, // 0x2B '+' + 0x00,0x00,0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00, + + 5, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0xC0, + + 5, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00, + + 5, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00, + + 5, // 0x2F '/' + 0x00,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x00, + + 5, // 0x30 '0' + 0x00,0x70,0x90,0x90,0x90,0x90,0x90,0x90,0xE0,0x00, + + 5, // 0x31 '1' + 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00, + + 5, // 0x32 '2' + 0x00,0x60,0x90,0x90,0x10,0x20,0x40,0x80,0xF0,0x00, + + 5, // 0x33 '3' + 0x00,0x60,0x90,0x10,0x60,0x10,0x10,0x90,0x60,0x00, + + 5, // 0x34 '4' + 0x00,0x10,0x30,0x50,0x50,0x90,0xF0,0x10,0x10,0x00, + + 5, // 0x35 '5' + 0x00,0xF0,0x80,0x80,0xE0,0x10,0x10,0x90,0x60,0x00, + + 5, // 0x36 '6' + 0x00,0x60,0x80,0x80,0xE0,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x37 '7' + 0x00,0xF0,0x10,0x10,0x20,0x20,0x40,0x40,0x40,0x00, + + 5, // 0x38 '8' + 0x00,0x60,0x90,0x90,0x60,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x39 '9' + 0x00,0x60,0x90,0x90,0x90,0x70,0x10,0x10,0x60,0x00, + + 5, // 0x3A ':' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00, + + 5, // 0x3B ';' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0xC0, + + 5, // 0x3C '<' + 0x00,0x08,0x10,0x20,0x40,0x80,0x40,0x20,0x10,0x08, + + 5, // 0x3D '=' + 0x00,0x00,0x00,0x00,0xF0,0x00,0xF0,0x00,0x00,0x00, + + 5, // 0x3E '>' + 0x00,0x80,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x80, + + 5, // 0x3F '?' + 0x00,0x60,0x90,0x10,0x10,0x20,0x40,0x00,0x40,0x00, + + 5, // 0x40 '@' + 0x00,0x60,0x90,0x90,0xB0,0xB0,0x80,0x80,0x70,0x00, + + 5, // 0x41 'A' + 0x00,0x60,0x90,0x90,0x90,0xF0,0x90,0x90,0x90,0x00, + + 5, // 0x42 'B' + 0x00,0xE0,0x90,0x90,0xE0,0x90,0x90,0x90,0xE0,0x00, + + 5, // 0x43 'C' + 0x00,0x60,0x90,0x80,0x80,0x80,0x80,0x90,0x60,0x00, + + 5, // 0x44 'D' + 0x00,0xE0,0x90,0x90,0x90,0x90,0x90,0x90,0xE0,0x00, + + 5, // 0x45 'E' + 0x00,0xF0,0x80,0x80,0xF0,0x80,0x80,0x80,0xF0,0x00, + + 5, // 0x46 'F' + 0x00,0xF0,0x80,0x80,0xF0,0x80,0x80,0x80,0x80,0x00, + + 5, // 0x47 'G' + 0x00,0x60,0x90,0x80,0x80,0xB0,0x90,0x90,0x60,0x00, + + 5, // 0x48 'H' + 0x00,0x90,0x90,0x90,0x90,0xF0,0x90,0x90,0x90,0x00, + + 5, // 0x49 'I' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00, + + 5, // 0x4A 'J' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0xA0,0x40,0x00, + + 5, // 0x4B 'K' + 0x00,0x90,0xA0,0xA0,0xC0,0xC0,0xA0,0xA0,0x90,0x00, + + 5, // 0x4C 'L' + 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xF0,0x00, + + 5, // 0x4D 'M' + 0x00,0x90,0x90,0xF0,0xF0,0x90,0x90,0x90,0x90,0x00, + + 5, // 0x4E 'N' + 0x00,0x90,0x90,0xD0,0xD0,0xB0,0xB0,0x90,0x90,0x00, + + 5, // 0x4F 'O' + 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x50 'P' + 0x00,0xE0,0x90,0x90,0x90,0xE0,0x80,0x80,0x80,0x00, + + 5, // 0x51 'Q' + 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x30, + + 5, // 0x52 'R' + 0x00,0xE0,0x90,0x90,0x90,0xE0,0xA0,0x90,0x90,0x00, + + 5, // 0x53 'S' + 0x00,0x60,0x90,0x80,0x60,0x10,0x90,0x90,0x60,0x00, + + 5, // 0x54 'T' + 0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00, + + 5, // 0x55 'U' + 0x00,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x56 'V' + 0x00,0x90,0x90,0x90,0x50,0x50,0x50,0x20,0x20,0x00, + + 5, // 0x57 'W' + 0x00,0x90,0x90,0x90,0x90,0x90,0xF0,0xF0,0x90,0x00, + + 5, // 0x58 'X' + 0x00,0x90,0x90,0x90,0x60,0x60,0x90,0x90,0x90,0x00, + + 5, // 0x59 'Y' + 0x00,0x88,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00, + + 5, // 0x5A 'Z' + 0x00,0xF0,0x10,0x20,0x20,0x40,0x40,0x80,0xF0,0x00, + + 5, // 0x5B '[' + 0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x60, + + 5, // 0x5C '\' + 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08, + + 5, // 0x5D ']' + 0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x60, + + 5, // 0x5E '^' + 0x00,0x20,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00, + + 5, // 0x60 '`' + 0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x61 'a' + 0x00,0x00,0x00,0x60,0x10,0x70,0x90,0x90,0x70,0x00, + + 5, // 0x62 'b' + 0x00,0x80,0x80,0xE0,0x90,0x90,0x90,0x90,0xE0,0x00, + + 5, // 0x63 'c' + 0x00,0x00,0x00,0x60,0x90,0x80,0x80,0x90,0x60,0x00, + + 5, // 0x64 'd' + 0x00,0x10,0x10,0x70,0x90,0x90,0x90,0x90,0x70,0x00, + + 5, // 0x65 'e' + 0x00,0x00,0x00,0x60,0x90,0x90,0xF0,0x80,0x70,0x00, + + 5, // 0x66 'f' + 0x00,0x30,0x40,0xE0,0x40,0x40,0x40,0x40,0x40,0x00, + + 5, // 0x67 'g' + 0x00,0x00,0x00,0x70,0x90,0x90,0x90,0x70,0x10,0xE0, + + 5, // 0x68 'h' + 0x00,0x80,0x80,0xE0,0x90,0x90,0x90,0x90,0x90,0x00, + + 5, // 0x69 'i' + 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x20,0x70,0x00, + + 5, // 0x6A 'j' + 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0xC0, + + 5, // 0x6B 'k' + 0x00,0x80,0x80,0x90,0xA0,0xC0,0xA0,0x90,0x90,0x00, + + 5, // 0x6C 'l' + 0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00, + + 5, // 0x6D 'm' + 0x00,0x00,0x00,0x90,0xF0,0x90,0x90,0x90,0x90,0x00, + + 5, // 0x6E 'n' + 0x00,0x00,0x00,0xE0,0x90,0x90,0x90,0x90,0x90,0x00, + + 5, // 0x6F 'o' + 0x00,0x00,0x00,0x60,0x90,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x70 'p' + 0x00,0x00,0x00,0xE0,0x90,0x90,0x90,0xE0,0x80,0x80, + + 5, // 0x71 'q' + 0x00,0x00,0x00,0x70,0x90,0x90,0x90,0x70,0x10,0x10, + + 5, // 0x72 'r' + 0x00,0x00,0x00,0xB0,0x50,0x40,0x40,0x40,0xE0,0x00, + + 5, // 0x73 's' + 0x00,0x00,0x00,0x60,0x90,0x40,0x20,0x90,0x60,0x00, + + 5, // 0x74 't' + 0x00,0x40,0x40,0xE0,0x40,0x40,0x40,0x50,0x20,0x00, + + 5, // 0x75 'u' + 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x90,0x70,0x00, + + 5, // 0x76 'v' + 0x00,0x00,0x00,0x90,0x90,0x50,0x50,0x20,0x20,0x00, + + 5, // 0x77 'w' + 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0xF0,0x90,0x00, + + 5, // 0x78 'x' + 0x00,0x00,0x00,0x90,0x90,0x60,0x60,0x90,0x90,0x00, + + 5, // 0x79 'y' + 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x70,0x10,0xE0, + + 5, // 0x7A 'z' + 0x00,0x00,0x00,0xF0,0x10,0x20,0x40,0x80,0xF0,0x00, + + 5, // 0x7B '{' + 0x30,0x40,0x40,0x40,0x80,0x40,0x40,0x40,0x40,0x30, + + 5, // 0x7C '|' + 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + + 5, // 0x7D '}' + 0xC0,0x20,0x20,0x20,0x10,0x20,0x20,0x20,0x20,0xC0, + + 5, // 0x7E '~' + 0x00,0x40,0xA8,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x7F '' + 0x00,0x20,0x70,0xD8,0x88,0x88,0xF8,0x00,0x00,0x00, + + 0 + }; + + const int8u mcs5x11_mono[] = + { + 11, 3, 32, 128-32, + 0x00,0x00,0x0C,0x00,0x18,0x00,0x24,0x00,0x30,0x00,0x3C,0x00,0x48,0x00,0x54,0x00,0x60,0x00, + 0x6C,0x00,0x78,0x00,0x84,0x00,0x90,0x00,0x9C,0x00,0xA8,0x00,0xB4,0x00,0xC0,0x00,0xCC,0x00, + 0xD8,0x00,0xE4,0x00,0xF0,0x00,0xFC,0x00,0x08,0x01,0x14,0x01,0x20,0x01,0x2C,0x01,0x38,0x01, + 0x44,0x01,0x50,0x01,0x5C,0x01,0x68,0x01,0x74,0x01,0x80,0x01,0x8C,0x01,0x98,0x01,0xA4,0x01, + 0xB0,0x01,0xBC,0x01,0xC8,0x01,0xD4,0x01,0xE0,0x01,0xEC,0x01,0xF8,0x01,0x04,0x02,0x10,0x02, + 0x1C,0x02,0x28,0x02,0x34,0x02,0x40,0x02,0x4C,0x02,0x58,0x02,0x64,0x02,0x70,0x02,0x7C,0x02, + 0x88,0x02,0x94,0x02,0xA0,0x02,0xAC,0x02,0xB8,0x02,0xC4,0x02,0xD0,0x02,0xDC,0x02,0xE8,0x02, + 0xF4,0x02,0x00,0x03,0x0C,0x03,0x18,0x03,0x24,0x03,0x30,0x03,0x3C,0x03,0x48,0x03,0x54,0x03, + 0x60,0x03,0x6C,0x03,0x78,0x03,0x84,0x03,0x90,0x03,0x9C,0x03,0xA8,0x03,0xB4,0x03,0xC0,0x03, + 0xCC,0x03,0xD8,0x03,0xE4,0x03,0xF0,0x03,0xFC,0x03,0x08,0x04,0x14,0x04,0x20,0x04,0x2C,0x04, + 0x38,0x04,0x44,0x04,0x50,0x04,0x5C,0x04,0x68,0x04,0x74,0x04, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x21 '!' + 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, + + 5, // 0x22 '"' + 0x00,0x50,0x50,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x23 '#' + 0x00,0x50,0x50,0xF8,0x50,0x50,0x50,0xF8,0x50,0x50,0x00, + + 5, // 0x24 '$' + 0x00,0x40,0x60,0x90,0x80,0x60,0x10,0x90,0x60,0x20,0x00, + + 5, // 0x25 '%' + 0x00,0x00,0x90,0x90,0x20,0x20,0x40,0x40,0x90,0x90,0x00, + + 5, // 0x26 '&' + 0x00,0x40,0xA0,0xA0,0x40,0xA8,0x90,0x90,0x68,0x00,0x00, + + 5, // 0x27 ''' + 0x00,0x20,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x28 '(' + 0x00,0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x20,0x20,0x10, + + 5, // 0x29 ')' + 0x00,0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x20,0x20,0x40, + + 5, // 0x2A '*' + 0x00,0x00,0x90,0x60,0xF0,0x60,0x90,0x00,0x00,0x00,0x00, + + 5, // 0x2B '+' + 0x00,0x00,0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00,0x00, + + 5, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x40,0x80, + + 5, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00, + + 5, // 0x2F '/' + 0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80,0x00, + + 5, // 0x30 '0' + 0x00,0x70,0x90,0x90,0x90,0x90,0x90,0x90,0xE0,0x00,0x00, + + 5, // 0x31 '1' + 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 5, // 0x32 '2' + 0x00,0x60,0x90,0x90,0x10,0x20,0x40,0x80,0xF0,0x00,0x00, + + 5, // 0x33 '3' + 0x00,0x60,0x90,0x10,0x60,0x10,0x10,0x90,0x60,0x00,0x00, + + 5, // 0x34 '4' + 0x00,0x10,0x30,0x50,0x50,0x90,0xF8,0x10,0x10,0x00,0x00, + + 5, // 0x35 '5' + 0x00,0xF0,0x80,0xE0,0x90,0x10,0x10,0x90,0x60,0x00,0x00, + + 5, // 0x36 '6' + 0x00,0x60,0x90,0x80,0xE0,0x90,0x90,0x90,0x60,0x00,0x00, + + 5, // 0x37 '7' + 0x00,0xF0,0x10,0x10,0x20,0x20,0x40,0x40,0x40,0x00,0x00, + + 5, // 0x38 '8' + 0x00,0x60,0x90,0x90,0x60,0x90,0x90,0x90,0x60,0x00,0x00, + + 5, // 0x39 '9' + 0x00,0x60,0x90,0x90,0x90,0x70,0x10,0x90,0x60,0x00,0x00, + + 5, // 0x3A ':' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00, + + 5, // 0x3B ';' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x40,0x80, + + 5, // 0x3C '<' + 0x00,0x08,0x10,0x20,0x40,0x80,0x40,0x20,0x10,0x08,0x00, + + 5, // 0x3D '=' + 0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0xF0,0x00,0x00,0x00, + + 5, // 0x3E '>' + 0x00,0x80,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x80,0x00, + + 5, // 0x3F '?' + 0x00,0x60,0x90,0x10,0x10,0x20,0x40,0x00,0x40,0x00,0x00, + + 5, // 0x40 '@' + 0x00,0x60,0x90,0x90,0xB0,0xB0,0x80,0x80,0x70,0x00,0x00, + + 5, // 0x41 'A' + 0x00,0x60,0x90,0x90,0x90,0xF0,0x90,0x90,0x90,0x00,0x00, + + 5, // 0x42 'B' + 0x00,0xE0,0x90,0x90,0xE0,0x90,0x90,0x90,0xE0,0x00,0x00, + + 5, // 0x43 'C' + 0x00,0x60,0x90,0x80,0x80,0x80,0x80,0x90,0x60,0x00,0x00, + + 5, // 0x44 'D' + 0x00,0xE0,0x90,0x90,0x90,0x90,0x90,0x90,0xE0,0x00,0x00, + + 5, // 0x45 'E' + 0x00,0xF0,0x80,0x80,0xE0,0x80,0x80,0x80,0xF0,0x00,0x00, + + 5, // 0x46 'F' + 0x00,0xF0,0x80,0x80,0xE0,0x80,0x80,0x80,0x80,0x00,0x00, + + 5, // 0x47 'G' + 0x00,0x60,0x90,0x80,0x80,0xB0,0x90,0x90,0x60,0x00,0x00, + + 5, // 0x48 'H' + 0x00,0x90,0x90,0x90,0xF0,0x90,0x90,0x90,0x90,0x00,0x00, + + 5, // 0x49 'I' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 5, // 0x4A 'J' + 0x00,0x70,0x20,0x20,0x20,0x20,0xA0,0xA0,0x40,0x00,0x00, + + 5, // 0x4B 'K' + 0x00,0x90,0xA0,0xA0,0xC0,0xA0,0xA0,0x90,0x90,0x00,0x00, + + 5, // 0x4C 'L' + 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xF0,0x00,0x00, + + 5, // 0x4D 'M' + 0x00,0x90,0xF0,0xF0,0x90,0x90,0x90,0x90,0x90,0x00,0x00, + + 5, // 0x4E 'N' + 0x00,0x90,0x90,0xD0,0xD0,0xB0,0xB0,0x90,0x90,0x00,0x00, + + 5, // 0x4F 'O' + 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00,0x00, + + 5, // 0x50 'P' + 0x00,0xE0,0x90,0x90,0x90,0xE0,0x80,0x80,0x80,0x00,0x00, + + 5, // 0x51 'Q' + 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x30,0x00, + + 5, // 0x52 'R' + 0x00,0xE0,0x90,0x90,0x90,0xE0,0xA0,0x90,0x90,0x00,0x00, + + 5, // 0x53 'S' + 0x00,0x60,0x90,0x80,0x60,0x10,0x90,0x90,0x60,0x00,0x00, + + 5, // 0x54 'T' + 0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00, + + 5, // 0x55 'U' + 0x00,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00,0x00, + + 5, // 0x56 'V' + 0x00,0x90,0x90,0x90,0x50,0x50,0x50,0x20,0x20,0x00,0x00, + + 5, // 0x57 'W' + 0x00,0x90,0x90,0x90,0x90,0x90,0xF0,0xF0,0x90,0x00,0x00, + + 5, // 0x58 'X' + 0x00,0x90,0x90,0x90,0x60,0x60,0x90,0x90,0x90,0x00,0x00, + + 5, // 0x59 'Y' + 0x00,0x88,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00,0x00, + + 5, // 0x5A 'Z' + 0x00,0xF0,0x10,0x20,0x20,0x40,0x40,0x80,0xF0,0x00,0x00, + + 5, // 0x5B '[' + 0x00,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x60, + + 5, // 0x5C '\' + 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00, + + 5, // 0x5D ']' + 0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x60, + + 5, // 0x5E '^' + 0x00,0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00, + + 5, // 0x60 '`' + 0x00,0x40,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x61 'a' + 0x00,0x00,0x00,0x60,0x10,0x70,0x90,0x90,0x70,0x00,0x00, + + 5, // 0x62 'b' + 0x00,0x80,0x80,0xE0,0x90,0x90,0x90,0x90,0xE0,0x00,0x00, + + 5, // 0x63 'c' + 0x00,0x00,0x00,0x60,0x90,0x80,0x80,0x90,0x60,0x00,0x00, + + 5, // 0x64 'd' + 0x00,0x10,0x10,0x70,0x90,0x90,0x90,0x90,0x70,0x00,0x00, + + 5, // 0x65 'e' + 0x00,0x00,0x00,0x60,0x90,0x90,0xF0,0x80,0x70,0x00,0x00, + + 5, // 0x66 'f' + 0x00,0x30,0x40,0xE0,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 5, // 0x67 'g' + 0x00,0x00,0x00,0x70,0x90,0x90,0x90,0x90,0x70,0x10,0xE0, + + 5, // 0x68 'h' + 0x00,0x80,0x80,0xE0,0x90,0x90,0x90,0x90,0x90,0x00,0x00, + + 5, // 0x69 'i' + 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 5, // 0x6A 'j' + 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0xA0,0x40, + + 5, // 0x6B 'k' + 0x00,0x80,0x80,0x90,0xA0,0xC0,0xA0,0x90,0x90,0x00,0x00, + + 5, // 0x6C 'l' + 0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 5, // 0x6D 'm' + 0x00,0x00,0x00,0x90,0xF0,0x90,0x90,0x90,0x90,0x00,0x00, + + 5, // 0x6E 'n' + 0x00,0x00,0x00,0xE0,0x90,0x90,0x90,0x90,0x90,0x00,0x00, + + 5, // 0x6F 'o' + 0x00,0x00,0x00,0x60,0x90,0x90,0x90,0x90,0x60,0x00,0x00, + + 5, // 0x70 'p' + 0x00,0x00,0x00,0xE0,0x90,0x90,0x90,0x90,0xE0,0x80,0x80, + + 5, // 0x71 'q' + 0x00,0x00,0x00,0x70,0x90,0x90,0x90,0x90,0x70,0x10,0x10, + + 5, // 0x72 'r' + 0x00,0x00,0x00,0xA0,0x50,0x40,0x40,0x40,0xE0,0x00,0x00, + + 5, // 0x73 's' + 0x00,0x00,0x00,0x60,0x90,0x40,0x20,0x90,0x60,0x00,0x00, + + 5, // 0x74 't' + 0x00,0x40,0x40,0xE0,0x40,0x40,0x40,0x40,0x30,0x00,0x00, + + 5, // 0x75 'u' + 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x90,0x70,0x00,0x00, + + 5, // 0x76 'v' + 0x00,0x00,0x00,0x90,0x90,0x50,0x50,0x20,0x20,0x00,0x00, + + 5, // 0x77 'w' + 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0xF0,0x90,0x00,0x00, + + 5, // 0x78 'x' + 0x00,0x00,0x00,0x90,0x90,0x60,0x60,0x90,0x90,0x00,0x00, + + 5, // 0x79 'y' + 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x90,0x70,0x10,0xE0, + + 5, // 0x7A 'z' + 0x00,0x00,0x00,0xF0,0x10,0x20,0x40,0x80,0xF0,0x00,0x00, + + 5, // 0x7B '{' + 0x30,0x40,0x40,0x40,0x40,0x80,0x40,0x40,0x40,0x40,0x30, + + 5, // 0x7C '|' + 0x00,0x20,0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x20,0x00, + + 5, // 0x7D '}' + 0xC0,0x20,0x20,0x20,0x20,0x10,0x20,0x20,0x20,0x20,0xC0, + + 5, // 0x7E '~' + 0x00,0x40,0xA8,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x7F '' + 0x00,0x20,0x70,0xD8,0x88,0x88,0xF8,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u mcs6x10_mono[] = + { + 10, 3, 32, 128-32, + 0x00,0x00,0x0B,0x00,0x16,0x00,0x21,0x00,0x2C,0x00,0x37,0x00,0x42,0x00,0x4D,0x00,0x58,0x00, + 0x63,0x00,0x6E,0x00,0x79,0x00,0x84,0x00,0x8F,0x00,0x9A,0x00,0xA5,0x00,0xB0,0x00,0xBB,0x00, + 0xC6,0x00,0xD1,0x00,0xDC,0x00,0xE7,0x00,0xF2,0x00,0xFD,0x00,0x08,0x01,0x13,0x01,0x1E,0x01, + 0x29,0x01,0x34,0x01,0x3F,0x01,0x4A,0x01,0x55,0x01,0x60,0x01,0x6B,0x01,0x76,0x01,0x81,0x01, + 0x8C,0x01,0x97,0x01,0xA2,0x01,0xAD,0x01,0xB8,0x01,0xC3,0x01,0xCE,0x01,0xD9,0x01,0xE4,0x01, + 0xEF,0x01,0xFA,0x01,0x05,0x02,0x10,0x02,0x1B,0x02,0x26,0x02,0x31,0x02,0x3C,0x02,0x47,0x02, + 0x52,0x02,0x5D,0x02,0x68,0x02,0x73,0x02,0x7E,0x02,0x89,0x02,0x94,0x02,0x9F,0x02,0xAA,0x02, + 0xB5,0x02,0xC0,0x02,0xCB,0x02,0xD6,0x02,0xE1,0x02,0xEC,0x02,0xF7,0x02,0x02,0x03,0x0D,0x03, + 0x18,0x03,0x23,0x03,0x2E,0x03,0x39,0x03,0x44,0x03,0x4F,0x03,0x5A,0x03,0x65,0x03,0x70,0x03, + 0x7B,0x03,0x86,0x03,0x91,0x03,0x9C,0x03,0xA7,0x03,0xB2,0x03,0xBD,0x03,0xC8,0x03,0xD3,0x03, + 0xDE,0x03,0xE9,0x03,0xF4,0x03,0xFF,0x03,0x0A,0x04,0x15,0x04, + + 6, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x21 '!' + 0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x00,0x00, + + 6, // 0x22 '"' + 0x00,0x28,0x28,0x50,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x23 '#' + 0x00,0x28,0x28,0x7C,0x28,0x28,0x7C,0x28,0x28,0x00, + + 6, // 0x24 '$' + 0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x00, + + 6, // 0x25 '%' + 0x00,0x08,0xC8,0xD0,0x10,0x20,0x2C,0x4C,0x40,0x00, + + 6, // 0x26 '&' + 0x00,0x20,0x50,0x50,0x24,0x54,0x48,0x34,0x00,0x00, + + 6, // 0x27 ''' + 0x00,0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x28 '(' + 0x08,0x10,0x10,0x20,0x20,0x20,0x10,0x10,0x08,0x00, + + 6, // 0x29 ')' + 0x20,0x10,0x10,0x08,0x08,0x08,0x10,0x10,0x20,0x00, + + 6, // 0x2A '*' + 0x00,0x00,0x28,0x7C,0x38,0x7C,0x28,0x00,0x00,0x00, + + 6, // 0x2B '+' + 0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, + + 6, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40, + + 6, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00, + + 6, // 0x2F '/' + 0x00,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00, + + 6, // 0x30 '0' + 0x00,0x38,0x44,0x4C,0x54,0x64,0x44,0x38,0x00,0x00, + + 6, // 0x31 '1' + 0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 6, // 0x32 '2' + 0x00,0x38,0x44,0x04,0x18,0x20,0x40,0x7C,0x00,0x00, + + 6, // 0x33 '3' + 0x00,0x38,0x44,0x04,0x38,0x04,0x44,0x38,0x00,0x00, + + 6, // 0x34 '4' + 0x00,0x08,0x18,0x28,0x48,0x7C,0x08,0x08,0x00,0x00, + + 6, // 0x35 '5' + 0x00,0x7C,0x40,0x40,0x78,0x04,0x44,0x38,0x00,0x00, + + 6, // 0x36 '6' + 0x00,0x38,0x40,0x40,0x78,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x37 '7' + 0x00,0x7C,0x04,0x08,0x10,0x20,0x20,0x20,0x00,0x00, + + 6, // 0x38 '8' + 0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x39 '9' + 0x00,0x38,0x44,0x44,0x3C,0x04,0x04,0x38,0x00,0x00, + + 6, // 0x3A ':' + 0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x00, + + 6, // 0x3B ';' + 0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x20,0x40, + + 6, // 0x3C '<' + 0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00, + + 6, // 0x3D '=' + 0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00, + + 6, // 0x3E '>' + 0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00, + + 6, // 0x3F '?' + 0x00,0x38,0x44,0x04,0x18,0x10,0x00,0x10,0x00,0x00, + + 6, // 0x40 '@' + 0x00,0x38,0x44,0x5C,0x54,0x5C,0x40,0x38,0x00,0x00, + + 6, // 0x41 'A' + 0x00,0x38,0x44,0x44,0x44,0x7C,0x44,0x44,0x00,0x00, + + 6, // 0x42 'B' + 0x00,0x78,0x44,0x44,0x78,0x44,0x44,0x78,0x00,0x00, + + 6, // 0x43 'C' + 0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00,0x00, + + 6, // 0x44 'D' + 0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00,0x00, + + 6, // 0x45 'E' + 0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x7C,0x00,0x00, + + 6, // 0x46 'F' + 0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x00,0x00, + + 6, // 0x47 'G' + 0x00,0x38,0x44,0x40,0x4C,0x44,0x44,0x3C,0x00,0x00, + + 6, // 0x48 'H' + 0x00,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x00,0x00, + + 6, // 0x49 'I' + 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 6, // 0x4A 'J' + 0x00,0x1C,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00, + + 6, // 0x4B 'K' + 0x00,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00, + + 6, // 0x4C 'L' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00, + + 6, // 0x4D 'M' + 0x00,0x44,0x6C,0x54,0x54,0x44,0x44,0x44,0x00,0x00, + + 6, // 0x4E 'N' + 0x00,0x44,0x44,0x64,0x54,0x4C,0x44,0x44,0x00,0x00, + + 6, // 0x4F 'O' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x50 'P' + 0x00,0x78,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00, + + 6, // 0x51 'Q' + 0x00,0x38,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00, + + 6, // 0x52 'R' + 0x00,0x78,0x44,0x44,0x78,0x48,0x44,0x44,0x00,0x00, + + 6, // 0x53 'S' + 0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00, + + 6, // 0x54 'T' + 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 6, // 0x55 'U' + 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x56 'V' + 0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x10,0x00,0x00, + + 6, // 0x57 'W' + 0x00,0x44,0x44,0x54,0x54,0x54,0x54,0x28,0x00,0x00, + + 6, // 0x58 'X' + 0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, + + 6, // 0x59 'Y' + 0x00,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x00,0x00, + + 6, // 0x5A 'Z' + 0x00,0x78,0x08,0x10,0x20,0x40,0x40,0x78,0x00,0x00, + + 6, // 0x5B '[' + 0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00, + + 6, // 0x5C '\' + 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00, + + 6, // 0x5D ']' + 0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x38,0x00, + + 6, // 0x5E '^' + 0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00, + + 6, // 0x60 '`' + 0x00,0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x61 'a' + 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x3C,0x00,0x00, + + 6, // 0x62 'b' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x78,0x00,0x00, + + 6, // 0x63 'c' + 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x3C,0x00,0x00, + + 6, // 0x64 'd' + 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x3C,0x00,0x00, + + 6, // 0x65 'e' + 0x00,0x00,0x00,0x38,0x44,0x78,0x40,0x3C,0x00,0x00, + + 6, // 0x66 'f' + 0x00,0x0C,0x10,0x10,0x38,0x10,0x10,0x10,0x00,0x00, + + 6, // 0x67 'g' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x3C,0x04,0x38, + + 6, // 0x68 'h' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x00,0x00, + + 6, // 0x69 'i' + 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x38,0x00,0x00, + + 6, // 0x6A 'j' + 0x00,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x48,0x30, + + 6, // 0x6B 'k' + 0x00,0x40,0x40,0x48,0x50,0x60,0x50,0x48,0x00,0x00, + + 6, // 0x6C 'l' + 0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 6, // 0x6D 'm' + 0x00,0x00,0x00,0x68,0x54,0x54,0x44,0x44,0x00,0x00, + + 6, // 0x6E 'n' + 0x00,0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x00,0x00, + + 6, // 0x6F 'o' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x70 'p' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40, + + 6, // 0x71 'q' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x3C,0x04,0x04, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x70,0x00,0x00, + + 6, // 0x73 's' + 0x00,0x00,0x00,0x38,0x40,0x38,0x04,0x78,0x00,0x00, + + 6, // 0x74 't' + 0x00,0x10,0x10,0x38,0x10,0x10,0x14,0x08,0x00,0x00, + + 6, // 0x75 'u' + 0x00,0x00,0x00,0x44,0x44,0x44,0x4C,0x34,0x00,0x00, + + 6, // 0x76 'v' + 0x00,0x00,0x00,0x44,0x44,0x44,0x28,0x10,0x00,0x00, + + 6, // 0x77 'w' + 0x00,0x00,0x00,0x44,0x44,0x54,0x7C,0x28,0x00,0x00, + + 6, // 0x78 'x' + 0x00,0x00,0x00,0x48,0x48,0x30,0x48,0x48,0x00,0x00, + + 6, // 0x79 'y' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x3C,0x04,0x38, + + 6, // 0x7A 'z' + 0x00,0x00,0x00,0x78,0x08,0x30,0x40,0x78,0x00,0x00, + + 6, // 0x7B '{' + 0x18,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x18,0x00, + + 6, // 0x7C '|' + 0x10,0x10,0x10,0x10,0x00,0x10,0x10,0x10,0x10,0x00, + + 6, // 0x7D '}' + 0x60,0x10,0x10,0x10,0x0C,0x10,0x10,0x10,0x60,0x00, + + 6, // 0x7E '~' + 0x00,0x48,0xA8,0x90,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x7F '' + 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00, + + 0 + }; + + const int8u mcs6x11_mono[] = + { + 11, 3, 32, 128-32, + 0x00,0x00,0x0C,0x00,0x18,0x00,0x24,0x00,0x30,0x00,0x3C,0x00,0x48,0x00,0x54,0x00,0x60,0x00, + 0x6C,0x00,0x78,0x00,0x84,0x00,0x90,0x00,0x9C,0x00,0xA8,0x00,0xB4,0x00,0xC0,0x00,0xCC,0x00, + 0xD8,0x00,0xE4,0x00,0xF0,0x00,0xFC,0x00,0x08,0x01,0x14,0x01,0x20,0x01,0x2C,0x01,0x38,0x01, + 0x44,0x01,0x50,0x01,0x5C,0x01,0x68,0x01,0x74,0x01,0x80,0x01,0x8C,0x01,0x98,0x01,0xA4,0x01, + 0xB0,0x01,0xBC,0x01,0xC8,0x01,0xD4,0x01,0xE0,0x01,0xEC,0x01,0xF8,0x01,0x04,0x02,0x10,0x02, + 0x1C,0x02,0x28,0x02,0x34,0x02,0x40,0x02,0x4C,0x02,0x58,0x02,0x64,0x02,0x70,0x02,0x7C,0x02, + 0x88,0x02,0x94,0x02,0xA0,0x02,0xAC,0x02,0xB8,0x02,0xC4,0x02,0xD0,0x02,0xDC,0x02,0xE8,0x02, + 0xF4,0x02,0x00,0x03,0x0C,0x03,0x18,0x03,0x24,0x03,0x30,0x03,0x3C,0x03,0x48,0x03,0x54,0x03, + 0x60,0x03,0x6C,0x03,0x78,0x03,0x84,0x03,0x90,0x03,0x9C,0x03,0xA8,0x03,0xB4,0x03,0xC0,0x03, + 0xCC,0x03,0xD8,0x03,0xE4,0x03,0xF0,0x03,0xFC,0x03,0x08,0x04,0x14,0x04,0x20,0x04,0x2C,0x04, + 0x38,0x04,0x44,0x04,0x50,0x04,0x5C,0x04,0x68,0x04,0x74,0x04, + + 6, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x21 '!' + 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, + + 6, // 0x22 '"' + 0x00,0x28,0x28,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x23 '#' + 0x00,0x28,0x28,0x7C,0x28,0x28,0x7C,0x28,0x28,0x00,0x00, + + 6, // 0x24 '$' + 0x00,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x00, + + 6, // 0x25 '%' + 0x00,0x68,0xA8,0xD0,0x10,0x20,0x2C,0x54,0x58,0x00,0x00, + + 6, // 0x26 '&' + 0x00,0x20,0x50,0x50,0x20,0x54,0x54,0x48,0x34,0x00,0x00, + + 6, // 0x27 ''' + 0x00,0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x28 '(' + 0x08,0x10,0x10,0x20,0x20,0x20,0x20,0x10,0x10,0x08,0x00, + + 6, // 0x29 ')' + 0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x00, + + 6, // 0x2A '*' + 0x00,0x00,0x28,0x7C,0x38,0x7C,0x28,0x00,0x00,0x00,0x00, + + 6, // 0x2B '+' + 0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, + + 6, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40, + + 6, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00, + + 6, // 0x2F '/' + 0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00, + + 6, // 0x30 '0' + 0x00,0x38,0x44,0x44,0x54,0x54,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x31 '1' + 0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 6, // 0x32 '2' + 0x00,0x38,0x44,0x44,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, + + 6, // 0x33 '3' + 0x00,0x38,0x44,0x04,0x38,0x04,0x04,0x44,0x38,0x00,0x00, + + 6, // 0x34 '4' + 0x00,0x08,0x18,0x28,0x28,0x48,0x7C,0x08,0x08,0x00,0x00, + + 6, // 0x35 '5' + 0x00,0x7C,0x40,0x78,0x44,0x04,0x04,0x44,0x38,0x00,0x00, + + 6, // 0x36 '6' + 0x00,0x38,0x44,0x40,0x78,0x44,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x37 '7' + 0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x00,0x00, + + 6, // 0x38 '8' + 0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x39 '9' + 0x00,0x38,0x44,0x44,0x3C,0x04,0x04,0x44,0x38,0x00,0x00, + + 6, // 0x3A ':' + 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x00, + + 6, // 0x3B ';' + 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x20,0x40, + + 6, // 0x3C '<' + 0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00, + + 6, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00, + + 6, // 0x3E '>' + 0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00, + + 6, // 0x3F '?' + 0x00,0x38,0x44,0x04,0x08,0x10,0x10,0x00,0x10,0x00,0x00, + + 6, // 0x40 '@' + 0x00,0x38,0x44,0x5C,0x54,0x54,0x4C,0x40,0x38,0x00,0x00, + + 6, // 0x41 'A' + 0x00,0x38,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x00,0x00, + + 6, // 0x42 'B' + 0x00,0x78,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00,0x00, + + 6, // 0x43 'C' + 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00, + + 6, // 0x44 'D' + 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00, + + 6, // 0x45 'E' + 0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x7C,0x00,0x00, + + 6, // 0x46 'F' + 0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00,0x00, + + 6, // 0x47 'G' + 0x00,0x38,0x44,0x40,0x40,0x5C,0x44,0x4C,0x34,0x00,0x00, + + 6, // 0x48 'H' + 0x00,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00, + + 6, // 0x49 'I' + 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 6, // 0x4A 'J' + 0x00,0x1C,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00, + + 6, // 0x4B 'K' + 0x00,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x44,0x00,0x00, + + 6, // 0x4C 'L' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00, + + 6, // 0x4D 'M' + 0x00,0x44,0x6C,0x54,0x54,0x54,0x44,0x44,0x44,0x00,0x00, + + 6, // 0x4E 'N' + 0x00,0x44,0x64,0x64,0x54,0x54,0x4C,0x4C,0x44,0x00,0x00, + + 6, // 0x4F 'O' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x50 'P' + 0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00, + + 6, // 0x51 'Q' + 0x00,0x38,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00, + + 6, // 0x52 'R' + 0x00,0x78,0x44,0x44,0x44,0x78,0x48,0x44,0x44,0x00,0x00, + + 6, // 0x53 'S' + 0x00,0x38,0x44,0x40,0x38,0x04,0x04,0x44,0x38,0x00,0x00, + + 6, // 0x54 'T' + 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 6, // 0x55 'U' + 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x56 'V' + 0x00,0x44,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00,0x00, + + 6, // 0x57 'W' + 0x00,0x44,0x44,0x54,0x54,0x54,0x54,0x54,0x28,0x00,0x00, + + 6, // 0x58 'X' + 0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00, + + 6, // 0x59 'Y' + 0x00,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00,0x00, + + 6, // 0x5A 'Z' + 0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x40,0x7C,0x00,0x00, + + 6, // 0x5B '[' + 0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00, + + 6, // 0x5C '\' + 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00, + + 6, // 0x5D ']' + 0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x38,0x00, + + 6, // 0x5E '^' + 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00, + + 6, // 0x60 '`' + 0x00,0x20,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x61 'a' + 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x3C,0x00,0x00, + + 6, // 0x62 'b' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x78,0x00,0x00, + + 6, // 0x63 'c' + 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x44,0x38,0x00,0x00, + + 6, // 0x64 'd' + 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x3C,0x00,0x00, + + 6, // 0x65 'e' + 0x00,0x00,0x00,0x38,0x44,0x7C,0x40,0x44,0x38,0x00,0x00, + + 6, // 0x66 'f' + 0x00,0x0C,0x10,0x38,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 6, // 0x67 'g' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x78, + + 6, // 0x68 'h' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x00,0x00, + + 6, // 0x69 'i' + 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 6, // 0x6A 'j' + 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x50,0x20, + + 6, // 0x6B 'k' + 0x00,0x40,0x40,0x4C,0x50,0x60,0x50,0x48,0x44,0x00,0x00, + + 6, // 0x6C 'l' + 0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 6, // 0x6D 'm' + 0x00,0x00,0x00,0x68,0x54,0x54,0x54,0x44,0x44,0x00,0x00, + + 6, // 0x6E 'n' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x00,0x00, + + 6, // 0x6F 'o' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x70 'p' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40, + + 6, // 0x71 'q' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x04, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x20,0x70,0x00,0x00, + + 6, // 0x73 's' + 0x00,0x00,0x00,0x38,0x44,0x30,0x08,0x44,0x38,0x00,0x00, + + 6, // 0x74 't' + 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x20,0x18,0x00,0x00, + + 6, // 0x75 'u' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x4C,0x34,0x00,0x00, + + 6, // 0x76 'v' + 0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00, + + 6, // 0x77 'w' + 0x00,0x00,0x00,0x44,0x44,0x44,0x54,0x7C,0x28,0x00,0x00, + + 6, // 0x78 'x' + 0x00,0x00,0x00,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, + + 6, // 0x79 'y' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x3C,0x08,0x70, + + 6, // 0x7A 'z' + 0x00,0x00,0x00,0x7C,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, + + 6, // 0x7B '{' + 0x18,0x20,0x20,0x20,0xC0,0xC0,0x20,0x20,0x20,0x18,0x00, + + 6, // 0x7C '|' + 0x00,0x10,0x10,0x10,0x10,0x00,0x10,0x10,0x10,0x10,0x00, + + 6, // 0x7D '}' + 0x60,0x10,0x10,0x10,0x0C,0x0C,0x10,0x10,0x10,0x60,0x00, + + 6, // 0x7E '~' + 0x00,0x24,0x54,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x7F '' + 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u mcs7x12_mono_high[] = + { + 12, 3, 32, 128-32, + 0x00,0x00,0x0D,0x00,0x1A,0x00,0x27,0x00,0x34,0x00,0x41,0x00,0x4E,0x00,0x5B,0x00,0x68,0x00, + 0x75,0x00,0x82,0x00,0x8F,0x00,0x9C,0x00,0xA9,0x00,0xB6,0x00,0xC3,0x00,0xD0,0x00,0xDD,0x00, + 0xEA,0x00,0xF7,0x00,0x04,0x01,0x11,0x01,0x1E,0x01,0x2B,0x01,0x38,0x01,0x45,0x01,0x52,0x01, + 0x5F,0x01,0x6C,0x01,0x79,0x01,0x86,0x01,0x93,0x01,0xA0,0x01,0xAD,0x01,0xBA,0x01,0xC7,0x01, + 0xD4,0x01,0xE1,0x01,0xEE,0x01,0xFB,0x01,0x08,0x02,0x15,0x02,0x22,0x02,0x2F,0x02,0x3C,0x02, + 0x49,0x02,0x56,0x02,0x63,0x02,0x70,0x02,0x7D,0x02,0x8A,0x02,0x97,0x02,0xA4,0x02,0xB1,0x02, + 0xBE,0x02,0xCB,0x02,0xD8,0x02,0xE5,0x02,0xF2,0x02,0xFF,0x02,0x0C,0x03,0x19,0x03,0x26,0x03, + 0x33,0x03,0x40,0x03,0x4D,0x03,0x5A,0x03,0x67,0x03,0x74,0x03,0x81,0x03,0x8E,0x03,0x9B,0x03, + 0xA8,0x03,0xB5,0x03,0xC2,0x03,0xCF,0x03,0xDC,0x03,0xE9,0x03,0xF6,0x03,0x03,0x04,0x10,0x04, + 0x1D,0x04,0x2A,0x04,0x37,0x04,0x44,0x04,0x51,0x04,0x5E,0x04,0x6B,0x04,0x78,0x04,0x85,0x04, + 0x92,0x04,0x9F,0x04,0xAC,0x04,0xB9,0x04,0xC6,0x04,0xD3,0x04, + + 7, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x21 '!' + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x00,0x00, + + 7, // 0x22 '"' + 0x28,0x28,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x23 '#' + 0x24,0x24,0x24,0x7E,0x24,0x24,0x24,0x7E,0x24,0x24,0x24,0x00, + + 7, // 0x24 '$' + 0x10,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x10,0x00, + + 7, // 0x25 '%' + 0x32,0x54,0x64,0x08,0x08,0x10,0x10,0x26,0x2A,0x4C,0x00,0x00, + + 7, // 0x26 '&' + 0x00,0x20,0x50,0x50,0x50,0x20,0x54,0x54,0x48,0x34,0x00,0x00, + + 7, // 0x27 ''' + 0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x28 '(' + 0x08,0x10,0x10,0x20,0x20,0x20,0x20,0x20,0x10,0x10,0x08,0x00, + + 7, // 0x29 ')' + 0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x00, + + 7, // 0x2A '*' + 0x00,0x00,0x10,0x54,0x38,0x7C,0x38,0x54,0x10,0x00,0x00,0x00, + + 7, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40, + + 7, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00, + + 7, // 0x2F '/' + 0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00,0x00, + + 7, // 0x30 '0' + 0x00,0x38,0x44,0x44,0x54,0x54,0x54,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x31 '1' + 0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 7, // 0x32 '2' + 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, + + 7, // 0x33 '3' + 0x00,0x38,0x44,0x04,0x04,0x38,0x04,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x34 '4' + 0x00,0x08,0x18,0x28,0x28,0x48,0x48,0x7C,0x08,0x08,0x00,0x00, + + 7, // 0x35 '5' + 0x00,0x7C,0x40,0x40,0x78,0x44,0x04,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x36 '6' + 0x00,0x38,0x44,0x40,0x78,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x37 '7' + 0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x20,0x00,0x00, + + 7, // 0x38 '8' + 0x00,0x38,0x44,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x39 '9' + 0x00,0x38,0x44,0x44,0x44,0x3C,0x04,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x3A ':' + 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x30,0x30,0x00,0x00, + + 7, // 0x3B ';' + 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x30,0x30,0x20,0x40, + + 7, // 0x3C '<' + 0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00,0x00, + + 7, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00,0x00, + + 7, // 0x3E '>' + 0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00,0x00, + + 7, // 0x3F '?' + 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x10,0x00,0x10,0x00,0x00, + + 7, // 0x40 '@' + 0x00,0x38,0x44,0x44,0x5C,0x54,0x54,0x4C,0x40,0x38,0x00,0x00, + + 7, // 0x41 'A' + 0x00,0x38,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x42 'B' + 0x00,0x78,0x44,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00,0x00, + + 7, // 0x43 'C' + 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00, + + 7, // 0x44 'D' + 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00, + + 7, // 0x45 'E' + 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x7C,0x00,0x00, + + 7, // 0x46 'F' + 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00,0x00, + + 7, // 0x47 'G' + 0x00,0x38,0x44,0x40,0x40,0x5C,0x44,0x44,0x4C,0x34,0x00,0x00, + + 7, // 0x48 'H' + 0x00,0x44,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x49 'I' + 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 7, // 0x4A 'J' + 0x00,0x1C,0x08,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00, + + 7, // 0x4B 'K' + 0x00,0x44,0x48,0x50,0x60,0x60,0x50,0x48,0x44,0x44,0x00,0x00, + + 7, // 0x4C 'L' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00, + + 7, // 0x4D 'M' + 0x00,0x44,0x6C,0x6C,0x54,0x54,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x4E 'N' + 0x00,0x44,0x64,0x64,0x54,0x54,0x4C,0x4C,0x44,0x44,0x00,0x00, + + 7, // 0x4F 'O' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00, + + 7, // 0x51 'Q' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00, + + 7, // 0x52 'R' + 0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x48,0x44,0x44,0x00,0x00, + + 7, // 0x53 'S' + 0x00,0x38,0x44,0x40,0x40,0x38,0x04,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x54 'T' + 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 7, // 0x55 'U' + 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x56 'V' + 0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00,0x00, + + 7, // 0x57 'W' + 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x54,0x54,0x28,0x00,0x00, + + 7, // 0x58 'X' + 0x00,0x44,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x44,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00,0x00, + + 7, // 0x5A 'Z' + 0x00,0x7C,0x04,0x04,0x08,0x10,0x20,0x40,0x40,0x7C,0x00,0x00, + + 7, // 0x5B '[' + 0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00, + + 7, // 0x5C '\' + 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00, + + 7, // 0x5D ']' + 0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x38,0x00, + + 7, // 0x5E '^' + 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00, + + 7, // 0x60 '`' + 0x00,0x20,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x61 'a' + 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x44,0x3C,0x00,0x00, + + 7, // 0x62 'b' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00,0x00, + + 7, // 0x63 'c' + 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00,0x00, + + 7, // 0x64 'd' + 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x00,0x00, + + 7, // 0x65 'e' + 0x00,0x00,0x00,0x38,0x44,0x44,0x7C,0x40,0x44,0x38,0x00,0x00, + + 7, // 0x66 'f' + 0x00,0x0C,0x10,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 7, // 0x67 'g' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x78, + + 7, // 0x68 'h' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x69 'i' + 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 7, // 0x6A 'j' + 0x00,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x08,0x48,0x30, + + 7, // 0x6B 'k' + 0x00,0x40,0x40,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00, + + 7, // 0x6C 'l' + 0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 7, // 0x6D 'm' + 0x00,0x00,0x00,0x68,0x54,0x54,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x6E 'n' + 0x00,0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x6F 'o' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x70 'p' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x40,0x40, + + 7, // 0x71 'q' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x04, + + 7, // 0x72 'r' + 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x74 't' + 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x20,0x24,0x18,0x00,0x00, + + 7, // 0x75 'u' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x4C,0x34,0x00,0x00, + + 7, // 0x76 'v' + 0x00,0x00,0x00,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00, + + 7, // 0x77 'w' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x54,0x54,0x28,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, + + 7, // 0x79 'y' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x3C,0x08,0x70, + + 7, // 0x7A 'z' + 0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, + + 7, // 0x7B '{' + 0x18,0x20,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x20,0x18,0x00, + + 7, // 0x7C '|' + 0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00, + + 7, // 0x7D '}' + 0x60,0x10,0x10,0x10,0x10,0x0C,0x10,0x10,0x10,0x10,0x60,0x00, + + 7, // 0x7E '~' + 0x00,0x60,0x92,0x92,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x7F '' + 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u mcs7x12_mono_low[] = + { + 12, 4, 32, 128-32, + 0x00,0x00,0x0D,0x00,0x1A,0x00,0x27,0x00,0x34,0x00,0x41,0x00,0x4E,0x00,0x5B,0x00,0x68,0x00, + 0x75,0x00,0x82,0x00,0x8F,0x00,0x9C,0x00,0xA9,0x00,0xB6,0x00,0xC3,0x00,0xD0,0x00,0xDD,0x00, + 0xEA,0x00,0xF7,0x00,0x04,0x01,0x11,0x01,0x1E,0x01,0x2B,0x01,0x38,0x01,0x45,0x01,0x52,0x01, + 0x5F,0x01,0x6C,0x01,0x79,0x01,0x86,0x01,0x93,0x01,0xA0,0x01,0xAD,0x01,0xBA,0x01,0xC7,0x01, + 0xD4,0x01,0xE1,0x01,0xEE,0x01,0xFB,0x01,0x08,0x02,0x15,0x02,0x22,0x02,0x2F,0x02,0x3C,0x02, + 0x49,0x02,0x56,0x02,0x63,0x02,0x70,0x02,0x7D,0x02,0x8A,0x02,0x97,0x02,0xA4,0x02,0xB1,0x02, + 0xBE,0x02,0xCB,0x02,0xD8,0x02,0xE5,0x02,0xF2,0x02,0xFF,0x02,0x0C,0x03,0x19,0x03,0x26,0x03, + 0x33,0x03,0x40,0x03,0x4D,0x03,0x5A,0x03,0x67,0x03,0x74,0x03,0x81,0x03,0x8E,0x03,0x9B,0x03, + 0xA8,0x03,0xB5,0x03,0xC2,0x03,0xCF,0x03,0xDC,0x03,0xE9,0x03,0xF6,0x03,0x03,0x04,0x10,0x04, + 0x1D,0x04,0x2A,0x04,0x37,0x04,0x44,0x04,0x51,0x04,0x5E,0x04,0x6B,0x04,0x78,0x04,0x85,0x04, + 0x92,0x04,0x9F,0x04,0xAC,0x04,0xB9,0x04,0xC6,0x04,0xD3,0x04, + + 7, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x21 '!' + 0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x00,0x00, + + 7, // 0x22 '"' + 0x28,0x28,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x23 '#' + 0x00,0x28,0x28,0x7C,0x28,0x28,0x28,0x7C,0x28,0x28,0x00,0x00, + + 7, // 0x24 '$' + 0x00,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x00,0x00, + + 7, // 0x25 '%' + 0x34,0x54,0x68,0x08,0x10,0x10,0x20,0x2C,0x54,0x58,0x00,0x00, + + 7, // 0x26 '&' + 0x00,0x20,0x50,0x50,0x20,0x54,0x54,0x48,0x34,0x00,0x00,0x00, + + 7, // 0x27 ''' + 0x00,0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x28 '(' + 0x08,0x10,0x10,0x20,0x20,0x20,0x20,0x20,0x10,0x10,0x08,0x00, + + 7, // 0x29 ')' + 0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x00, + + 7, // 0x2A '*' + 0x00,0x00,0x10,0x54,0x38,0x7C,0x38,0x54,0x10,0x00,0x00,0x00, + + 7, // 0x2B '+' + 0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00,0x00, + + 7, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40,0x00, + + 7, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x2F '/' + 0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00,0x00, + + 7, // 0x30 '0' + 0x00,0x38,0x44,0x44,0x54,0x54,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x31 '1' + 0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, + + 7, // 0x32 '2' + 0x00,0x38,0x44,0x44,0x08,0x10,0x20,0x40,0x7C,0x00,0x00,0x00, + + 7, // 0x33 '3' + 0x00,0x38,0x44,0x04,0x38,0x04,0x04,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x34 '4' + 0x00,0x08,0x18,0x28,0x28,0x48,0x7C,0x08,0x08,0x00,0x00,0x00, + + 7, // 0x35 '5' + 0x00,0x7C,0x40,0x78,0x44,0x04,0x04,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x36 '6' + 0x00,0x38,0x44,0x40,0x78,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x37 '7' + 0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x00,0x00,0x00, + + 7, // 0x38 '8' + 0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x39 '9' + 0x00,0x38,0x44,0x44,0x44,0x3C,0x04,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x3A ':' + 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x3B ';' + 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x20,0x40,0x00, + + 7, // 0x3C '<' + 0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00,0x00, + + 7, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00,0x00, + + 7, // 0x3E '>' + 0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00,0x00, + + 7, // 0x3F '?' + 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x10,0x00,0x10,0x00,0x00, + + 7, // 0x40 '@' + 0x00,0x38,0x44,0x44,0x5C,0x54,0x4C,0x40,0x38,0x00,0x00,0x00, + + 7, // 0x41 'A' + 0x00,0x38,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x42 'B' + 0x00,0x78,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00,0x00,0x00, + + 7, // 0x43 'C' + 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x44 'D' + 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00,0x00, + + 7, // 0x45 'E' + 0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x7C,0x00,0x00,0x00, + + 7, // 0x46 'F' + 0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 7, // 0x47 'G' + 0x00,0x38,0x44,0x40,0x40,0x4C,0x44,0x4C,0x34,0x00,0x00,0x00, + + 7, // 0x48 'H' + 0x00,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x49 'I' + 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, + + 7, // 0x4A 'J' + 0x00,0x1C,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00,0x00, + + 7, // 0x4B 'K' + 0x00,0x44,0x48,0x50,0x60,0x60,0x50,0x48,0x44,0x00,0x00,0x00, + + 7, // 0x4C 'L' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00,0x00, + + 7, // 0x4D 'M' + 0x00,0x44,0x6C,0x54,0x54,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x4E 'N' + 0x00,0x44,0x64,0x64,0x54,0x54,0x4C,0x4C,0x44,0x00,0x00,0x00, + + 7, // 0x4F 'O' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00,0x00, + + 7, // 0x51 'Q' + 0x00,0x38,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00,0x00, + + 7, // 0x52 'R' + 0x00,0x78,0x44,0x44,0x44,0x78,0x48,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x53 'S' + 0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x54 'T' + 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x55 'U' + 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x56 'V' + 0x00,0x44,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x57 'W' + 0x00,0x44,0x44,0x44,0x44,0x44,0x54,0x54,0x28,0x00,0x00,0x00, + + 7, // 0x58 'X' + 0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x5A 'Z' + 0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x40,0x7C,0x00,0x00,0x00, + + 7, // 0x5B '[' + 0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00, + + 7, // 0x5C '\' + 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00, + + 7, // 0x5D ']' + 0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x38,0x00, + + 7, // 0x5E '^' + 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00, + + 7, // 0x60 '`' + 0x00,0x20,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x61 'a' + 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x3C,0x00,0x00,0x00, + + 7, // 0x62 'b' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x78,0x00,0x00,0x00, + + 7, // 0x63 'c' + 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x64 'd' + 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x3C,0x00,0x00,0x00, + + 7, // 0x65 'e' + 0x00,0x00,0x00,0x38,0x44,0x7C,0x40,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x66 'f' + 0x00,0x0C,0x10,0x38,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x67 'g' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x44,0x38, + + 7, // 0x68 'h' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x69 'i' + 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, + + 7, // 0x6A 'j' + 0x00,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x48,0x48,0x30, + + 7, // 0x6B 'k' + 0x00,0x40,0x40,0x4C,0x50,0x60,0x50,0x48,0x44,0x00,0x00,0x00, + + 7, // 0x6C 'l' + 0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, + + 7, // 0x6D 'm' + 0x00,0x00,0x00,0x68,0x54,0x54,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x6E 'n' + 0x00,0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x6F 'o' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x70 'p' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40, + + 7, // 0x71 'q' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x04,0x04, + + 7, // 0x72 'r' + 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x20,0x70,0x00,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x38,0x44,0x30,0x08,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x74 't' + 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x24,0x18,0x00,0x00,0x00, + + 7, // 0x75 'u' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x4C,0x34,0x00,0x00,0x00, + + 7, // 0x76 'v' + 0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x77 'w' + 0x00,0x00,0x00,0x44,0x44,0x44,0x54,0x54,0x28,0x00,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x79 'y' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x08,0x70, + + 7, // 0x7A 'z' + 0x00,0x00,0x00,0x7C,0x08,0x10,0x20,0x40,0x7C,0x00,0x00,0x00, + + 7, // 0x7B '{' + 0x18,0x20,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x20,0x18,0x00, + + 7, // 0x7C '|' + 0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00, + + 7, // 0x7D '}' + 0x60,0x10,0x10,0x10,0x10,0x0C,0x10,0x10,0x10,0x10,0x60,0x00, + + 7, // 0x7E '~' + 0x00,0x24,0x54,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x7F '' + 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana12[] = + { + 12, 3, 32, 128-32, + 0x00,0x00,0x0D,0x00,0x1A,0x00,0x27,0x00,0x34,0x00,0x41,0x00,0x5A,0x00,0x67,0x00,0x74,0x00, + 0x81,0x00,0x8E,0x00,0x9B,0x00,0xA8,0x00,0xB5,0x00,0xC2,0x00,0xCF,0x00,0xDC,0x00,0xE9,0x00, + 0xF6,0x00,0x03,0x01,0x10,0x01,0x1D,0x01,0x2A,0x01,0x37,0x01,0x44,0x01,0x51,0x01,0x5E,0x01, + 0x6B,0x01,0x78,0x01,0x85,0x01,0x92,0x01,0x9F,0x01,0xAC,0x01,0xC5,0x01,0xD2,0x01,0xDF,0x01, + 0xEC,0x01,0xF9,0x01,0x06,0x02,0x13,0x02,0x20,0x02,0x2D,0x02,0x3A,0x02,0x47,0x02,0x54,0x02, + 0x61,0x02,0x7A,0x02,0x87,0x02,0xA0,0x02,0xAD,0x02,0xC6,0x02,0xD3,0x02,0xE0,0x02,0xED,0x02, + 0xFA,0x02,0x07,0x03,0x20,0x03,0x2D,0x03,0x3A,0x03,0x47,0x03,0x54,0x03,0x61,0x03,0x6E,0x03, + 0x7B,0x03,0x88,0x03,0x95,0x03,0xA2,0x03,0xAF,0x03,0xBC,0x03,0xC9,0x03,0xD6,0x03,0xE3,0x03, + 0xF0,0x03,0xFD,0x03,0x0A,0x04,0x17,0x04,0x24,0x04,0x31,0x04,0x4A,0x04,0x57,0x04,0x64,0x04, + 0x71,0x04,0x7E,0x04,0x8B,0x04,0x98,0x04,0xA5,0x04,0xB2,0x04,0xBF,0x04,0xCC,0x04,0xD9,0x04, + 0xE6,0x04,0xF3,0x04,0x00,0x05,0x0D,0x05,0x1A,0x05,0x27,0x05, + + 3, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x21 '!' + 0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, + + 5, // 0x22 '"' + 0x00,0x00,0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x28,0x7C,0x28,0x7C,0x28,0x00,0x00,0x00, + + 7, // 0x24 '$' + 0x00,0x00,0x10,0x10,0x3C,0x50,0x30,0x18,0x14,0x78,0x10,0x10, + + 11, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x00,0x4A,0x00,0x4A,0x00,0x35,0x80,0x0A,0x40,0x0A,0x40,0x11,0x80,0x00,0x00,0x00,0x00, + + 7, // 0x26 '&' + 0x00,0x00,0x00,0x30,0x48,0x48,0x32,0x4A,0x44,0x3A,0x00,0x00, + + 3, // 0x27 ''' + 0x00,0x00,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x28 '(' + 0x00,0x00,0x10,0x20,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x10, + + 4, // 0x29 ')' + 0x00,0x00,0x80,0x40,0x20,0x20,0x20,0x20,0x20,0x20,0x40,0x80, + + 7, // 0x2A '*' + 0x00,0x10,0x54,0x38,0x54,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, + + 3, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x80,0x00, + + 5, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00, + + 3, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x00,0x00, + + 4, // 0x2F '/' + 0x00,0x00,0x10,0x10,0x20,0x20,0x40,0x40,0x40,0x80,0x80,0x00, + + 7, // 0x30 '0' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x31 '1' + 0x00,0x00,0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 7, // 0x32 '2' + 0x00,0x00,0x00,0x38,0x44,0x04,0x08,0x10,0x20,0x7C,0x00,0x00, + + 7, // 0x33 '3' + 0x00,0x00,0x00,0x38,0x44,0x04,0x18,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x34 '4' + 0x00,0x00,0x00,0x08,0x18,0x28,0x48,0x7C,0x08,0x08,0x00,0x00, + + 7, // 0x35 '5' + 0x00,0x00,0x00,0x7C,0x40,0x78,0x04,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x36 '6' + 0x00,0x00,0x00,0x18,0x20,0x40,0x78,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x37 '7' + 0x00,0x00,0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x10,0x00,0x00, + + 7, // 0x38 '8' + 0x00,0x00,0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x39 '9' + 0x00,0x00,0x00,0x38,0x44,0x44,0x3C,0x04,0x08,0x30,0x00,0x00, + + 4, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x00, + + 4, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x00,0x40,0x40,0x80,0x00, + + 7, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x04,0x18,0x60,0x18,0x04,0x00,0x00,0x00, + + 7, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x7C,0x00,0x00,0x00,0x00, + + 7, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x40,0x30,0x0C,0x30,0x40,0x00,0x00,0x00, + + 6, // 0x3F '?' + 0x00,0x00,0x00,0x70,0x08,0x08,0x10,0x20,0x00,0x20,0x00,0x00, + + 10, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x20,0x80,0x4E,0x80,0x52,0x80,0x52,0x80,0x4D,0x00,0x20,0x00,0x1F,0x00,0x00,0x00, + + 8, // 0x41 'A' + 0x00,0x00,0x00,0x18,0x18,0x24,0x24,0x7E,0x42,0x42,0x00,0x00, + + 7, // 0x42 'B' + 0x00,0x00,0x00,0x70,0x48,0x48,0x78,0x44,0x44,0x78,0x00,0x00, + + 8, // 0x43 'C' + 0x00,0x00,0x00,0x1C,0x22,0x40,0x40,0x40,0x22,0x1C,0x00,0x00, + + 8, // 0x44 'D' + 0x00,0x00,0x00,0x78,0x44,0x42,0x42,0x42,0x44,0x78,0x00,0x00, + + 7, // 0x45 'E' + 0x00,0x00,0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x7C,0x00,0x00, + + 6, // 0x46 'F' + 0x00,0x00,0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x00,0x00, + + 8, // 0x47 'G' + 0x00,0x00,0x00,0x1C,0x22,0x40,0x4E,0x42,0x22,0x1C,0x00,0x00, + + 8, // 0x48 'H' + 0x00,0x00,0x00,0x42,0x42,0x42,0x7E,0x42,0x42,0x42,0x00,0x00, + + 5, // 0x49 'I' + 0x00,0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 5, // 0x4A 'J' + 0x00,0x00,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0xE0,0x00,0x00, + + 7, // 0x4B 'K' + 0x00,0x00,0x00,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00, + + 6, // 0x4C 'L' + 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00, + + 9, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x55,0x00,0x55,0x00,0x49,0x00,0x49,0x00,0x41,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x4E 'N' + 0x00,0x00,0x00,0x42,0x62,0x52,0x4A,0x46,0x42,0x42,0x00,0x00, + + 9, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,0x00,0x00, + + 9, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x04,0x00,0x03,0x00, + + 7, // 0x52 'R' + 0x00,0x00,0x00,0x78,0x44,0x44,0x78,0x50,0x48,0x44,0x00,0x00, + + 7, // 0x53 'S' + 0x00,0x00,0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x54 'T' + 0x00,0x00,0x00,0xFE,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 8, // 0x55 'U' + 0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00, + + 8, // 0x56 'V' + 0x00,0x00,0x00,0x42,0x42,0x42,0x24,0x24,0x18,0x18,0x00,0x00, + + 9, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x49,0x00,0x49,0x00,0x55,0x00,0x55,0x00,0x22,0x00,0x22,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x58 'X' + 0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x10,0x10,0x10,0x00,0x00, + + 7, // 0x5A 'Z' + 0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, + + 4, // 0x5B '[' + 0x00,0x00,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x60, + + 4, // 0x5C '\' + 0x00,0x00,0x80,0x80,0x40,0x40,0x40,0x20,0x20,0x10,0x10,0x00, + + 4, // 0x5D ']' + 0x00,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x60, + + 7, // 0x5E '^' + 0x00,0x00,0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC, + + 6, // 0x60 '`' + 0x00,0x00,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x30,0x08,0x38,0x48,0x38,0x00,0x00, + + 6, // 0x62 'b' + 0x00,0x00,0x40,0x40,0x40,0x70,0x48,0x48,0x48,0x70,0x00,0x00, + + 6, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x40,0x40,0x38,0x00,0x00, + + 6, // 0x64 'd' + 0x00,0x00,0x08,0x08,0x08,0x38,0x48,0x48,0x48,0x38,0x00,0x00, + + 6, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x30,0x48,0x78,0x40,0x38,0x00,0x00, + + 4, // 0x66 'f' + 0x00,0x00,0x30,0x40,0x40,0xE0,0x40,0x40,0x40,0x40,0x00,0x00, + + 6, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x38,0x48,0x48,0x48,0x38,0x08,0x30, + + 6, // 0x68 'h' + 0x00,0x00,0x40,0x40,0x40,0x70,0x48,0x48,0x48,0x48,0x00,0x00, + + 3, // 0x69 'i' + 0x00,0x00,0x00,0x40,0x00,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 3, // 0x6A 'j' + 0x00,0x00,0x00,0x40,0x00,0xC0,0x40,0x40,0x40,0x40,0x40,0x80, + + 6, // 0x6B 'k' + 0x00,0x00,0x40,0x40,0x40,0x48,0x50,0x60,0x50,0x48,0x00,0x00, + + 3, // 0x6C 'l' + 0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 9, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x70,0x48,0x48,0x48,0x48,0x00,0x00, + + 6, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x30,0x48,0x48,0x48,0x30,0x00,0x00, + + 6, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x70,0x48,0x48,0x48,0x70,0x40,0x40, + + 6, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x38,0x48,0x48,0x48,0x38,0x08,0x08, + + 4, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x50,0x60,0x40,0x40,0x40,0x00,0x00, + + 6, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x30,0x08,0x70,0x00,0x00, + + 4, // 0x74 't' + 0x00,0x00,0x00,0x00,0x40,0xF0,0x40,0x40,0x40,0x30,0x00,0x00, + + 6, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x48,0x48,0x48,0x48,0x38,0x00,0x00, + + 6, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x48,0x48,0x48,0x30,0x30,0x00,0x00, + + 7, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x44,0x54,0x54,0x28,0x28,0x00,0x00, + + 6, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x48,0x48,0x30,0x48,0x48,0x00,0x00, + + 6, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x48,0x48,0x48,0x30,0x10,0x20,0x20, + + 5, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x70,0x10,0x20,0x40,0x70,0x00,0x00, + + 6, // 0x7B '{' + 0x00,0x00,0x18,0x20,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x18, + + 5, // 0x7C '|' + 0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + + 6, // 0x7D '}' + 0x00,0x00,0x60,0x10,0x10,0x10,0x10,0x0C,0x10,0x10,0x10,0x60, + + 7, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x34,0x58,0x00,0x00,0x00,0x00, + + 9, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x7F,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana12_bold[] = + { + 12, 3, 32, 128-32, + 0x00,0x00,0x0D,0x00,0x1A,0x00,0x27,0x00,0x34,0x00,0x41,0x00,0x5A,0x00,0x67,0x00,0x74,0x00, + 0x81,0x00,0x8E,0x00,0x9B,0x00,0xA8,0x00,0xB5,0x00,0xC2,0x00,0xCF,0x00,0xDC,0x00,0xE9,0x00, + 0xF6,0x00,0x03,0x01,0x10,0x01,0x1D,0x01,0x2A,0x01,0x37,0x01,0x44,0x01,0x51,0x01,0x5E,0x01, + 0x6B,0x01,0x78,0x01,0x85,0x01,0x92,0x01,0x9F,0x01,0xAC,0x01,0xC5,0x01,0xD2,0x01,0xDF,0x01, + 0xEC,0x01,0xF9,0x01,0x06,0x02,0x13,0x02,0x20,0x02,0x2D,0x02,0x3A,0x02,0x47,0x02,0x54,0x02, + 0x61,0x02,0x6E,0x02,0x7B,0x02,0x88,0x02,0x95,0x02,0xA2,0x02,0xAF,0x02,0xBC,0x02,0xC9,0x02, + 0xD6,0x02,0xE3,0x02,0xFC,0x02,0x09,0x03,0x16,0x03,0x23,0x03,0x30,0x03,0x3D,0x03,0x4A,0x03, + 0x57,0x03,0x64,0x03,0x71,0x03,0x7E,0x03,0x8B,0x03,0x98,0x03,0xA5,0x03,0xB2,0x03,0xBF,0x03, + 0xCC,0x03,0xD9,0x03,0xE6,0x03,0xF3,0x03,0x00,0x04,0x0D,0x04,0x26,0x04,0x33,0x04,0x40,0x04, + 0x4D,0x04,0x5A,0x04,0x67,0x04,0x74,0x04,0x81,0x04,0x8E,0x04,0x9B,0x04,0xB4,0x04,0xC1,0x04, + 0xCE,0x04,0xDB,0x04,0xE8,0x04,0xF5,0x04,0x02,0x05,0x0F,0x05, + + 3, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x21 '!' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x00,0x60,0x00,0x00, + + 5, // 0x22 '"' + 0x00,0x00,0xD8,0xD8,0xD8,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x23 '#' + 0x00,0x00,0x00,0x14,0x14,0x7E,0x28,0xFC,0x50,0x50,0x00,0x00, + + 6, // 0x24 '$' + 0x00,0x00,0x20,0x20,0x70,0xE8,0xE0,0x38,0xB8,0x70,0x20,0x20, + + 11, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x00,0x94,0x00,0x94,0x00,0x69,0x80,0x0A,0x40,0x0A,0x40,0x11,0x80,0x00,0x00,0x00,0x00, + + 8, // 0x26 '&' + 0x00,0x00,0x00,0x70,0xD8,0xD8,0x76,0xDC,0xCC,0x76,0x00,0x00, + + 3, // 0x27 ''' + 0x00,0x00,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x28 '(' + 0x00,0x00,0x30,0x60,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x60,0x30, + + 5, // 0x29 ')' + 0x00,0x00,0xC0,0x60,0x30,0x30,0x30,0x30,0x30,0x30,0x60,0xC0, + + 6, // 0x2A '*' + 0x00,0x00,0x20,0xA8,0x70,0xA8,0x20,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, + + 3, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x80,0x00, + + 4, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x00, + + 3, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x00,0x00, + + 6, // 0x2F '/' + 0x00,0x00,0x08,0x08,0x10,0x10,0x20,0x40,0x40,0x80,0x80,0x00, + + 6, // 0x30 '0' + 0x00,0x00,0x00,0x70,0xD8,0xD8,0xD8,0xD8,0xD8,0x70,0x00,0x00, + + 6, // 0x31 '1' + 0x00,0x00,0x00,0x30,0x70,0x30,0x30,0x30,0x30,0x78,0x00,0x00, + + 6, // 0x32 '2' + 0x00,0x00,0x00,0x70,0x98,0x18,0x30,0x60,0xC0,0xF8,0x00,0x00, + + 6, // 0x33 '3' + 0x00,0x00,0x00,0x70,0x98,0x18,0x70,0x18,0x98,0x70,0x00,0x00, + + 6, // 0x34 '4' + 0x00,0x00,0x00,0x18,0x38,0x58,0x98,0xFC,0x18,0x18,0x00,0x00, + + 6, // 0x35 '5' + 0x00,0x00,0x00,0xF8,0xC0,0xF0,0x18,0x18,0x98,0x70,0x00,0x00, + + 6, // 0x36 '6' + 0x00,0x00,0x00,0x70,0xC0,0xF0,0xD8,0xD8,0xD8,0x70,0x00,0x00, + + 6, // 0x37 '7' + 0x00,0x00,0x00,0xF8,0x18,0x30,0x30,0x60,0x60,0xC0,0x00,0x00, + + 6, // 0x38 '8' + 0x00,0x00,0x00,0x70,0xD8,0xD8,0x70,0xD8,0xD8,0x70,0x00,0x00, + + 6, // 0x39 '9' + 0x00,0x00,0x00,0x70,0xD8,0xD8,0xD8,0x78,0x18,0x70,0x00,0x00, + + 4, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x60,0x60,0x00,0x00, + + 4, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x60,0x60,0x40,0x00, + + 8, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x04,0x18,0x60,0x60,0x18,0x04,0x00,0x00, + + 8, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x7C,0x00,0x00,0x00,0x00, + + 8, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x40,0x30,0x0C,0x0C,0x30,0x40,0x00,0x00, + + 6, // 0x3F '?' + 0x00,0x00,0x00,0xF0,0x18,0x18,0x30,0x60,0x00,0x60,0x00,0x00, + + 9, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x42,0x00,0x9D,0x00,0xA5,0x00,0xA5,0x00,0x9E,0x00,0x40,0x00,0x3C,0x00,0x00,0x00, + + 8, // 0x41 'A' + 0x00,0x00,0x00,0x38,0x38,0x6C,0x6C,0x7C,0xC6,0xC6,0x00,0x00, + + 7, // 0x42 'B' + 0x00,0x00,0x00,0xF8,0xCC,0xCC,0xF8,0xCC,0xCC,0xF8,0x00,0x00, + + 6, // 0x43 'C' + 0x00,0x00,0x00,0x70,0xC8,0xC0,0xC0,0xC0,0xC8,0x70,0x00,0x00, + + 7, // 0x44 'D' + 0x00,0x00,0x00,0xF8,0xCC,0xCC,0xCC,0xCC,0xCC,0xF8,0x00,0x00, + + 6, // 0x45 'E' + 0x00,0x00,0x00,0xF8,0xC0,0xC0,0xF8,0xC0,0xC0,0xF8,0x00,0x00, + + 6, // 0x46 'F' + 0x00,0x00,0x00,0xF8,0xC0,0xC0,0xF8,0xC0,0xC0,0xC0,0x00,0x00, + + 7, // 0x47 'G' + 0x00,0x00,0x00,0x78,0xC4,0xC0,0xC0,0xDC,0xCC,0x7C,0x00,0x00, + + 7, // 0x48 'H' + 0x00,0x00,0x00,0xCC,0xCC,0xCC,0xFC,0xCC,0xCC,0xCC,0x00,0x00, + + 5, // 0x49 'I' + 0x00,0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0xF0,0x00,0x00, + + 5, // 0x4A 'J' + 0x00,0x00,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0xE0,0x00,0x00, + + 7, // 0x4B 'K' + 0x00,0x00,0x00,0xCC,0xD8,0xF0,0xE0,0xF0,0xD8,0xCC,0x00,0x00, + + 6, // 0x4C 'L' + 0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xF8,0x00,0x00, + + 8, // 0x4D 'M' + 0x00,0x00,0x00,0x82,0xC6,0xEE,0xB6,0xB6,0x86,0x86,0x00,0x00, + + 7, // 0x4E 'N' + 0x00,0x00,0x00,0x84,0xC4,0xE4,0xB4,0x9C,0x8C,0x84,0x00,0x00, + + 8, // 0x4F 'O' + 0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0x00,0x00,0xF8,0xCC,0xCC,0xCC,0xF8,0xC0,0xC0,0x00,0x00, + + 8, // 0x51 'Q' + 0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x18,0x0E, + + 7, // 0x52 'R' + 0x00,0x00,0x00,0xF8,0xCC,0xCC,0xF8,0xD8,0xCC,0xC6,0x00,0x00, + + 6, // 0x53 'S' + 0x00,0x00,0x00,0x70,0xC8,0xC0,0x70,0x18,0x98,0x70,0x00,0x00, + + 6, // 0x54 'T' + 0x00,0x00,0x00,0xFC,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00, + + 7, // 0x55 'U' + 0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00, + + 7, // 0x56 'V' + 0x00,0x00,0x00,0xCC,0xCC,0x78,0x78,0x78,0x30,0x30,0x00,0x00, + + 11, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0xCC,0xC0,0xCC,0xC0,0x6D,0x80,0x6D,0x80,0x73,0x80,0x33,0x00,0x33,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x58 'X' + 0x00,0x00,0x00,0xCC,0xCC,0x78,0x30,0x78,0xCC,0xCC,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x00,0x00,0xCC,0xCC,0x78,0x30,0x30,0x30,0x30,0x00,0x00, + + 6, // 0x5A 'Z' + 0x00,0x00,0x00,0xF8,0x18,0x30,0x60,0xC0,0xC0,0xF8,0x00,0x00, + + 5, // 0x5B '[' + 0x00,0x00,0x70,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x70, + + 6, // 0x5C '\' + 0x00,0x00,0x80,0x80,0x40,0x40,0x20,0x10,0x10,0x08,0x08,0x00, + + 5, // 0x5D ']' + 0x00,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x70, + + 8, // 0x5E '^' + 0x00,0x00,0x00,0x18,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC, + + 6, // 0x60 '`' + 0x00,0x00,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x70,0x18,0x78,0xD8,0x78,0x00,0x00, + + 6, // 0x62 'b' + 0x00,0x00,0xC0,0xC0,0xC0,0xF0,0xD8,0xD8,0xD8,0xF0,0x00,0x00, + + 5, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x70,0xC0,0xC0,0xC0,0x70,0x00,0x00, + + 6, // 0x64 'd' + 0x00,0x00,0x18,0x18,0x18,0x78,0xD8,0xD8,0xD8,0x78,0x00,0x00, + + 6, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x70,0xD8,0xF8,0xC0,0x78,0x00,0x00, + + 5, // 0x66 'f' + 0x00,0x00,0x38,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x00,0x00, + + 6, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x78,0xD8,0xD8,0xD8,0x78,0x18,0x70, + + 6, // 0x68 'h' + 0x00,0x00,0xC0,0xC0,0xC0,0xF0,0xD8,0xD8,0xD8,0xD8,0x00,0x00, + + 3, // 0x69 'i' + 0x00,0x00,0x00,0xC0,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00, + + 4, // 0x6A 'j' + 0x00,0x00,0x00,0x60,0x00,0xE0,0x60,0x60,0x60,0x60,0x60,0xC0, + + 6, // 0x6B 'k' + 0x00,0x00,0xC0,0xC0,0xC0,0xD8,0xD8,0xF0,0xD8,0xD8,0x00,0x00, + + 3, // 0x6C 'l' + 0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00, + + 9, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF6,0x00,0xDB,0x00,0xDB,0x00,0xDB,0x00,0xDB,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0xF0,0xD8,0xD8,0xD8,0xD8,0x00,0x00, + + 6, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x70,0xD8,0xD8,0xD8,0x70,0x00,0x00, + + 6, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0xF0,0xD8,0xD8,0xD8,0xF0,0xC0,0xC0, + + 6, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x78,0xD8,0xD8,0xD8,0x78,0x18,0x18, + + 4, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0xD0,0xE0,0xC0,0xC0,0xC0,0x00,0x00, + + 5, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x70,0xC0,0xF0,0x30,0xE0,0x00,0x00, + + 5, // 0x74 't' + 0x00,0x00,0x00,0x60,0x60,0xF8,0x60,0x60,0x60,0x38,0x00,0x00, + + 6, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0xD8,0xD8,0xD8,0xD8,0x78,0x00,0x00, + + 6, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0xD8,0xD8,0xD8,0x70,0x70,0x00,0x00, + + 9, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDB,0x00,0xDB,0x00,0xDB,0x00,0x66,0x00,0x66,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0xD8,0xD8,0x70,0xD8,0xD8,0x00,0x00, + + 6, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0xD8,0xD8,0xD8,0x70,0x70,0x30,0x60, + + 5, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0xF0,0x30,0x60,0xC0,0xF0,0x00,0x00, + + 6, // 0x7B '{' + 0x00,0x00,0x18,0x30,0x30,0x30,0xE0,0x30,0x30,0x30,0x30,0x18, + + 5, // 0x7C '|' + 0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + + 6, // 0x7D '}' + 0x00,0x00,0xC0,0x60,0x60,0x60,0x38,0x60,0x60,0x60,0x60,0xC0, + + 8, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x92,0x8C,0x00,0x00,0x00, + + 9, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x7F,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana13[] = + { + 13, 3, 32, 128-32, + 0x00,0x00,0x0E,0x00,0x1C,0x00,0x2A,0x00,0x45,0x00,0x53,0x00,0x6E,0x00,0x7C,0x00,0x8A,0x00, + 0x98,0x00,0xA6,0x00,0xB4,0x00,0xCF,0x00,0xDD,0x00,0xEB,0x00,0xF9,0x00,0x07,0x01,0x15,0x01, + 0x23,0x01,0x31,0x01,0x3F,0x01,0x4D,0x01,0x5B,0x01,0x69,0x01,0x77,0x01,0x85,0x01,0x93,0x01, + 0xA1,0x01,0xAF,0x01,0xCA,0x01,0xE5,0x01,0x00,0x02,0x0E,0x02,0x29,0x02,0x37,0x02,0x45,0x02, + 0x60,0x02,0x7B,0x02,0x89,0x02,0x97,0x02,0xB2,0x02,0xC0,0x02,0xCE,0x02,0xDC,0x02,0xEA,0x02, + 0xF8,0x02,0x13,0x03,0x21,0x03,0x3C,0x03,0x4A,0x03,0x65,0x03,0x73,0x03,0x81,0x03,0x8F,0x03, + 0x9D,0x03,0xAB,0x03,0xC6,0x03,0xD4,0x03,0xE2,0x03,0xF0,0x03,0xFE,0x03,0x0C,0x04,0x1A,0x04, + 0x35,0x04,0x43,0x04,0x51,0x04,0x5F,0x04,0x6D,0x04,0x7B,0x04,0x89,0x04,0x97,0x04,0xA5,0x04, + 0xB3,0x04,0xC1,0x04,0xCF,0x04,0xDD,0x04,0xEB,0x04,0xF9,0x04,0x14,0x05,0x22,0x05,0x30,0x05, + 0x3E,0x05,0x4C,0x05,0x5A,0x05,0x68,0x05,0x76,0x05,0x84,0x05,0x92,0x05,0xAD,0x05,0xBB,0x05, + 0xC9,0x05,0xD7,0x05,0xE5,0x05,0xF3,0x05,0x01,0x06,0x1C,0x06, + + 4, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x21 '!' + 0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, + + 5, // 0x22 '"' + 0x00,0x00,0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x0A,0x00,0x3F,0x00,0x14,0x00,0x14,0x00,0x7E,0x00,0x28,0x00,0x28,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x24 '$' + 0x00,0x00,0x10,0x10,0x3C,0x50,0x50,0x38,0x14,0x14,0x78,0x10,0x10, + + 12, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x00,0x49,0x00,0x4A,0x00,0x32,0x00,0x04,0xC0,0x05,0x20,0x09,0x20,0x08,0xC0,0x00,0x00,0x00,0x00, + + 8, // 0x26 '&' + 0x00,0x00,0x00,0x30,0x48,0x48,0x32,0x4A,0x44,0x46,0x39,0x00,0x00, + + 3, // 0x27 ''' + 0x00,0x00,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x28 '(' + 0x00,0x00,0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10, + + 5, // 0x29 ')' + 0x00,0x00,0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x20,0x20,0x40, + + 7, // 0x2A '*' + 0x00,0x00,0x10,0x54,0x38,0x54,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x7F,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40, + + 5, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00, + + 5, // 0x2F '/' + 0x00,0x00,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80,0x00, + + 7, // 0x30 '0' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x31 '1' + 0x00,0x00,0x00,0x10,0x70,0x10,0x10,0x10,0x10,0x10,0x7C,0x00,0x00, + + 7, // 0x32 '2' + 0x00,0x00,0x00,0x38,0x44,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, + + 7, // 0x33 '3' + 0x00,0x00,0x00,0x38,0x44,0x04,0x18,0x04,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x34 '4' + 0x00,0x00,0x00,0x08,0x18,0x28,0x48,0x88,0xFC,0x08,0x08,0x00,0x00, + + 7, // 0x35 '5' + 0x00,0x00,0x00,0x7C,0x40,0x40,0x78,0x04,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x36 '6' + 0x00,0x00,0x00,0x18,0x20,0x40,0x78,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x37 '7' + 0x00,0x00,0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x00,0x00, + + 7, // 0x38 '8' + 0x00,0x00,0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x39 '9' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x3C,0x04,0x08,0x30,0x00,0x00, + + 5, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x20,0x20,0x00,0x00, + + 5, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x20,0x20,0x20,0x40, + + 9, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x18,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x0C,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x3F '?' + 0x00,0x00,0x00,0x70,0x08,0x08,0x10,0x20,0x20,0x00,0x20,0x00,0x00, + + 10, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x20,0x80,0x4E,0x80,0x52,0x80,0x52,0x80,0x52,0x80,0x4D,0x00,0x20,0x00,0x1E,0x00,0x00,0x00, + + 8, // 0x41 'A' + 0x00,0x00,0x00,0x18,0x18,0x24,0x24,0x24,0x7E,0x42,0x42,0x00,0x00, + + 8, // 0x42 'B' + 0x00,0x00,0x00,0x78,0x44,0x44,0x7C,0x42,0x42,0x42,0x7C,0x00,0x00, + + 9, // 0x43 'C' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x44 'D' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x42,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x45 'E' + 0x00,0x00,0x00,0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x7C,0x00,0x00, + + 6, // 0x46 'F' + 0x00,0x00,0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00,0x00, + + 9, // 0x47 'G' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x00,0x40,0x00,0x47,0x00,0x41,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x48 'H' + 0x00,0x00,0x00,0x42,0x42,0x42,0x7E,0x42,0x42,0x42,0x42,0x00,0x00, + + 5, // 0x49 'I' + 0x00,0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 5, // 0x4A 'J' + 0x00,0x00,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0xE0,0x00,0x00, + + 8, // 0x4B 'K' + 0x00,0x00,0x00,0x42,0x44,0x48,0x50,0x70,0x48,0x44,0x42,0x00,0x00, + + 6, // 0x4C 'L' + 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00, + + 9, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x55,0x00,0x55,0x00,0x49,0x00,0x49,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x4E 'N' + 0x00,0x00,0x00,0x62,0x62,0x52,0x52,0x4A,0x4A,0x46,0x46,0x00,0x00, + + 9, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00, + + 9, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x04,0x00,0x03,0x00, + + 8, // 0x52 'R' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x48,0x44,0x42,0x00,0x00, + + 8, // 0x53 'S' + 0x00,0x00,0x00,0x3C,0x42,0x40,0x30,0x0C,0x02,0x42,0x3C,0x00,0x00, + + 7, // 0x54 'T' + 0x00,0x00,0x00,0xFE,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 8, // 0x55 'U' + 0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00, + + 8, // 0x56 'V' + 0x00,0x00,0x00,0x42,0x42,0x42,0x24,0x24,0x24,0x18,0x18,0x00,0x00, + + 11, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x40,0x44,0x40,0x2A,0x80,0x2A,0x80,0x2A,0x80,0x2A,0x80,0x11,0x00,0x11,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x58 'X' + 0x00,0x00,0x00,0x42,0x42,0x24,0x18,0x18,0x24,0x42,0x42,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x00,0x00,0x82,0x44,0x28,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 8, // 0x5A 'Z' + 0x00,0x00,0x00,0x7E,0x02,0x04,0x08,0x10,0x20,0x40,0x7E,0x00,0x00, + + 5, // 0x5B '[' + 0x00,0x00,0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x70, + + 5, // 0x5C '\' + 0x00,0x00,0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00, + + 5, // 0x5D ']' + 0x00,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70, + + 9, // 0x5E '^' + 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x14,0x00,0x22,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE, + + 7, // 0x60 '`' + 0x00,0x00,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x3C,0x00,0x00, + + 7, // 0x62 'b' + 0x00,0x00,0x40,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x78,0x00,0x00, + + 6, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x44,0x38,0x00,0x00, + + 7, // 0x64 'd' + 0x00,0x00,0x04,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x3C,0x00,0x00, + + 7, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x7C,0x40,0x44,0x38,0x00,0x00, + + 4, // 0x66 'f' + 0x00,0x00,0x30,0x40,0x40,0xF0,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 7, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x38, + + 7, // 0x68 'h' + 0x00,0x00,0x40,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x00,0x00, + + 3, // 0x69 'i' + 0x00,0x00,0x40,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 4, // 0x6A 'j' + 0x00,0x00,0x20,0x00,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0xC0, + + 7, // 0x6B 'k' + 0x00,0x00,0x40,0x40,0x40,0x44,0x48,0x50,0x70,0x48,0x44,0x00,0x00, + + 3, // 0x6C 'l' + 0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 11, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7B,0x80,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x00,0x00,0x00,0x00, + + 7, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40, + + 7, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x04, + + 5, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x58,0x60,0x40,0x40,0x40,0x40,0x00,0x00, + + 6, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x60,0x18,0x08,0x70,0x00,0x00, + + 4, // 0x74 't' + 0x00,0x00,0x00,0x40,0x40,0xF0,0x40,0x40,0x40,0x40,0x30,0x00,0x00, + + 7, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x3C,0x00,0x00, + + 7, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00, + + 9, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x49,0x00,0x49,0x00,0x55,0x00,0x55,0x00,0x22,0x00,0x22,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x44,0x28,0x10,0x10,0x28,0x44,0x00,0x00, + + 7, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x44,0x28,0x28,0x28,0x10,0x10,0x10,0x20, + + 6, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x78,0x08,0x10,0x20,0x40,0x78,0x00,0x00, + + 7, // 0x7B '{' + 0x00,0x00,0x0C,0x10,0x10,0x10,0x10,0x60,0x10,0x10,0x10,0x10,0x0C, + + 5, // 0x7C '|' + 0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + + 7, // 0x7D '}' + 0x00,0x00,0x60,0x10,0x10,0x10,0x10,0x0C,0x10,0x10,0x10,0x10,0x60, + + 9, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x00,0x49,0x00,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x7F,0x80,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana13_bold[] = + { + 13, 3, 32, 128-32, + 0x00,0x00,0x0E,0x00,0x1C,0x00,0x2A,0x00,0x45,0x00,0x53,0x00,0x6E,0x00,0x89,0x00,0x97,0x00, + 0xA5,0x00,0xB3,0x00,0xC1,0x00,0xDC,0x00,0xEA,0x00,0xF8,0x00,0x06,0x01,0x14,0x01,0x22,0x01, + 0x30,0x01,0x3E,0x01,0x4C,0x01,0x5A,0x01,0x68,0x01,0x76,0x01,0x84,0x01,0x92,0x01,0xA0,0x01, + 0xAE,0x01,0xBC,0x01,0xD7,0x01,0xF2,0x01,0x0D,0x02,0x1B,0x02,0x36,0x02,0x51,0x02,0x5F,0x02, + 0x6D,0x02,0x88,0x02,0x96,0x02,0xA4,0x02,0xBF,0x02,0xDA,0x02,0xE8,0x02,0xF6,0x02,0x04,0x03, + 0x12,0x03,0x2D,0x03,0x48,0x03,0x63,0x03,0x71,0x03,0x8C,0x03,0x9A,0x03,0xA8,0x03,0xB6,0x03, + 0xD1,0x03,0xDF,0x03,0xFA,0x03,0x08,0x04,0x16,0x04,0x24,0x04,0x32,0x04,0x40,0x04,0x4E,0x04, + 0x69,0x04,0x77,0x04,0x85,0x04,0x93,0x04,0xA1,0x04,0xAF,0x04,0xBD,0x04,0xCB,0x04,0xD9,0x04, + 0xE7,0x04,0xF5,0x04,0x03,0x05,0x11,0x05,0x1F,0x05,0x2D,0x05,0x48,0x05,0x56,0x05,0x64,0x05, + 0x72,0x05,0x80,0x05,0x8E,0x05,0x9C,0x05,0xAA,0x05,0xB8,0x05,0xC6,0x05,0xE1,0x05,0xEF,0x05, + 0xFD,0x05,0x0B,0x06,0x19,0x06,0x27,0x06,0x35,0x06,0x50,0x06, + + 4, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x21 '!' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x60,0x00,0x00, + + 7, // 0x22 '"' + 0x00,0x00,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x0A,0x00,0x3F,0x00,0x14,0x00,0x14,0x00,0x7E,0x00,0x28,0x00,0x28,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x24 '$' + 0x00,0x00,0x08,0x08,0x3C,0x6A,0x68,0x3C,0x16,0x56,0x3C,0x10,0x10, + + 14, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x80,0x6C,0x80,0x6D,0x00,0x6D,0x70,0x3A,0xD8,0x02,0xD8,0x04,0xD8,0x04,0x70,0x00,0x00,0x00,0x00, + + 10, // 0x26 '&' + 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x6C,0x00,0x6C,0x00,0x39,0x80,0x6D,0x00,0x66,0x00,0x63,0x00,0x3D,0x80,0x00,0x00,0x00,0x00, + + 4, // 0x27 ''' + 0x00,0x00,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x28 '(' + 0x00,0x00,0x18,0x30,0x30,0x60,0x60,0x60,0x60,0x60,0x30,0x30,0x18, + + 6, // 0x29 ')' + 0x00,0x00,0x60,0x30,0x30,0x18,0x18,0x18,0x18,0x18,0x30,0x30,0x60, + + 8, // 0x2A '*' + 0x00,0x00,0x10,0x54,0x38,0x54,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x7F,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x60,0x40, + + 6, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00, + + 8, // 0x2F '/' + 0x00,0x00,0x06,0x06,0x0C,0x0C,0x18,0x18,0x18,0x30,0x30,0x60,0x60, + + 8, // 0x30 '0' + 0x00,0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,0x00, + + 8, // 0x31 '1' + 0x00,0x00,0x00,0x18,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00, + + 8, // 0x32 '2' + 0x00,0x00,0x00,0x3C,0x66,0x06,0x0C,0x18,0x30,0x60,0x7E,0x00,0x00, + + 8, // 0x33 '3' + 0x00,0x00,0x00,0x3C,0x66,0x06,0x1C,0x06,0x06,0x66,0x3C,0x00,0x00, + + 8, // 0x34 '4' + 0x00,0x00,0x00,0x04,0x0C,0x1C,0x2C,0x4C,0x7E,0x0C,0x0C,0x00,0x00, + + 8, // 0x35 '5' + 0x00,0x00,0x00,0x3E,0x30,0x30,0x3C,0x06,0x06,0x66,0x3C,0x00,0x00, + + 8, // 0x36 '6' + 0x00,0x00,0x00,0x1C,0x30,0x60,0x7C,0x66,0x66,0x66,0x3C,0x00,0x00, + + 8, // 0x37 '7' + 0x00,0x00,0x00,0x7E,0x06,0x0C,0x0C,0x18,0x18,0x30,0x30,0x00,0x00, + + 8, // 0x38 '8' + 0x00,0x00,0x00,0x3C,0x66,0x66,0x3C,0x66,0x66,0x66,0x3C,0x00,0x00, + + 8, // 0x39 '9' + 0x00,0x00,0x00,0x3C,0x66,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00,0x00, + + 4, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00, + + 4, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x60,0x40, + + 9, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x00,0x06,0x00,0x18,0x00,0x60,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x3F '?' + 0x00,0x00,0x00,0x38,0x4C,0x0C,0x18,0x30,0x30,0x00,0x30,0x00,0x00, + + 11, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x20,0x40,0x4F,0x40,0x5B,0x40,0x5B,0x40,0x5B,0x40,0x4F,0x80,0x20,0x00,0x1F,0x00,0x00,0x00, + + 9, // 0x41 'A' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x1C,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x7F,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x42 'B' + 0x00,0x00,0x00,0x7C,0x66,0x66,0x7C,0x66,0x66,0x66,0x7C,0x00,0x00, + + 8, // 0x43 'C' + 0x00,0x00,0x00,0x3C,0x62,0x60,0x60,0x60,0x60,0x62,0x3C,0x00,0x00, + + 9, // 0x44 'D' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x66,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x66,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x45 'E' + 0x00,0x00,0x00,0x7E,0x60,0x60,0x7E,0x60,0x60,0x60,0x7E,0x00,0x00, + + 8, // 0x46 'F' + 0x00,0x00,0x00,0x7E,0x60,0x60,0x7E,0x60,0x60,0x60,0x60,0x00,0x00, + + 9, // 0x47 'G' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x61,0x00,0x60,0x00,0x60,0x00,0x67,0x00,0x63,0x00,0x63,0x00,0x3F,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x48 'H' + 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7F,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x49 'I' + 0x00,0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00, + + 6, // 0x4A 'J' + 0x00,0x00,0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0xF0,0x00,0x00, + + 8, // 0x4B 'K' + 0x00,0x00,0x00,0x66,0x6C,0x78,0x70,0x70,0x78,0x6C,0x66,0x00,0x00, + + 7, // 0x4C 'L' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x7E,0x00,0x00, + + 10, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x80,0x71,0x80,0x7B,0x80,0x5D,0x80,0x49,0x80,0x41,0x80,0x41,0x80,0x41,0x80,0x00,0x00,0x00,0x00, + + 9, // 0x4E 'N' + 0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x61,0x00,0x71,0x00,0x59,0x00,0x4D,0x00,0x47,0x00,0x43,0x00,0x41,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x50 'P' + 0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x00,0x00, + + 9, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x0C,0x00,0x07,0x00, + + 8, // 0x52 'R' + 0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x7C,0x6C,0x66,0x63,0x00,0x00, + + 8, // 0x53 'S' + 0x00,0x00,0x00,0x3C,0x62,0x60,0x7C,0x3E,0x06,0x46,0x3C,0x00,0x00, + + 8, // 0x54 'T' + 0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00, + + 9, // 0x55 'U' + 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x56 'V' + 0x00,0x00,0x00,0x66,0x66,0x66,0x3C,0x3C,0x3C,0x18,0x18,0x00,0x00, + + 12, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x60,0x66,0x60,0x66,0x60,0x36,0xC0,0x3F,0xC0,0x39,0xC0,0x19,0x80,0x19,0x80,0x00,0x00,0x00,0x00, + + 8, // 0x58 'X' + 0x00,0x00,0x00,0x66,0x66,0x3C,0x18,0x18,0x3C,0x66,0x66,0x00,0x00, + + 8, // 0x59 'Y' + 0x00,0x00,0x00,0x66,0x66,0x3C,0x3C,0x18,0x18,0x18,0x18,0x00,0x00, + + 8, // 0x5A 'Z' + 0x00,0x00,0x00,0x7E,0x06,0x0E,0x1C,0x38,0x70,0x60,0x7E,0x00,0x00, + + 6, // 0x5B '[' + 0x00,0x00,0x78,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x78, + + 8, // 0x5C '\' + 0x00,0x00,0x60,0x60,0x30,0x30,0x18,0x18,0x18,0x0C,0x0C,0x06,0x06, + + 6, // 0x5D ']' + 0x00,0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x78, + + 10, // 0x5E '^' + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF, + + 8, // 0x60 '`' + 0x00,0x00,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x06,0x3E,0x66,0x66,0x3E,0x00,0x00, + + 8, // 0x62 'b' + 0x00,0x00,0x60,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00, + + 7, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x60,0x60,0x60,0x60,0x3C,0x00,0x00, + + 8, // 0x64 'd' + 0x00,0x00,0x06,0x06,0x06,0x3E,0x66,0x66,0x66,0x66,0x3E,0x00,0x00, + + 8, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x7E,0x60,0x62,0x3C,0x00,0x00, + + 5, // 0x66 'f' + 0x00,0x00,0x38,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x60,0x00,0x00, + + 8, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x3E,0x06,0x3C, + + 8, // 0x68 'h' + 0x00,0x00,0x60,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x66,0x00,0x00, + + 4, // 0x69 'i' + 0x00,0x00,0x00,0x60,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00, + + 5, // 0x6A 'j' + 0x00,0x00,0x00,0x30,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x30,0xE0, + + 8, // 0x6B 'k' + 0x00,0x00,0x60,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0x00,0x00, + + 4, // 0x6C 'l' + 0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00, + + 12, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7D,0xC0,0x66,0x60,0x66,0x60,0x66,0x60,0x66,0x60,0x66,0x60,0x00,0x00,0x00,0x00, + + 8, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x66,0x00,0x00, + + 8, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x00,0x00, + + 8, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x7C,0x60,0x60, + + 8, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x3E,0x06,0x06, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x6C,0x7C,0x60,0x60,0x60,0x60,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x60,0x78,0x3C,0x0C,0x78,0x00,0x00, + + 5, // 0x74 't' + 0x00,0x00,0x00,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x38,0x00,0x00, + + 8, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3E,0x00,0x00, + + 8, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x3C,0x3C,0x18,0x00,0x00, + + 10, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x33,0x00,0x33,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x3C,0x3C,0x66,0x66,0x00,0x00, + + 8, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x3C,0x3C,0x18,0x18,0x30,0x30, + + 7, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x0C,0x18,0x30,0x60,0x7C,0x00,0x00, + + 8, // 0x7B '{' + 0x00,0x00,0x0E,0x18,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E, + + 6, // 0x7C '|' + 0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + + 8, // 0x7D '}' + 0x00,0x00,0x70,0x18,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70, + + 9, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x00,0x49,0x00,0x49,0x00,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x7F,0x80,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana14[] = + { + 14, 3, 32, 128-32, + 0x00,0x00,0x0F,0x00,0x1E,0x00,0x2D,0x00,0x4A,0x00,0x59,0x00,0x76,0x00,0x93,0x00,0xA2,0x00, + 0xB1,0x00,0xC0,0x00,0xCF,0x00,0xEC,0x00,0xFB,0x00,0x0A,0x01,0x19,0x01,0x28,0x01,0x37,0x01, + 0x46,0x01,0x55,0x01,0x64,0x01,0x73,0x01,0x82,0x01,0x91,0x01,0xA0,0x01,0xAF,0x01,0xBE,0x01, + 0xCD,0x01,0xDC,0x01,0xF9,0x01,0x16,0x02,0x33,0x02,0x42,0x02,0x5F,0x02,0x6E,0x02,0x7D,0x02, + 0x9A,0x02,0xB7,0x02,0xC6,0x02,0xD5,0x02,0xF2,0x02,0x0F,0x03,0x1E,0x03,0x2D,0x03,0x3C,0x03, + 0x4B,0x03,0x68,0x03,0x85,0x03,0xA2,0x03,0xB1,0x03,0xCE,0x03,0xDD,0x03,0xEC,0x03,0xFB,0x03, + 0x18,0x04,0x27,0x04,0x44,0x04,0x53,0x04,0x62,0x04,0x71,0x04,0x80,0x04,0x8F,0x04,0x9E,0x04, + 0xBB,0x04,0xCA,0x04,0xD9,0x04,0xE8,0x04,0xF7,0x04,0x06,0x05,0x15,0x05,0x24,0x05,0x33,0x05, + 0x42,0x05,0x51,0x05,0x60,0x05,0x6F,0x05,0x7E,0x05,0x8D,0x05,0xAA,0x05,0xB9,0x05,0xC8,0x05, + 0xD7,0x05,0xE6,0x05,0xF5,0x05,0x04,0x06,0x13,0x06,0x22,0x06,0x31,0x06,0x4E,0x06,0x5D,0x06, + 0x6C,0x06,0x7B,0x06,0x8A,0x06,0x99,0x06,0xA8,0x06,0xC5,0x06, + + 4, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x21 '!' + 0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, + + 6, // 0x22 '"' + 0x00,0x00,0x48,0x48,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,0x09,0x00,0x12,0x00,0x3F,0x80,0x12,0x00,0x12,0x00,0x7F,0x00,0x24,0x00,0x24,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x24 '$' + 0x00,0x00,0x10,0x10,0x3E,0x50,0x50,0x30,0x1C,0x12,0x12,0x7C,0x10,0x10, + + 13, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x80,0x49,0x00,0x49,0x00,0x4A,0x00,0x32,0x60,0x02,0x90,0x04,0x90,0x04,0x90,0x08,0x60,0x00,0x00,0x00,0x00, + + 10, // 0x26 '&' + 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x44,0x00,0x44,0x00,0x44,0x00,0x39,0x00,0x45,0x00,0x42,0x00,0x43,0x00,0x3C,0x80,0x00,0x00,0x00,0x00, + + 3, // 0x27 ''' + 0x00,0x00,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x28 '(' + 0x00,0x00,0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10, + + 5, // 0x29 ')' + 0x00,0x00,0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x10,0x20,0x20,0x40, + + 8, // 0x2A '*' + 0x00,0x00,0x10,0x54,0x38,0x54,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x7F,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40, + + 5, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00, + + 5, // 0x2F '/' + 0x00,0x00,0x08,0x08,0x10,0x10,0x10,0x20,0x20,0x20,0x40,0x40,0x40,0x80, + + 8, // 0x30 '0' + 0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00, + + 8, // 0x31 '1' + 0x00,0x00,0x00,0x08,0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00, + + 8, // 0x32 '2' + 0x00,0x00,0x00,0x3C,0x42,0x42,0x02,0x04,0x18,0x20,0x40,0x7E,0x00,0x00, + + 8, // 0x33 '3' + 0x00,0x00,0x00,0x3C,0x42,0x02,0x02,0x1C,0x02,0x02,0x42,0x3C,0x00,0x00, + + 8, // 0x34 '4' + 0x00,0x00,0x00,0x04,0x0C,0x14,0x24,0x44,0x7F,0x04,0x04,0x04,0x00,0x00, + + 8, // 0x35 '5' + 0x00,0x00,0x00,0x7E,0x40,0x40,0x7C,0x02,0x02,0x02,0x42,0x3C,0x00,0x00, + + 8, // 0x36 '6' + 0x00,0x00,0x00,0x1C,0x20,0x40,0x7C,0x42,0x42,0x42,0x42,0x3C,0x00,0x00, + + 8, // 0x37 '7' + 0x00,0x00,0x00,0x7E,0x02,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x00,0x00, + + 8, // 0x38 '8' + 0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x3C,0x42,0x42,0x42,0x3C,0x00,0x00, + + 8, // 0x39 '9' + 0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x3E,0x02,0x04,0x38,0x00,0x00, + + 5, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00,0x20,0x20,0x00,0x00, + + 5, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00,0x20,0x20,0x20,0x40, + + 9, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x00,0x06,0x00,0x18,0x00,0x60,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x3F '?' + 0x00,0x00,0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x10,0x00,0x10,0x00,0x00, + + 12, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x27,0x40,0x49,0x20,0x49,0x20,0x49,0x20,0x49,0x20,0x27,0xC0,0x30,0x00,0x0F,0x00,0x00,0x00, + + 8, // 0x41 'A' + 0x00,0x00,0x00,0x18,0x18,0x24,0x24,0x42,0x42,0x7E,0x81,0x81,0x00,0x00, + + 8, // 0x42 'B' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x7C,0x42,0x42,0x42,0x7C,0x00,0x00, + + 9, // 0x43 'C' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x44 'D' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x42,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x45 'E' + 0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x7E,0x40,0x40,0x40,0x7E,0x00,0x00, + + 7, // 0x46 'F' + 0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x7C,0x40,0x40,0x40,0x40,0x00,0x00, + + 9, // 0x47 'G' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x00,0x40,0x00,0x47,0x00,0x41,0x00,0x41,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x48 'H' + 0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x7F,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x49 'I' + 0x00,0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 5, // 0x4A 'J' + 0x00,0x00,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0xE0,0x00,0x00, + + 8, // 0x4B 'K' + 0x00,0x00,0x00,0x42,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x42,0x00,0x00, + + 7, // 0x4C 'L' + 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7E,0x00,0x00, + + 10, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x52,0x80,0x52,0x80,0x52,0x80,0x4C,0x80,0x4C,0x80,0x40,0x80,0x40,0x80,0x00,0x00,0x00,0x00, + + 9, // 0x4E 'N' + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x00,0x61,0x00,0x51,0x00,0x51,0x00,0x49,0x00,0x45,0x00,0x45,0x00,0x43,0x00,0x43,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x50 'P' + 0x00,0x00,0x00,0x7C,0x42,0x42,0x42,0x42,0x7C,0x40,0x40,0x40,0x00,0x00, + + 10, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x02,0x00,0x01,0x80, + + 8, // 0x52 'R' + 0x00,0x00,0x00,0x7C,0x42,0x42,0x42,0x7C,0x48,0x44,0x42,0x41,0x00,0x00, + + 8, // 0x53 'S' + 0x00,0x00,0x00,0x3C,0x42,0x40,0x40,0x3C,0x02,0x02,0x42,0x3C,0x00,0x00, + + 7, // 0x54 'T' + 0x00,0x00,0x00,0xFE,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 9, // 0x55 'U' + 0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x56 'V' + 0x00,0x00,0x00,0x81,0x81,0x42,0x42,0x42,0x24,0x24,0x18,0x18,0x00,0x00, + + 13, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x10,0x42,0x10,0x45,0x10,0x45,0x10,0x25,0x20,0x28,0xA0,0x28,0xA0,0x10,0x40,0x10,0x40,0x00,0x00,0x00,0x00, + + 8, // 0x58 'X' + 0x00,0x00,0x00,0x42,0x42,0x24,0x18,0x18,0x18,0x24,0x42,0x42,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x00,0x00,0x82,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 8, // 0x5A 'Z' + 0x00,0x00,0x00,0x7E,0x02,0x04,0x08,0x10,0x10,0x20,0x40,0x7E,0x00,0x00, + + 5, // 0x5B '[' + 0x00,0x00,0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x70, + + 5, // 0x5C '\' + 0x00,0x00,0x80,0x80,0x40,0x40,0x40,0x20,0x20,0x10,0x10,0x10,0x08,0x08, + + 5, // 0x5D ']' + 0x00,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70, + + 10, // 0x5E '^' + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x12,0x00,0x21,0x00,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF, + + 8, // 0x60 '`' + 0x00,0x00,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x02,0x02,0x3E,0x42,0x42,0x3E,0x00,0x00, + + 8, // 0x62 'b' + 0x00,0x00,0x40,0x40,0x40,0x5C,0x62,0x42,0x42,0x42,0x42,0x7C,0x00,0x00, + + 6, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00,0x00, + + 8, // 0x64 'd' + 0x00,0x00,0x02,0x02,0x02,0x3E,0x42,0x42,0x42,0x42,0x46,0x3A,0x00,0x00, + + 8, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x7E,0x40,0x42,0x3C,0x00,0x00, + + 4, // 0x66 'f' + 0x00,0x00,0x30,0x40,0x40,0xF0,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 8, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x3E,0x42,0x42,0x42,0x42,0x46,0x3A,0x02,0x3C, + + 8, // 0x68 'h' + 0x00,0x00,0x40,0x40,0x40,0x5C,0x62,0x42,0x42,0x42,0x42,0x42,0x00,0x00, + + 3, // 0x69 'i' + 0x00,0x00,0x40,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 4, // 0x6A 'j' + 0x00,0x00,0x20,0x00,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xC0, + + 7, // 0x6B 'k' + 0x00,0x00,0x40,0x40,0x40,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00, + + 3, // 0x6C 'l' + 0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 11, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7B,0x80,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x00,0x00,0x00,0x00, + + 8, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x5C,0x62,0x42,0x42,0x42,0x42,0x42,0x00,0x00, + + 8, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00, + + 8, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x5C,0x62,0x42,0x42,0x42,0x42,0x7C,0x40,0x40, + + 8, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x3E,0x42,0x42,0x42,0x42,0x46,0x3A,0x02,0x02, + + 5, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x58,0x60,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x40,0x40,0x38,0x04,0x04,0x78,0x00,0x00, + + 5, // 0x74 't' + 0x00,0x00,0x00,0x40,0x40,0xF8,0x40,0x40,0x40,0x40,0x40,0x38,0x00,0x00, + + 8, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x46,0x3A,0x00,0x00, + + 7, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00,0x00, + + 11, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x40,0x44,0x40,0x2A,0x80,0x2A,0x80,0x2A,0x80,0x11,0x00,0x11,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, + + 7, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x10,0x20, + + 7, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, + + 8, // 0x7B '{' + 0x00,0x00,0x0C,0x10,0x10,0x10,0x10,0x60,0x10,0x10,0x10,0x10,0x10,0x0C, + + 5, // 0x7C '|' + 0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + + 8, // 0x7D '}' + 0x00,0x00,0x30,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x30, + + 10, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x80,0x4C,0x80,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3F,0xE0,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana14_bold[] = + { + 14, 3, 32, 128-32, + 0x00,0x00,0x0F,0x00,0x1E,0x00,0x2D,0x00,0x4A,0x00,0x67,0x00,0x84,0x00,0xA1,0x00,0xB0,0x00, + 0xBF,0x00,0xCE,0x00,0xEB,0x00,0x08,0x01,0x17,0x01,0x26,0x01,0x35,0x01,0x44,0x01,0x61,0x01, + 0x7E,0x01,0x9B,0x01,0xB8,0x01,0xD5,0x01,0xF2,0x01,0x0F,0x02,0x2C,0x02,0x49,0x02,0x66,0x02, + 0x75,0x02,0x84,0x02,0xA1,0x02,0xBE,0x02,0xDB,0x02,0xEA,0x02,0x07,0x03,0x24,0x03,0x41,0x03, + 0x5E,0x03,0x7B,0x03,0x8A,0x03,0x99,0x03,0xB6,0x03,0xD3,0x03,0xE2,0x03,0xF1,0x03,0x0E,0x04, + 0x1D,0x04,0x3A,0x04,0x57,0x04,0x74,0x04,0x91,0x04,0xAE,0x04,0xCB,0x04,0xE8,0x04,0xF7,0x04, + 0x14,0x05,0x31,0x05,0x4E,0x05,0x6B,0x05,0x88,0x05,0x97,0x05,0xA6,0x05,0xB5,0x05,0xC4,0x05, + 0xE1,0x05,0xFE,0x05,0x1B,0x06,0x2A,0x06,0x39,0x06,0x48,0x06,0x57,0x06,0x66,0x06,0x75,0x06, + 0x84,0x06,0x93,0x06,0xA2,0x06,0xB1,0x06,0xC0,0x06,0xCF,0x06,0xEC,0x06,0xFB,0x06,0x0A,0x07, + 0x19,0x07,0x28,0x07,0x37,0x07,0x46,0x07,0x55,0x07,0x64,0x07,0x73,0x07,0x90,0x07,0x9F,0x07, + 0xAE,0x07,0xBD,0x07,0xDA,0x07,0xE9,0x07,0x06,0x08,0x23,0x08, + + 4, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x21 '!' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x60,0x60,0x00,0x00, + + 7, // 0x22 '"' + 0x00,0x00,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,0x09,0x00,0x3F,0x80,0x3F,0x80,0x12,0x00,0x7F,0x00,0x7F,0x00,0x24,0x00,0x24,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x24 '$' + 0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x3E,0x00,0x69,0x00,0x68,0x00,0x7E,0x00,0x3F,0x00,0x0B,0x00,0x4B,0x00,0x3E,0x00,0x08,0x00,0x08,0x00, + + 15, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x6C,0x40,0x6C,0x80,0x6C,0xB8,0x6D,0x6C,0x3A,0x6C,0x02,0x6C,0x04,0x6C,0x04,0x38,0x00,0x00,0x00,0x00, + + 10, // 0x26 '&' + 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x6C,0x00,0x6C,0x00,0x6C,0x00,0x39,0x80,0x6D,0x00,0x66,0x00,0x63,0x00,0x3D,0x80,0x00,0x00,0x00,0x00, + + 4, // 0x27 ''' + 0x00,0x00,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x28 '(' + 0x00,0x00,0x18,0x30,0x30,0x60,0x60,0x60,0x60,0x60,0x60,0x30,0x30,0x18, + + 7, // 0x29 ')' + 0x00,0x00,0x30,0x18,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x18,0x30, + + 9, // 0x2A '*' + 0x00,0x00,0x00,0x00,0x08,0x00,0x2A,0x00,0x1C,0x00,0x1C,0x00,0x2A,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x7F,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x60,0x40, + + 6, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00, + + 8, // 0x2F '/' + 0x00,0x00,0x06,0x06,0x0C,0x0C,0x0C,0x18,0x18,0x30,0x30,0x30,0x60,0x60, + + 9, // 0x30 '0' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x31 '1' + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x32 '2' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x7F,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x33 '3' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x03,0x00,0x03,0x00,0x1E,0x00,0x03,0x00,0x03,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x34 '4' + 0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0E,0x00,0x16,0x00,0x16,0x00,0x26,0x00,0x46,0x00,0x7F,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x35 '5' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x30,0x00,0x30,0x00,0x3E,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x36 '6' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x30,0x00,0x60,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x37 '7' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x38 '8' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x39 '9' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3F,0x00,0x03,0x00,0x06,0x00,0x3C,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x00,0x00, + + 5, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x60,0x40, + + 10, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x06,0x00,0x18,0x00,0x60,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x3F '?' + 0x00,0x00,0x00,0x38,0x4C,0x0C,0x18,0x30,0x30,0x00,0x30,0x30,0x00,0x00, + + 12, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x2F,0x40,0x5B,0x20,0x5B,0x20,0x5B,0x20,0x5B,0x20,0x2F,0xC0,0x30,0x00,0x0F,0x00,0x00,0x00, + + 9, // 0x41 'A' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x1C,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x7F,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x42 'B' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x43 'C' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x31,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x31,0x00,0x1E,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x44 'D' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x45 'E' + 0x00,0x00,0x00,0x7E,0x60,0x60,0x60,0x7E,0x60,0x60,0x60,0x7E,0x00,0x00, + + 8, // 0x46 'F' + 0x00,0x00,0x00,0x7E,0x60,0x60,0x60,0x7E,0x60,0x60,0x60,0x60,0x00,0x00, + + 10, // 0x47 'G' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x30,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x67,0x80,0x61,0x80,0x31,0x80,0x1F,0x80,0x00,0x00,0x00,0x00, + + 10, // 0x48 'H' + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00, + + 6, // 0x49 'I' + 0x00,0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00, + + 7, // 0x4A 'J' + 0x00,0x00,0x00,0x7C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0xF8,0x00,0x00, + + 9, // 0x4B 'K' + 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x66,0x00,0x6C,0x00,0x78,0x00,0x70,0x00,0x78,0x00,0x6C,0x00,0x66,0x00,0x63,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x4C 'L' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x7F,0x00,0x00, + + 11, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x71,0xC0,0x71,0xC0,0x5A,0xC0,0x5A,0xC0,0x4C,0xC0,0x4C,0xC0,0x40,0xC0,0x40,0xC0,0x00,0x00,0x00,0x00, + + 10, // 0x4E 'N' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x80,0x70,0x80,0x58,0x80,0x58,0x80,0x4C,0x80,0x46,0x80,0x46,0x80,0x43,0x80,0x41,0x80,0x00,0x00,0x00,0x00, + + 11, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x50 'P' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x06,0x00,0x03,0xC0, + + 9, // 0x52 'R' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x6C,0x00,0x66,0x00,0x63,0x00,0x61,0x80,0x00,0x00,0x00,0x00, + + 9, // 0x53 'S' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x61,0x00,0x60,0x00,0x70,0x00,0x3E,0x00,0x07,0x00,0x03,0x00,0x43,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x54 'T' + 0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00, + + 10, // 0x55 'U' + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x56 'V' + 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x00,0x00,0x00,0x00, + + 14, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x18,0x63,0x18,0x63,0x18,0x33,0x30,0x37,0xB0,0x34,0xB0,0x1C,0xE0,0x18,0x60,0x18,0x60,0x00,0x00,0x00,0x00, + + 9, // 0x58 'X' + 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x36,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x59 'Y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x5A 'Z' + 0x00,0x00,0x00,0x7E,0x0C,0x0C,0x18,0x18,0x30,0x30,0x60,0x7E,0x00,0x00, + + 6, // 0x5B '[' + 0x00,0x00,0x78,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x78, + + 8, // 0x5C '\' + 0x00,0x00,0x60,0x60,0x30,0x30,0x30,0x18,0x18,0x0C,0x0C,0x0C,0x06,0x06, + + 6, // 0x5D ']' + 0x00,0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x78, + + 10, // 0x5E '^' + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x5F '_' + 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,0xFF,0x80, + + 9, // 0x60 '`' + 0x00,0x00,0x00,0x00,0x30,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x06,0x3E,0x66,0x66,0x66,0x3E,0x00,0x00, + + 8, // 0x62 'b' + 0x00,0x00,0x60,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x66,0x7C,0x00,0x00, + + 7, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x62,0x60,0x60,0x60,0x62,0x3C,0x00,0x00, + + 8, // 0x64 'd' + 0x00,0x00,0x06,0x06,0x06,0x3E,0x66,0x66,0x66,0x66,0x66,0x3E,0x00,0x00, + + 8, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x66,0x7E,0x60,0x62,0x3C,0x00,0x00, + + 5, // 0x66 'f' + 0x00,0x00,0x38,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00, + + 8, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x66,0x3E,0x06,0x3C, + + 8, // 0x68 'h' + 0x00,0x00,0x60,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00, + + 4, // 0x69 'i' + 0x00,0x00,0x60,0x60,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00, + + 5, // 0x6A 'j' + 0x00,0x00,0x30,0x30,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0xE0, + + 8, // 0x6B 'k' + 0x00,0x00,0x60,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0x63,0x00,0x00, + + 4, // 0x6C 'l' + 0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00, + + 12, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0xC0,0x77,0x60,0x66,0x60,0x66,0x60,0x66,0x60,0x66,0x60,0x66,0x60,0x00,0x00,0x00,0x00, + + 8, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00, + + 8, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,0x00, + + 8, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60, + + 8, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x66,0x3E,0x06,0x06, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x6C,0x7C,0x60,0x60,0x60,0x60,0x60,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x60,0x60,0x38,0x0C,0x0C,0x78,0x00,0x00, + + 5, // 0x74 't' + 0x00,0x00,0x00,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x60,0x38,0x00,0x00, + + 8, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x3E,0x00,0x00, + + 8, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x3C,0x3C,0x3C,0x18,0x00,0x00, + + 12, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x60,0x66,0x60,0x66,0x60,0x69,0x60,0x39,0xC0,0x30,0xC0,0x30,0xC0,0x00,0x00,0x00,0x00, + + 8, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x3C,0x18,0x3C,0x66,0x66,0x00,0x00, + + 8, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x3C,0x3C,0x3C,0x18,0x18,0x30, + + 7, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x0C,0x18,0x38,0x30,0x60,0x7C,0x00,0x00, + + 9, // 0x7B '{' + 0x00,0x00,0x00,0x00,0x0E,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x70,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x0E,0x00, + + 6, // 0x7C '|' + 0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + + 9, // 0x7D '}' + 0x00,0x00,0x00,0x00,0x38,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x07,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x38,0x00, + + 10, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x80,0x48,0x80,0x44,0x80,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3F,0xE0,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana16[] = + { + 16, 4, 32, 128-32, + 0x00,0x00,0x11,0x00,0x22,0x00,0x33,0x00,0x54,0x00,0x65,0x00,0x86,0x00,0xA7,0x00,0xB8,0x00, + 0xC9,0x00,0xDA,0x00,0xFB,0x00,0x1C,0x01,0x2D,0x01,0x3E,0x01,0x4F,0x01,0x60,0x01,0x71,0x01, + 0x82,0x01,0x93,0x01,0xA4,0x01,0xB5,0x01,0xC6,0x01,0xD7,0x01,0xE8,0x01,0xF9,0x01,0x0A,0x02, + 0x1B,0x02,0x2C,0x02,0x4D,0x02,0x6E,0x02,0x8F,0x02,0xA0,0x02,0xC1,0x02,0xE2,0x02,0xF3,0x02, + 0x14,0x03,0x35,0x03,0x46,0x03,0x57,0x03,0x78,0x03,0x99,0x03,0xAA,0x03,0xBB,0x03,0xCC,0x03, + 0xDD,0x03,0xFE,0x03,0x1F,0x04,0x40,0x04,0x51,0x04,0x72,0x04,0x93,0x04,0xB4,0x04,0xD5,0x04, + 0xF6,0x04,0x17,0x05,0x38,0x05,0x59,0x05,0x7A,0x05,0x9B,0x05,0xAC,0x05,0xBD,0x05,0xCE,0x05, + 0xEF,0x05,0x00,0x06,0x11,0x06,0x22,0x06,0x33,0x06,0x44,0x06,0x55,0x06,0x66,0x06,0x77,0x06, + 0x88,0x06,0x99,0x06,0xAA,0x06,0xBB,0x06,0xCC,0x06,0xDD,0x06,0xFE,0x06,0x0F,0x07,0x20,0x07, + 0x31,0x07,0x42,0x07,0x53,0x07,0x64,0x07,0x75,0x07,0x86,0x07,0x97,0x07,0xB8,0x07,0xC9,0x07, + 0xDA,0x07,0xEB,0x07,0xFC,0x07,0x0D,0x08,0x1E,0x08,0x3F,0x08, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x21 '!' + 0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x20,0x00,0x00,0x00, + + 5, // 0x22 '"' + 0x00,0x00,0x00,0x50,0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,0x09,0x00,0x3F,0x80,0x12,0x00,0x12,0x00,0x7F,0x00,0x24,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x24 '$' + 0x00,0x00,0x00,0x10,0x10,0x3E,0x50,0x50,0x30,0x1C,0x12,0x12,0x7C,0x10,0x10,0x00, + + 13, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x44,0x80,0x45,0x00,0x45,0x00,0x3A,0xE0,0x05,0x10,0x05,0x10,0x09,0x10,0x10,0xE0,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x26 '&' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x44,0x00,0x44,0x00,0x44,0x00,0x38,0x80,0x45,0x00,0x42,0x00,0x46,0x00,0x39,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 3, // 0x27 ''' + 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x28 '(' + 0x00,0x00,0x00,0x08,0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10,0x08, + + 6, // 0x29 ')' + 0x00,0x00,0x00,0x40,0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x40, + + 9, // 0x2A '*' + 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x2A,0x00,0x1C,0x00,0x2A,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x7F,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40,0x00, + + 7, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00, + + 6, // 0x2F '/' + 0x00,0x00,0x00,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80,0x00, + + 8, // 0x30 '0' + 0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00,0x00, + + 8, // 0x31 '1' + 0x00,0x00,0x00,0x00,0x08,0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00,0x00, + + 8, // 0x32 '2' + 0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x02,0x04,0x18,0x20,0x40,0x7E,0x00,0x00,0x00, + + 8, // 0x33 '3' + 0x00,0x00,0x00,0x00,0x3C,0x42,0x02,0x02,0x1C,0x02,0x02,0x42,0x3C,0x00,0x00,0x00, + + 8, // 0x34 '4' + 0x00,0x00,0x00,0x00,0x04,0x0C,0x14,0x24,0x44,0x7F,0x04,0x04,0x04,0x00,0x00,0x00, + + 8, // 0x35 '5' + 0x00,0x00,0x00,0x00,0x3E,0x20,0x20,0x20,0x3C,0x02,0x02,0x42,0x3C,0x00,0x00,0x00, + + 8, // 0x36 '6' + 0x00,0x00,0x00,0x00,0x1C,0x20,0x40,0x7C,0x42,0x42,0x42,0x42,0x3C,0x00,0x00,0x00, + + 8, // 0x37 '7' + 0x00,0x00,0x00,0x00,0x7E,0x02,0x04,0x04,0x08,0x08,0x10,0x10,0x10,0x00,0x00,0x00, + + 8, // 0x38 '8' + 0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x3C,0x42,0x42,0x42,0x3C,0x00,0x00,0x00, + + 8, // 0x39 '9' + 0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x3E,0x02,0x04,0x38,0x00,0x00,0x00, + + 6, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00, + + 6, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00,0x20,0x20,0x20,0x40,0x00, + + 9, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x00,0x06,0x00,0x18,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x3F '?' + 0x00,0x00,0x00,0x00,0x38,0x44,0x04,0x08,0x10,0x10,0x00,0x10,0x10,0x00,0x00,0x00, + + 13, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x10,0x40,0x27,0xA0,0x48,0x90,0x48,0x90,0x48,0x90,0x48,0x90,0x48,0x90,0x27,0xE0,0x10,0x00,0x0F,0x80,0x00,0x00, + + 9, // 0x41 'A' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x14,0x00,0x14,0x00,0x22,0x00,0x22,0x00,0x3E,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x42 'B' + 0x00,0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x7C,0x42,0x42,0x42,0x7C,0x00,0x00,0x00, + + 9, // 0x43 'C' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x44 'D' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x42,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x45 'E' + 0x00,0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x7E,0x40,0x40,0x40,0x7E,0x00,0x00,0x00, + + 8, // 0x46 'F' + 0x00,0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x7C,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 9, // 0x47 'G' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x47,0x00,0x41,0x00,0x21,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x48 'H' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x7F,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x49 'I' + 0x00,0x00,0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00,0x00, + + 6, // 0x4A 'J' + 0x00,0x00,0x00,0x00,0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0xF0,0x00,0x00,0x00, + + 8, // 0x4B 'K' + 0x00,0x00,0x00,0x00,0x42,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x42,0x00,0x00,0x00, + + 7, // 0x4C 'L' + 0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7E,0x00,0x00,0x00, + + 11, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x51,0x40,0x51,0x40,0x4A,0x40,0x4A,0x40,0x44,0x40,0x44,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x4E 'N' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x00,0x61,0x00,0x51,0x00,0x51,0x00,0x49,0x00,0x45,0x00,0x45,0x00,0x43,0x00,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x50 'P' + 0x00,0x00,0x00,0x00,0x7C,0x42,0x42,0x42,0x42,0x7C,0x40,0x40,0x40,0x00,0x00,0x00, + + 10, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x02,0x00,0x01,0x80,0x00,0x00, + + 9, // 0x52 'R' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x44,0x00,0x78,0x00,0x44,0x00,0x42,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x53 'S' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x41,0x00,0x40,0x00,0x40,0x00,0x3E,0x00,0x01,0x00,0x01,0x00,0x41,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x54 'T' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x55 'U' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x56 'V' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x10,0x42,0x10,0x45,0x10,0x45,0x10,0x25,0x20,0x28,0xA0,0x28,0xA0,0x10,0x40,0x10,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x58 'X' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x14,0x00,0x08,0x00,0x14,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x59 'Y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x5A 'Z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x01,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5B '[' + 0x00,0x00,0x00,0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00, + + 6, // 0x5C '\' + 0x00,0x00,0x00,0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00, + + 6, // 0x5D ']' + 0x00,0x00,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70,0x00, + + 11, // 0x5E '^' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00, + + 8, // 0x60 '`' + 0x00,0x00,0x00,0x10,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x02,0x02,0x3E,0x42,0x42,0x3E,0x00,0x00,0x00, + + 8, // 0x62 'b' + 0x00,0x00,0x00,0x40,0x40,0x40,0x5C,0x62,0x42,0x42,0x42,0x42,0x7C,0x00,0x00,0x00, + + 8, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x40,0x40,0x40,0x42,0x3C,0x00,0x00,0x00, + + 8, // 0x64 'd' + 0x00,0x00,0x00,0x02,0x02,0x02,0x3E,0x42,0x42,0x42,0x42,0x46,0x3A,0x00,0x00,0x00, + + 8, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x7E,0x40,0x42,0x3C,0x00,0x00,0x00, + + 6, // 0x66 'f' + 0x00,0x00,0x00,0x1C,0x20,0x20,0x78,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x00, + + 8, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x42,0x42,0x42,0x42,0x46,0x3A,0x02,0x02,0x3C, + + 8, // 0x68 'h' + 0x00,0x00,0x00,0x40,0x40,0x40,0x5C,0x62,0x42,0x42,0x42,0x42,0x42,0x00,0x00,0x00, + + 3, // 0x69 'i' + 0x00,0x00,0x00,0x40,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 4, // 0x6A 'j' + 0x00,0x00,0x00,0x20,0x00,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xC0, + + 7, // 0x6B 'k' + 0x00,0x00,0x00,0x40,0x40,0x40,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00,0x00, + + 3, // 0x6C 'l' + 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 11, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x59,0x80,0x66,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x62,0x42,0x42,0x42,0x42,0x42,0x00,0x00,0x00, + + 8, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00,0x00, + + 8, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x62,0x42,0x42,0x42,0x42,0x7C,0x40,0x40,0x40, + + 8, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x42,0x42,0x42,0x42,0x46,0x3A,0x02,0x02,0x02, + + 5, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x60,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x40,0x40,0x38,0x04,0x04,0x78,0x00,0x00,0x00, + + 6, // 0x74 't' + 0x00,0x00,0x00,0x00,0x20,0x20,0x78,0x20,0x20,0x20,0x20,0x20,0x18,0x00,0x00,0x00, + + 8, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x46,0x3A,0x00,0x00,0x00, + + 8, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x24,0x24,0x24,0x18,0x18,0x00,0x00,0x00, + + 11, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x40,0x44,0x40,0x2A,0x80,0x2A,0x80,0x2A,0x80,0x11,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00,0x00, + + 8, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x24,0x24,0x24,0x18,0x18,0x10,0x10,0x20, + + 7, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00,0x00, + + 8, // 0x7B '{' + 0x00,0x00,0x00,0x0C,0x10,0x10,0x10,0x10,0x60,0x10,0x10,0x10,0x10,0x10,0x0C,0x00, + + 7, // 0x7C '|' + 0x00,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00, + + 8, // 0x7D '}' + 0x00,0x00,0x00,0x30,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x30,0x00, + + 11, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x80,0x4C,0x80,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF0,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x3F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana16_bold[] = + { + 16, 4, 32, 128-32, + 0x00,0x00,0x11,0x00,0x22,0x00,0x33,0x00,0x54,0x00,0x75,0x00,0xA6,0x00,0xC7,0x00,0xD8,0x00, + 0xE9,0x00,0xFA,0x00,0x1B,0x01,0x3C,0x01,0x4D,0x01,0x5E,0x01,0x6F,0x01,0x90,0x01,0xB1,0x01, + 0xD2,0x01,0xF3,0x01,0x14,0x02,0x35,0x02,0x56,0x02,0x77,0x02,0x98,0x02,0xB9,0x02,0xDA,0x02, + 0xEB,0x02,0xFC,0x02,0x1D,0x03,0x3E,0x03,0x5F,0x03,0x70,0x03,0x91,0x03,0xB2,0x03,0xD3,0x03, + 0xF4,0x03,0x15,0x04,0x36,0x04,0x57,0x04,0x78,0x04,0x99,0x04,0xAA,0x04,0xBB,0x04,0xDC,0x04, + 0xED,0x04,0x0E,0x05,0x2F,0x05,0x50,0x05,0x71,0x05,0x92,0x05,0xB3,0x05,0xD4,0x05,0xE5,0x05, + 0x06,0x06,0x27,0x06,0x48,0x06,0x69,0x06,0x8A,0x06,0xAB,0x06,0xBC,0x06,0xDD,0x06,0xEE,0x06, + 0x0F,0x07,0x30,0x07,0x51,0x07,0x72,0x07,0x93,0x07,0xA4,0x07,0xC5,0x07,0xE6,0x07,0xF7,0x07, + 0x18,0x08,0x39,0x08,0x4A,0x08,0x5B,0x08,0x6C,0x08,0x7D,0x08,0x9E,0x08,0xBF,0x08,0xE0,0x08, + 0x01,0x09,0x22,0x09,0x33,0x09,0x44,0x09,0x55,0x09,0x76,0x09,0x97,0x09,0xB8,0x09,0xD9,0x09, + 0xFA,0x09,0x0B,0x0A,0x2C,0x0A,0x3D,0x0A,0x5E,0x0A,0x7F,0x0A, + + 4, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x21 '!' + 0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x22 '"' + 0x00,0x00,0x00,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,0x09,0x00,0x3F,0x80,0x3F,0x80,0x12,0x00,0x7F,0x00,0x7F,0x00,0x24,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x24 '$' + 0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x3E,0x00,0x69,0x00,0x68,0x00,0x78,0x00,0x3E,0x00,0x0F,0x00,0x0B,0x00,0x4B,0x00,0x3E,0x00,0x08,0x00,0x08,0x00,0x00,0x00, + + 17, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x20,0x00,0x66,0x20,0x00,0x66,0x40,0x00,0x66,0x5E,0x00,0x66,0xB3,0x00,0x3D,0x33,0x00,0x01,0x33,0x00,0x02,0x33,0x00,0x02,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x26 '&' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x66,0x00,0x66,0x00,0x66,0xC0,0x3C,0xC0,0x66,0x80,0x63,0x00,0x63,0x80,0x3C,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x27 ''' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x28 '(' + 0x00,0x00,0x00,0x0C,0x18,0x30,0x30,0x60,0x60,0x60,0x60,0x60,0x30,0x30,0x18,0x0C, + + 7, // 0x29 ')' + 0x00,0x00,0x00,0x60,0x30,0x18,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x18,0x30,0x60, + + 9, // 0x2A '*' + 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x49,0x00,0x2A,0x00,0x1C,0x00,0x2A,0x00,0x49,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x3F,0x80,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x60,0x60,0xC0,0xC0, + + 7, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00, + + 9, // 0x2F '/' + 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x60,0x00,0x60,0x00,0x00,0x00, + + 9, // 0x30 '0' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x31 '1' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x32 '2' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x33 '3' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x03,0x00,0x0E,0x00,0x03,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x34 '4' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0E,0x00,0x16,0x00,0x26,0x00,0x46,0x00,0x7F,0x80,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x35 '5' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x30,0x00,0x30,0x00,0x3E,0x00,0x03,0x00,0x03,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x36 '6' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x30,0x00,0x60,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x37 '7' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x38 '8' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x39 '9' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3F,0x00,0x03,0x00,0x06,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00, + + 5, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x38,0x30,0x30,0x60,0x60, + + 11, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x00,0x00,0x00,0x00,0x3F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x18,0x00,0x06,0x00,0x01,0x80,0x00,0x40,0x01,0x80,0x06,0x00,0x18,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x3F '?' + 0x00,0x00,0x00,0x00,0x3C,0x66,0x06,0x0C,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00, + + 13, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x30,0x60,0x27,0xA0,0x4D,0x90,0x4D,0x90,0x4D,0x90,0x4D,0x90,0x27,0xE0,0x30,0x00,0x0F,0x80,0x00,0x00,0x00,0x00, + + 10, // 0x41 'A' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x1E,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x7F,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x42 'B' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7F,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x43 'C' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x61,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x61,0x80,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x44 'D' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x45 'E' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x46 'F' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x47 'G' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x61,0x80,0x60,0x00,0x60,0x00,0x63,0x80,0x61,0x80,0x31,0x80,0x1F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x48 'H' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x7F,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x49 'I' + 0x00,0x00,0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00, + + 7, // 0x4A 'J' + 0x00,0x00,0x00,0x00,0x7C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0xF8,0x00,0x00,0x00, + + 9, // 0x4B 'K' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x66,0x00,0x6C,0x00,0x78,0x00,0x78,0x00,0x6C,0x00,0x66,0x00,0x63,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x4C 'L' + 0x00,0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x7F,0x00,0x00,0x00, + + 12, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xE0,0x70,0xE0,0x59,0x60,0x59,0x60,0x4E,0x60,0x4E,0x60,0x44,0x60,0x44,0x60,0x40,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x4E 'N' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x80,0x70,0x80,0x58,0x80,0x58,0x80,0x4C,0x80,0x46,0x80,0x46,0x80,0x43,0x80,0x43,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x50 'P' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x03,0x00,0x01,0xC0,0x00,0x00, + + 9, // 0x52 'R' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x6C,0x00,0x66,0x00,0x63,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x53 'S' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x70,0x00,0x3E,0x00,0x07,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x54 'T' + 0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00, + + 10, // 0x55 'U' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x56 'V' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 14, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x18,0x63,0x18,0x63,0x18,0x33,0x30,0x37,0xB0,0x34,0xB0,0x1C,0xE0,0x18,0x60,0x18,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x58 'X' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x59 'Y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x5A 'Z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5B '[' + 0x00,0x00,0x00,0x78,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x78,0x00, + + 9, // 0x5C '\' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x30,0x00,0x30,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x06,0x00,0x03,0x00,0x03,0x00,0x00,0x00, + + 6, // 0x5D ']' + 0x00,0x00,0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x78,0x00, + + 10, // 0x5E '^' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x5F '_' + 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,0xFF,0x80,0x00,0x00, + + 9, // 0x60 '`' + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x03,0x00,0x3F,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x62 'b' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x60,0x60,0x60,0x63,0x3E,0x00,0x00,0x00, + + 9, // 0x64 'd' + 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x3F,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x67,0x00,0x3B,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x7F,0x00,0x60,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x66 'f' + 0x00,0x00,0x00,0x38,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, + + 9, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x67,0x00,0x3B,0x00,0x03,0x00,0x03,0x00,0x3E,0x00, + + 9, // 0x68 'h' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x69 'i' + 0x00,0x00,0x00,0x60,0x60,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, + + 5, // 0x6A 'j' + 0x00,0x00,0x00,0x30,0x30,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0xE0, + + 8, // 0x6B 'k' + 0x00,0x00,0x00,0x60,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0x63,0x00,0x00,0x00, + + 4, // 0x6C 'l' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, + + 14, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x70,0x73,0x98,0x63,0x18,0x63,0x18,0x63,0x18,0x63,0x18,0x63,0x18,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00, + + 9, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x67,0x00,0x3B,0x00,0x03,0x00,0x03,0x00,0x03,0x00, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x7C,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, + + 8, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x60,0x70,0x3C,0x0E,0x06,0x7C,0x00,0x00,0x00, + + 6, // 0x74 't' + 0x00,0x00,0x00,0x00,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x60,0x38,0x00,0x00,0x00, + + 9, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x67,0x00,0x3B,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x60,0x66,0x60,0x66,0x60,0x69,0x60,0x39,0xC0,0x30,0xC0,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x1C,0x00,0x36,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00, + + 8, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x06,0x0C,0x18,0x30,0x60,0x7E,0x00,0x00,0x00, + + 9, // 0x7B '{' + 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x70,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x07,0x00,0x00,0x00, + + 8, // 0x7C '|' + 0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00, + + 9, // 0x7D '}' + 0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x07,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x70,0x00,0x00,0x00, + + 11, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x44,0x40,0x44,0x40,0x43,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF0,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x3F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana17[] = + { + 17, 4, 32, 128-32, + 0x00,0x00,0x12,0x00,0x24,0x00,0x36,0x00,0x59,0x00,0x7C,0x00,0x9F,0x00,0xC2,0x00,0xD4,0x00, + 0xE6,0x00,0xF8,0x00,0x1B,0x01,0x3E,0x01,0x50,0x01,0x62,0x01,0x74,0x01,0x86,0x01,0xA9,0x01, + 0xCC,0x01,0xEF,0x01,0x12,0x02,0x35,0x02,0x58,0x02,0x7B,0x02,0x9E,0x02,0xC1,0x02,0xE4,0x02, + 0xF6,0x02,0x08,0x03,0x2B,0x03,0x4E,0x03,0x71,0x03,0x83,0x03,0xA6,0x03,0xC9,0x03,0xEC,0x03, + 0x0F,0x04,0x32,0x04,0x55,0x04,0x67,0x04,0x8A,0x04,0xAD,0x04,0xBF,0x04,0xD1,0x04,0xF4,0x04, + 0x06,0x05,0x29,0x05,0x4C,0x05,0x6F,0x05,0x81,0x05,0xA4,0x05,0xC7,0x05,0xEA,0x05,0x0D,0x06, + 0x30,0x06,0x53,0x06,0x76,0x06,0x99,0x06,0xBC,0x06,0xDF,0x06,0xF1,0x06,0x03,0x07,0x15,0x07, + 0x38,0x07,0x5B,0x07,0x7E,0x07,0x90,0x07,0xB3,0x07,0xC5,0x07,0xE8,0x07,0xFA,0x07,0x0C,0x08, + 0x2F,0x08,0x52,0x08,0x64,0x08,0x76,0x08,0x88,0x08,0x9A,0x08,0xBD,0x08,0xE0,0x08,0x03,0x09, + 0x26,0x09,0x49,0x09,0x5B,0x09,0x6D,0x09,0x7F,0x09,0xA2,0x09,0xB4,0x09,0xD7,0x09,0xFA,0x09, + 0x0C,0x0A,0x1E,0x0A,0x41,0x0A,0x53,0x0A,0x76,0x0A,0x99,0x0A, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x21 '!' + 0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x20,0x00,0x00,0x00, + + 6, // 0x22 '"' + 0x00,0x00,0x00,0x48,0x48,0x48,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x80,0x04,0x80,0x09,0x00,0x3F,0xC0,0x09,0x00,0x12,0x00,0x7F,0x80,0x12,0x00,0x24,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x24 '$' + 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x3E,0x00,0x49,0x00,0x48,0x00,0x48,0x00,0x3E,0x00,0x09,0x00,0x09,0x00,0x49,0x00,0x3E,0x00,0x08,0x00,0x08,0x00,0x00,0x00, + + 15, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x20,0x44,0x40,0x44,0x80,0x44,0x80,0x45,0x38,0x39,0x44,0x02,0x44,0x04,0x44,0x04,0x44,0x08,0x38,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x26 '&' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x42,0x00,0x42,0x00,0x44,0x00,0x38,0x80,0x44,0x80,0x42,0x80,0x41,0x00,0x22,0x80,0x1C,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x27 ''' + 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x28 '(' + 0x00,0x00,0x00,0x08,0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10,0x08, + + 6, // 0x29 ')' + 0x00,0x00,0x00,0x40,0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x40, + + 9, // 0x2A '*' + 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x49,0x00,0x2A,0x00,0x1C,0x00,0x2A,0x00,0x49,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x7F,0xC0,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40,0x00, + + 7, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00, + + 6, // 0x2F '/' + 0x00,0x00,0x00,0x04,0x08,0x08,0x08,0x10,0x10,0x20,0x20,0x20,0x40,0x40,0x80,0x80,0x00, + + 9, // 0x30 '0' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x31 '1' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x38,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x32 '2' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x41,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x0C,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x33 '3' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x41,0x00,0x01,0x00,0x02,0x00,0x1C,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x42,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x34 '4' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x06,0x00,0x0A,0x00,0x12,0x00,0x22,0x00,0x42,0x00,0x7F,0x80,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x35 '5' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x7C,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x42,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x36 '6' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x30,0x00,0x20,0x00,0x40,0x00,0x7C,0x00,0x42,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x37 '7' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x08,0x00,0x10,0x00,0x10,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x38 '8' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x3E,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x39 '9' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x21,0x00,0x1F,0x00,0x01,0x00,0x02,0x00,0x06,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00, + + 6, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40,0x00, + + 11, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x06,0x00,0x18,0x00,0x60,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xC0,0x00,0x00,0x00,0x00,0x3F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0xC0,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x3F '?' + 0x00,0x00,0x00,0x00,0x3C,0x42,0x02,0x02,0x0C,0x10,0x10,0x00,0x10,0x10,0x00,0x00,0x00, + + 14, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x18,0x20,0x20,0x10,0x27,0xC8,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x27,0xF0,0x20,0x00,0x18,0x00,0x07,0xC0,0x00,0x00, + + 10, // 0x41 'A' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x12,0x00,0x12,0x00,0x21,0x00,0x21,0x00,0x21,0x00,0x7F,0x80,0x40,0x80,0x80,0x40,0x80,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x42 'B' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x7E,0x00,0x41,0x00,0x40,0x80,0x40,0x80,0x41,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x43 'C' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0x80,0x20,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x30,0x80,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x44 'D' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x41,0x80,0x40,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x41,0x80,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x45 'E' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x46 'F' + 0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x7E,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 11, // 0x47 'G' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x20,0x40,0x40,0x00,0x40,0x00,0x43,0xC0,0x40,0x40,0x20,0x40,0x30,0x40,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x48 'H' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x7F,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x49 'I' + 0x00,0x00,0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00,0x00, + + 6, // 0x4A 'J' + 0x00,0x00,0x00,0x00,0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0xF0,0x00,0x00,0x00, + + 10, // 0x4B 'K' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x42,0x00,0x44,0x00,0x48,0x00,0x50,0x00,0x68,0x00,0x44,0x00,0x42,0x00,0x41,0x00,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x4C 'L' + 0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7F,0x00,0x00,0x00, + + 11, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x51,0x40,0x51,0x40,0x4A,0x40,0x4A,0x40,0x44,0x40,0x44,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x4E 'N' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x80,0x60,0x80,0x50,0x80,0x48,0x80,0x48,0x80,0x44,0x80,0x44,0x80,0x42,0x80,0x41,0x80,0x41,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x31,0x80,0x20,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x80,0x31,0x80,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x50 'P' + 0x00,0x00,0x00,0x00,0x7C,0x42,0x41,0x41,0x42,0x7C,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 11, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x31,0x80,0x20,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x80,0x31,0x80,0x0E,0x00,0x02,0x00,0x02,0x00,0x01,0xC0, + + 10, // 0x52 'R' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x44,0x00,0x78,0x00,0x44,0x00,0x42,0x00,0x41,0x00,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x53 'S' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x20,0x80,0x40,0x00,0x40,0x00,0x38,0x00,0x07,0x00,0x00,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x54 'T' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x80,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x55 'U' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x56 'V' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x80,0x40,0x40,0x80,0x40,0x80,0x21,0x00,0x21,0x00,0x21,0x00,0x12,0x00,0x12,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 15, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x04,0x41,0x04,0x22,0x88,0x22,0x88,0x22,0x88,0x14,0x50,0x14,0x50,0x14,0x50,0x08,0x20,0x08,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x58 'X' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x21,0x00,0x12,0x00,0x12,0x00,0x0C,0x00,0x0C,0x00,0x12,0x00,0x12,0x00,0x21,0x00,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x59 'Y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x41,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x5A 'Z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x00,0x80,0x01,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5B '[' + 0x00,0x00,0x00,0x3C,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3C, + + 6, // 0x5C '\' + 0x00,0x00,0x00,0x80,0x40,0x40,0x40,0x20,0x20,0x10,0x10,0x10,0x08,0x08,0x08,0x04,0x00, + + 6, // 0x5D ']' + 0x00,0x00,0x00,0x78,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x78, + + 11, // 0x5E '^' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x5F '_' + 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,0xFF,0x80,0x00,0x00, + + 9, // 0x60 '`' + 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,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, + + 8, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x22,0x02,0x3E,0x42,0x42,0x46,0x3A,0x00,0x00,0x00, + + 9, // 0x62 'b' + 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x5C,0x00,0x62,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x22,0x40,0x40,0x40,0x40,0x22,0x1C,0x00,0x00,0x00, + + 9, // 0x64 'd' + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x1F,0x00,0x21,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x23,0x00,0x1D,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x24,0x42,0x7E,0x40,0x40,0x22,0x1C,0x00,0x00,0x00, + + 6, // 0x66 'f' + 0x00,0x00,0x00,0x1C,0x20,0x20,0x7C,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x00, + + 9, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x21,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x23,0x00,0x1D,0x00,0x01,0x00,0x22,0x00,0x1C,0x00, + + 9, // 0x68 'h' + 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x5E,0x00,0x61,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 3, // 0x69 'i' + 0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 5, // 0x6A 'j' + 0x00,0x00,0x00,0x00,0x10,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0xE0, + + 8, // 0x6B 'k' + 0x00,0x00,0x00,0x40,0x40,0x40,0x42,0x44,0x48,0x50,0x70,0x48,0x44,0x42,0x00,0x00,0x00, + + 3, // 0x6C 'l' + 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 13, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0xE0,0x63,0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5E,0x00,0x61,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x00,0x62,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x40,0x00,0x40,0x00,0x40,0x00, + + 9, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x21,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x23,0x00,0x1D,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 8, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x40,0x30,0x0C,0x02,0x42,0x3C,0x00,0x00,0x00, + + 6, // 0x74 't' + 0x00,0x00,0x00,0x00,0x20,0x20,0x7C,0x20,0x20,0x20,0x20,0x20,0x20,0x1C,0x00,0x00,0x00, + + 9, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x43,0x00,0x3D,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x24,0x24,0x24,0x18,0x18,0x18,0x00,0x00,0x00, + + 11, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x40,0x44,0x40,0x2A,0x80,0x2A,0x80,0x2A,0x80,0x2A,0x80,0x11,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x22,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x14,0x00,0x22,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x24,0x24,0x24,0x18,0x18,0x18,0x10,0x10,0x20, + + 8, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x02,0x04,0x08,0x10,0x20,0x40,0x7E,0x00,0x00,0x00, + + 9, // 0x7B '{' + 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0x60,0x00,0x10,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x07,0x00, + + 6, // 0x7C '|' + 0x00,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + + 9, // 0x7D '}' + 0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x04,0x00,0x03,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x70,0x00, + + 11, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x44,0x40,0x44,0x40,0x43,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 14, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF8,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x3F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana17_bold[] = + { + 17, 4, 32, 128-32, + 0x00,0x00,0x12,0x00,0x24,0x00,0x36,0x00,0x59,0x00,0x7C,0x00,0xB0,0x00,0xD3,0x00,0xE5,0x00, + 0xF7,0x00,0x09,0x01,0x2C,0x01,0x4F,0x01,0x61,0x01,0x73,0x01,0x85,0x01,0xA8,0x01,0xCB,0x01, + 0xEE,0x01,0x11,0x02,0x34,0x02,0x57,0x02,0x7A,0x02,0x9D,0x02,0xC0,0x02,0xE3,0x02,0x06,0x03, + 0x18,0x03,0x2A,0x03,0x4D,0x03,0x70,0x03,0x93,0x03,0xB6,0x03,0xD9,0x03,0xFC,0x03,0x1F,0x04, + 0x42,0x04,0x65,0x04,0x88,0x04,0xAB,0x04,0xCE,0x04,0xF1,0x04,0x03,0x05,0x15,0x05,0x38,0x05, + 0x5B,0x05,0x7E,0x05,0xA1,0x05,0xC4,0x05,0xE7,0x05,0x0A,0x06,0x2D,0x06,0x50,0x06,0x73,0x06, + 0x96,0x06,0xB9,0x06,0xDC,0x06,0xFF,0x06,0x22,0x07,0x45,0x07,0x57,0x07,0x7A,0x07,0x8C,0x07, + 0xAF,0x07,0xD2,0x07,0xF5,0x07,0x18,0x08,0x3B,0x08,0x4D,0x08,0x70,0x08,0x93,0x08,0xA5,0x08, + 0xC8,0x08,0xEB,0x08,0xFD,0x08,0x0F,0x09,0x32,0x09,0x44,0x09,0x67,0x09,0x8A,0x09,0xAD,0x09, + 0xD0,0x09,0xF3,0x09,0x05,0x0A,0x17,0x0A,0x29,0x0A,0x4C,0x0A,0x6F,0x0A,0x92,0x0A,0xB5,0x0A, + 0xD8,0x0A,0xEA,0x0A,0x0D,0x0B,0x1F,0x0B,0x42,0x0B,0x65,0x0B, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x21 '!' + 0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x30,0x30,0x00,0x00,0x00, + + 8, // 0x22 '"' + 0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x40,0x04,0x40,0x3F,0xE0,0x3F,0xE0,0x08,0x80,0x11,0x00,0x7F,0xC0,0x7F,0xC0,0x22,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x24 '$' + 0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x1F,0x00,0x34,0x80,0x64,0x00,0x74,0x00,0x3C,0x00,0x0F,0x00,0x0B,0x80,0x09,0x80,0x4B,0x00,0x3E,0x00,0x08,0x00,0x08,0x00,0x00,0x00, + + 18, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x08,0x00,0x66,0x10,0x00,0x66,0x20,0x00,0x66,0x2F,0x00,0x66,0x59,0x80,0x66,0x99,0x80,0x3D,0x19,0x80,0x01,0x19,0x80,0x02,0x19,0x80,0x04,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x26 '&' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x36,0x00,0x1C,0x60,0x36,0x60,0x63,0x60,0x61,0xC0,0x31,0xC0,0x1F,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x27 ''' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x28 '(' + 0x00,0x00,0x00,0x0C,0x18,0x30,0x30,0x60,0x60,0x60,0x60,0x60,0x60,0x30,0x30,0x18,0x0C, + + 8, // 0x29 ')' + 0x00,0x00,0x00,0x30,0x18,0x0C,0x0C,0x06,0x06,0x06,0x06,0x06,0x06,0x0C,0x0C,0x18,0x30, + + 10, // 0x2A '*' + 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x49,0x00,0x2A,0x00,0x1C,0x00,0x2A,0x00,0x49,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x7F,0xC0,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x60,0x60,0xC0,0xC0,0x00, + + 7, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x00, + + 10, // 0x2F '/' + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x60,0x00,0x60,0x00,0x00,0x00, + + 10, // 0x30 '0' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x31 '1' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x32 '2' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x61,0x80,0x01,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x33 '3' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x61,0x80,0x01,0x80,0x0F,0x00,0x03,0x00,0x01,0x80,0x61,0x80,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x34 '4' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x07,0x00,0x0B,0x00,0x13,0x00,0x23,0x00,0x43,0x00,0x7F,0xC0,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x35 '5' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x30,0x00,0x30,0x00,0x3E,0x00,0x03,0x00,0x01,0x80,0x01,0x80,0x61,0x80,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x36 '6' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x38,0x00,0x30,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x37 '7' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x38 '8' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x3F,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x39 '9' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x03,0x00,0x07,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x00, + + 6, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x38,0x30,0x30,0x60,0x60,0x00, + + 12, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x80,0x00,0x40,0x01,0x80,0x06,0x00,0x18,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x3F '?' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 14, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x18,0x20,0x20,0x10,0x27,0xC8,0x4C,0xC8,0x4C,0xC8,0x4C,0xC8,0x4C,0xC8,0x27,0xF0,0x20,0x00,0x18,0x00,0x07,0xC0,0x00,0x00, + + 11, // 0x41 'A' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x1B,0x00,0x1B,0x00,0x31,0x80,0x3F,0x80,0x31,0x80,0x60,0xC0,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x42 'B' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x00,0x61,0x80,0x60,0xC0,0x60,0xC0,0x61,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x43 'C' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x30,0xC0,0x30,0xC0,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x30,0xC0,0x30,0xC0,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x44 'D' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x61,0x80,0x61,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x61,0x80,0x61,0x80,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x45 'E' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x46 'F' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x47 'G' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x30,0xC0,0x30,0xC0,0x60,0x00,0x60,0x00,0x63,0xC0,0x60,0xC0,0x30,0xC0,0x30,0xC0,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x48 'H' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x7F,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x49 'I' + 0x00,0x00,0x00,0x00,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00, + + 8, // 0x4A 'J' + 0x00,0x00,0x00,0x00,0x3E,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0C,0xF8,0x00,0x00,0x00, + + 11, // 0x4B 'K' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x61,0x80,0x63,0x00,0x66,0x00,0x6C,0x00,0x7C,0x00,0x76,0x00,0x63,0x00,0x61,0x80,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x4C 'L' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x70,0x70,0x70,0x70,0xF0,0x58,0xB0,0x59,0xB0,0x4D,0x30,0x4F,0x30,0x46,0x30,0x46,0x30,0x40,0x30,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x4E 'N' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x40,0x70,0x40,0x58,0x40,0x4C,0x40,0x4C,0x40,0x46,0x40,0x43,0x40,0x43,0x40,0x41,0xC0,0x40,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x30,0xC0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x30,0xC0,0x30,0xC0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x50 'P' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x30,0xC0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x30,0xC0,0x30,0xC0,0x0F,0x80,0x03,0x00,0x03,0x00,0x01,0xE0, + + 11, // 0x52 'R' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x61,0x80,0x60,0xC0,0x60,0xC0,0x61,0x80,0x7F,0x00,0x63,0x00,0x61,0x80,0x60,0xC0,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x53 'S' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x61,0x80,0x60,0x00,0x3E,0x00,0x1F,0x00,0x01,0x80,0x61,0x80,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x54 'T' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x55 'U' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x56 'V' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x31,0x80,0x31,0x80,0x1B,0x00,0x1B,0x00,0x0E,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 16, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x86,0x61,0x86,0x63,0xC6,0x32,0x4C,0x36,0x6C,0x36,0x6C,0x34,0x2C,0x1C,0x38,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x58 'X' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x31,0x80,0x31,0x80,0x1B,0x00,0x0E,0x00,0x0E,0x00,0x1B,0x00,0x31,0x80,0x31,0x80,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x59 'Y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x5A 'Z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x5B '[' + 0x00,0x00,0x00,0x3E,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3E, + + 10, // 0x5C '\' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x30,0x00,0x30,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x06,0x00,0x03,0x00,0x03,0x00,0x01,0x80,0x01,0x80,0x00,0x00, + + 8, // 0x5D ']' + 0x00,0x00,0x00,0x7C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x7C, + + 12, // 0x5E '^' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x0E,0x00,0x1B,0x00,0x31,0x80,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x5F '_' + 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,0xFF,0xC0,0x00,0x00, + + 10, // 0x60 '`' + 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x0C,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, + + 9, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x03,0x00,0x03,0x00,0x3F,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x62 'b' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x33,0x60,0x60,0x60,0x60,0x33,0x1E,0x00,0x00,0x00, + + 10, // 0x64 'd' + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x1F,0x80,0x31,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x63,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x66 'f' + 0x00,0x00,0x00,0x1C,0x30,0x30,0x7C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00, + + 10, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x31,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x03,0x00,0x3E,0x00, + + 10, // 0x68 'h' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6F,0x00,0x71,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x69 'i' + 0x00,0x00,0x00,0x60,0x60,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, + + 6, // 0x6A 'j' + 0x00,0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF0, + + 9, // 0x6B 'k' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x63,0x00,0x66,0x00,0x6C,0x00,0x78,0x00,0x7C,0x00,0x66,0x00,0x63,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x6C 'l' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, + + 14, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x70,0x73,0x98,0x63,0x18,0x63,0x18,0x63,0x18,0x63,0x18,0x63,0x18,0x63,0x18,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0x00,0x71,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00, + + 10, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x31,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x01,0x80,0x01,0x80, + + 7, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x7E,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, + + 8, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x62,0x60,0x7C,0x3E,0x06,0x46,0x3C,0x00,0x00,0x00, + + 6, // 0x74 't' + 0x00,0x00,0x00,0x00,0x60,0x60,0xFC,0x60,0x60,0x60,0x60,0x60,0x60,0x3C,0x00,0x00,0x00, + + 10, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x80,0x3D,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 14, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x18,0x63,0x18,0x33,0x30,0x37,0xB0,0x34,0xB0,0x1C,0xE0,0x1C,0xE0,0x0C,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x36,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00, + + 8, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x06,0x0C,0x18,0x18,0x30,0x60,0x7E,0x00,0x00,0x00, + + 10, // 0x7B '{' + 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x70,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x07,0x80, + + 8, // 0x7C '|' + 0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + + 10, // 0x7D '}' + 0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x03,0x80,0x06,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x78,0x00, + + 12, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x20,0x24,0x20,0x46,0x20,0x42,0x40,0x41,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 14, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF8,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x3F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana18[] = + { + 18, 4, 32, 128-32, + 0x00,0x00,0x13,0x00,0x26,0x00,0x39,0x00,0x5E,0x00,0x83,0x00,0xA8,0x00,0xCD,0x00,0xE0,0x00, + 0xF3,0x00,0x06,0x01,0x2B,0x01,0x50,0x01,0x63,0x01,0x76,0x01,0x89,0x01,0x9C,0x01,0xC1,0x01, + 0xE6,0x01,0x0B,0x02,0x30,0x02,0x55,0x02,0x7A,0x02,0x9F,0x02,0xC4,0x02,0xE9,0x02,0x0E,0x03, + 0x21,0x03,0x34,0x03,0x59,0x03,0x7E,0x03,0xA3,0x03,0xB6,0x03,0xDB,0x03,0x00,0x04,0x25,0x04, + 0x4A,0x04,0x6F,0x04,0x94,0x04,0xB9,0x04,0xDE,0x04,0x03,0x05,0x16,0x05,0x29,0x05,0x4E,0x05, + 0x61,0x05,0x86,0x05,0xAB,0x05,0xD0,0x05,0xF5,0x05,0x1A,0x06,0x3F,0x06,0x64,0x06,0x89,0x06, + 0xAE,0x06,0xD3,0x06,0xF8,0x06,0x1D,0x07,0x42,0x07,0x67,0x07,0x7A,0x07,0x8D,0x07,0xA0,0x07, + 0xC5,0x07,0xEA,0x07,0x0F,0x08,0x34,0x08,0x59,0x08,0x6C,0x08,0x91,0x08,0xB6,0x08,0xC9,0x08, + 0xEE,0x08,0x13,0x09,0x26,0x09,0x39,0x09,0x5E,0x09,0x71,0x09,0x96,0x09,0xBB,0x09,0xE0,0x09, + 0x05,0x0A,0x2A,0x0A,0x3D,0x0A,0x50,0x0A,0x63,0x0A,0x88,0x0A,0xAD,0x0A,0xD2,0x0A,0xF7,0x0A, + 0x1C,0x0B,0x41,0x0B,0x66,0x0B,0x79,0x0B,0x9E,0x0B,0xC3,0x0B, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x21 '!' + 0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x20,0x00,0x00,0x00, + + 7, // 0x22 '"' + 0x00,0x00,0x00,0x48,0x48,0x48,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x80,0x04,0x80,0x09,0x00,0x3F,0xC0,0x09,0x00,0x11,0x00,0x12,0x00,0x7F,0x80,0x12,0x00,0x24,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x24 '$' + 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x3E,0x00,0x49,0x00,0x48,0x00,0x48,0x00,0x38,0x00,0x0E,0x00,0x09,0x00,0x09,0x00,0x49,0x00,0x3E,0x00,0x08,0x00,0x08,0x00,0x08,0x00, + + 16, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x20,0x44,0x40,0x44,0x40,0x44,0x80,0x44,0x80,0x38,0x9C,0x01,0x22,0x01,0x22,0x02,0x22,0x02,0x22,0x04,0x1C,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x26 '&' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x21,0x00,0x21,0x00,0x1E,0x40,0x24,0x40,0x42,0x40,0x41,0x40,0x40,0x80,0x21,0x40,0x1E,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x27 ''' + 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x28 '(' + 0x00,0x00,0x00,0x08,0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10,0x08, + + 7, // 0x29 ')' + 0x00,0x00,0x00,0x20,0x10,0x08,0x08,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x08,0x08,0x10,0x20, + + 10, // 0x2A '*' + 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x49,0x00,0x2A,0x00,0x1C,0x00,0x2A,0x00,0x49,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x3F,0xE0,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40,0x40, + + 7, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00, + + 7, // 0x2F '/' + 0x00,0x00,0x00,0x02,0x04,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x40,0x80,0x00, + + 10, // 0x30 '0' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x31 '1' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x1C,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x32 '2' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x41,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x01,0x00,0x02,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x33 '3' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x40,0x80,0x00,0x80,0x01,0x00,0x0E,0x00,0x01,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x41,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x34 '4' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x05,0x00,0x09,0x00,0x11,0x00,0x21,0x00,0x41,0x00,0x7F,0xC0,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x35 '5' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x20,0x00,0x20,0x00,0x20,0x00,0x3E,0x00,0x01,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x41,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x36 '6' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x5E,0x00,0x61,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x37 '7' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0x10,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x38 '8' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x39 '9' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x20,0x80,0x1F,0x80,0x00,0x80,0x01,0x00,0x02,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x00,0x10,0x10,0x10,0x20,0x20, + + 12, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x00,0x00,0x00,0x00,0x3F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0xC0,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x3F '?' + 0x00,0x00,0x00,0x00,0x3C,0x42,0x02,0x02,0x04,0x08,0x10,0x10,0x00,0x10,0x10,0x00,0x00,0x00, + + 15, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x18,0x60,0x20,0x10,0x23,0xD0,0x44,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x44,0x48,0x23,0xF0,0x20,0x00,0x18,0x00,0x07,0xC0,0x00,0x00, + + 10, // 0x41 'A' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x21,0x00,0x21,0x00,0x40,0x80,0x7F,0x80,0x40,0x80,0x80,0x40,0x80,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x42 'B' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x7E,0x00,0x41,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x41,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x43 'C' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x20,0x40,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x20,0x40,0x30,0xC0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x44 'D' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x41,0x80,0x40,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x41,0x80,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x45 'E' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x46 'F' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x40,0x00,0x40,0x00,0x40,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x47 'G' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x30,0x60,0x20,0x20,0x40,0x00,0x40,0x00,0x41,0xE0,0x40,0x20,0x40,0x20,0x20,0x20,0x30,0x20,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x48 'H' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7F,0xC0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x49 'I' + 0x00,0x00,0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00,0x00, + + 7, // 0x4A 'J' + 0x00,0x00,0x00,0x00,0x3C,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x08,0xF0,0x00,0x00,0x00, + + 10, // 0x4B 'K' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x41,0x00,0x42,0x00,0x44,0x00,0x48,0x00,0x50,0x00,0x68,0x00,0x44,0x00,0x42,0x00,0x41,0x00,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x4C 'L' + 0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7F,0x00,0x00,0x00, + + 13, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x30,0x50,0x50,0x50,0x50,0x48,0x90,0x48,0x90,0x45,0x10,0x45,0x10,0x42,0x10,0x42,0x10,0x40,0x10,0x40,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x4E 'N' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x60,0x40,0x50,0x40,0x48,0x40,0x48,0x40,0x44,0x40,0x42,0x40,0x42,0x40,0x41,0x40,0x40,0xC0,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x20,0x40,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x20,0x40,0x30,0xC0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x50 'P' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x41,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x41,0x00,0x7E,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x20,0x40,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x20,0x40,0x30,0xC0,0x0F,0x00,0x01,0x00,0x01,0x00,0x00,0xE0, + + 10, // 0x52 'R' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x42,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x42,0x00,0x41,0x00,0x40,0x80,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x53 'S' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x20,0x80,0x40,0x00,0x40,0x00,0x20,0x00,0x1E,0x00,0x01,0x00,0x00,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x54 'T' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x80,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x55 'U' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x56 'V' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x80,0x40,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x21,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 15, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x04,0x41,0x04,0x22,0x88,0x22,0x88,0x22,0x88,0x12,0x90,0x14,0x50,0x14,0x50,0x14,0x50,0x08,0x20,0x08,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x58 'X' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x21,0x00,0x21,0x00,0x12,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x12,0x00,0x21,0x00,0x21,0x00,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x59 'Y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x41,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x5A 'Z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x00,0x80,0x01,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x5B '[' + 0x00,0x00,0x00,0x3C,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3C, + + 7, // 0x5C '\' + 0x00,0x00,0x00,0x80,0x40,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x04,0x02,0x00, + + 7, // 0x5D ']' + 0x00,0x00,0x00,0x78,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x78, + + 12, // 0x5E '^' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x09,0x00,0x10,0x80,0x20,0x40,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x5F '_' + 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,0xFF,0xC0,0x00,0x00, + + 10, // 0x60 '`' + 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,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, + + 9, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x01,0x00,0x3F,0x00,0x41,0x00,0x41,0x00,0x43,0x00,0x3D,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x62 'b' + 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x5C,0x00,0x62,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x21,0x40,0x40,0x40,0x40,0x21,0x1E,0x00,0x00,0x00, + + 9, // 0x64 'd' + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x1F,0x00,0x21,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x23,0x00,0x1D,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x66 'f' + 0x00,0x00,0x00,0x1C,0x20,0x20,0x20,0x7C,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x00, + + 9, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x21,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x23,0x00,0x1D,0x00,0x01,0x00,0x22,0x00,0x1C,0x00, + + 9, // 0x68 'h' + 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x5E,0x00,0x61,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 3, // 0x69 'i' + 0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 5, // 0x6A 'j' + 0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0xE0, + + 9, // 0x6B 'k' + 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x42,0x00,0x44,0x00,0x48,0x00,0x50,0x00,0x68,0x00,0x44,0x00,0x42,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 3, // 0x6C 'l' + 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 15, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2E,0x70,0x31,0x88,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5E,0x00,0x61,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x00,0x62,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x40,0x00,0x40,0x00,0x40,0x00, + + 9, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x21,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x23,0x00,0x1D,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 8, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x40,0x30,0x0C,0x02,0x42,0x3C,0x00,0x00,0x00, + + 6, // 0x74 't' + 0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x7C,0x20,0x20,0x20,0x20,0x20,0x20,0x1C,0x00,0x00,0x00, + + 9, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x43,0x00,0x3D,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x14,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x10,0x42,0x10,0x25,0x20,0x25,0x20,0x28,0xA0,0x28,0xA0,0x10,0x40,0x10,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x22,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x14,0x00,0x22,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0x10,0x00, + + 9, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x7B '{' + 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0x60,0x00,0x10,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x07,0x00, + + 7, // 0x7C '|' + 0x00,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + + 10, // 0x7D '}' + 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x02,0x00,0x01,0x80,0x02,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x38,0x00, + + 12, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x20,0x24,0x20,0x42,0x40,0x41,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 15, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF8,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x3F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana18_bold[] = + { + 18, 4, 32, 128-32, + 0x00,0x00,0x13,0x00,0x26,0x00,0x4B,0x00,0x70,0x00,0x95,0x00,0xCC,0x00,0xF1,0x00,0x04,0x01, + 0x17,0x01,0x2A,0x01,0x4F,0x01,0x74,0x01,0x87,0x01,0x9A,0x01,0xAD,0x01,0xD2,0x01,0xF7,0x01, + 0x1C,0x02,0x41,0x02,0x66,0x02,0x8B,0x02,0xB0,0x02,0xD5,0x02,0xFA,0x02,0x1F,0x03,0x44,0x03, + 0x57,0x03,0x6A,0x03,0x8F,0x03,0xB4,0x03,0xD9,0x03,0xFE,0x03,0x23,0x04,0x48,0x04,0x6D,0x04, + 0x92,0x04,0xB7,0x04,0xDC,0x04,0x01,0x05,0x26,0x05,0x4B,0x05,0x5E,0x05,0x71,0x05,0x96,0x05, + 0xBB,0x05,0xE0,0x05,0x05,0x06,0x2A,0x06,0x4F,0x06,0x74,0x06,0x99,0x06,0xBE,0x06,0xE3,0x06, + 0x08,0x07,0x2D,0x07,0x52,0x07,0x77,0x07,0x9C,0x07,0xC1,0x07,0xD4,0x07,0xF9,0x07,0x0C,0x08, + 0x31,0x08,0x56,0x08,0x7B,0x08,0xA0,0x08,0xC5,0x08,0xD8,0x08,0xFD,0x08,0x22,0x09,0x35,0x09, + 0x5A,0x09,0x7F,0x09,0x92,0x09,0xA5,0x09,0xCA,0x09,0xDD,0x09,0x02,0x0A,0x27,0x0A,0x4C,0x0A, + 0x71,0x0A,0x96,0x0A,0xA9,0x0A,0xCE,0x0A,0xE1,0x0A,0x06,0x0B,0x2B,0x0B,0x50,0x0B,0x75,0x0B, + 0x9A,0x0B,0xBF,0x0B,0xE4,0x0B,0xF7,0x0B,0x1C,0x0C,0x41,0x0C, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x21 '!' + 0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x30,0x30,0x00,0x00,0x00, + + 9, // 0x22 '"' + 0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x20,0x04,0x20,0x08,0x40,0x3F,0xF0,0x3F,0xF0,0x08,0x40,0x10,0x80,0x7F,0xE0,0x7F,0xE0,0x21,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x24 '$' + 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x1F,0x80,0x34,0xC0,0x64,0xC0,0x64,0x00,0x3C,0x00,0x07,0x80,0x04,0xC0,0x64,0xC0,0x65,0x80,0x3F,0x00,0x04,0x00,0x04,0x00,0x00,0x00, + + 19, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x08,0x00,0x63,0x10,0x00,0x63,0x10,0x00,0x63,0x20,0x00,0x63,0x2F,0x80,0x63,0x58,0xC0,0x3E,0x98,0xC0,0x00,0x98,0xC0,0x01,0x18,0xC0,0x01,0x18,0xC0,0x02,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x26 '&' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x1E,0x60,0x36,0x60,0x63,0x60,0x61,0xC0,0x60,0xC0,0x30,0xE0,0x1F,0x30,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x27 ''' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x28 '(' + 0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x30,0x60,0x60,0x60,0x60,0x60,0x30,0x30,0x18,0x0C,0x06, + + 8, // 0x29 ')' + 0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x0C,0x06,0x06,0x06,0x06,0x06,0x0C,0x0C,0x18,0x30,0x60, + + 11, // 0x2A '*' + 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x24,0x80,0x15,0x00,0x0E,0x00,0x15,0x00,0x24,0x80,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x3F,0xE0,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x60,0x60,0x60,0xC0,0xC0, + + 7, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x00, + + 10, // 0x2F '/' + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x60,0x00,0x60,0x00,0x00,0x00, + + 11, // 0x30 '0' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x31 '1' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x1E,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x1F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x32 '2' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x60,0xC0,0x00,0xC0,0x01,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x33 '3' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x60,0xC0,0x00,0xC0,0x01,0x80,0x0F,0x00,0x01,0x80,0x00,0xC0,0x60,0xC0,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x34 '4' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x80,0x05,0x80,0x09,0x80,0x11,0x80,0x21,0x80,0x41,0x80,0x7F,0xE0,0x01,0x80,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x35 '5' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xC0,0x30,0x00,0x30,0x00,0x30,0x00,0x3F,0x00,0x01,0x80,0x00,0xC0,0x00,0xC0,0x60,0xC0,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x36 '6' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x18,0x00,0x30,0x00,0x60,0x00,0x6F,0x00,0x71,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x37 '7' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xC0,0x00,0xC0,0x01,0x80,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x38 '8' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x39 '9' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0xC0,0x1E,0xC0,0x00,0xC0,0x01,0x80,0x03,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x00, + + 6, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x38,0x30,0x30,0x30,0x60,0x60, + + 13, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0xC0,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x18,0x00,0x06,0x00,0x01,0x80,0x00,0x60,0x00,0x60,0x01,0x80,0x06,0x00,0x18,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x3F '?' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 14, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x18,0x60,0x20,0x10,0x27,0xD0,0x4C,0xC8,0x4C,0xC8,0x4C,0xC8,0x4C,0xC8,0x4C,0xC8,0x27,0xF0,0x20,0x00,0x18,0x00,0x07,0xC0,0x00,0x00, + + 12, // 0x41 'A' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x0F,0x00,0x0F,0x00,0x19,0x80,0x19,0x80,0x30,0xC0,0x3F,0xC0,0x30,0xC0,0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x42 'B' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7F,0x00,0x61,0x80,0x60,0xC0,0x60,0xC0,0x61,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x43 'C' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x38,0xC0,0x30,0xC0,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x30,0xC0,0x38,0xC0,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x44 'D' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x61,0xC0,0x60,0xC0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0xC0,0x61,0xC0,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x45 'E' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x46 'F' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x47 'G' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x38,0x60,0x30,0x60,0x60,0x00,0x60,0x00,0x63,0xE0,0x60,0x60,0x60,0x60,0x30,0x60,0x38,0x60,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x48 'H' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x7F,0xE0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x49 'I' + 0x00,0x00,0x00,0x00,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00, + + 8, // 0x4A 'J' + 0x00,0x00,0x00,0x00,0x3E,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0C,0xF8,0x00,0x00,0x00, + + 12, // 0x4B 'K' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x60,0xC0,0x61,0x80,0x63,0x00,0x66,0x00,0x6C,0x00,0x7E,0x00,0x73,0x00,0x61,0x80,0x60,0xC0,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x4C 'L' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 14, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x38,0x70,0x38,0x70,0x78,0x58,0x58,0x58,0xD8,0x4C,0x98,0x4D,0x98,0x47,0x18,0x47,0x18,0x42,0x18,0x40,0x18,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x4E 'N' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x20,0x70,0x20,0x58,0x20,0x4C,0x20,0x4C,0x20,0x46,0x20,0x43,0x20,0x43,0x20,0x41,0xA0,0x40,0xE0,0x40,0xE0,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x38,0xE0,0x30,0x60,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x30,0x60,0x38,0xE0,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x50 'P' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x61,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x61,0x80,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x38,0xE0,0x30,0x60,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x30,0x60,0x38,0xE0,0x0F,0x80,0x03,0x00,0x03,0x80,0x01,0xF0, + + 12, // 0x52 'R' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x61,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x61,0x80,0x7F,0x00,0x61,0x80,0x60,0xC0,0x60,0x60,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x53 'S' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x30,0xC0,0x60,0xC0,0x60,0x00,0x7C,0x00,0x3F,0x80,0x03,0xC0,0x00,0xC0,0x60,0xC0,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x54 'T' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x55 'U' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x30,0xC0,0x1F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x56 'V' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x31,0x80,0x31,0x80,0x1B,0x00,0x1B,0x00,0x1B,0x00,0x0E,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 16, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x86,0x61,0x86,0x63,0xC6,0x33,0xCC,0x32,0x4C,0x32,0x4C,0x1E,0x78,0x1C,0x38,0x1C,0x38,0x0C,0x30,0x0C,0x30,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x58 'X' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x31,0x80,0x31,0x80,0x1B,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x1B,0x00,0x31,0x80,0x31,0x80,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x59 'Y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x5A 'Z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0x80,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x5B '[' + 0x00,0x00,0x00,0x3E,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3E, + + 10, // 0x5C '\' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x30,0x00,0x30,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x06,0x00,0x03,0x00,0x03,0x00,0x01,0x80,0x01,0x80,0x00,0x00, + + 8, // 0x5D ']' + 0x00,0x00,0x00,0x7C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x7C, + + 13, // 0x5E '^' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0F,0x00,0x19,0x80,0x30,0xC0,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x5F '_' + 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,0xFF,0xE0,0x00,0x00, + + 11, // 0x60 '`' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x0C,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, + + 10, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x01,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x63,0x80,0x3D,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x62 'b' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x33,0x60,0x60,0x60,0x60,0x33,0x1E,0x00,0x00,0x00, + + 10, // 0x64 'd' + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x1F,0x80,0x31,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x7F,0x80,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x66 'f' + 0x00,0x00,0x00,0x1C,0x30,0x30,0x30,0x7C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00, + + 10, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x31,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x03,0x00,0x3E,0x00, + + 10, // 0x68 'h' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6F,0x00,0x71,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x69 'i' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, + + 6, // 0x6A 'j' + 0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF0, + + 10, // 0x6B 'k' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x61,0x80,0x63,0x00,0x66,0x00,0x6C,0x00,0x7E,0x00,0x73,0x00,0x61,0x80,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x6C 'l' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, + + 16, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0x3C,0x71,0xC6,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0x00,0x71,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00, + + 10, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x31,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x01,0x80,0x01,0x80, + + 7, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x7E,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, + + 9, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x61,0x00,0x60,0x00,0x7E,0x00,0x3F,0x00,0x03,0x00,0x43,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x74 't' + 0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x7E,0x30,0x30,0x30,0x30,0x30,0x30,0x1E,0x00,0x00,0x00, + + 10, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x80,0x3D,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 14, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x18,0x63,0x18,0x63,0x18,0x37,0xB0,0x34,0xB0,0x3C,0xF0,0x18,0x60,0x18,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00, + + 9, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x7B '{' + 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x70,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x07,0x80, + + 8, // 0x7C '|' + 0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + + 11, // 0x7D '}' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x03,0x00,0x01,0xC0,0x03,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x3C,0x00, + + 13, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x10,0x24,0x10,0x42,0x10,0x41,0x20,0x40,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 15, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF8,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x3F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + +} + diff --git a/jni/desmume/src/android/agg/src/agg_gsv_text.cpp b/jni/desmume/src/android/agg/src/agg_gsv_text.cpp new file mode 100755 index 0000000..e5976a3 --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_gsv_text.cpp @@ -0,0 +1,681 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <string.h> +#include <stdio.h> +#include "agg_gsv_text.h" +#include "agg_bounding_rect.h" + + + +namespace agg +{ + int8u gsv_default_font[] = + { + 0x40,0x00,0x6c,0x0f,0x15,0x00,0x0e,0x00,0xf9,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0d,0x0a,0x0d,0x0a,0x46,0x6f,0x6e,0x74,0x20,0x28, + 0x63,0x29,0x20,0x4d,0x69,0x63,0x72,0x6f,0x50,0x72, + 0x6f,0x66,0x20,0x32,0x37,0x20,0x53,0x65,0x70,0x74, + 0x65,0x6d,0x62,0x2e,0x31,0x39,0x38,0x39,0x00,0x0d, + 0x0a,0x0d,0x0a,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, + 0x02,0x00,0x12,0x00,0x34,0x00,0x46,0x00,0x94,0x00, + 0xd0,0x00,0x2e,0x01,0x3e,0x01,0x64,0x01,0x8a,0x01, + 0x98,0x01,0xa2,0x01,0xb4,0x01,0xba,0x01,0xc6,0x01, + 0xcc,0x01,0xf0,0x01,0xfa,0x01,0x18,0x02,0x38,0x02, + 0x44,0x02,0x68,0x02,0x98,0x02,0xa2,0x02,0xde,0x02, + 0x0e,0x03,0x24,0x03,0x40,0x03,0x48,0x03,0x52,0x03, + 0x5a,0x03,0x82,0x03,0xec,0x03,0xfa,0x03,0x26,0x04, + 0x4c,0x04,0x6a,0x04,0x7c,0x04,0x8a,0x04,0xb6,0x04, + 0xc4,0x04,0xca,0x04,0xe0,0x04,0xee,0x04,0xf8,0x04, + 0x0a,0x05,0x18,0x05,0x44,0x05,0x5e,0x05,0x8e,0x05, + 0xac,0x05,0xd6,0x05,0xe0,0x05,0xf6,0x05,0x00,0x06, + 0x12,0x06,0x1c,0x06,0x28,0x06,0x36,0x06,0x48,0x06, + 0x4e,0x06,0x60,0x06,0x6e,0x06,0x74,0x06,0x84,0x06, + 0xa6,0x06,0xc8,0x06,0xe6,0x06,0x08,0x07,0x2c,0x07, + 0x3c,0x07,0x68,0x07,0x7c,0x07,0x8c,0x07,0xa2,0x07, + 0xb0,0x07,0xb6,0x07,0xd8,0x07,0xec,0x07,0x10,0x08, + 0x32,0x08,0x54,0x08,0x64,0x08,0x88,0x08,0x98,0x08, + 0xac,0x08,0xb6,0x08,0xc8,0x08,0xd2,0x08,0xe4,0x08, + 0xf2,0x08,0x3e,0x09,0x48,0x09,0x94,0x09,0xc2,0x09, + 0xc4,0x09,0xd0,0x09,0xe2,0x09,0x04,0x0a,0x0e,0x0a, + 0x26,0x0a,0x34,0x0a,0x4a,0x0a,0x66,0x0a,0x70,0x0a, + 0x7e,0x0a,0x8e,0x0a,0x9a,0x0a,0xa6,0x0a,0xb4,0x0a, + 0xd8,0x0a,0xe2,0x0a,0xf6,0x0a,0x18,0x0b,0x22,0x0b, + 0x32,0x0b,0x56,0x0b,0x60,0x0b,0x6e,0x0b,0x7c,0x0b, + 0x8a,0x0b,0x9c,0x0b,0x9e,0x0b,0xb2,0x0b,0xc2,0x0b, + 0xd8,0x0b,0xf4,0x0b,0x08,0x0c,0x30,0x0c,0x56,0x0c, + 0x72,0x0c,0x90,0x0c,0xb2,0x0c,0xce,0x0c,0xe2,0x0c, + 0xfe,0x0c,0x10,0x0d,0x26,0x0d,0x36,0x0d,0x42,0x0d, + 0x4e,0x0d,0x5c,0x0d,0x78,0x0d,0x8c,0x0d,0x8e,0x0d, + 0x90,0x0d,0x92,0x0d,0x94,0x0d,0x96,0x0d,0x98,0x0d, + 0x9a,0x0d,0x9c,0x0d,0x9e,0x0d,0xa0,0x0d,0xa2,0x0d, + 0xa4,0x0d,0xa6,0x0d,0xa8,0x0d,0xaa,0x0d,0xac,0x0d, + 0xae,0x0d,0xb0,0x0d,0xb2,0x0d,0xb4,0x0d,0xb6,0x0d, + 0xb8,0x0d,0xba,0x0d,0xbc,0x0d,0xbe,0x0d,0xc0,0x0d, + 0xc2,0x0d,0xc4,0x0d,0xc6,0x0d,0xc8,0x0d,0xca,0x0d, + 0xcc,0x0d,0xce,0x0d,0xd0,0x0d,0xd2,0x0d,0xd4,0x0d, + 0xd6,0x0d,0xd8,0x0d,0xda,0x0d,0xdc,0x0d,0xde,0x0d, + 0xe0,0x0d,0xe2,0x0d,0xe4,0x0d,0xe6,0x0d,0xe8,0x0d, + 0xea,0x0d,0xec,0x0d,0x0c,0x0e,0x26,0x0e,0x48,0x0e, + 0x64,0x0e,0x88,0x0e,0x92,0x0e,0xa6,0x0e,0xb4,0x0e, + 0xd0,0x0e,0xee,0x0e,0x02,0x0f,0x16,0x0f,0x26,0x0f, + 0x3c,0x0f,0x58,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f, + 0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f, + 0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f, + 0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x10,0x80, + 0x05,0x95,0x00,0x72,0x00,0xfb,0xff,0x7f,0x01,0x7f, + 0x01,0x01,0xff,0x01,0x05,0xfe,0x05,0x95,0xff,0x7f, + 0x00,0x7a,0x01,0x86,0xff,0x7a,0x01,0x87,0x01,0x7f, + 0xfe,0x7a,0x0a,0x87,0xff,0x7f,0x00,0x7a,0x01,0x86, + 0xff,0x7a,0x01,0x87,0x01,0x7f,0xfe,0x7a,0x05,0xf2, + 0x0b,0x95,0xf9,0x64,0x0d,0x9c,0xf9,0x64,0xfa,0x91, + 0x0e,0x00,0xf1,0xfa,0x0e,0x00,0x04,0xfc,0x08,0x99, + 0x00,0x63,0x04,0x9d,0x00,0x63,0x04,0x96,0xff,0x7f, + 0x01,0x7f,0x01,0x01,0x00,0x01,0xfe,0x02,0xfd,0x01, + 0xfc,0x00,0xfd,0x7f,0xfe,0x7e,0x00,0x7e,0x01,0x7e, + 0x01,0x7f,0x02,0x7f,0x06,0x7e,0x02,0x7f,0x02,0x7e, + 0xf2,0x89,0x02,0x7e,0x02,0x7f,0x06,0x7e,0x02,0x7f, + 0x01,0x7f,0x01,0x7e,0x00,0x7c,0xfe,0x7e,0xfd,0x7f, + 0xfc,0x00,0xfd,0x01,0xfe,0x02,0x00,0x01,0x01,0x01, + 0x01,0x7f,0xff,0x7f,0x10,0xfd,0x15,0x95,0xee,0x6b, + 0x05,0x95,0x02,0x7e,0x00,0x7e,0xff,0x7e,0xfe,0x7f, + 0xfe,0x00,0xfe,0x02,0x00,0x02,0x01,0x02,0x02,0x01, + 0x02,0x00,0x02,0x7f,0x03,0x7f,0x03,0x00,0x03,0x01, + 0x02,0x01,0xfc,0xf2,0xfe,0x7f,0xff,0x7e,0x00,0x7e, + 0x02,0x7e,0x02,0x00,0x02,0x01,0x01,0x02,0x00,0x02, + 0xfe,0x02,0xfe,0x00,0x07,0xf9,0x15,0x8d,0xff,0x7f, + 0x01,0x7f,0x01,0x01,0x00,0x01,0xff,0x01,0xff,0x00, + 0xff,0x7f,0xff,0x7e,0xfe,0x7b,0xfe,0x7d,0xfe,0x7e, + 0xfe,0x7f,0xfd,0x00,0xfd,0x01,0xff,0x02,0x00,0x03, + 0x01,0x02,0x06,0x04,0x02,0x02,0x01,0x02,0x00,0x02, + 0xff,0x02,0xfe,0x01,0xfe,0x7f,0xff,0x7e,0x00,0x7e, + 0x01,0x7d,0x02,0x7d,0x05,0x79,0x02,0x7e,0x03,0x7f, + 0x01,0x00,0x01,0x01,0x00,0x01,0xf1,0xfe,0xfe,0x01, + 0xff,0x02,0x00,0x03,0x01,0x02,0x02,0x02,0x00,0x86, + 0x01,0x7e,0x08,0x75,0x02,0x7e,0x02,0x7f,0x05,0x80, + 0x05,0x93,0xff,0x01,0x01,0x01,0x01,0x7f,0x00,0x7e, + 0xff,0x7e,0xff,0x7f,0x06,0xf1,0x0b,0x99,0xfe,0x7e, + 0xfe,0x7d,0xfe,0x7c,0xff,0x7b,0x00,0x7c,0x01,0x7b, + 0x02,0x7c,0x02,0x7d,0x02,0x7e,0xfe,0x9e,0xfe,0x7c, + 0xff,0x7d,0xff,0x7b,0x00,0x7c,0x01,0x7b,0x01,0x7d, + 0x02,0x7c,0x05,0x85,0x03,0x99,0x02,0x7e,0x02,0x7d, + 0x02,0x7c,0x01,0x7b,0x00,0x7c,0xff,0x7b,0xfe,0x7c, + 0xfe,0x7d,0xfe,0x7e,0x02,0x9e,0x02,0x7c,0x01,0x7d, + 0x01,0x7b,0x00,0x7c,0xff,0x7b,0xff,0x7d,0xfe,0x7c, + 0x09,0x85,0x08,0x95,0x00,0x74,0xfb,0x89,0x0a,0x7a, + 0x00,0x86,0xf6,0x7a,0x0d,0xf4,0x0d,0x92,0x00,0x6e, + 0xf7,0x89,0x12,0x00,0x04,0xf7,0x06,0x81,0xff,0x7f, + 0xff,0x01,0x01,0x01,0x01,0x7f,0x00,0x7e,0xff,0x7e, + 0xff,0x7f,0x06,0x84,0x04,0x89,0x12,0x00,0x04,0xf7, + 0x05,0x82,0xff,0x7f,0x01,0x7f,0x01,0x01,0xff,0x01, + 0x05,0xfe,0x00,0xfd,0x0e,0x18,0x00,0xeb,0x09,0x95, + 0xfd,0x7f,0xfe,0x7d,0xff,0x7b,0x00,0x7d,0x01,0x7b, + 0x02,0x7d,0x03,0x7f,0x02,0x00,0x03,0x01,0x02,0x03, + 0x01,0x05,0x00,0x03,0xff,0x05,0xfe,0x03,0xfd,0x01, + 0xfe,0x00,0x0b,0xeb,0x06,0x91,0x02,0x01,0x03,0x03, + 0x00,0x6b,0x09,0x80,0x04,0x90,0x00,0x01,0x01,0x02, + 0x01,0x01,0x02,0x01,0x04,0x00,0x02,0x7f,0x01,0x7f, + 0x01,0x7e,0x00,0x7e,0xff,0x7e,0xfe,0x7d,0xf6,0x76, + 0x0e,0x00,0x03,0x80,0x05,0x95,0x0b,0x00,0xfa,0x78, + 0x03,0x00,0x02,0x7f,0x01,0x7f,0x01,0x7d,0x00,0x7e, + 0xff,0x7d,0xfe,0x7e,0xfd,0x7f,0xfd,0x00,0xfd,0x01, + 0xff,0x01,0xff,0x02,0x11,0xfc,0x0d,0x95,0xf6,0x72, + 0x0f,0x00,0xfb,0x8e,0x00,0x6b,0x07,0x80,0x0f,0x95, + 0xf6,0x00,0xff,0x77,0x01,0x01,0x03,0x01,0x03,0x00, + 0x03,0x7f,0x02,0x7e,0x01,0x7d,0x00,0x7e,0xff,0x7d, + 0xfe,0x7e,0xfd,0x7f,0xfd,0x00,0xfd,0x01,0xff,0x01, + 0xff,0x02,0x11,0xfc,0x10,0x92,0xff,0x02,0xfd,0x01, + 0xfe,0x00,0xfd,0x7f,0xfe,0x7d,0xff,0x7b,0x00,0x7b, + 0x01,0x7c,0x02,0x7e,0x03,0x7f,0x01,0x00,0x03,0x01, + 0x02,0x02,0x01,0x03,0x00,0x01,0xff,0x03,0xfe,0x02, + 0xfd,0x01,0xff,0x00,0xfd,0x7f,0xfe,0x7e,0xff,0x7d, + 0x10,0xf9,0x11,0x95,0xf6,0x6b,0xfc,0x95,0x0e,0x00, + 0x03,0xeb,0x08,0x95,0xfd,0x7f,0xff,0x7e,0x00,0x7e, + 0x01,0x7e,0x02,0x7f,0x04,0x7f,0x03,0x7f,0x02,0x7e, + 0x01,0x7e,0x00,0x7d,0xff,0x7e,0xff,0x7f,0xfd,0x7f, + 0xfc,0x00,0xfd,0x01,0xff,0x01,0xff,0x02,0x00,0x03, + 0x01,0x02,0x02,0x02,0x03,0x01,0x04,0x01,0x02,0x01, + 0x01,0x02,0x00,0x02,0xff,0x02,0xfd,0x01,0xfc,0x00, + 0x0c,0xeb,0x10,0x8e,0xff,0x7d,0xfe,0x7e,0xfd,0x7f, + 0xff,0x00,0xfd,0x01,0xfe,0x02,0xff,0x03,0x00,0x01, + 0x01,0x03,0x02,0x02,0x03,0x01,0x01,0x00,0x03,0x7f, + 0x02,0x7e,0x01,0x7c,0x00,0x7b,0xff,0x7b,0xfe,0x7d, + 0xfd,0x7f,0xfe,0x00,0xfd,0x01,0xff,0x02,0x10,0xfd, + 0x05,0x8e,0xff,0x7f,0x01,0x7f,0x01,0x01,0xff,0x01, + 0x00,0xf4,0xff,0x7f,0x01,0x7f,0x01,0x01,0xff,0x01, + 0x05,0xfe,0x05,0x8e,0xff,0x7f,0x01,0x7f,0x01,0x01, + 0xff,0x01,0x01,0xf3,0xff,0x7f,0xff,0x01,0x01,0x01, + 0x01,0x7f,0x00,0x7e,0xff,0x7e,0xff,0x7f,0x06,0x84, + 0x14,0x92,0xf0,0x77,0x10,0x77,0x04,0x80,0x04,0x8c, + 0x12,0x00,0xee,0xfa,0x12,0x00,0x04,0xfa,0x04,0x92, + 0x10,0x77,0xf0,0x77,0x14,0x80,0x03,0x90,0x00,0x01, + 0x01,0x02,0x01,0x01,0x02,0x01,0x04,0x00,0x02,0x7f, + 0x01,0x7f,0x01,0x7e,0x00,0x7e,0xff,0x7e,0xff,0x7f, + 0xfc,0x7e,0x00,0x7d,0x00,0xfb,0xff,0x7f,0x01,0x7f, + 0x01,0x01,0xff,0x01,0x09,0xfe,0x12,0x8d,0xff,0x02, + 0xfe,0x01,0xfd,0x00,0xfe,0x7f,0xff,0x7f,0xff,0x7d, + 0x00,0x7d,0x01,0x7e,0x02,0x7f,0x03,0x00,0x02,0x01, + 0x01,0x02,0xfb,0x88,0xfe,0x7e,0xff,0x7d,0x00,0x7d, + 0x01,0x7e,0x01,0x7f,0x07,0x8b,0xff,0x78,0x00,0x7e, + 0x02,0x7f,0x02,0x00,0x02,0x02,0x01,0x03,0x00,0x02, + 0xff,0x03,0xff,0x02,0xfe,0x02,0xfe,0x01,0xfd,0x01, + 0xfd,0x00,0xfd,0x7f,0xfe,0x7f,0xfe,0x7e,0xff,0x7e, + 0xff,0x7d,0x00,0x7d,0x01,0x7d,0x01,0x7e,0x02,0x7e, + 0x02,0x7f,0x03,0x7f,0x03,0x00,0x03,0x01,0x02,0x01, + 0x01,0x01,0xfe,0x8d,0xff,0x78,0x00,0x7e,0x01,0x7f, + 0x08,0xfb,0x09,0x95,0xf8,0x6b,0x08,0x95,0x08,0x6b, + 0xf3,0x87,0x0a,0x00,0x04,0xf9,0x04,0x95,0x00,0x6b, + 0x00,0x95,0x09,0x00,0x03,0x7f,0x01,0x7f,0x01,0x7e, + 0x00,0x7e,0xff,0x7e,0xff,0x7f,0xfd,0x7f,0xf7,0x80, + 0x09,0x00,0x03,0x7f,0x01,0x7f,0x01,0x7e,0x00,0x7d, + 0xff,0x7e,0xff,0x7f,0xfd,0x7f,0xf7,0x00,0x11,0x80, + 0x12,0x90,0xff,0x02,0xfe,0x02,0xfe,0x01,0xfc,0x00, + 0xfe,0x7f,0xfe,0x7e,0xff,0x7e,0xff,0x7d,0x00,0x7b, + 0x01,0x7d,0x01,0x7e,0x02,0x7e,0x02,0x7f,0x04,0x00, + 0x02,0x01,0x02,0x02,0x01,0x02,0x03,0xfb,0x04,0x95, + 0x00,0x6b,0x00,0x95,0x07,0x00,0x03,0x7f,0x02,0x7e, + 0x01,0x7e,0x01,0x7d,0x00,0x7b,0xff,0x7d,0xff,0x7e, + 0xfe,0x7e,0xfd,0x7f,0xf9,0x00,0x11,0x80,0x04,0x95, + 0x00,0x6b,0x00,0x95,0x0d,0x00,0xf3,0xf6,0x08,0x00, + 0xf8,0xf5,0x0d,0x00,0x02,0x80,0x04,0x95,0x00,0x6b, + 0x00,0x95,0x0d,0x00,0xf3,0xf6,0x08,0x00,0x06,0xf5, + 0x12,0x90,0xff,0x02,0xfe,0x02,0xfe,0x01,0xfc,0x00, + 0xfe,0x7f,0xfe,0x7e,0xff,0x7e,0xff,0x7d,0x00,0x7b, + 0x01,0x7d,0x01,0x7e,0x02,0x7e,0x02,0x7f,0x04,0x00, + 0x02,0x01,0x02,0x02,0x01,0x02,0x00,0x03,0xfb,0x80, + 0x05,0x00,0x03,0xf8,0x04,0x95,0x00,0x6b,0x0e,0x95, + 0x00,0x6b,0xf2,0x8b,0x0e,0x00,0x04,0xf5,0x04,0x95, + 0x00,0x6b,0x04,0x80,0x0c,0x95,0x00,0x70,0xff,0x7d, + 0xff,0x7f,0xfe,0x7f,0xfe,0x00,0xfe,0x01,0xff,0x01, + 0xff,0x03,0x00,0x02,0x0e,0xf9,0x04,0x95,0x00,0x6b, + 0x0e,0x95,0xf2,0x72,0x05,0x85,0x09,0x74,0x03,0x80, + 0x04,0x95,0x00,0x6b,0x00,0x80,0x0c,0x00,0x01,0x80, + 0x04,0x95,0x00,0x6b,0x00,0x95,0x08,0x6b,0x08,0x95, + 0xf8,0x6b,0x08,0x95,0x00,0x6b,0x04,0x80,0x04,0x95, + 0x00,0x6b,0x00,0x95,0x0e,0x6b,0x00,0x95,0x00,0x6b, + 0x04,0x80,0x09,0x95,0xfe,0x7f,0xfe,0x7e,0xff,0x7e, + 0xff,0x7d,0x00,0x7b,0x01,0x7d,0x01,0x7e,0x02,0x7e, + 0x02,0x7f,0x04,0x00,0x02,0x01,0x02,0x02,0x01,0x02, + 0x01,0x03,0x00,0x05,0xff,0x03,0xff,0x02,0xfe,0x02, + 0xfe,0x01,0xfc,0x00,0x0d,0xeb,0x04,0x95,0x00,0x6b, + 0x00,0x95,0x09,0x00,0x03,0x7f,0x01,0x7f,0x01,0x7e, + 0x00,0x7d,0xff,0x7e,0xff,0x7f,0xfd,0x7f,0xf7,0x00, + 0x11,0xf6,0x09,0x95,0xfe,0x7f,0xfe,0x7e,0xff,0x7e, + 0xff,0x7d,0x00,0x7b,0x01,0x7d,0x01,0x7e,0x02,0x7e, + 0x02,0x7f,0x04,0x00,0x02,0x01,0x02,0x02,0x01,0x02, + 0x01,0x03,0x00,0x05,0xff,0x03,0xff,0x02,0xfe,0x02, + 0xfe,0x01,0xfc,0x00,0x03,0xef,0x06,0x7a,0x04,0x82, + 0x04,0x95,0x00,0x6b,0x00,0x95,0x09,0x00,0x03,0x7f, + 0x01,0x7f,0x01,0x7e,0x00,0x7e,0xff,0x7e,0xff,0x7f, + 0xfd,0x7f,0xf7,0x00,0x07,0x80,0x07,0x75,0x03,0x80, + 0x11,0x92,0xfe,0x02,0xfd,0x01,0xfc,0x00,0xfd,0x7f, + 0xfe,0x7e,0x00,0x7e,0x01,0x7e,0x01,0x7f,0x02,0x7f, + 0x06,0x7e,0x02,0x7f,0x01,0x7f,0x01,0x7e,0x00,0x7d, + 0xfe,0x7e,0xfd,0x7f,0xfc,0x00,0xfd,0x01,0xfe,0x02, + 0x11,0xfd,0x08,0x95,0x00,0x6b,0xf9,0x95,0x0e,0x00, + 0x01,0xeb,0x04,0x95,0x00,0x71,0x01,0x7d,0x02,0x7e, + 0x03,0x7f,0x02,0x00,0x03,0x01,0x02,0x02,0x01,0x03, + 0x00,0x0f,0x04,0xeb,0x01,0x95,0x08,0x6b,0x08,0x95, + 0xf8,0x6b,0x09,0x80,0x02,0x95,0x05,0x6b,0x05,0x95, + 0xfb,0x6b,0x05,0x95,0x05,0x6b,0x05,0x95,0xfb,0x6b, + 0x07,0x80,0x03,0x95,0x0e,0x6b,0x00,0x95,0xf2,0x6b, + 0x11,0x80,0x01,0x95,0x08,0x76,0x00,0x75,0x08,0x95, + 0xf8,0x76,0x09,0xf5,0x11,0x95,0xf2,0x6b,0x00,0x95, + 0x0e,0x00,0xf2,0xeb,0x0e,0x00,0x03,0x80,0x03,0x93, + 0x00,0x6c,0x01,0x94,0x00,0x6c,0xff,0x94,0x05,0x00, + 0xfb,0xec,0x05,0x00,0x02,0x81,0x00,0x95,0x0e,0x68, + 0x00,0x83,0x06,0x93,0x00,0x6c,0x01,0x94,0x00,0x6c, + 0xfb,0x94,0x05,0x00,0xfb,0xec,0x05,0x00,0x03,0x81, + 0x03,0x87,0x08,0x05,0x08,0x7b,0xf0,0x80,0x08,0x04, + 0x08,0x7c,0x03,0xf9,0x01,0x80,0x10,0x00,0x01,0x80, + 0x06,0x95,0xff,0x7f,0xff,0x7e,0x00,0x7e,0x01,0x7f, + 0x01,0x01,0xff,0x01,0x05,0xef,0x0f,0x8e,0x00,0x72, + 0x00,0x8b,0xfe,0x02,0xfe,0x01,0xfd,0x00,0xfe,0x7f, + 0xfe,0x7e,0xff,0x7d,0x00,0x7e,0x01,0x7d,0x02,0x7e, + 0x02,0x7f,0x03,0x00,0x02,0x01,0x02,0x02,0x04,0xfd, + 0x04,0x95,0x00,0x6b,0x00,0x8b,0x02,0x02,0x02,0x01, + 0x03,0x00,0x02,0x7f,0x02,0x7e,0x01,0x7d,0x00,0x7e, + 0xff,0x7d,0xfe,0x7e,0xfe,0x7f,0xfd,0x00,0xfe,0x01, + 0xfe,0x02,0x0f,0xfd,0x0f,0x8b,0xfe,0x02,0xfe,0x01, + 0xfd,0x00,0xfe,0x7f,0xfe,0x7e,0xff,0x7d,0x00,0x7e, + 0x01,0x7d,0x02,0x7e,0x02,0x7f,0x03,0x00,0x02,0x01, + 0x02,0x02,0x03,0xfd,0x0f,0x95,0x00,0x6b,0x00,0x8b, + 0xfe,0x02,0xfe,0x01,0xfd,0x00,0xfe,0x7f,0xfe,0x7e, + 0xff,0x7d,0x00,0x7e,0x01,0x7d,0x02,0x7e,0x02,0x7f, + 0x03,0x00,0x02,0x01,0x02,0x02,0x04,0xfd,0x03,0x88, + 0x0c,0x00,0x00,0x02,0xff,0x02,0xff,0x01,0xfe,0x01, + 0xfd,0x00,0xfe,0x7f,0xfe,0x7e,0xff,0x7d,0x00,0x7e, + 0x01,0x7d,0x02,0x7e,0x02,0x7f,0x03,0x00,0x02,0x01, + 0x02,0x02,0x03,0xfd,0x0a,0x95,0xfe,0x00,0xfe,0x7f, + 0xff,0x7d,0x00,0x6f,0xfd,0x8e,0x07,0x00,0x03,0xf2, + 0x0f,0x8e,0x00,0x70,0xff,0x7d,0xff,0x7f,0xfe,0x7f, + 0xfd,0x00,0xfe,0x01,0x09,0x91,0xfe,0x02,0xfe,0x01, + 0xfd,0x00,0xfe,0x7f,0xfe,0x7e,0xff,0x7d,0x00,0x7e, + 0x01,0x7d,0x02,0x7e,0x02,0x7f,0x03,0x00,0x02,0x01, + 0x02,0x02,0x04,0xfd,0x04,0x95,0x00,0x6b,0x00,0x8a, + 0x03,0x03,0x02,0x01,0x03,0x00,0x02,0x7f,0x01,0x7d, + 0x00,0x76,0x04,0x80,0x03,0x95,0x01,0x7f,0x01,0x01, + 0xff,0x01,0xff,0x7f,0x01,0xf9,0x00,0x72,0x04,0x80, + 0x05,0x95,0x01,0x7f,0x01,0x01,0xff,0x01,0xff,0x7f, + 0x01,0xf9,0x00,0x6f,0xff,0x7d,0xfe,0x7f,0xfe,0x00, + 0x09,0x87,0x04,0x95,0x00,0x6b,0x0a,0x8e,0xf6,0x76, + 0x04,0x84,0x07,0x78,0x02,0x80,0x04,0x95,0x00,0x6b, + 0x04,0x80,0x04,0x8e,0x00,0x72,0x00,0x8a,0x03,0x03, + 0x02,0x01,0x03,0x00,0x02,0x7f,0x01,0x7d,0x00,0x76, + 0x00,0x8a,0x03,0x03,0x02,0x01,0x03,0x00,0x02,0x7f, + 0x01,0x7d,0x00,0x76,0x04,0x80,0x04,0x8e,0x00,0x72, + 0x00,0x8a,0x03,0x03,0x02,0x01,0x03,0x00,0x02,0x7f, + 0x01,0x7d,0x00,0x76,0x04,0x80,0x08,0x8e,0xfe,0x7f, + 0xfe,0x7e,0xff,0x7d,0x00,0x7e,0x01,0x7d,0x02,0x7e, + 0x02,0x7f,0x03,0x00,0x02,0x01,0x02,0x02,0x01,0x03, + 0x00,0x02,0xff,0x03,0xfe,0x02,0xfe,0x01,0xfd,0x00, + 0x0b,0xf2,0x04,0x8e,0x00,0x6b,0x00,0x92,0x02,0x02, + 0x02,0x01,0x03,0x00,0x02,0x7f,0x02,0x7e,0x01,0x7d, + 0x00,0x7e,0xff,0x7d,0xfe,0x7e,0xfe,0x7f,0xfd,0x00, + 0xfe,0x01,0xfe,0x02,0x0f,0xfd,0x0f,0x8e,0x00,0x6b, + 0x00,0x92,0xfe,0x02,0xfe,0x01,0xfd,0x00,0xfe,0x7f, + 0xfe,0x7e,0xff,0x7d,0x00,0x7e,0x01,0x7d,0x02,0x7e, + 0x02,0x7f,0x03,0x00,0x02,0x01,0x02,0x02,0x04,0xfd, + 0x04,0x8e,0x00,0x72,0x00,0x88,0x01,0x03,0x02,0x02, + 0x02,0x01,0x03,0x00,0x01,0xf2,0x0e,0x8b,0xff,0x02, + 0xfd,0x01,0xfd,0x00,0xfd,0x7f,0xff,0x7e,0x01,0x7e, + 0x02,0x7f,0x05,0x7f,0x02,0x7f,0x01,0x7e,0x00,0x7f, + 0xff,0x7e,0xfd,0x7f,0xfd,0x00,0xfd,0x01,0xff,0x02, + 0x0e,0xfd,0x05,0x95,0x00,0x6f,0x01,0x7d,0x02,0x7f, + 0x02,0x00,0xf8,0x8e,0x07,0x00,0x03,0xf2,0x04,0x8e, + 0x00,0x76,0x01,0x7d,0x02,0x7f,0x03,0x00,0x02,0x01, + 0x03,0x03,0x00,0x8a,0x00,0x72,0x04,0x80,0x02,0x8e, + 0x06,0x72,0x06,0x8e,0xfa,0x72,0x08,0x80,0x03,0x8e, + 0x04,0x72,0x04,0x8e,0xfc,0x72,0x04,0x8e,0x04,0x72, + 0x04,0x8e,0xfc,0x72,0x07,0x80,0x03,0x8e,0x0b,0x72, + 0x00,0x8e,0xf5,0x72,0x0e,0x80,0x02,0x8e,0x06,0x72, + 0x06,0x8e,0xfa,0x72,0xfe,0x7c,0xfe,0x7e,0xfe,0x7f, + 0xff,0x00,0x0f,0x87,0x0e,0x8e,0xf5,0x72,0x00,0x8e, + 0x0b,0x00,0xf5,0xf2,0x0b,0x00,0x03,0x80,0x09,0x99, + 0xfe,0x7f,0xff,0x7f,0xff,0x7e,0x00,0x7e,0x01,0x7e, + 0x01,0x7f,0x01,0x7e,0x00,0x7e,0xfe,0x7e,0x01,0x8e, + 0xff,0x7e,0x00,0x7e,0x01,0x7e,0x01,0x7f,0x01,0x7e, + 0x00,0x7e,0xff,0x7e,0xfc,0x7e,0x04,0x7e,0x01,0x7e, + 0x00,0x7e,0xff,0x7e,0xff,0x7f,0xff,0x7e,0x00,0x7e, + 0x01,0x7e,0xff,0x8e,0x02,0x7e,0x00,0x7e,0xff,0x7e, + 0xff,0x7f,0xff,0x7e,0x00,0x7e,0x01,0x7e,0x01,0x7f, + 0x02,0x7f,0x05,0x87,0x04,0x95,0x00,0x77,0x00,0xfd, + 0x00,0x77,0x04,0x80,0x05,0x99,0x02,0x7f,0x01,0x7f, + 0x01,0x7e,0x00,0x7e,0xff,0x7e,0xff,0x7f,0xff,0x7e, + 0x00,0x7e,0x02,0x7e,0xff,0x8e,0x01,0x7e,0x00,0x7e, + 0xff,0x7e,0xff,0x7f,0xff,0x7e,0x00,0x7e,0x01,0x7e, + 0x04,0x7e,0xfc,0x7e,0xff,0x7e,0x00,0x7e,0x01,0x7e, + 0x01,0x7f,0x01,0x7e,0x00,0x7e,0xff,0x7e,0x01,0x8e, + 0xfe,0x7e,0x00,0x7e,0x01,0x7e,0x01,0x7f,0x01,0x7e, + 0x00,0x7e,0xff,0x7e,0xff,0x7f,0xfe,0x7f,0x09,0x87, + 0x03,0x86,0x00,0x02,0x01,0x03,0x02,0x01,0x02,0x00, + 0x02,0x7f,0x04,0x7d,0x02,0x7f,0x02,0x00,0x02,0x01, + 0x01,0x02,0xee,0xfe,0x01,0x02,0x02,0x01,0x02,0x00, + 0x02,0x7f,0x04,0x7d,0x02,0x7f,0x02,0x00,0x02,0x01, + 0x01,0x03,0x00,0x02,0x03,0xf4,0x10,0x80,0x03,0x80, + 0x07,0x15,0x08,0x6b,0xfe,0x85,0xf5,0x00,0x10,0xfb, + 0x0d,0x95,0xf6,0x00,0x00,0x6b,0x0a,0x00,0x02,0x02, + 0x00,0x08,0xfe,0x02,0xf6,0x00,0x0e,0xf4,0x03,0x80, + 0x00,0x15,0x0a,0x00,0x02,0x7e,0x00,0x7e,0x00,0x7d, + 0x00,0x7e,0xfe,0x7f,0xf6,0x00,0x0a,0x80,0x02,0x7e, + 0x01,0x7e,0x00,0x7d,0xff,0x7d,0xfe,0x7f,0xf6,0x00, + 0x10,0x80,0x03,0x80,0x00,0x15,0x0c,0x00,0xff,0x7e, + 0x03,0xed,0x03,0xfd,0x00,0x03,0x02,0x00,0x00,0x12, + 0x02,0x03,0x0a,0x00,0x00,0x6b,0x02,0x00,0x00,0x7d, + 0xfe,0x83,0xf4,0x00,0x11,0x80,0x0f,0x80,0xf4,0x00, + 0x00,0x15,0x0c,0x00,0xff,0xf6,0xf5,0x00,0x0f,0xf5, + 0x04,0x95,0x07,0x76,0x00,0x0a,0x07,0x80,0xf9,0x76, + 0x00,0x75,0xf8,0x80,0x07,0x0c,0x09,0xf4,0xf9,0x0c, + 0x09,0xf4,0x03,0x92,0x02,0x03,0x07,0x00,0x03,0x7d, + 0x00,0x7b,0xfc,0x7e,0x04,0x7d,0x00,0x7a,0xfd,0x7e, + 0xf9,0x00,0xfe,0x02,0x06,0x89,0x02,0x00,0x06,0xf5, + 0x03,0x95,0x00,0x6b,0x0c,0x15,0x00,0x6b,0x02,0x80, + 0x03,0x95,0x00,0x6b,0x0c,0x15,0x00,0x6b,0xf8,0x96, + 0x03,0x00,0x07,0xea,0x03,0x80,0x00,0x15,0x0c,0x80, + 0xf7,0x76,0xfd,0x00,0x03,0x80,0x0a,0x75,0x03,0x80, + 0x03,0x80,0x07,0x13,0x02,0x02,0x03,0x00,0x00,0x6b, + 0x02,0x80,0x03,0x80,0x00,0x15,0x09,0x6b,0x09,0x15, + 0x00,0x6b,0x03,0x80,0x03,0x80,0x00,0x15,0x00,0xf6, + 0x0d,0x00,0x00,0x8a,0x00,0x6b,0x03,0x80,0x07,0x80, + 0xfd,0x00,0xff,0x03,0x00,0x04,0x00,0x07,0x00,0x04, + 0x01,0x02,0x03,0x01,0x06,0x00,0x03,0x7f,0x01,0x7e, + 0x01,0x7c,0x00,0x79,0xff,0x7c,0xff,0x7d,0xfd,0x00, + 0xfa,0x00,0x0e,0x80,0x03,0x80,0x00,0x15,0x0c,0x00, + 0x00,0x6b,0x02,0x80,0x03,0x80,0x00,0x15,0x0a,0x00, + 0x02,0x7f,0x01,0x7d,0x00,0x7b,0xff,0x7e,0xfe,0x7f, + 0xf6,0x00,0x10,0xf7,0x11,0x8f,0xff,0x03,0xff,0x02, + 0xfe,0x01,0xfa,0x00,0xfd,0x7f,0xff,0x7e,0x00,0x7c, + 0x00,0x79,0x00,0x7b,0x01,0x7e,0x03,0x00,0x06,0x00, + 0x02,0x00,0x01,0x03,0x01,0x02,0x03,0xfb,0x03,0x95, + 0x0c,0x00,0xfa,0x80,0x00,0x6b,0x09,0x80,0x03,0x95, + 0x00,0x77,0x06,0x7a,0x06,0x06,0x00,0x09,0xfa,0xf1, + 0xfa,0x7a,0x0e,0x80,0x03,0x87,0x00,0x0b,0x02,0x02, + 0x03,0x00,0x02,0x7e,0x01,0x02,0x04,0x00,0x02,0x7e, + 0x00,0x75,0xfe,0x7e,0xfc,0x00,0xff,0x01,0xfe,0x7f, + 0xfd,0x00,0xfe,0x02,0x07,0x8e,0x00,0x6b,0x09,0x80, + 0x03,0x80,0x0e,0x15,0xf2,0x80,0x0e,0x6b,0x03,0x80, + 0x03,0x95,0x00,0x6b,0x0e,0x00,0x00,0x7d,0xfe,0x98, + 0x00,0x6b,0x05,0x80,0x03,0x95,0x00,0x75,0x02,0x7d, + 0x0a,0x00,0x00,0x8e,0x00,0x6b,0x02,0x80,0x03,0x95, + 0x00,0x6b,0x10,0x00,0x00,0x15,0xf8,0x80,0x00,0x6b, + 0x0a,0x80,0x03,0x95,0x00,0x6b,0x10,0x00,0x00,0x15, + 0xf8,0x80,0x00,0x6b,0x0a,0x00,0x00,0x7d,0x02,0x83, + 0x10,0x80,0x03,0x95,0x00,0x6b,0x09,0x00,0x03,0x02, + 0x00,0x08,0xfd,0x02,0xf7,0x00,0x0e,0x89,0x00,0x6b, + 0x03,0x80,0x03,0x95,0x00,0x6b,0x09,0x00,0x03,0x02, + 0x00,0x08,0xfd,0x02,0xf7,0x00,0x0e,0xf4,0x03,0x92, + 0x02,0x03,0x07,0x00,0x03,0x7d,0x00,0x70,0xfd,0x7e, + 0xf9,0x00,0xfe,0x02,0x03,0x89,0x09,0x00,0x02,0xf5, + 0x03,0x80,0x00,0x15,0x00,0xf5,0x07,0x00,0x00,0x08, + 0x02,0x03,0x06,0x00,0x02,0x7d,0x00,0x70,0xfe,0x7e, + 0xfa,0x00,0xfe,0x02,0x00,0x08,0x0c,0xf6,0x0f,0x80, + 0x00,0x15,0xf6,0x00,0xfe,0x7d,0x00,0x79,0x02,0x7e, + 0x0a,0x00,0xf4,0xf7,0x07,0x09,0x07,0xf7,0x03,0x8c, + 0x01,0x02,0x01,0x01,0x05,0x00,0x02,0x7f,0x01,0x7e, + 0x00,0x74,0x00,0x86,0xff,0x01,0xfe,0x01,0xfb,0x00, + 0xff,0x7f,0xff,0x7f,0x00,0x7c,0x01,0x7e,0x01,0x00, + 0x05,0x00,0x02,0x00,0x01,0x02,0x03,0xfe,0x04,0x8e, + 0x02,0x01,0x04,0x00,0x02,0x7f,0x01,0x7e,0x00,0x77, + 0xff,0x7e,0xfe,0x7f,0xfc,0x00,0xfe,0x01,0xff,0x02, + 0x00,0x09,0x01,0x02,0x02,0x02,0x03,0x01,0x02,0x01, + 0x01,0x01,0x01,0x02,0x02,0xeb,0x03,0x80,0x00,0x15, + 0x03,0x00,0x02,0x7e,0x00,0x7b,0xfe,0x7e,0xfd,0x00, + 0x03,0x80,0x04,0x00,0x03,0x7e,0x00,0x78,0xfd,0x7e, + 0xf9,0x00,0x0c,0x80,0x03,0x8c,0x02,0x02,0x02,0x01, + 0x03,0x00,0x02,0x7f,0x01,0x7d,0xfe,0x7e,0xf9,0x7d, + 0xff,0x7e,0x00,0x7d,0x03,0x7f,0x02,0x00,0x03,0x01, + 0x02,0x01,0x02,0xfe,0x0d,0x8c,0xff,0x02,0xfe,0x01, + 0xfc,0x00,0xfe,0x7f,0xff,0x7e,0x00,0x77,0x01,0x7e, + 0x02,0x7f,0x04,0x00,0x02,0x01,0x01,0x02,0x00,0x0f, + 0xff,0x02,0xfe,0x01,0xf9,0x00,0x0c,0xeb,0x03,0x88, + 0x0a,0x00,0x00,0x02,0x00,0x03,0xfe,0x02,0xfa,0x00, + 0xff,0x7e,0xff,0x7d,0x00,0x7b,0x01,0x7c,0x01,0x7f, + 0x06,0x00,0x02,0x02,0x03,0xfe,0x03,0x8f,0x06,0x77, + 0x06,0x09,0xfa,0x80,0x00,0x71,0xff,0x87,0xfb,0x79, + 0x07,0x87,0x05,0x79,0x02,0x80,0x03,0x8d,0x02,0x02, + 0x06,0x00,0x02,0x7e,0x00,0x7d,0xfc,0x7d,0x04,0x7e, + 0x00,0x7d,0xfe,0x7e,0xfa,0x00,0xfe,0x02,0x04,0x85, + 0x02,0x00,0x06,0xf9,0x03,0x8f,0x00,0x73,0x01,0x7e, + 0x07,0x00,0x02,0x02,0x00,0x0d,0x00,0xf3,0x01,0x7e, + 0x03,0x80,0x03,0x8f,0x00,0x73,0x01,0x7e,0x07,0x00, + 0x02,0x02,0x00,0x0d,0x00,0xf3,0x01,0x7e,0xf8,0x90, + 0x03,0x00,0x08,0xf0,0x03,0x80,0x00,0x15,0x00,0xf3, + 0x02,0x00,0x06,0x07,0xfa,0xf9,0x07,0x78,0x03,0x80, + 0x03,0x80,0x04,0x0c,0x02,0x03,0x04,0x00,0x00,0x71, + 0x02,0x80,0x03,0x80,0x00,0x0f,0x06,0x77,0x06,0x09, + 0x00,0x71,0x02,0x80,0x03,0x80,0x00,0x0f,0x0a,0xf1, + 0x00,0x0f,0xf6,0xf8,0x0a,0x00,0x02,0xf9,0x05,0x80, + 0xff,0x01,0xff,0x04,0x00,0x05,0x01,0x03,0x01,0x02, + 0x06,0x00,0x02,0x7e,0x00,0x7d,0x00,0x7b,0x00,0x7c, + 0xfe,0x7f,0xfa,0x00,0x0b,0x80,0x03,0x80,0x00,0x0f, + 0x00,0xfb,0x01,0x03,0x01,0x02,0x05,0x00,0x02,0x7e, + 0x01,0x7d,0x00,0x76,0x03,0x80,0x10,0x80,0x10,0x80, + 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, + 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, + 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, + 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, + 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, + 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, + 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, + 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, + 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, + 0x10,0x80,0x0a,0x8f,0x02,0x7f,0x01,0x7e,0x00,0x76, + 0xff,0x7f,0xfe,0x7f,0xfb,0x00,0xff,0x01,0xff,0x01, + 0x00,0x0a,0x01,0x02,0x01,0x01,0x05,0x00,0xf9,0x80, + 0x00,0x6b,0x0c,0x86,0x0d,0x8a,0xff,0x03,0xfe,0x02, + 0xfb,0x00,0xff,0x7e,0xff,0x7d,0x00,0x7b,0x01,0x7c, + 0x01,0x7f,0x05,0x00,0x02,0x01,0x01,0x03,0x03,0xfc, + 0x03,0x80,0x00,0x0f,0x00,0xfb,0x01,0x03,0x01,0x02, + 0x04,0x00,0x01,0x7e,0x01,0x7d,0x00,0x76,0x00,0x8a, + 0x01,0x03,0x02,0x02,0x03,0x00,0x02,0x7e,0x01,0x7d, + 0x00,0x76,0x03,0x80,0x03,0x8f,0x00,0x74,0x01,0x7e, + 0x02,0x7f,0x04,0x00,0x02,0x01,0x01,0x01,0x00,0x8d, + 0x00,0x6e,0xff,0x7e,0xfe,0x7f,0xfb,0x00,0xfe,0x01, + 0x0c,0x85,0x03,0x8d,0x01,0x02,0x03,0x00,0x02,0x7e, + 0x01,0x02,0x03,0x00,0x02,0x7e,0x00,0x74,0xfe,0x7f, + 0xfd,0x00,0xff,0x01,0xfe,0x7f,0xfd,0x00,0xff,0x01, + 0x00,0x0c,0x06,0x82,0x00,0x6b,0x08,0x86,0x03,0x80, + 0x0a,0x0f,0xf6,0x80,0x0a,0x71,0x03,0x80,0x03,0x8f, + 0x00,0x73,0x01,0x7e,0x07,0x00,0x02,0x02,0x00,0x0d, + 0x00,0xf3,0x01,0x7e,0x00,0x7e,0x03,0x82,0x03,0x8f, + 0x00,0x79,0x02,0x7e,0x08,0x00,0x00,0x89,0x00,0x71, + 0x02,0x80,0x03,0x8f,0x00,0x73,0x01,0x7e,0x03,0x00, + 0x02,0x02,0x00,0x0d,0x00,0xf3,0x01,0x7e,0x03,0x00, + 0x02,0x02,0x00,0x0d,0x00,0xf3,0x01,0x7e,0x03,0x80, + 0x03,0x8f,0x00,0x73,0x01,0x7e,0x03,0x00,0x02,0x02, + 0x00,0x0d,0x00,0xf3,0x01,0x7e,0x03,0x00,0x02,0x02, + 0x00,0x0d,0x00,0xf3,0x01,0x7e,0x00,0x7e,0x03,0x82, + 0x03,0x8d,0x00,0x02,0x02,0x00,0x00,0x71,0x08,0x00, + 0x02,0x02,0x00,0x06,0xfe,0x02,0xf8,0x00,0x0c,0xf6, + 0x03,0x8f,0x00,0x71,0x07,0x00,0x02,0x02,0x00,0x06, + 0xfe,0x02,0xf9,0x00,0x0c,0x85,0x00,0x71,0x02,0x80, + 0x03,0x8f,0x00,0x71,0x07,0x00,0x03,0x02,0x00,0x06, + 0xfd,0x02,0xf9,0x00,0x0c,0xf6,0x03,0x8d,0x02,0x02, + 0x06,0x00,0x02,0x7e,0x00,0x75,0xfe,0x7e,0xfa,0x00, + 0xfe,0x02,0x04,0x85,0x06,0x00,0x02,0xf9,0x03,0x80, + 0x00,0x0f,0x00,0xf8,0x04,0x00,0x00,0x06,0x02,0x02, + 0x04,0x00,0x02,0x7e,0x00,0x75,0xfe,0x7e,0xfc,0x00, + 0xfe,0x02,0x00,0x05,0x0a,0xf9,0x0d,0x80,0x00,0x0f, + 0xf7,0x00,0xff,0x7e,0x00,0x7b,0x01,0x7e,0x09,0x00, + 0xf6,0xfa,0x04,0x06,0x08,0xfa + }; + + //------------------------------------------------------------------------- + gsv_text::gsv_text() : + m_x(0.0), + m_y(0.0), + m_start_x(0.0), + m_width(10.0), + m_height(0.0), + m_space(0.0), + m_line_space(0.0), + m_text(m_chr), + m_text_buf(), + m_cur_chr(m_chr), + m_font(gsv_default_font), + m_loaded_font(), + m_status(initial), + m_big_endian(false), + m_flip(false) + { + m_chr[0] = m_chr[1] = 0; + + int t = 1; + if(*(char*)&t == 0) m_big_endian = true; + } + + //------------------------------------------------------------------------- + void gsv_text::font(const void* font) + { + m_font = font; + if(m_font == 0) m_font = &m_loaded_font[0]; + } + + //------------------------------------------------------------------------- + void gsv_text::size(double height, double width) + { + m_height = height; + m_width = width; + } + + //------------------------------------------------------------------------- + void gsv_text::space(double space) + { + m_space = space; + } + + //------------------------------------------------------------------------- + void gsv_text::line_space(double line_space) + { + m_line_space = line_space; + } + + //------------------------------------------------------------------------- + void gsv_text::start_point(double x, double y) + { + m_x = m_start_x = x; + m_y = y; + //if(m_flip) m_y += m_height; + } + + //------------------------------------------------------------------------- + void gsv_text::load_font(const char* file) + { + m_loaded_font.resize(0); + FILE* fd = fopen(file, "rb"); + if(fd) + { + unsigned len; + + fseek(fd, 0l, SEEK_END); + len = ftell(fd); + fseek(fd, 0l, SEEK_SET); + if(len > 0) + { + m_loaded_font.resize(len); + fread(&m_loaded_font[0], 1, len, fd); + m_font = &m_loaded_font[0]; + } + fclose(fd); + } + } + + //------------------------------------------------------------------------- + void gsv_text::text(const char* text) + { + if(text == 0) + { + m_chr[0] = 0; + m_text = m_chr; + return; + } + unsigned new_size = strlen(text) + 1; + if(new_size > m_text_buf.size()) + { + m_text_buf.resize(new_size); + } + memcpy(&m_text_buf[0], text, new_size); + m_text = &m_text_buf[0]; + } + + //------------------------------------------------------------------------- + void gsv_text::rewind(unsigned) + { + m_status = initial; + if(m_font == 0) return; + + m_indices = (int8u*)m_font; + double base_height = value(m_indices + 4); + m_indices += value(m_indices); + m_glyphs = (int8*)(m_indices + 257*2); + m_h = m_height / base_height; + m_w = (m_width == 0.0) ? m_h : m_width / base_height; + if(m_flip) m_h = -m_h; + m_cur_chr = m_text; + } + + //------------------------------------------------------------------------- + unsigned gsv_text::vertex(double* x, double* y) + { + unsigned idx; + int8 yc, yf; + int dx, dy; + bool quit = false; + + while(!quit) + { + switch(m_status) + { + case initial: + if(m_font == 0) + { + quit = true; + break; + } + m_status = next_char; + + case next_char: + if(*m_cur_chr == 0) + { + quit = true; + break; + } + idx = (*m_cur_chr++) & 0xFF; + if(idx == '\n') + { + m_x = m_start_x; + m_y -= m_flip ? -m_height - m_line_space : m_height + m_line_space; + break; + } + idx <<= 1; + m_bglyph = m_glyphs + value(m_indices + idx); + m_eglyph = m_glyphs + value(m_indices + idx + 2); + m_status = start_glyph; + + case start_glyph: + *x = m_x; + *y = m_y; + m_status = glyph; + return path_cmd_move_to; + + case glyph: + if(m_bglyph >= m_eglyph) + { + m_status = next_char; + m_x += m_space; + break; + } + dx = int(*m_bglyph++); + yf = (yc = *m_bglyph++) & 0x80; + yc <<= 1; + yc >>= 1; + dy = int(yc); + m_x += double(dx) * m_w; + m_y += double(dy) * m_h; + *x = m_x; + *y = m_y; + return yf ? path_cmd_move_to : path_cmd_line_to; + } + + } + return path_cmd_stop; + } + + //------------------------------------------------------------------------- + double gsv_text::text_width() + { + double x1, y1, x2, y2; + bounding_rect_single(*this, 0, &x1, &y1, &x2, &y2); + return x2 - x1; + } + + +} diff --git a/jni/desmume/src/android/agg/src/agg_image_filters.cpp b/jni/desmume/src/android/agg/src/agg_image_filters.cpp new file mode 100755 index 0000000..a228f25 --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_image_filters.cpp @@ -0,0 +1,107 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include "agg_image_filters.h" + + +namespace agg +{ + //-------------------------------------------------------------------- + void image_filter_lut::realloc_lut(double radius) + { + m_radius = radius; + m_diameter = uceil(radius) * 2; + m_start = -int(m_diameter / 2 - 1); + unsigned size = m_diameter << image_subpixel_shift; + if(size > m_weight_array.size()) + { + m_weight_array.resize(size); + } + } + + + + //-------------------------------------------------------------------- + // This function normalizes integer values and corrects the rounding + // errors. It doesn't do anything with the source floating point values + // (m_weight_array_dbl), it corrects only integers according to the rule + // of 1.0 which means that any sum of pixel weights must be equal to 1.0. + // So, the filter function must produce a graph of the proper shape. + //-------------------------------------------------------------------- + void image_filter_lut::normalize() + { + unsigned i; + int flip = 1; + + for(i = 0; i < image_subpixel_scale; i++) + { + for(;;) + { + int sum = 0; + unsigned j; + for(j = 0; j < m_diameter; j++) + { + sum += m_weight_array[j * image_subpixel_scale + i]; + } + + if(sum == image_filter_scale) break; + + double k = double(image_filter_scale) / double(sum); + sum = 0; + for(j = 0; j < m_diameter; j++) + { + sum += m_weight_array[j * image_subpixel_scale + i] = + iround(m_weight_array[j * image_subpixel_scale + i] * k); + } + + sum -= image_filter_scale; + int inc = (sum > 0) ? -1 : 1; + + for(j = 0; j < m_diameter && sum; j++) + { + flip ^= 1; + unsigned idx = flip ? m_diameter/2 + j/2 : m_diameter/2 - j/2; + int v = m_weight_array[idx * image_subpixel_scale + i]; + if(v < image_filter_scale) + { + m_weight_array[idx * image_subpixel_scale + i] += inc; + sum += inc; + } + } + } + } + + unsigned pivot = m_diameter << (image_subpixel_shift - 1); + + for(i = 0; i < pivot; i++) + { + m_weight_array[pivot + i] = m_weight_array[pivot - i]; + } + unsigned end = (diameter() << image_subpixel_shift) - 1; + m_weight_array[0] = m_weight_array[end]; + } + + +} + diff --git a/jni/desmume/src/android/agg/src/agg_line_aa_basics.cpp b/jni/desmume/src/android/agg/src/agg_line_aa_basics.cpp new file mode 100755 index 0000000..16c6a7b --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_line_aa_basics.cpp @@ -0,0 +1,91 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <math.h> +#include "agg_line_aa_basics.h" + +namespace agg +{ + //------------------------------------------------------------------------- + // The number of the octant is determined as a 3-bit value as follows: + // bit 0 = vertical flag + // bit 1 = sx < 0 + // bit 2 = sy < 0 + // + // [N] shows the number of the orthogonal quadrant + // <M> shows the number of the diagonal quadrant + // <1> + // [1] | [0] + // . (3)011 | 001(1) . + // . | . + // . | . + // . | . + // (2)010 .|. 000(0) + // <2> ----------.+.----------- <0> + // (6)110 . | . 100(4) + // . | . + // . | . + // . | . + // (7)111 | 101(5) + // [2] | [3] + // <3> + // 0,1,2,3,4,5,6,7 + const int8u line_parameters::s_orthogonal_quadrant[8] = { 0,0,1,1,3,3,2,2 }; + const int8u line_parameters::s_diagonal_quadrant[8] = { 0,1,2,1,0,3,2,3 }; + + + + //------------------------------------------------------------------------- + void bisectrix(const line_parameters& l1, + const line_parameters& l2, + int* x, int* y) + { + double k = double(l2.len) / double(l1.len); + double tx = l2.x2 - (l2.x1 - l1.x1) * k; + double ty = l2.y2 - (l2.y1 - l1.y1) * k; + + //All bisectrices must be on the right of the line + //If the next point is on the left (l1 => l2.2) + //then the bisectix should be rotated by 180 degrees. + if(double(l2.x2 - l2.x1) * double(l2.y1 - l1.y1) < + double(l2.y2 - l2.y1) * double(l2.x1 - l1.x1) + 100.0) + { + tx -= (tx - l2.x1) * 2.0; + ty -= (ty - l2.y1) * 2.0; + } + + // Check if the bisectrix is too short + double dx = tx - l2.x1; + double dy = ty - l2.y1; + if((int)sqrt(dx * dx + dy * dy) < line_subpixel_scale) + { + *x = (l2.x1 + l2.x1 + (l2.y1 - l1.y1) + (l2.y2 - l2.y1)) >> 1; + *y = (l2.y1 + l2.y1 - (l2.x1 - l1.x1) - (l2.x2 - l2.x1)) >> 1; + return; + } + *x = iround(tx); + *y = iround(ty); + } + +} diff --git a/jni/desmume/src/android/agg/src/agg_line_profile_aa.cpp b/jni/desmume/src/android/agg/src/agg_line_profile_aa.cpp new file mode 100755 index 0000000..a927740 --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_line_profile_aa.cpp @@ -0,0 +1,125 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include "agg_renderer_outline_aa.h" + +namespace agg +{ + + //--------------------------------------------------------------------- + void line_profile_aa::width(double w) + { + if(w < 0.0) w = 0.0; + + if(w < m_smoother_width) w += w; + else w += m_smoother_width; + + w *= 0.5; + + w -= m_smoother_width; + double s = m_smoother_width; + if(w < 0.0) + { + s += w; + w = 0.0; + } + set(w, s); + } + + + //--------------------------------------------------------------------- + line_profile_aa::value_type* line_profile_aa::profile(double w) + { + m_subpixel_width = uround(w * subpixel_scale); + unsigned size = m_subpixel_width + subpixel_scale * 6; + if(size > m_profile.size()) + { + m_profile.resize(size); + } + return &m_profile[0]; + } + + + //--------------------------------------------------------------------- + void line_profile_aa::set(double center_width, double smoother_width) + { + double base_val = 1.0; + if(center_width == 0.0) center_width = 1.0 / subpixel_scale; + if(smoother_width == 0.0) smoother_width = 1.0 / subpixel_scale; + + double width = center_width + smoother_width; + if(width < m_min_width) + { + double k = width / m_min_width; + base_val *= k; + center_width /= k; + smoother_width /= k; + } + + value_type* ch = profile(center_width + smoother_width); + + unsigned subpixel_center_width = unsigned(center_width * subpixel_scale); + unsigned subpixel_smoother_width = unsigned(smoother_width * subpixel_scale); + + value_type* ch_center = ch + subpixel_scale*2; + value_type* ch_smoother = ch_center + subpixel_center_width; + + unsigned i; + + unsigned val = m_gamma[unsigned(base_val * aa_mask)]; + ch = ch_center; + for(i = 0; i < subpixel_center_width; i++) + { + *ch++ = (value_type)val; + } + + for(i = 0; i < subpixel_smoother_width; i++) + { + *ch_smoother++ = + m_gamma[unsigned((base_val - + base_val * + (double(i) / subpixel_smoother_width)) * aa_mask)]; + } + + unsigned n_smoother = profile_size() - + subpixel_smoother_width - + subpixel_center_width - + subpixel_scale*2; + + val = m_gamma[0]; + for(i = 0; i < n_smoother; i++) + { + *ch_smoother++ = (value_type)val; + } + + ch = ch_center; + for(i = 0; i < subpixel_scale*2; i++) + { + *--ch = *ch_center++; + } + } + + +} + diff --git a/jni/desmume/src/android/agg/src/agg_rounded_rect.cpp b/jni/desmume/src/android/agg/src/agg_rounded_rect.cpp new file mode 100755 index 0000000..5fa33fa --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_rounded_rect.cpp @@ -0,0 +1,169 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <math.h> +#include "agg_rounded_rect.h" + + +namespace agg +{ + //------------------------------------------------------------------------ + rounded_rect::rounded_rect(double x1, double y1, double x2, double y2, double r) : + m_x1(x1), m_y1(y1), m_x2(x2), m_y2(y2), + m_rx1(r), m_ry1(r), m_rx2(r), m_ry2(r), + m_rx3(r), m_ry3(r), m_rx4(r), m_ry4(r) + { + if(x1 > x2) { m_x1 = x2; m_x2 = x1; } + if(y1 > y2) { m_y1 = y2; m_y2 = y1; } + } + + //-------------------------------------------------------------------- + void rounded_rect::rect(double x1, double y1, double x2, double y2) + { + m_x1 = x1; + m_y1 = y1; + m_x2 = x2; + m_y2 = y2; + if(x1 > x2) { m_x1 = x2; m_x2 = x1; } + if(y1 > y2) { m_y1 = y2; m_y2 = y1; } + } + + //-------------------------------------------------------------------- + void rounded_rect::radius(double r) + { + m_rx1 = m_ry1 = m_rx2 = m_ry2 = m_rx3 = m_ry3 = m_rx4 = m_ry4 = r; + } + + //-------------------------------------------------------------------- + void rounded_rect::radius(double rx, double ry) + { + m_rx1 = m_rx2 = m_rx3 = m_rx4 = rx; + m_ry1 = m_ry2 = m_ry3 = m_ry4 = ry; + } + + //-------------------------------------------------------------------- + void rounded_rect::radius(double rx_bottom, double ry_bottom, + double rx_top, double ry_top) + { + m_rx1 = m_rx2 = rx_bottom; + m_rx3 = m_rx4 = rx_top; + m_ry1 = m_ry2 = ry_bottom; + m_ry3 = m_ry4 = ry_top; + } + + //-------------------------------------------------------------------- + void rounded_rect::radius(double rx1, double ry1, double rx2, double ry2, + double rx3, double ry3, double rx4, double ry4) + { + m_rx1 = rx1; m_ry1 = ry1; m_rx2 = rx2; m_ry2 = ry2; + m_rx3 = rx3; m_ry3 = ry3; m_rx4 = rx4; m_ry4 = ry4; + } + + //-------------------------------------------------------------------- + void rounded_rect::normalize_radius() + { + double dx = fabs(m_x2 - m_x1); + double dy = fabs(m_y2 - m_y1); + + double k = 1.0; + double t; + t = dx / (m_rx1 + m_rx2); if(t < k) k = t; + t = dx / (m_rx3 + m_rx4); if(t < k) k = t; + t = dy / (m_ry1 + m_ry2); if(t < k) k = t; + t = dy / (m_ry3 + m_ry4); if(t < k) k = t; + + if(k < 1.0) + { + m_rx1 *= k; m_ry1 *= k; m_rx2 *= k; m_ry2 *= k; + m_rx3 *= k; m_ry3 *= k; m_rx4 *= k; m_ry4 *= k; + } + } + + //-------------------------------------------------------------------- + void rounded_rect::rewind(unsigned) + { + m_status = 0; + } + + //-------------------------------------------------------------------- + unsigned rounded_rect::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + switch(m_status) + { + case 0: + m_arc.init(m_x1 + m_rx1, m_y1 + m_ry1, m_rx1, m_ry1, + pi, pi+pi*0.5); + m_arc.rewind(0); + m_status++; + + case 1: + cmd = m_arc.vertex(x, y); + if(is_stop(cmd)) m_status++; + else return cmd; + + case 2: + m_arc.init(m_x2 - m_rx2, m_y1 + m_ry2, m_rx2, m_ry2, + pi+pi*0.5, 0.0); + m_arc.rewind(0); + m_status++; + + case 3: + cmd = m_arc.vertex(x, y); + if(is_stop(cmd)) m_status++; + else return path_cmd_line_to; + + case 4: + m_arc.init(m_x2 - m_rx3, m_y2 - m_ry3, m_rx3, m_ry3, + 0.0, pi*0.5); + m_arc.rewind(0); + m_status++; + + case 5: + cmd = m_arc.vertex(x, y); + if(is_stop(cmd)) m_status++; + else return path_cmd_line_to; + + case 6: + m_arc.init(m_x1 + m_rx4, m_y2 - m_ry4, m_rx4, m_ry4, + pi*0.5, pi); + m_arc.rewind(0); + m_status++; + + case 7: + cmd = m_arc.vertex(x, y); + if(is_stop(cmd)) m_status++; + else return path_cmd_line_to; + + case 8: + cmd = path_cmd_end_poly | path_flags_close | path_flags_ccw; + m_status++; + break; + } + return cmd; + } + + +} + diff --git a/jni/desmume/src/android/agg/src/agg_sqrt_tables.cpp b/jni/desmume/src/android/agg/src/agg_sqrt_tables.cpp new file mode 100755 index 0000000..2f7e0d6 --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_sqrt_tables.cpp @@ -0,0 +1,120 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include "agg_basics.h" + +namespace agg +{ + int16u g_sqrt_table[1024] = //----------g_sqrt_table + { + 0, + 2048,2896,3547,4096,4579,5017,5418,5793,6144,6476,6792,7094,7384,7663,7932,8192,8444, + 8689,8927,9159,9385,9606,9822,10033,10240,10443,10642,10837,11029,11217,11403,11585, + 11765,11942,12116,12288,12457,12625,12790,12953,13114,13273,13430,13585,13738,13890, + 14040,14189,14336,14482,14626,14768,14910,15050,15188,15326,15462,15597,15731,15864, + 15995,16126,16255,16384,16512,16638,16764,16888,17012,17135,17257,17378,17498,17618, + 17736,17854,17971,18087,18203,18318,18432,18545,18658,18770,18882,18992,19102,19212, + 19321,19429,19537,19644,19750,19856,19961,20066,20170,20274,20377,20480,20582,20684, + 20785,20886,20986,21085,21185,21283,21382,21480,21577,21674,21771,21867,21962,22058, + 22153,22247,22341,22435,22528,22621,22713,22806,22897,22989,23080,23170,23261,23351, + 23440,23530,23619,23707,23796,23884,23971,24059,24146,24232,24319,24405,24491,24576, + 24661,24746,24831,24915,24999,25083,25166,25249,25332,25415,25497,25580,25661,25743, + 25824,25905,25986,26067,26147,26227,26307,26387,26466,26545,26624,26703,26781,26859, + 26937,27015,27092,27170,27247,27324,27400,27477,27553,27629,27705,27780,27856,27931, + 28006,28081,28155,28230,28304,28378,28452,28525,28599,28672,28745,28818,28891,28963, + 29035,29108,29180,29251,29323,29394,29466,29537,29608,29678,29749,29819,29890,29960, + 30030,30099,30169,30238,30308,30377,30446,30515,30583,30652,30720,30788,30856,30924, + 30992,31059,31127,31194,31261,31328,31395,31462,31529,31595,31661,31727,31794,31859, + 31925,31991,32056,32122,32187,32252,32317,32382,32446,32511,32575,32640,32704,32768, + 32832,32896,32959,33023,33086,33150,33213,33276,33339,33402,33465,33527,33590,33652, + 33714,33776,33839,33900,33962,34024,34086,34147,34208,34270,34331,34392,34453,34514, + 34574,34635,34695,34756,34816,34876,34936,34996,35056,35116,35176,35235,35295,35354, + 35413,35472,35531,35590,35649,35708,35767,35825,35884,35942,36001,36059,36117,36175, + 36233,36291,36348,36406,36464,36521,36578,36636,36693,36750,36807,36864,36921,36978, + 37034,37091,37147,37204,37260,37316,37372,37429,37485,37540,37596,37652,37708,37763, + 37819,37874,37929,37985,38040,38095,38150,38205,38260,38315,38369,38424,38478,38533, + 38587,38642,38696,38750,38804,38858,38912,38966,39020,39073,39127,39181,39234,39287, + 39341,39394,39447,39500,39553,39606,39659,39712,39765,39818,39870,39923,39975,40028, + 40080,40132,40185,40237,40289,40341,40393,40445,40497,40548,40600,40652,40703,40755, + 40806,40857,40909,40960,41011,41062,41113,41164,41215,41266,41317,41368,41418,41469, + 41519,41570,41620,41671,41721,41771,41821,41871,41922,41972,42021,42071,42121,42171, + 42221,42270,42320,42369,42419,42468,42518,42567,42616,42665,42714,42763,42813,42861, + 42910,42959,43008,43057,43105,43154,43203,43251,43300,43348,43396,43445,43493,43541, + 43589,43637,43685,43733,43781,43829,43877,43925,43972,44020,44068,44115,44163,44210, + 44258,44305,44352,44400,44447,44494,44541,44588,44635,44682,44729,44776,44823,44869, + 44916,44963,45009,45056,45103,45149,45195,45242,45288,45334,45381,45427,45473,45519, + 45565,45611,45657,45703,45749,45795,45840,45886,45932,45977,46023,46069,46114,46160, + 46205,46250,46296,46341,46386,46431,46477,46522,46567,46612,46657,46702,46746,46791, + 46836,46881,46926,46970,47015,47059,47104,47149,47193,47237,47282,47326,47370,47415, + 47459,47503,47547,47591,47635,47679,47723,47767,47811,47855,47899,47942,47986,48030, + 48074,48117,48161,48204,48248,48291,48335,48378,48421,48465,48508,48551,48594,48637, + 48680,48723,48766,48809,48852,48895,48938,48981,49024,49067,49109,49152,49195,49237, + 49280,49322,49365,49407,49450,49492,49535,49577,49619,49661,49704,49746,49788,49830, + 49872,49914,49956,49998,50040,50082,50124,50166,50207,50249,50291,50332,50374,50416, + 50457,50499,50540,50582,50623,50665,50706,50747,50789,50830,50871,50912,50954,50995, + 51036,51077,51118,51159,51200,51241,51282,51323,51364,51404,51445,51486,51527,51567, + 51608,51649,51689,51730,51770,51811,51851,51892,51932,51972,52013,52053,52093,52134, + 52174,52214,52254,52294,52334,52374,52414,52454,52494,52534,52574,52614,52654,52694, + 52734,52773,52813,52853,52892,52932,52972,53011,53051,53090,53130,53169,53209,53248, + 53287,53327,53366,53405,53445,53484,53523,53562,53601,53640,53679,53719,53758,53797, + 53836,53874,53913,53952,53991,54030,54069,54108,54146,54185,54224,54262,54301,54340, + 54378,54417,54455,54494,54532,54571,54609,54647,54686,54724,54762,54801,54839,54877, + 54915,54954,54992,55030,55068,55106,55144,55182,55220,55258,55296,55334,55372,55410, + 55447,55485,55523,55561,55599,55636,55674,55712,55749,55787,55824,55862,55900,55937, + 55975,56012,56049,56087,56124,56162,56199,56236,56273,56311,56348,56385,56422,56459, + 56497,56534,56571,56608,56645,56682,56719,56756,56793,56830,56867,56903,56940,56977, + 57014,57051,57087,57124,57161,57198,57234,57271,57307,57344,57381,57417,57454,57490, + 57527,57563,57599,57636,57672,57709,57745,57781,57817,57854,57890,57926,57962,57999, + 58035,58071,58107,58143,58179,58215,58251,58287,58323,58359,58395,58431,58467,58503, + 58538,58574,58610,58646,58682,58717,58753,58789,58824,58860,58896,58931,58967,59002, + 59038,59073,59109,59144,59180,59215,59251,59286,59321,59357,59392,59427,59463,59498, + 59533,59568,59603,59639,59674,59709,59744,59779,59814,59849,59884,59919,59954,59989, + 60024,60059,60094,60129,60164,60199,60233,60268,60303,60338,60373,60407,60442,60477, + 60511,60546,60581,60615,60650,60684,60719,60753,60788,60822,60857,60891,60926,60960, + 60995,61029,61063,61098,61132,61166,61201,61235,61269,61303,61338,61372,61406,61440, + 61474,61508,61542,61576,61610,61644,61678,61712,61746,61780,61814,61848,61882,61916, + 61950,61984,62018,62051,62085,62119,62153,62186,62220,62254,62287,62321,62355,62388, + 62422,62456,62489,62523,62556,62590,62623,62657,62690,62724,62757,62790,62824,62857, + 62891,62924,62957,62991,63024,63057,63090,63124,63157,63190,63223,63256,63289,63323, + 63356,63389,63422,63455,63488,63521,63554,63587,63620,63653,63686,63719,63752,63785, + 63817,63850,63883,63916,63949,63982,64014,64047,64080,64113,64145,64178,64211,64243, + 64276,64309,64341,64374,64406,64439,64471,64504,64536,64569,64601,64634,64666,64699, + 64731,64763,64796,64828,64861,64893,64925,64957,64990,65022,65054,65086,65119,65151, + 65183,65215,65247,65279,65312,65344,65376,65408,65440,65472,65504 + }; + + + int8 g_elder_bit_table[256] = //---------g_elder_bit_table + { + 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 + }; + +} diff --git a/jni/desmume/src/android/agg/src/agg_trans_affine.cpp b/jni/desmume/src/android/agg/src/agg_trans_affine.cpp new file mode 100755 index 0000000..aca18c2 --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_trans_affine.cpp @@ -0,0 +1,200 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include "agg_trans_affine.h" + + + +namespace agg +{ + + //------------------------------------------------------------------------ + const trans_affine& trans_affine::parl_to_parl(const double* src, + const double* dst) + { + sx = src[2] - src[0]; + shy = src[3] - src[1]; + shx = src[4] - src[0]; + sy = src[5] - src[1]; + tx = src[0]; + ty = src[1]; + invert(); + multiply(trans_affine(dst[2] - dst[0], dst[3] - dst[1], + dst[4] - dst[0], dst[5] - dst[1], + dst[0], dst[1])); + return *this; + } + + //------------------------------------------------------------------------ + const trans_affine& trans_affine::rect_to_parl(double x1, double y1, + double x2, double y2, + const double* parl) + { + double src[6]; + src[0] = x1; src[1] = y1; + src[2] = x2; src[3] = y1; + src[4] = x2; src[5] = y2; + parl_to_parl(src, parl); + return *this; + } + + //------------------------------------------------------------------------ + const trans_affine& trans_affine::parl_to_rect(const double* parl, + double x1, double y1, + double x2, double y2) + { + double dst[6]; + dst[0] = x1; dst[1] = y1; + dst[2] = x2; dst[3] = y1; + dst[4] = x2; dst[5] = y2; + parl_to_parl(parl, dst); + return *this; + } + + //------------------------------------------------------------------------ + const trans_affine& trans_affine::multiply(const trans_affine& m) + { + double t0 = sx * m.sx + shy * m.shx; + double t2 = shx * m.sx + sy * m.shx; + double t4 = tx * m.sx + ty * m.shx + m.tx; + shy = sx * m.shy + shy * m.sy; + sy = shx * m.shy + sy * m.sy; + ty = tx * m.shy + ty * m.sy + m.ty; + sx = t0; + shx = t2; + tx = t4; + return *this; + } + + + //------------------------------------------------------------------------ + const trans_affine& trans_affine::invert() + { + double d = determinant_reciprocal(); + + double t0 = sy * d; + sy = sx * d; + shy = -shy * d; + shx = -shx * d; + + double t4 = -tx * t0 - ty * shx; + ty = -tx * shy - ty * sy; + + sx = t0; + tx = t4; + return *this; + } + + + //------------------------------------------------------------------------ + const trans_affine& trans_affine::flip_x() + { + sx = -sx; + shy = -shy; + tx = -tx; + return *this; + } + + //------------------------------------------------------------------------ + const trans_affine& trans_affine::flip_y() + { + shx = -shx; + sy = -sy; + ty = -ty; + return *this; + } + + //------------------------------------------------------------------------ + const trans_affine& trans_affine::reset() + { + sx = sy = 1.0; + shy = shx = tx = ty = 0.0; + return *this; + } + + //------------------------------------------------------------------------ + bool trans_affine::is_identity(double epsilon) const + { + return is_equal_eps(sx, 1.0, epsilon) && + is_equal_eps(shy, 0.0, epsilon) && + is_equal_eps(shx, 0.0, epsilon) && + is_equal_eps(sy, 1.0, epsilon) && + is_equal_eps(tx, 0.0, epsilon) && + is_equal_eps(ty, 0.0, epsilon); + } + + //------------------------------------------------------------------------ + bool trans_affine::is_valid(double epsilon) const + { + return fabs(sx) > epsilon && fabs(sy) > epsilon; + } + + //------------------------------------------------------------------------ + bool trans_affine::is_equal(const trans_affine& m, double epsilon) const + { + return is_equal_eps(sx, m.sx, epsilon) && + is_equal_eps(shy, m.shy, epsilon) && + is_equal_eps(shx, m.shx, epsilon) && + is_equal_eps(sy, m.sy, epsilon) && + is_equal_eps(tx, m.tx, epsilon) && + is_equal_eps(ty, m.ty, epsilon); + } + + //------------------------------------------------------------------------ + double trans_affine::rotation() const + { + double x1 = 0.0; + double y1 = 0.0; + double x2 = 1.0; + double y2 = 0.0; + transform(&x1, &y1); + transform(&x2, &y2); + return atan2(y2-y1, x2-x1); + } + + //------------------------------------------------------------------------ + void trans_affine::translation(double* dx, double* dy) const + { + *dx = tx; + *dy = ty; + } + + //------------------------------------------------------------------------ + void trans_affine::scaling(double* x, double* y) const + { + double x1 = 0.0; + double y1 = 0.0; + double x2 = 1.0; + double y2 = 1.0; + trans_affine t(*this); + t *= trans_affine_rotation(-rotation()); + t.transform(&x1, &y1); + t.transform(&x2, &y2); + *x = x2 - x1; + *y = y2 - y1; + } + + +} + diff --git a/jni/desmume/src/android/agg/src/agg_trans_double_path.cpp b/jni/desmume/src/android/agg/src/agg_trans_double_path.cpp new file mode 100755 index 0000000..13e4435 --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_trans_double_path.cpp @@ -0,0 +1,282 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include "agg_math.h" +#include "agg_trans_double_path.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + trans_double_path::trans_double_path() : + m_kindex1(0.0), + m_kindex2(0.0), + m_base_length(0.0), + m_base_height(1.0), + m_status1(initial), + m_status2(initial), + m_preserve_x_scale(true) + { + } + + + //------------------------------------------------------------------------ + void trans_double_path::reset() + { + m_src_vertices1.remove_all(); + m_src_vertices2.remove_all(); + m_kindex1 = 0.0; + m_kindex1 = 0.0; + m_status1 = initial; + m_status2 = initial; + } + + + //------------------------------------------------------------------------ + void trans_double_path::move_to1(double x, double y) + { + if(m_status1 == initial) + { + m_src_vertices1.modify_last(vertex_dist(x, y)); + m_status1 = making_path; + } + else + { + line_to1(x, y); + } + } + + + //------------------------------------------------------------------------ + void trans_double_path::line_to1(double x, double y) + { + if(m_status1 == making_path) + { + m_src_vertices1.add(vertex_dist(x, y)); + } + } + + + //------------------------------------------------------------------------ + void trans_double_path::move_to2(double x, double y) + { + if(m_status2 == initial) + { + m_src_vertices2.modify_last(vertex_dist(x, y)); + m_status2 = making_path; + } + else + { + line_to2(x, y); + } + } + + + //------------------------------------------------------------------------ + void trans_double_path::line_to2(double x, double y) + { + if(m_status2 == making_path) + { + m_src_vertices2.add(vertex_dist(x, y)); + } + } + + + //------------------------------------------------------------------------ + double trans_double_path::finalize_path(vertex_storage& vertices) + { + unsigned i; + double dist; + double d; + + vertices.close(false); + if(vertices.size() > 2) + { + if(vertices[vertices.size() - 2].dist * 10.0 < + vertices[vertices.size() - 3].dist) + { + d = vertices[vertices.size() - 3].dist + + vertices[vertices.size() - 2].dist; + + vertices[vertices.size() - 2] = + vertices[vertices.size() - 1]; + + vertices.remove_last(); + vertices[vertices.size() - 2].dist = d; + } + } + + dist = 0; + for(i = 0; i < vertices.size(); i++) + { + vertex_dist& v = vertices[i]; + d = v.dist; + v.dist = dist; + dist += d; + } + + return (vertices.size() - 1) / dist; + } + + + //------------------------------------------------------------------------ + void trans_double_path::finalize_paths() + { + if(m_status1 == making_path && m_src_vertices1.size() > 1 && + m_status2 == making_path && m_src_vertices2.size() > 1) + { + m_kindex1 = finalize_path(m_src_vertices1); + m_kindex2 = finalize_path(m_src_vertices2); + m_status1 = ready; + m_status2 = ready; + } + } + + + //------------------------------------------------------------------------ + double trans_double_path::total_length1() const + { + if(m_base_length >= 1e-10) return m_base_length; + return (m_status1 == ready) ? + m_src_vertices1[m_src_vertices1.size() - 1].dist : + 0.0; + } + + + //------------------------------------------------------------------------ + double trans_double_path::total_length2() const + { + if(m_base_length >= 1e-10) return m_base_length; + return (m_status2 == ready) ? + m_src_vertices2[m_src_vertices2.size() - 1].dist : + 0.0; + } + + + //------------------------------------------------------------------------ + void trans_double_path::transform1(const vertex_storage& vertices, + double kindex, double kx, + double *x, double* y) const + { + double x1 = 0.0; + double y1 = 0.0; + double dx = 1.0; + double dy = 1.0; + double d = 0.0; + double dd = 1.0; + *x *= kx; + if(*x < 0.0) + { + // Extrapolation on the left + //-------------------------- + x1 = vertices[0].x; + y1 = vertices[0].y; + dx = vertices[1].x - x1; + dy = vertices[1].y - y1; + dd = vertices[1].dist - vertices[0].dist; + d = *x; + } + else + if(*x > vertices[vertices.size() - 1].dist) + { + // Extrapolation on the right + //-------------------------- + unsigned i = vertices.size() - 2; + unsigned j = vertices.size() - 1; + x1 = vertices[j].x; + y1 = vertices[j].y; + dx = x1 - vertices[i].x; + dy = y1 - vertices[i].y; + dd = vertices[j].dist - vertices[i].dist; + d = *x - vertices[j].dist; + } + else + { + // Interpolation + //-------------------------- + unsigned i = 0; + unsigned j = vertices.size() - 1; + if(m_preserve_x_scale) + { + unsigned k; + for(i = 0; (j - i) > 1; ) + { + if(*x < vertices[k = (i + j) >> 1].dist) + { + j = k; + } + else + { + i = k; + } + } + d = vertices[i].dist; + dd = vertices[j].dist - d; + d = *x - d; + } + else + { + i = unsigned(*x * kindex); + j = i + 1; + dd = vertices[j].dist - vertices[i].dist; + d = ((*x * kindex) - i) * dd; + } + x1 = vertices[i].x; + y1 = vertices[i].y; + dx = vertices[j].x - x1; + dy = vertices[j].y - y1; + } + *x = x1 + dx * d / dd; + *y = y1 + dy * d / dd; + } + + + //------------------------------------------------------------------------ + void trans_double_path::transform(double *x, double *y) const + { + if(m_status1 == ready && m_status2 == ready) + { + if(m_base_length > 1e-10) + { + *x *= m_src_vertices1[m_src_vertices1.size() - 1].dist / + m_base_length; + } + + double x1 = *x; + double y1 = *y; + double x2 = *x; + double y2 = *y; + double dd = m_src_vertices2[m_src_vertices2.size() - 1].dist / + m_src_vertices1[m_src_vertices1.size() - 1].dist; + + transform1(m_src_vertices1, m_kindex1, 1.0, &x1, &y1); + transform1(m_src_vertices2, m_kindex2, dd, &x2, &y2); + + *x = x1 + *y * (x2 - x1) / m_base_height; + *y = y1 + *y * (y2 - y1) / m_base_height; + } + } + +} + diff --git a/jni/desmume/src/android/agg/src/agg_trans_single_path.cpp b/jni/desmume/src/android/agg/src/agg_trans_single_path.cpp new file mode 100755 index 0000000..9742dab --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_trans_single_path.cpp @@ -0,0 +1,211 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include "agg_math.h" +#include "agg_vertex_sequence.h" +#include "agg_trans_single_path.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + trans_single_path::trans_single_path() : + m_base_length(0.0), + m_kindex(0.0), + m_status(initial), + m_preserve_x_scale(true) + { + } + + //------------------------------------------------------------------------ + void trans_single_path::reset() + { + m_src_vertices.remove_all(); + m_kindex = 0.0; + m_status = initial; + } + + //------------------------------------------------------------------------ + void trans_single_path::move_to(double x, double y) + { + if(m_status == initial) + { + m_src_vertices.modify_last(vertex_dist(x, y)); + m_status = making_path; + } + else + { + line_to(x, y); + } + } + + //------------------------------------------------------------------------ + void trans_single_path::line_to(double x, double y) + { + if(m_status == making_path) + { + m_src_vertices.add(vertex_dist(x, y)); + } + } + + + //------------------------------------------------------------------------ + void trans_single_path::finalize_path() + { + if(m_status == making_path && m_src_vertices.size() > 1) + { + unsigned i; + double dist; + double d; + + m_src_vertices.close(false); + if(m_src_vertices.size() > 2) + { + if(m_src_vertices[m_src_vertices.size() - 2].dist * 10.0 < + m_src_vertices[m_src_vertices.size() - 3].dist) + { + d = m_src_vertices[m_src_vertices.size() - 3].dist + + m_src_vertices[m_src_vertices.size() - 2].dist; + + m_src_vertices[m_src_vertices.size() - 2] = + m_src_vertices[m_src_vertices.size() - 1]; + + m_src_vertices.remove_last(); + m_src_vertices[m_src_vertices.size() - 2].dist = d; + } + } + + dist = 0.0; + for(i = 0; i < m_src_vertices.size(); i++) + { + vertex_dist& v = m_src_vertices[i]; + double d = v.dist; + v.dist = dist; + dist += d; + } + m_kindex = (m_src_vertices.size() - 1) / dist; + m_status = ready; + } + } + + + + //------------------------------------------------------------------------ + double trans_single_path::total_length() const + { + if(m_base_length >= 1e-10) return m_base_length; + return (m_status == ready) ? + m_src_vertices[m_src_vertices.size() - 1].dist : + 0.0; + } + + + //------------------------------------------------------------------------ + void trans_single_path::transform(double *x, double *y) const + { + if(m_status == ready) + { + if(m_base_length > 1e-10) + { + *x *= m_src_vertices[m_src_vertices.size() - 1].dist / + m_base_length; + } + + double x1 = 0.0; + double y1 = 0.0; + double dx = 1.0; + double dy = 1.0; + double d = 0.0; + double dd = 1.0; + if(*x < 0.0) + { + // Extrapolation on the left + //-------------------------- + x1 = m_src_vertices[0].x; + y1 = m_src_vertices[0].y; + dx = m_src_vertices[1].x - x1; + dy = m_src_vertices[1].y - y1; + dd = m_src_vertices[1].dist - m_src_vertices[0].dist; + d = *x; + } + else + if(*x > m_src_vertices[m_src_vertices.size() - 1].dist) + { + // Extrapolation on the right + //-------------------------- + unsigned i = m_src_vertices.size() - 2; + unsigned j = m_src_vertices.size() - 1; + x1 = m_src_vertices[j].x; + y1 = m_src_vertices[j].y; + dx = x1 - m_src_vertices[i].x; + dy = y1 - m_src_vertices[i].y; + dd = m_src_vertices[j].dist - m_src_vertices[i].dist; + d = *x - m_src_vertices[j].dist; + } + else + { + // Interpolation + //-------------------------- + unsigned i = 0; + unsigned j = m_src_vertices.size() - 1; + if(m_preserve_x_scale) + { + unsigned k; + for(i = 0; (j - i) > 1; ) + { + if(*x < m_src_vertices[k = (i + j) >> 1].dist) + { + j = k; + } + else + { + i = k; + } + } + d = m_src_vertices[i].dist; + dd = m_src_vertices[j].dist - d; + d = *x - d; + } + else + { + i = unsigned(*x * m_kindex); + j = i + 1; + dd = m_src_vertices[j].dist - m_src_vertices[i].dist; + d = ((*x * m_kindex) - i) * dd; + } + x1 = m_src_vertices[i].x; + y1 = m_src_vertices[i].y; + dx = m_src_vertices[j].x - x1; + dy = m_src_vertices[j].y - y1; + } + double x2 = x1 + dx * d / dd; + double y2 = y1 + dy * d / dd; + *x = x2 - *y * dy / dd; + *y = y2 + *y * dx / dd; + } + } + + +} + diff --git a/jni/desmume/src/android/agg/src/agg_trans_warp_magnifier.cpp b/jni/desmume/src/android/agg/src/agg_trans_warp_magnifier.cpp new file mode 100755 index 0000000..55fde4e --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_trans_warp_magnifier.cpp @@ -0,0 +1,79 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <math.h> +#include "agg_trans_warp_magnifier.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + void trans_warp_magnifier::transform(double* x, double* y) const + { + double dx = *x - m_xc; + double dy = *y - m_yc; + double r = sqrt(dx * dx + dy * dy); + if(r < m_radius) + { + *x = m_xc + dx * m_magn; + *y = m_yc + dy * m_magn; + return; + } + + double m = (r + m_radius * (m_magn - 1.0)) / r; + *x = m_xc + dx * m; + *y = m_yc + dy * m; + } + + //------------------------------------------------------------------------ + void trans_warp_magnifier::inverse_transform(double* x, double* y) const + { + // New version by Andrew Skalkin + //----------------- + double dx = *x - m_xc; + double dy = *y - m_yc; + double r = sqrt(dx * dx + dy * dy); + + if(r < m_radius * m_magn) + { + *x = m_xc + dx / m_magn; + *y = m_yc + dy / m_magn; + } + else + { + double rnew = r - m_radius * (m_magn - 1.0); + *x = m_xc + rnew * dx / r; + *y = m_yc + rnew * dy / r; + } + + // Old version + //----------------- + //trans_warp_magnifier t(*this); + //t.magnification(1.0 / m_magn); + //t.radius(m_radius * m_magn); + //t.transform(x, y); + } + + +} diff --git a/jni/desmume/src/android/agg/src/agg_vcgen_bspline.cpp b/jni/desmume/src/android/agg/src/agg_vcgen_bspline.cpp new file mode 100755 index 0000000..78a814a --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_vcgen_bspline.cpp @@ -0,0 +1,203 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include "agg_vcgen_bspline.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + vcgen_bspline::vcgen_bspline() : + m_src_vertices(), + m_spline_x(), + m_spline_y(), + m_interpolation_step(1.0/50.0), + m_closed(0), + m_status(initial), + m_src_vertex(0) + { + } + + + //------------------------------------------------------------------------ + void vcgen_bspline::remove_all() + { + m_src_vertices.remove_all(); + m_closed = 0; + m_status = initial; + m_src_vertex = 0; + } + + + //------------------------------------------------------------------------ + void vcgen_bspline::add_vertex(double x, double y, unsigned cmd) + { + m_status = initial; + if(is_move_to(cmd)) + { + m_src_vertices.modify_last(point_d(x, y)); + } + else + { + if(is_vertex(cmd)) + { + m_src_vertices.add(point_d(x, y)); + } + else + { + m_closed = get_close_flag(cmd); + } + } + } + + + //------------------------------------------------------------------------ + void vcgen_bspline::rewind(unsigned) + { + m_cur_abscissa = 0.0; + m_max_abscissa = 0.0; + m_src_vertex = 0; + if(m_status == initial && m_src_vertices.size() > 2) + { + if(m_closed) + { + m_spline_x.init(m_src_vertices.size() + 8); + m_spline_y.init(m_src_vertices.size() + 8); + m_spline_x.add_point(0.0, m_src_vertices.prev(m_src_vertices.size() - 3).x); + m_spline_y.add_point(0.0, m_src_vertices.prev(m_src_vertices.size() - 3).y); + m_spline_x.add_point(1.0, m_src_vertices[m_src_vertices.size() - 3].x); + m_spline_y.add_point(1.0, m_src_vertices[m_src_vertices.size() - 3].y); + m_spline_x.add_point(2.0, m_src_vertices[m_src_vertices.size() - 2].x); + m_spline_y.add_point(2.0, m_src_vertices[m_src_vertices.size() - 2].y); + m_spline_x.add_point(3.0, m_src_vertices[m_src_vertices.size() - 1].x); + m_spline_y.add_point(3.0, m_src_vertices[m_src_vertices.size() - 1].y); + } + else + { + m_spline_x.init(m_src_vertices.size()); + m_spline_y.init(m_src_vertices.size()); + } + unsigned i; + for(i = 0; i < m_src_vertices.size(); i++) + { + double x = m_closed ? i + 4 : i; + m_spline_x.add_point(x, m_src_vertices[i].x); + m_spline_y.add_point(x, m_src_vertices[i].y); + } + m_cur_abscissa = 0.0; + m_max_abscissa = m_src_vertices.size() - 1; + if(m_closed) + { + m_cur_abscissa = 4.0; + m_max_abscissa += 5.0; + m_spline_x.add_point(m_src_vertices.size() + 4, m_src_vertices[0].x); + m_spline_y.add_point(m_src_vertices.size() + 4, m_src_vertices[0].y); + m_spline_x.add_point(m_src_vertices.size() + 5, m_src_vertices[1].x); + m_spline_y.add_point(m_src_vertices.size() + 5, m_src_vertices[1].y); + m_spline_x.add_point(m_src_vertices.size() + 6, m_src_vertices[2].x); + m_spline_y.add_point(m_src_vertices.size() + 6, m_src_vertices[2].y); + m_spline_x.add_point(m_src_vertices.size() + 7, m_src_vertices.next(2).x); + m_spline_y.add_point(m_src_vertices.size() + 7, m_src_vertices.next(2).y); + } + m_spline_x.prepare(); + m_spline_y.prepare(); + } + m_status = ready; + } + + + + + + + //------------------------------------------------------------------------ + unsigned vcgen_bspline::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + while(!is_stop(cmd)) + { + switch(m_status) + { + case initial: + rewind(0); + + case ready: + if(m_src_vertices.size() < 2) + { + cmd = path_cmd_stop; + break; + } + + if(m_src_vertices.size() == 2) + { + *x = m_src_vertices[m_src_vertex].x; + *y = m_src_vertices[m_src_vertex].y; + m_src_vertex++; + if(m_src_vertex == 1) return path_cmd_move_to; + if(m_src_vertex == 2) return path_cmd_line_to; + cmd = path_cmd_stop; + break; + } + + cmd = path_cmd_move_to; + m_status = polygon; + m_src_vertex = 0; + + case polygon: + if(m_cur_abscissa >= m_max_abscissa) + { + if(m_closed) + { + m_status = end_poly; + break; + } + else + { + *x = m_src_vertices[m_src_vertices.size() - 1].x; + *y = m_src_vertices[m_src_vertices.size() - 1].y; + m_status = end_poly; + return path_cmd_line_to; + } + } + + *x = m_spline_x.get_stateful(m_cur_abscissa); + *y = m_spline_y.get_stateful(m_cur_abscissa); + m_src_vertex++; + m_cur_abscissa += m_interpolation_step; + return (m_src_vertex == 1) ? path_cmd_move_to : path_cmd_line_to; + + case end_poly: + m_status = stop; + return path_cmd_end_poly | m_closed; + + case stop: + return path_cmd_stop; + } + } + return cmd; + } + + +} + diff --git a/jni/desmume/src/android/agg/src/agg_vcgen_contour.cpp b/jni/desmume/src/android/agg/src/agg_vcgen_contour.cpp new file mode 100755 index 0000000..6ffb318 --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_vcgen_contour.cpp @@ -0,0 +1,170 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <math.h> +#include "agg_vcgen_contour.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + vcgen_contour::vcgen_contour() : + m_stroker(), + m_width(1), + m_src_vertices(), + m_out_vertices(), + m_status(initial), + m_src_vertex(0), + m_closed(0), + m_orientation(0), + m_auto_detect(false) + { + } + + //------------------------------------------------------------------------ + void vcgen_contour::remove_all() + { + m_src_vertices.remove_all(); + m_closed = 0; + m_orientation = 0; + m_status = initial; + } + + //------------------------------------------------------------------------ + void vcgen_contour::add_vertex(double x, double y, unsigned cmd) + { + m_status = initial; + if(is_move_to(cmd)) + { + m_src_vertices.modify_last(vertex_dist(x, y)); + } + else + { + if(is_vertex(cmd)) + { + m_src_vertices.add(vertex_dist(x, y)); + } + else + { + if(is_end_poly(cmd)) + { + m_closed = get_close_flag(cmd); + if(m_orientation == path_flags_none) + { + m_orientation = get_orientation(cmd); + } + } + } + } + } + + //------------------------------------------------------------------------ + void vcgen_contour::rewind(unsigned) + { + if(m_status == initial) + { + m_src_vertices.close(true); + if(m_auto_detect) + { + if(!is_oriented(m_orientation)) + { + m_orientation = (calc_polygon_area(m_src_vertices) > 0.0) ? + path_flags_ccw : + path_flags_cw; + } + } + if(is_oriented(m_orientation)) + { + m_stroker.width(is_ccw(m_orientation) ? m_width : -m_width); + } + } + m_status = ready; + m_src_vertex = 0; + } + + //------------------------------------------------------------------------ + unsigned vcgen_contour::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + while(!is_stop(cmd)) + { + switch(m_status) + { + case initial: + rewind(0); + + case ready: + if(m_src_vertices.size() < 2 + unsigned(m_closed != 0)) + { + cmd = path_cmd_stop; + break; + } + m_status = outline; + cmd = path_cmd_move_to; + m_src_vertex = 0; + m_out_vertex = 0; + + case outline: + if(m_src_vertex >= m_src_vertices.size()) + { + m_status = end_poly; + break; + } + m_stroker.calc_join(m_out_vertices, + m_src_vertices.prev(m_src_vertex), + m_src_vertices.curr(m_src_vertex), + m_src_vertices.next(m_src_vertex), + m_src_vertices.prev(m_src_vertex).dist, + m_src_vertices.curr(m_src_vertex).dist); + ++m_src_vertex; + m_status = out_vertices; + m_out_vertex = 0; + + case out_vertices: + if(m_out_vertex >= m_out_vertices.size()) + { + m_status = outline; + } + else + { + const point_d& c = m_out_vertices[m_out_vertex++]; + *x = c.x; + *y = c.y; + return cmd; + } + break; + + case end_poly: + if(!m_closed) return path_cmd_stop; + m_status = stop; + return path_cmd_end_poly | path_flags_close | path_flags_ccw; + + case stop: + return path_cmd_stop; + } + } + return cmd; + } + +} diff --git a/jni/desmume/src/android/agg/src/agg_vcgen_dash.cpp b/jni/desmume/src/android/agg/src/agg_vcgen_dash.cpp new file mode 100755 index 0000000..1dd403e --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_vcgen_dash.cpp @@ -0,0 +1,240 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <math.h> +#include "agg_vcgen_dash.h" +#include "agg_shorten_path.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + vcgen_dash::vcgen_dash() : + m_total_dash_len(0.0), + m_num_dashes(0), + m_dash_start(0.0), + m_shorten(0.0), + m_curr_dash_start(0.0), + m_curr_dash(0), + m_src_vertices(), + m_closed(0), + m_status(initial), + m_src_vertex(0) + { + } + + + + //------------------------------------------------------------------------ + void vcgen_dash::remove_all_dashes() + { + m_total_dash_len = 0.0; + m_num_dashes = 0; + m_curr_dash_start = 0.0; + m_curr_dash = 0; + } + + + //------------------------------------------------------------------------ + void vcgen_dash::add_dash(double dash_len, double gap_len) + { + if(m_num_dashes < max_dashes) + { + m_total_dash_len += dash_len + gap_len; + m_dashes[m_num_dashes++] = dash_len; + m_dashes[m_num_dashes++] = gap_len; + } + } + + + //------------------------------------------------------------------------ + void vcgen_dash::dash_start(double ds) + { + m_dash_start = ds; + calc_dash_start(fabs(ds)); + } + + + //------------------------------------------------------------------------ + void vcgen_dash::calc_dash_start(double ds) + { + m_curr_dash = 0; + m_curr_dash_start = 0.0; + while(ds > 0.0) + { + if(ds > m_dashes[m_curr_dash]) + { + ds -= m_dashes[m_curr_dash]; + ++m_curr_dash; + m_curr_dash_start = 0.0; + if(m_curr_dash >= m_num_dashes) m_curr_dash = 0; + } + else + { + m_curr_dash_start = ds; + ds = 0.0; + } + } + } + + + //------------------------------------------------------------------------ + void vcgen_dash::remove_all() + { + m_status = initial; + m_src_vertices.remove_all(); + m_closed = 0; + } + + + //------------------------------------------------------------------------ + void vcgen_dash::add_vertex(double x, double y, unsigned cmd) + { + m_status = initial; + if(is_move_to(cmd)) + { + m_src_vertices.modify_last(vertex_dist(x, y)); + } + else + { + if(is_vertex(cmd)) + { + m_src_vertices.add(vertex_dist(x, y)); + } + else + { + m_closed = get_close_flag(cmd); + } + } + } + + + //------------------------------------------------------------------------ + void vcgen_dash::rewind(unsigned) + { + if(m_status == initial) + { + m_src_vertices.close(m_closed != 0); + shorten_path(m_src_vertices, m_shorten, m_closed); + } + m_status = ready; + m_src_vertex = 0; + } + + + //------------------------------------------------------------------------ + unsigned vcgen_dash::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_move_to; + while(!is_stop(cmd)) + { + switch(m_status) + { + case initial: + rewind(0); + + case ready: + if(m_num_dashes < 2 || m_src_vertices.size() < 2) + { + cmd = path_cmd_stop; + break; + } + m_status = polyline; + m_src_vertex = 1; + m_v1 = &m_src_vertices[0]; + m_v2 = &m_src_vertices[1]; + m_curr_rest = m_v1->dist; + *x = m_v1->x; + *y = m_v1->y; + if(m_dash_start >= 0.0) calc_dash_start(m_dash_start); + return path_cmd_move_to; + + case polyline: + { + double dash_rest = m_dashes[m_curr_dash] - m_curr_dash_start; + + unsigned cmd = (m_curr_dash & 1) ? + path_cmd_move_to : + path_cmd_line_to; + + if(m_curr_rest > dash_rest) + { + m_curr_rest -= dash_rest; + ++m_curr_dash; + if(m_curr_dash >= m_num_dashes) m_curr_dash = 0; + m_curr_dash_start = 0.0; + *x = m_v2->x - (m_v2->x - m_v1->x) * m_curr_rest / m_v1->dist; + *y = m_v2->y - (m_v2->y - m_v1->y) * m_curr_rest / m_v1->dist; + } + else + { + m_curr_dash_start += m_curr_rest; + *x = m_v2->x; + *y = m_v2->y; + ++m_src_vertex; + m_v1 = m_v2; + m_curr_rest = m_v1->dist; + if(m_closed) + { + if(m_src_vertex > m_src_vertices.size()) + { + m_status = stop; + } + else + { + m_v2 = &m_src_vertices + [ + (m_src_vertex >= m_src_vertices.size()) ? 0 : + m_src_vertex + ]; + } + } + else + { + if(m_src_vertex >= m_src_vertices.size()) + { + m_status = stop; + } + else + { + m_v2 = &m_src_vertices[m_src_vertex]; + } + } + } + return cmd; + } + break; + + case stop: + cmd = path_cmd_stop; + break; + } + + } + return path_cmd_stop; + } + + +} + diff --git a/jni/desmume/src/android/agg/src/agg_vcgen_markers_term.cpp b/jni/desmume/src/android/agg/src/agg_vcgen_markers_term.cpp new file mode 100755 index 0000000..6a99e20 --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_vcgen_markers_term.cpp @@ -0,0 +1,108 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include "agg_vcgen_markers_term.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + void vcgen_markers_term::remove_all() + { + m_markers.remove_all(); + } + + + //------------------------------------------------------------------------ + void vcgen_markers_term::add_vertex(double x, double y, unsigned cmd) + { + if(is_move_to(cmd)) + { + if(m_markers.size() & 1) + { + // Initial state, the first coordinate was added. + // If two of more calls of start_vertex() occures + // we just modify the last one. + m_markers.modify_last(coord_type(x, y)); + } + else + { + m_markers.add(coord_type(x, y)); + } + } + else + { + if(is_vertex(cmd)) + { + if(m_markers.size() & 1) + { + // Initial state, the first coordinate was added. + // Add three more points, 0,1,1,0 + m_markers.add(coord_type(x, y)); + m_markers.add(m_markers[m_markers.size() - 1]); + m_markers.add(m_markers[m_markers.size() - 3]); + } + else + { + if(m_markers.size()) + { + // Replace two last points: 0,1,1,0 -> 0,1,2,1 + m_markers[m_markers.size() - 1] = m_markers[m_markers.size() - 2]; + m_markers[m_markers.size() - 2] = coord_type(x, y); + } + } + } + } + } + + + //------------------------------------------------------------------------ + void vcgen_markers_term::rewind(unsigned path_id) + { + m_curr_id = path_id * 2; + m_curr_idx = m_curr_id; + } + + + //------------------------------------------------------------------------ + unsigned vcgen_markers_term::vertex(double* x, double* y) + { + if(m_curr_id > 2 || m_curr_idx >= m_markers.size()) + { + return path_cmd_stop; + } + const coord_type& c = m_markers[m_curr_idx]; + *x = c.x; + *y = c.y; + if(m_curr_idx & 1) + { + m_curr_idx += 3; + return path_cmd_line_to; + } + ++m_curr_idx; + return path_cmd_move_to; + } + + +} diff --git a/jni/desmume/src/android/agg/src/agg_vcgen_smooth_poly1.cpp b/jni/desmume/src/android/agg/src/agg_vcgen_smooth_poly1.cpp new file mode 100755 index 0000000..4d0f3a2 --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_vcgen_smooth_poly1.cpp @@ -0,0 +1,230 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include "agg_vcgen_smooth_poly1.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + vcgen_smooth_poly1::vcgen_smooth_poly1() : + m_src_vertices(), + m_smooth_value(0.5), + m_closed(0), + m_status(initial), + m_src_vertex(0) + { + } + + + //------------------------------------------------------------------------ + void vcgen_smooth_poly1::remove_all() + { + m_src_vertices.remove_all(); + m_closed = 0; + m_status = initial; + } + + + //------------------------------------------------------------------------ + void vcgen_smooth_poly1::add_vertex(double x, double y, unsigned cmd) + { + m_status = initial; + if(is_move_to(cmd)) + { + m_src_vertices.modify_last(vertex_dist(x, y)); + } + else + { + if(is_vertex(cmd)) + { + m_src_vertices.add(vertex_dist(x, y)); + } + else + { + m_closed = get_close_flag(cmd); + } + } + } + + + //------------------------------------------------------------------------ + void vcgen_smooth_poly1::rewind(unsigned) + { + if(m_status == initial) + { + m_src_vertices.close(m_closed != 0); + } + m_status = ready; + m_src_vertex = 0; + } + + + //------------------------------------------------------------------------ + void vcgen_smooth_poly1::calculate(const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + const vertex_dist& v3) + { + + double k1 = v0.dist / (v0.dist + v1.dist); + double k2 = v1.dist / (v1.dist + v2.dist); + + double xm1 = v0.x + (v2.x - v0.x) * k1; + double ym1 = v0.y + (v2.y - v0.y) * k1; + double xm2 = v1.x + (v3.x - v1.x) * k2; + double ym2 = v1.y + (v3.y - v1.y) * k2; + + m_ctrl1_x = v1.x + m_smooth_value * (v2.x - xm1); + m_ctrl1_y = v1.y + m_smooth_value * (v2.y - ym1); + m_ctrl2_x = v2.x + m_smooth_value * (v1.x - xm2); + m_ctrl2_y = v2.y + m_smooth_value * (v1.y - ym2); + } + + + //------------------------------------------------------------------------ + unsigned vcgen_smooth_poly1::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + while(!is_stop(cmd)) + { + switch(m_status) + { + case initial: + rewind(0); + + case ready: + if(m_src_vertices.size() < 2) + { + cmd = path_cmd_stop; + break; + } + + if(m_src_vertices.size() == 2) + { + *x = m_src_vertices[m_src_vertex].x; + *y = m_src_vertices[m_src_vertex].y; + m_src_vertex++; + if(m_src_vertex == 1) return path_cmd_move_to; + if(m_src_vertex == 2) return path_cmd_line_to; + cmd = path_cmd_stop; + break; + } + + cmd = path_cmd_move_to; + m_status = polygon; + m_src_vertex = 0; + + case polygon: + if(m_closed) + { + if(m_src_vertex >= m_src_vertices.size()) + { + *x = m_src_vertices[0].x; + *y = m_src_vertices[0].y; + m_status = end_poly; + return path_cmd_curve4; + } + } + else + { + if(m_src_vertex >= m_src_vertices.size() - 1) + { + *x = m_src_vertices[m_src_vertices.size() - 1].x; + *y = m_src_vertices[m_src_vertices.size() - 1].y; + m_status = end_poly; + return path_cmd_curve3; + } + } + + calculate(m_src_vertices.prev(m_src_vertex), + m_src_vertices.curr(m_src_vertex), + m_src_vertices.next(m_src_vertex), + m_src_vertices.next(m_src_vertex + 1)); + + *x = m_src_vertices[m_src_vertex].x; + *y = m_src_vertices[m_src_vertex].y; + m_src_vertex++; + + if(m_closed) + { + m_status = ctrl1; + return ((m_src_vertex == 1) ? + path_cmd_move_to : + path_cmd_curve4); + } + else + { + if(m_src_vertex == 1) + { + m_status = ctrl_b; + return path_cmd_move_to; + } + if(m_src_vertex >= m_src_vertices.size() - 1) + { + m_status = ctrl_e; + return path_cmd_curve3; + } + m_status = ctrl1; + return path_cmd_curve4; + } + break; + + case ctrl_b: + *x = m_ctrl2_x; + *y = m_ctrl2_y; + m_status = polygon; + return path_cmd_curve3; + + case ctrl_e: + *x = m_ctrl1_x; + *y = m_ctrl1_y; + m_status = polygon; + return path_cmd_curve3; + + case ctrl1: + *x = m_ctrl1_x; + *y = m_ctrl1_y; + m_status = ctrl2; + return path_cmd_curve4; + + case ctrl2: + *x = m_ctrl2_x; + *y = m_ctrl2_y; + m_status = polygon; + return path_cmd_curve4; + + case end_poly: + m_status = stop; + return path_cmd_end_poly | m_closed; + + case stop: + return path_cmd_stop; + } + } + return cmd; + } + +} + diff --git a/jni/desmume/src/android/agg/src/agg_vcgen_stroke.cpp b/jni/desmume/src/android/agg/src/agg_vcgen_stroke.cpp new file mode 100755 index 0000000..db3ced9 --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_vcgen_stroke.cpp @@ -0,0 +1,219 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <math.h> +#include "agg_vcgen_stroke.h" +#include "agg_shorten_path.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + vcgen_stroke::vcgen_stroke() : + m_stroker(), + m_src_vertices(), + m_out_vertices(), + m_shorten(0.0), + m_closed(0), + m_status(initial), + m_src_vertex(0), + m_out_vertex(0) + { + } + + //------------------------------------------------------------------------ + void vcgen_stroke::remove_all() + { + m_src_vertices.remove_all(); + m_closed = 0; + m_status = initial; + } + + + //------------------------------------------------------------------------ + void vcgen_stroke::add_vertex(double x, double y, unsigned cmd) + { + m_status = initial; + if(is_move_to(cmd)) + { + m_src_vertices.modify_last(vertex_dist(x, y)); + } + else + { + if(is_vertex(cmd)) + { + m_src_vertices.add(vertex_dist(x, y)); + } + else + { + m_closed = get_close_flag(cmd); + } + } + } + + //------------------------------------------------------------------------ + void vcgen_stroke::rewind(unsigned) + { + if(m_status == initial) + { + m_src_vertices.close(m_closed != 0); + shorten_path(m_src_vertices, m_shorten, m_closed); + if(m_src_vertices.size() < 3) m_closed = 0; + } + m_status = ready; + m_src_vertex = 0; + m_out_vertex = 0; + } + + + //------------------------------------------------------------------------ + unsigned vcgen_stroke::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + while(!is_stop(cmd)) + { + switch(m_status) + { + case initial: + rewind(0); + + case ready: + if(m_src_vertices.size() < 2 + unsigned(m_closed != 0)) + { + cmd = path_cmd_stop; + break; + } + m_status = m_closed ? outline1 : cap1; + cmd = path_cmd_move_to; + m_src_vertex = 0; + m_out_vertex = 0; + break; + + case cap1: + m_stroker.calc_cap(m_out_vertices, + m_src_vertices[0], + m_src_vertices[1], + m_src_vertices[0].dist); + m_src_vertex = 1; + m_prev_status = outline1; + m_status = out_vertices; + m_out_vertex = 0; + break; + + case cap2: + m_stroker.calc_cap(m_out_vertices, + m_src_vertices[m_src_vertices.size() - 1], + m_src_vertices[m_src_vertices.size() - 2], + m_src_vertices[m_src_vertices.size() - 2].dist); + m_prev_status = outline2; + m_status = out_vertices; + m_out_vertex = 0; + break; + + case outline1: + if(m_closed) + { + if(m_src_vertex >= m_src_vertices.size()) + { + m_prev_status = close_first; + m_status = end_poly1; + break; + } + } + else + { + if(m_src_vertex >= m_src_vertices.size() - 1) + { + m_status = cap2; + break; + } + } + m_stroker.calc_join(m_out_vertices, + m_src_vertices.prev(m_src_vertex), + m_src_vertices.curr(m_src_vertex), + m_src_vertices.next(m_src_vertex), + m_src_vertices.prev(m_src_vertex).dist, + m_src_vertices.curr(m_src_vertex).dist); + ++m_src_vertex; + m_prev_status = m_status; + m_status = out_vertices; + m_out_vertex = 0; + break; + + case close_first: + m_status = outline2; + cmd = path_cmd_move_to; + + case outline2: + if(m_src_vertex <= unsigned(m_closed == 0)) + { + m_status = end_poly2; + m_prev_status = stop; + break; + } + + --m_src_vertex; + m_stroker.calc_join(m_out_vertices, + m_src_vertices.next(m_src_vertex), + m_src_vertices.curr(m_src_vertex), + m_src_vertices.prev(m_src_vertex), + m_src_vertices.curr(m_src_vertex).dist, + m_src_vertices.prev(m_src_vertex).dist); + + m_prev_status = m_status; + m_status = out_vertices; + m_out_vertex = 0; + break; + + case out_vertices: + if(m_out_vertex >= m_out_vertices.size()) + { + m_status = m_prev_status; + } + else + { + const point_d& c = m_out_vertices[m_out_vertex++]; + *x = c.x; + *y = c.y; + return cmd; + } + break; + + case end_poly1: + m_status = m_prev_status; + return path_cmd_end_poly | path_flags_close | path_flags_ccw; + + case end_poly2: + m_status = m_prev_status; + return path_cmd_end_poly | path_flags_close | path_flags_cw; + + case stop: + cmd = path_cmd_stop; + break; + } + } + return cmd; + } + +} diff --git a/jni/desmume/src/android/agg/src/agg_vpgen_clip_polygon.cpp b/jni/desmume/src/android/agg/src/agg_vpgen_clip_polygon.cpp new file mode 100755 index 0000000..7933826 --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_vpgen_clip_polygon.cpp @@ -0,0 +1,142 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include "agg_vpgen_clip_polygon.h" +#include "agg_clip_liang_barsky.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + // Determine the clipping code of the vertex according to the + // Cyrus-Beck line clipping algorithm + // + // | | + // 0110 | 0010 | 0011 + // | | + // -------+--------+-------- clip_box.y2 + // | | + // 0100 | 0000 | 0001 + // | | + // -------+--------+-------- clip_box.y1 + // | | + // 1100 | 1000 | 1001 + // | | + // clip_box.x1 clip_box.x2 + // + // + unsigned vpgen_clip_polygon::clipping_flags(double x, double y) + { + if(x < m_clip_box.x1) + { + if(y > m_clip_box.y2) return 6; + if(y < m_clip_box.y1) return 12; + return 4; + } + + if(x > m_clip_box.x2) + { + if(y > m_clip_box.y2) return 3; + if(y < m_clip_box.y1) return 9; + return 1; + } + + if(y > m_clip_box.y2) return 2; + if(y < m_clip_box.y1) return 8; + + return 0; + } + + //---------------------------------------------------------------------------- + void vpgen_clip_polygon::reset() + { + m_vertex = 0; + m_num_vertices = 0; + } + + //---------------------------------------------------------------------------- + void vpgen_clip_polygon::move_to(double x, double y) + { + m_vertex = 0; + m_num_vertices = 0; + m_clip_flags = clipping_flags(x, y); + if(m_clip_flags == 0) + { + m_x[0] = x; + m_y[0] = y; + m_num_vertices = 1; + } + m_x1 = x; + m_y1 = y; + m_cmd = path_cmd_move_to; + } + + + //---------------------------------------------------------------------------- + void vpgen_clip_polygon::line_to(double x, double y) + { + m_vertex = 0; + m_num_vertices = 0; + unsigned flags = clipping_flags(x, y); + + if(m_clip_flags == flags) + { + if(flags == 0) + { + m_x[0] = x; + m_y[0] = y; + m_num_vertices = 1; + } + } + else + { + m_num_vertices = clip_liang_barsky(m_x1, m_y1, + x, y, + m_clip_box, + m_x, m_y); + } + + m_clip_flags = flags; + m_x1 = x; + m_y1 = y; + } + + + //---------------------------------------------------------------------------- + unsigned vpgen_clip_polygon::vertex(double* x, double* y) + { + if(m_vertex < m_num_vertices) + { + *x = m_x[m_vertex]; + *y = m_y[m_vertex]; + ++m_vertex; + unsigned cmd = m_cmd; + m_cmd = path_cmd_line_to; + return cmd; + } + return path_cmd_stop; + } + + +} diff --git a/jni/desmume/src/android/agg/src/agg_vpgen_clip_polyline.cpp b/jni/desmume/src/android/agg/src/agg_vpgen_clip_polyline.cpp new file mode 100755 index 0000000..0b31864 --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_vpgen_clip_polyline.cpp @@ -0,0 +1,86 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include "agg_vpgen_clip_polyline.h" +#include "agg_clip_liang_barsky.h" + +namespace agg +{ + //---------------------------------------------------------------------------- + void vpgen_clip_polyline::reset() + { + m_vertex = 0; + m_num_vertices = 0; + m_move_to = false; + } + + //---------------------------------------------------------------------------- + void vpgen_clip_polyline::move_to(double x, double y) + { + m_vertex = 0; + m_num_vertices = 0; + m_x1 = x; + m_y1 = y; + m_move_to = true; + } + + //---------------------------------------------------------------------------- + void vpgen_clip_polyline::line_to(double x, double y) + { + double x2 = x; + double y2 = y; + unsigned flags = clip_line_segment(&m_x1, &m_y1, &x2, &y2, m_clip_box); + + m_vertex = 0; + m_num_vertices = 0; + if((flags & 4) == 0) + { + if((flags & 1) != 0 || m_move_to) + { + m_x[0] = m_x1; + m_y[0] = m_y1; + m_cmd[0] = path_cmd_move_to; + m_num_vertices = 1; + } + m_x[m_num_vertices] = x2; + m_y[m_num_vertices] = y2; + m_cmd[m_num_vertices++] = path_cmd_line_to; + m_move_to = (flags & 2) != 0; + } + m_x1 = x; + m_y1 = y; + } + + //---------------------------------------------------------------------------- + unsigned vpgen_clip_polyline::vertex(double* x, double* y) + { + if(m_vertex < m_num_vertices) + { + *x = m_x[m_vertex]; + *y = m_y[m_vertex]; + return m_cmd[m_vertex++]; + } + return path_cmd_stop; + } +} diff --git a/jni/desmume/src/android/agg/src/agg_vpgen_segmentator.cpp b/jni/desmume/src/android/agg/src/agg_vpgen_segmentator.cpp new file mode 100755 index 0000000..0ea3b9a --- /dev/null +++ b/jni/desmume/src/android/agg/src/agg_vpgen_segmentator.cpp @@ -0,0 +1,76 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <math.h> +#include "agg_vpgen_segmentator.h" + +namespace agg +{ + + void vpgen_segmentator::move_to(double x, double y) + { + m_x1 = x; + m_y1 = y; + m_dx = 0.0; + m_dy = 0.0; + m_dl = 2.0; + m_ddl = 2.0; + m_cmd = path_cmd_move_to; + } + + void vpgen_segmentator::line_to(double x, double y) + { + m_x1 += m_dx; + m_y1 += m_dy; + m_dx = x - m_x1; + m_dy = y - m_y1; + double len = sqrt(m_dx * m_dx + m_dy * m_dy) * m_approximation_scale; + if(len < 1e-30) len = 1e-30; + m_ddl = 1.0 / len; + m_dl = (m_cmd == path_cmd_move_to) ? 0.0 : m_ddl; + if(m_cmd == path_cmd_stop) m_cmd = path_cmd_line_to; + } + + unsigned vpgen_segmentator::vertex(double* x, double* y) + { + if(m_cmd == path_cmd_stop) return path_cmd_stop; + + unsigned cmd = m_cmd; + m_cmd = path_cmd_line_to; + if(m_dl >= 1.0 - m_ddl) + { + m_dl = 1.0; + m_cmd = path_cmd_stop; + *x = m_x1 + m_dx; + *y = m_y1 + m_dy; + return cmd; + } + *x = m_x1 + m_dx * m_dl; + *y = m_y1 + m_dy * m_dl; + m_dl += m_ddl; + return cmd; + } + +} + diff --git a/jni/desmume/src/android/agg/src/authors b/jni/desmume/src/android/agg/src/authors new file mode 100755 index 0000000..e69de29 diff --git a/jni/desmume/src/android/agg/src/autogen.sh b/jni/desmume/src/android/agg/src/autogen.sh new file mode 100755 index 0000000..47b83a0 --- /dev/null +++ b/jni/desmume/src/android/agg/src/autogen.sh @@ -0,0 +1,20 @@ +# autogen.sh +# +# invoke the auto* tools to create the configureation system + +# build aclocal.m4 +aclocal + +# build the configure script +autoconf + +# set up libtool +libtoolize --force + +# invoke automake +automake --foreign --add-missing + +# and finally invoke our new configure +./configure $* + +# end diff --git a/jni/desmume/src/android/agg/src/configure.in b/jni/desmume/src/android/agg/src/configure.in new file mode 100755 index 0000000..e821f6f --- /dev/null +++ b/jni/desmume/src/android/agg/src/configure.in @@ -0,0 +1,15 @@ +AC_INIT(src/agg_arc.cpp) # give me a source file, any source file... +AM_INIT_AUTOMAKE(agg, 2.0.0) + +AC_PROG_LN_S +AC_PROG_CC +AC_PROG_CPP +AC_PROG_CXX +AC_PROG_LIBTOOL + +AC_OUTPUT( + Makefile + gpc/Makefile + src/Makefile + src/ctrl/Makefile +) diff --git a/jni/desmume/src/android/agg/src/copying b/jni/desmume/src/android/agg/src/copying new file mode 100755 index 0000000..addf69c --- /dev/null +++ b/jni/desmume/src/android/agg/src/copying @@ -0,0 +1,21 @@ +Anti-Grain Geometry (AGG) - Version 2.5 +A high quality rendering engine for C++ +Copyright (C) 2002-2006 Maxim Shemanarev +Contact: mcseem@antigrain.com + mcseemagg@yahoo.com + http://antigrain.com + +AGG 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. + +AGG 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 AGG; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +MA 02110-1301, USA. diff --git a/jni/desmume/src/android/agg/src/ctrl/Makefile.am b/jni/desmume/src/android/agg/src/ctrl/Makefile.am new file mode 100755 index 0000000..c51aab6 --- /dev/null +++ b/jni/desmume/src/android/agg/src/ctrl/Makefile.am @@ -0,0 +1,11 @@ +if ENABLE_CTRL +INCLUDES = -I$(top_srcdir)/include + +noinst_LTLIBRARIES = libaggctrl.la + +libaggctrl_la_LDFLAGS = -no-undefined -version-info @AGG_LIB_VERSION@ +libaggctrl_la_SOURCES = agg_cbox_ctrl.cpp agg_gamma_ctrl.cpp agg_gamma_spline.cpp agg_rbox_ctrl.cpp \ + agg_slider_ctrl.cpp agg_spline_ctrl.cpp agg_scale_ctrl.cpp \ + agg_bezier_ctrl.cpp agg_polygon_ctrl.cpp + +endif diff --git a/jni/desmume/src/android/agg/src/ctrl/agg_bezier_ctrl.cpp b/jni/desmume/src/android/agg/src/ctrl/agg_bezier_ctrl.cpp new file mode 100755 index 0000000..92e060d --- /dev/null +++ b/jni/desmume/src/android/agg/src/ctrl/agg_bezier_ctrl.cpp @@ -0,0 +1,375 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <string.h> +#include <stdio.h> +#include "ctrl/agg_bezier_ctrl.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + bezier_ctrl_impl::bezier_ctrl_impl() : + ctrl(0,0,1,1,false), + m_stroke(m_curve), + m_poly(4, 5.0), + m_idx(0) + { + m_poly.in_polygon_check(false); + m_poly.xn(0) = 100.0; + m_poly.yn(0) = 0.0; + m_poly.xn(1) = 100.0; + m_poly.yn(1) = 50.0; + m_poly.xn(2) = 50.0; + m_poly.yn(2) = 100.0; + m_poly.xn(3) = 0.0; + m_poly.yn(3) = 100.0; + } + + + //------------------------------------------------------------------------ + void bezier_ctrl_impl::curve(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + m_poly.xn(0) = x1; + m_poly.yn(0) = y1; + m_poly.xn(1) = x2; + m_poly.yn(1) = y2; + m_poly.xn(2) = x3; + m_poly.yn(2) = y3; + m_poly.xn(3) = x4; + m_poly.yn(3) = y4; + curve(); + } + + //------------------------------------------------------------------------ + curve4& bezier_ctrl_impl::curve() + { + m_curve.init(m_poly.xn(0), m_poly.yn(0), + m_poly.xn(1), m_poly.yn(1), + m_poly.xn(2), m_poly.yn(2), + m_poly.xn(3), m_poly.yn(3)); + return m_curve; + } + + //------------------------------------------------------------------------ + void bezier_ctrl_impl::rewind(unsigned idx) + { + m_idx = idx; + + m_curve.approximation_scale(scale()); + switch(idx) + { + default: + case 0: // Control line 1 + m_curve.init(m_poly.xn(0), m_poly.yn(0), + (m_poly.xn(0) + m_poly.xn(1)) * 0.5, + (m_poly.yn(0) + m_poly.yn(1)) * 0.5, + (m_poly.xn(0) + m_poly.xn(1)) * 0.5, + (m_poly.yn(0) + m_poly.yn(1)) * 0.5, + m_poly.xn(1), m_poly.yn(1)); + m_stroke.rewind(0); + break; + + case 1: // Control line 2 + m_curve.init(m_poly.xn(2), m_poly.yn(2), + (m_poly.xn(2) + m_poly.xn(3)) * 0.5, + (m_poly.yn(2) + m_poly.yn(3)) * 0.5, + (m_poly.xn(2) + m_poly.xn(3)) * 0.5, + (m_poly.yn(2) + m_poly.yn(3)) * 0.5, + m_poly.xn(3), m_poly.yn(3)); + m_stroke.rewind(0); + break; + + case 2: // Curve itself + m_curve.init(m_poly.xn(0), m_poly.yn(0), + m_poly.xn(1), m_poly.yn(1), + m_poly.xn(2), m_poly.yn(2), + m_poly.xn(3), m_poly.yn(3)); + m_stroke.rewind(0); + break; + + case 3: // Point 1 + m_ellipse.init(m_poly.xn(0), m_poly.yn(0), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + + case 4: // Point 2 + m_ellipse.init(m_poly.xn(1), m_poly.yn(1), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + + case 5: // Point 3 + m_ellipse.init(m_poly.xn(2), m_poly.yn(2), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + + case 6: // Point 4 + m_ellipse.init(m_poly.xn(3), m_poly.yn(3), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + } + } + + + //------------------------------------------------------------------------ + unsigned bezier_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + switch(m_idx) + { + case 0: + case 1: + case 2: + cmd = m_stroke.vertex(x, y); + break; + + case 3: + case 4: + case 5: + case 6: + case 7: + cmd = m_ellipse.vertex(x, y); + break; + } + + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + return cmd; + } + + + + //------------------------------------------------------------------------ + bool bezier_ctrl_impl::in_rect(double x, double y) const + { + return false; + } + + + //------------------------------------------------------------------------ + bool bezier_ctrl_impl::on_mouse_button_down(double x, double y) + { + inverse_transform_xy(&x, &y); + return m_poly.on_mouse_button_down(x, y); + } + + + //------------------------------------------------------------------------ + bool bezier_ctrl_impl::on_mouse_move(double x, double y, bool button_flag) + { + inverse_transform_xy(&x, &y); + return m_poly.on_mouse_move(x, y, button_flag); + } + + + //------------------------------------------------------------------------ + bool bezier_ctrl_impl::on_mouse_button_up(double x, double y) + { + return m_poly.on_mouse_button_up(x, y); + } + + + //------------------------------------------------------------------------ + bool bezier_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up) + { + return m_poly.on_arrow_keys(left, right, down, up); + } + + + + + + + //------------------------------------------------------------------------ + curve3_ctrl_impl::curve3_ctrl_impl() : + ctrl(0,0,1,1,false), + m_stroke(m_curve), + m_poly(3, 5.0), + m_idx(0) + { + m_poly.in_polygon_check(false); + m_poly.xn(0) = 100.0; + m_poly.yn(0) = 0.0; + m_poly.xn(1) = 100.0; + m_poly.yn(1) = 50.0; + m_poly.xn(2) = 50.0; + m_poly.yn(2) = 100.0; + } + + + //------------------------------------------------------------------------ + void curve3_ctrl_impl::curve(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + m_poly.xn(0) = x1; + m_poly.yn(0) = y1; + m_poly.xn(1) = x2; + m_poly.yn(1) = y2; + m_poly.xn(2) = x3; + m_poly.yn(2) = y3; + curve(); + } + + //------------------------------------------------------------------------ + curve3& curve3_ctrl_impl::curve() + { + m_curve.init(m_poly.xn(0), m_poly.yn(0), + m_poly.xn(1), m_poly.yn(1), + m_poly.xn(2), m_poly.yn(2)); + return m_curve; + } + + //------------------------------------------------------------------------ + void curve3_ctrl_impl::rewind(unsigned idx) + { + m_idx = idx; + + switch(idx) + { + default: + case 0: // Control line + m_curve.init(m_poly.xn(0), m_poly.yn(0), + (m_poly.xn(0) + m_poly.xn(1)) * 0.5, + (m_poly.yn(0) + m_poly.yn(1)) * 0.5, + m_poly.xn(1), m_poly.yn(1)); + m_stroke.rewind(0); + break; + + case 1: // Control line 2 + m_curve.init(m_poly.xn(1), m_poly.yn(1), + (m_poly.xn(1) + m_poly.xn(2)) * 0.5, + (m_poly.yn(1) + m_poly.yn(2)) * 0.5, + m_poly.xn(2), m_poly.yn(2)); + m_stroke.rewind(0); + break; + + case 2: // Curve itself + m_curve.init(m_poly.xn(0), m_poly.yn(0), + m_poly.xn(1), m_poly.yn(1), + m_poly.xn(2), m_poly.yn(2)); + m_stroke.rewind(0); + break; + + case 3: // Point 1 + m_ellipse.init(m_poly.xn(0), m_poly.yn(0), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + + case 4: // Point 2 + m_ellipse.init(m_poly.xn(1), m_poly.yn(1), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + + case 5: // Point 3 + m_ellipse.init(m_poly.xn(2), m_poly.yn(2), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + } + } + + + //------------------------------------------------------------------------ + unsigned curve3_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + switch(m_idx) + { + case 0: + case 1: + case 2: + cmd = m_stroke.vertex(x, y); + break; + + case 3: + case 4: + case 5: + case 6: + cmd = m_ellipse.vertex(x, y); + break; + } + + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + return cmd; + } + + + + //------------------------------------------------------------------------ + bool curve3_ctrl_impl::in_rect(double x, double y) const + { + return false; + } + + + //------------------------------------------------------------------------ + bool curve3_ctrl_impl::on_mouse_button_down(double x, double y) + { + inverse_transform_xy(&x, &y); + return m_poly.on_mouse_button_down(x, y); + } + + + //------------------------------------------------------------------------ + bool curve3_ctrl_impl::on_mouse_move(double x, double y, bool button_flag) + { + inverse_transform_xy(&x, &y); + return m_poly.on_mouse_move(x, y, button_flag); + } + + + //------------------------------------------------------------------------ + bool curve3_ctrl_impl::on_mouse_button_up(double x, double y) + { + return m_poly.on_mouse_button_up(x, y); + } + + + //------------------------------------------------------------------------ + bool curve3_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up) + { + return m_poly.on_arrow_keys(left, right, down, up); + } + + + + + + + + + + + + +} + diff --git a/jni/desmume/src/android/agg/src/ctrl/agg_cbox_ctrl.cpp b/jni/desmume/src/android/agg/src/ctrl/agg_cbox_ctrl.cpp new file mode 100755 index 0000000..0d8c3e6 --- /dev/null +++ b/jni/desmume/src/android/agg/src/ctrl/agg_cbox_ctrl.cpp @@ -0,0 +1,219 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <string.h> +#include "ctrl/agg_cbox_ctrl.h" + + +namespace agg +{ + + //------------------------------------------------------------------------ + cbox_ctrl_impl::cbox_ctrl_impl(double x, double y, + const char* l, + bool flip_y) : + ctrl(x, y, x + 9.0 * 1.5, y + 9.0 * 1.5, flip_y), + m_text_thickness(1.5), + m_text_height(9.0), + m_text_width(0.0), + m_status(false), + m_text_poly(m_text) + { + label(l); + } + + + //------------------------------------------------------------------------ + void cbox_ctrl_impl::text_size(double h, double w) + { + m_text_width = w; + m_text_height = h; + } + + //------------------------------------------------------------------------ + void cbox_ctrl_impl::label(const char* l) + { + unsigned len = strlen(l); + if(len > 127) len = 127; + memcpy(m_label, l, len); + m_label[len] = 0; + } + + + //------------------------------------------------------------------------ + bool cbox_ctrl_impl::on_mouse_button_down(double x, double y) + { + inverse_transform_xy(&x, &y); + if(x >= m_x1 && y >= m_y1 && x <= m_x2 && y <= m_y2) + { + m_status = !m_status; + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + bool cbox_ctrl_impl::on_mouse_move(double, double, bool) + { + return false; + } + + //------------------------------------------------------------------------ + bool cbox_ctrl_impl::in_rect(double x, double y) const + { + inverse_transform_xy(&x, &y); + return x >= m_x1 && y >= m_y1 && x <= m_x2 && y <= m_y2; + } + + //------------------------------------------------------------------------ + bool cbox_ctrl_impl::on_mouse_button_up(double, double) + { + return false; + } + + //------------------------------------------------------------------------ + bool cbox_ctrl_impl::on_arrow_keys(bool, bool, bool, bool) + { + return false; + } + + + //------------------------------------------------------------------------ + void cbox_ctrl_impl::rewind(unsigned idx) + { + m_idx = idx; + + double d2; + double t; + + switch(idx) + { + default: + case 0: // Border + m_vertex = 0; + m_vx[0] = m_x1; + m_vy[0] = m_y1; + m_vx[1] = m_x2; + m_vy[1] = m_y1; + m_vx[2] = m_x2; + m_vy[2] = m_y2; + m_vx[3] = m_x1; + m_vy[3] = m_y2; + m_vx[4] = m_x1 + m_text_thickness; + m_vy[4] = m_y1 + m_text_thickness; + m_vx[5] = m_x1 + m_text_thickness; + m_vy[5] = m_y2 - m_text_thickness; + m_vx[6] = m_x2 - m_text_thickness; + m_vy[6] = m_y2 - m_text_thickness; + m_vx[7] = m_x2 - m_text_thickness; + m_vy[7] = m_y1 + m_text_thickness; + break; + + case 1: // Text + m_text.text(m_label); + m_text.start_point(m_x1 + m_text_height * 2.0, m_y1 + m_text_height / 5.0); + m_text.size(m_text_height, m_text_width); + m_text_poly.width(m_text_thickness); + m_text_poly.line_join(round_join); + m_text_poly.line_cap(round_cap); + m_text_poly.rewind(0); + break; + + case 2: // Active item + m_vertex = 0; + d2 = (m_y2 - m_y1) / 2.0; + t = m_text_thickness * 1.5; + m_vx[0] = m_x1 + m_text_thickness; + m_vy[0] = m_y1 + m_text_thickness; + m_vx[1] = m_x1 + d2; + m_vy[1] = m_y1 + d2 - t; + m_vx[2] = m_x2 - m_text_thickness; + m_vy[2] = m_y1 + m_text_thickness; + m_vx[3] = m_x1 + d2 + t; + m_vy[3] = m_y1 + d2; + m_vx[4] = m_x2 - m_text_thickness; + m_vy[4] = m_y2 - m_text_thickness; + m_vx[5] = m_x1 + d2; + m_vy[5] = m_y1 + d2 + t; + m_vx[6] = m_x1 + m_text_thickness; + m_vy[6] = m_y2 - m_text_thickness; + m_vx[7] = m_x1 + d2 - t; + m_vy[7] = m_y1 + d2; + break; + + } + } + + + + + //------------------------------------------------------------------------ + unsigned cbox_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + switch(m_idx) + { + case 0: + if(m_vertex == 0 || m_vertex == 4) cmd = path_cmd_move_to; + if(m_vertex >= 8) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 1: + cmd = m_text_poly.vertex(x, y); + break; + + case 2: + if(m_status) + { + if(m_vertex == 0) cmd = path_cmd_move_to; + if(m_vertex >= 8) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + } + else + { + cmd = path_cmd_stop; + } + break; + + default: + cmd = path_cmd_stop; + break; + } + + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + return cmd; + } +} + + + diff --git a/jni/desmume/src/android/agg/src/ctrl/agg_gamma_ctrl.cpp b/jni/desmume/src/android/agg/src/ctrl/agg_gamma_ctrl.cpp new file mode 100755 index 0000000..7db8a9e --- /dev/null +++ b/jni/desmume/src/android/agg/src/ctrl/agg_gamma_ctrl.cpp @@ -0,0 +1,438 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <stdio.h> +#include "agg_math.h" +#include "ctrl/agg_gamma_ctrl.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + gamma_ctrl_impl::gamma_ctrl_impl(double x1, double y1, double x2, double y2, bool flip_y) : + ctrl(x1, y1, x2, y2, flip_y), + m_border_width(2.0), + m_border_extra(0.0), + m_curve_width(2.0), + m_grid_width(0.2), + m_text_thickness(1.5), + m_point_size(5.0), + m_text_height(9.0), + m_text_width(0.0), + m_xc1(x1), + m_yc1(y1), + m_xc2(x2), + m_yc2(y2 - m_text_height * 2.0), + m_xt1(x1), + m_yt1(y2 - m_text_height * 2.0), + m_xt2(x2), + m_yt2(y2), + m_curve_poly(m_gamma_spline), + m_text_poly(m_text), + m_idx(0), + m_vertex(0), + m_p1_active(true), + m_mouse_point(0), + m_pdx(0.0), + m_pdy(0.0) + { + calc_spline_box(); + } + + + //------------------------------------------------------------------------ + void gamma_ctrl_impl::calc_spline_box() + { + m_xs1 = m_xc1 + m_border_width; + m_ys1 = m_yc1 + m_border_width; + m_xs2 = m_xc2 - m_border_width; + m_ys2 = m_yc2 - m_border_width * 0.5; + } + + + //------------------------------------------------------------------------ + void gamma_ctrl_impl::calc_points() + { + double kx1, ky1, kx2, ky2; + m_gamma_spline.values(&kx1, &ky1, &kx2, &ky2); + m_xp1 = m_xs1 + (m_xs2 - m_xs1) * kx1 * 0.25; + m_yp1 = m_ys1 + (m_ys2 - m_ys1) * ky1 * 0.25; + m_xp2 = m_xs2 - (m_xs2 - m_xs1) * kx2 * 0.25; + m_yp2 = m_ys2 - (m_ys2 - m_ys1) * ky2 * 0.25; + } + + + //------------------------------------------------------------------------ + void gamma_ctrl_impl::calc_values() + { + double kx1, ky1, kx2, ky2; + + kx1 = (m_xp1 - m_xs1) * 4.0 / (m_xs2 - m_xs1); + ky1 = (m_yp1 - m_ys1) * 4.0 / (m_ys2 - m_ys1); + kx2 = (m_xs2 - m_xp2) * 4.0 / (m_xs2 - m_xs1); + ky2 = (m_ys2 - m_yp2) * 4.0 / (m_ys2 - m_ys1); + m_gamma_spline.values(kx1, ky1, kx2, ky2); + } + + + //------------------------------------------------------------------------ + void gamma_ctrl_impl::text_size(double h, double w) + { + m_text_width = w; + m_text_height = h; + m_yc2 = m_y2 - m_text_height * 2.0; + m_yt1 = m_y2 - m_text_height * 2.0; + calc_spline_box(); + } + + + //------------------------------------------------------------------------ + void gamma_ctrl_impl::border_width(double t, double extra) + { + m_border_width = t; + m_border_extra = extra; + calc_spline_box(); + } + + //------------------------------------------------------------------------ + void gamma_ctrl_impl::values(double kx1, double ky1, double kx2, double ky2) + { + m_gamma_spline.values(kx1, ky1, kx2, ky2); + } + + + //------------------------------------------------------------------------ + void gamma_ctrl_impl::values(double* kx1, double* ky1, double* kx2, double* ky2) const + { + m_gamma_spline.values(kx1, ky1, kx2, ky2); + } + + //------------------------------------------------------------------------ + void gamma_ctrl_impl::rewind(unsigned idx) + { + double kx1, ky1, kx2, ky2; + char tbuf[32]; + + m_idx = idx; + + switch(idx) + { + default: + + case 0: // Background + m_vertex = 0; + m_vx[0] = m_x1 - m_border_extra; + m_vy[0] = m_y1 - m_border_extra; + m_vx[1] = m_x2 + m_border_extra; + m_vy[1] = m_y1 - m_border_extra; + m_vx[2] = m_x2 + m_border_extra; + m_vy[2] = m_y2 + m_border_extra; + m_vx[3] = m_x1 - m_border_extra; + m_vy[3] = m_y2 + m_border_extra; + break; + + case 1: // Border + m_vertex = 0; + m_vx[0] = m_x1; + m_vy[0] = m_y1; + m_vx[1] = m_x2; + m_vy[1] = m_y1; + m_vx[2] = m_x2; + m_vy[2] = m_y2; + m_vx[3] = m_x1; + m_vy[3] = m_y2; + m_vx[4] = m_x1 + m_border_width; + m_vy[4] = m_y1 + m_border_width; + m_vx[5] = m_x1 + m_border_width; + m_vy[5] = m_y2 - m_border_width; + m_vx[6] = m_x2 - m_border_width; + m_vy[6] = m_y2 - m_border_width; + m_vx[7] = m_x2 - m_border_width; + m_vy[7] = m_y1 + m_border_width; + m_vx[8] = m_xc1 + m_border_width; + m_vy[8] = m_yc2 - m_border_width * 0.5; + m_vx[9] = m_xc2 - m_border_width; + m_vy[9] = m_yc2 - m_border_width * 0.5; + m_vx[10] = m_xc2 - m_border_width; + m_vy[10] = m_yc2 + m_border_width * 0.5; + m_vx[11] = m_xc1 + m_border_width; + m_vy[11] = m_yc2 + m_border_width * 0.5; + break; + + case 2: // Curve + m_gamma_spline.box(m_xs1, m_ys1, m_xs2, m_ys2); + m_curve_poly.width(m_curve_width); + m_curve_poly.rewind(0); + break; + + case 3: // Grid + m_vertex = 0; + m_vx[0] = m_xs1; + m_vy[0] = (m_ys1 + m_ys2) * 0.5 - m_grid_width * 0.5; + m_vx[1] = m_xs2; + m_vy[1] = (m_ys1 + m_ys2) * 0.5 - m_grid_width * 0.5; + m_vx[2] = m_xs2; + m_vy[2] = (m_ys1 + m_ys2) * 0.5 + m_grid_width * 0.5; + m_vx[3] = m_xs1; + m_vy[3] = (m_ys1 + m_ys2) * 0.5 + m_grid_width * 0.5; + m_vx[4] = (m_xs1 + m_xs2) * 0.5 - m_grid_width * 0.5; + m_vy[4] = m_ys1; + m_vx[5] = (m_xs1 + m_xs2) * 0.5 - m_grid_width * 0.5; + m_vy[5] = m_ys2; + m_vx[6] = (m_xs1 + m_xs2) * 0.5 + m_grid_width * 0.5; + m_vy[6] = m_ys2; + m_vx[7] = (m_xs1 + m_xs2) * 0.5 + m_grid_width * 0.5; + m_vy[7] = m_ys1; + calc_points(); + m_vx[8] = m_xs1; + m_vy[8] = m_yp1 - m_grid_width * 0.5; + m_vx[9] = m_xp1 - m_grid_width * 0.5; + m_vy[9] = m_yp1 - m_grid_width * 0.5; + m_vx[10] = m_xp1 - m_grid_width * 0.5; + m_vy[10] = m_ys1; + m_vx[11] = m_xp1 + m_grid_width * 0.5; + m_vy[11] = m_ys1; + m_vx[12] = m_xp1 + m_grid_width * 0.5; + m_vy[12] = m_yp1 + m_grid_width * 0.5; + m_vx[13] = m_xs1; + m_vy[13] = m_yp1 + m_grid_width * 0.5; + m_vx[14] = m_xs2; + m_vy[14] = m_yp2 + m_grid_width * 0.5; + m_vx[15] = m_xp2 + m_grid_width * 0.5; + m_vy[15] = m_yp2 + m_grid_width * 0.5; + m_vx[16] = m_xp2 + m_grid_width * 0.5; + m_vy[16] = m_ys2; + m_vx[17] = m_xp2 - m_grid_width * 0.5; + m_vy[17] = m_ys2; + m_vx[18] = m_xp2 - m_grid_width * 0.5; + m_vy[18] = m_yp2 - m_grid_width * 0.5; + m_vx[19] = m_xs2; + m_vy[19] = m_yp2 - m_grid_width * 0.5; + break; + + case 4: // Point1 + calc_points(); + if(m_p1_active) m_ellipse.init(m_xp2, m_yp2, m_point_size, m_point_size, 32); + else m_ellipse.init(m_xp1, m_yp1, m_point_size, m_point_size, 32); + break; + + case 5: // Point2 + calc_points(); + if(m_p1_active) m_ellipse.init(m_xp1, m_yp1, m_point_size, m_point_size, 32); + else m_ellipse.init(m_xp2, m_yp2, m_point_size, m_point_size, 32); + break; + + case 6: // Text + m_gamma_spline.values(&kx1, &ky1, &kx2, &ky2); + sprintf(tbuf, "%5.3f %5.3f %5.3f %5.3f", kx1, ky1, kx2, ky2); + m_text.text(tbuf); + m_text.size(m_text_height, m_text_width); + m_text.start_point(m_xt1 + m_border_width * 2.0, (m_yt1 + m_yt2) * 0.5 - m_text_height * 0.5); + m_text_poly.width(m_text_thickness); + m_text_poly.line_join(round_join); + m_text_poly.line_cap(round_cap); + m_text_poly.rewind(0); + break; + } + } + + + //------------------------------------------------------------------------ + unsigned gamma_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + switch(m_idx) + { + case 0: + if(m_vertex == 0) cmd = path_cmd_move_to; + if(m_vertex >= 4) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 1: + if(m_vertex == 0 || m_vertex == 4 || m_vertex == 8) cmd = path_cmd_move_to; + if(m_vertex >= 12) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 2: + cmd = m_curve_poly.vertex(x, y); + break; + + case 3: + if(m_vertex == 0 || + m_vertex == 4 || + m_vertex == 8 || + m_vertex == 14) cmd = path_cmd_move_to; + + if(m_vertex >= 20) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 4: // Point1 + case 5: // Point2 + cmd = m_ellipse.vertex(x, y); + break; + + case 6: + cmd = m_text_poly.vertex(x, y); + break; + + default: + cmd = path_cmd_stop; + break; + } + + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + + return cmd; + } + + + + //------------------------------------------------------------------------ + bool gamma_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up) + { + double kx1, ky1, kx2, ky2; + bool ret = false; + m_gamma_spline.values(&kx1, &ky1, &kx2, &ky2); + if(m_p1_active) + { + if(left) { kx1 -= 0.005; ret = true; } + if(right) { kx1 += 0.005; ret = true; } + if(down) { ky1 -= 0.005; ret = true; } + if(up) { ky1 += 0.005; ret = true; } + } + else + { + if(left) { kx2 += 0.005; ret = true; } + if(right) { kx2 -= 0.005; ret = true; } + if(down) { ky2 += 0.005; ret = true; } + if(up) { ky2 -= 0.005; ret = true; } + } + if(ret) + { + m_gamma_spline.values(kx1, ky1, kx2, ky2); + } + return ret; + } + + + + //------------------------------------------------------------------------ + void gamma_ctrl_impl::change_active_point() + { + m_p1_active = m_p1_active ? false : true; + } + + + + + //------------------------------------------------------------------------ + bool gamma_ctrl_impl::in_rect(double x, double y) const + { + inverse_transform_xy(&x, &y); + return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2; + } + + + //------------------------------------------------------------------------ + bool gamma_ctrl_impl::on_mouse_button_down(double x, double y) + { + inverse_transform_xy(&x, &y); + calc_points(); + + if(calc_distance(x, y, m_xp1, m_yp1) <= m_point_size + 1) + { + m_mouse_point = 1; + m_pdx = m_xp1 - x; + m_pdy = m_yp1 - y; + m_p1_active = true; + return true; + } + + if(calc_distance(x, y, m_xp2, m_yp2) <= m_point_size + 1) + { + m_mouse_point = 2; + m_pdx = m_xp2 - x; + m_pdy = m_yp2 - y; + m_p1_active = false; + return true; + } + + return false; + } + + + //------------------------------------------------------------------------ + bool gamma_ctrl_impl::on_mouse_button_up(double, double) + { + if(m_mouse_point) + { + m_mouse_point = 0; + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + bool gamma_ctrl_impl::on_mouse_move(double x, double y, bool button_flag) + { + inverse_transform_xy(&x, &y); + if(!button_flag) + { + return on_mouse_button_up(x, y); + } + + if(m_mouse_point == 1) + { + m_xp1 = x + m_pdx; + m_yp1 = y + m_pdy; + calc_values(); + return true; + } + if(m_mouse_point == 2) + { + m_xp2 = x + m_pdx; + m_yp2 = y + m_pdy; + calc_values(); + return true; + } + return false; + } + + + +} + diff --git a/jni/desmume/src/android/agg/src/ctrl/agg_gamma_spline.cpp b/jni/desmume/src/android/agg/src/ctrl/agg_gamma_spline.cpp new file mode 100755 index 0000000..b7458ee --- /dev/null +++ b/jni/desmume/src/android/agg/src/ctrl/agg_gamma_spline.cpp @@ -0,0 +1,135 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include "ctrl/agg_gamma_spline.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + gamma_spline::gamma_spline() : + m_x1(0), m_y1(0), m_x2(10), m_y2(10), m_cur_x(0.0) + { + values(1.0, 1.0, 1.0, 1.0); + } + + + //------------------------------------------------------------------------ + double gamma_spline::y(double x) const + { + if(x < 0.0) x = 0.0; + if(x > 1.0) x = 1.0; + double val = m_spline.get(x); + if(val < 0.0) val = 0.0; + if(val > 1.0) val = 1.0; + return val; + } + + + + //------------------------------------------------------------------------ + void gamma_spline::values(double kx1, double ky1, double kx2, double ky2) + { + if(kx1 < 0.001) kx1 = 0.001; + if(kx1 > 1.999) kx1 = 1.999; + if(ky1 < 0.001) ky1 = 0.001; + if(ky1 > 1.999) ky1 = 1.999; + if(kx2 < 0.001) kx2 = 0.001; + if(kx2 > 1.999) kx2 = 1.999; + if(ky2 < 0.001) ky2 = 0.001; + if(ky2 > 1.999) ky2 = 1.999; + + m_x[0] = 0.0; + m_y[0] = 0.0; + m_x[1] = kx1 * 0.25; + m_y[1] = ky1 * 0.25; + m_x[2] = 1.0 - kx2 * 0.25; + m_y[2] = 1.0 - ky2 * 0.25; + m_x[3] = 1.0; + m_y[3] = 1.0; + + m_spline.init(4, m_x, m_y); + + int i; + for(i = 0; i < 256; i++) + { + m_gamma[i] = (unsigned char)(y(double(i) / 255.0) * 255.0); + } + } + + + //------------------------------------------------------------------------ + void gamma_spline::values(double* kx1, double* ky1, double* kx2, double* ky2) const + { + *kx1 = m_x[1] * 4.0; + *ky1 = m_y[1] * 4.0; + *kx2 = (1.0 - m_x[2]) * 4.0; + *ky2 = (1.0 - m_y[2]) * 4.0; + } + + + //------------------------------------------------------------------------ + void gamma_spline::box(double x1, double y1, double x2, double y2) + { + m_x1 = x1; + m_y1 = y1; + m_x2 = x2; + m_y2 = y2; + } + + + //------------------------------------------------------------------------ + void gamma_spline::rewind(unsigned) + { + m_cur_x = 0.0; + } + + + //------------------------------------------------------------------------ + unsigned gamma_spline::vertex(double* vx, double* vy) + { + if(m_cur_x == 0.0) + { + *vx = m_x1; + *vy = m_y1; + m_cur_x += 1.0 / (m_x2 - m_x1); + return path_cmd_move_to; + } + + if(m_cur_x > 1.0) + { + return path_cmd_stop; + } + + *vx = m_x1 + m_cur_x * (m_x2 - m_x1); + *vy = m_y1 + y(m_cur_x) * (m_y2 - m_y1); + + m_cur_x += 1.0 / (m_x2 - m_x1); + return path_cmd_line_to; + } + + + +} + diff --git a/jni/desmume/src/android/agg/src/ctrl/agg_polygon_ctrl.cpp b/jni/desmume/src/android/agg/src/ctrl/agg_polygon_ctrl.cpp new file mode 100755 index 0000000..6121181 --- /dev/null +++ b/jni/desmume/src/android/agg/src/ctrl/agg_polygon_ctrl.cpp @@ -0,0 +1,337 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include "ctrl/agg_polygon_ctrl.h" + +namespace agg +{ + + polygon_ctrl_impl::polygon_ctrl_impl(unsigned np, double point_radius) : + ctrl(0, 0, 1, 1, false), + m_polygon(np * 2), + m_num_points(np), + m_node(-1), + m_edge(-1), + m_vs(&m_polygon[0], m_num_points, false), + m_stroke(m_vs), + m_point_radius(point_radius), + m_status(0), + m_dx(0.0), + m_dy(0.0), + m_in_polygon_check(true) + { + m_stroke.width(1.0); + } + + + void polygon_ctrl_impl::rewind(unsigned) + { + m_status = 0; + m_stroke.rewind(0); + } + + unsigned polygon_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + double r = m_point_radius; + if(m_status == 0) + { + cmd = m_stroke.vertex(x, y); + if(!is_stop(cmd)) + { + transform_xy(x, y); + return cmd; + } + if(m_node >= 0 && m_node == int(m_status)) r *= 1.2; + m_ellipse.init(xn(m_status), yn(m_status), r, r, 32); + ++m_status; + } + cmd = m_ellipse.vertex(x, y); + if(!is_stop(cmd)) + { + transform_xy(x, y); + return cmd; + } + if(m_status >= m_num_points) return path_cmd_stop; + if(m_node >= 0 && m_node == int(m_status)) r *= 1.2; + m_ellipse.init(xn(m_status), yn(m_status), r, r, 32); + ++m_status; + cmd = m_ellipse.vertex(x, y); + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + return cmd; + } + + + bool polygon_ctrl_impl::check_edge(unsigned i, double x, double y) const + { + bool ret = false; + + unsigned n1 = i; + unsigned n2 = (i + m_num_points - 1) % m_num_points; + double x1 = xn(n1); + double y1 = yn(n1); + double x2 = xn(n2); + double y2 = yn(n2); + + double dx = x2 - x1; + double dy = y2 - y1; + + if(sqrt(dx*dx + dy*dy) > 0.0000001) + { + double x3 = x; + double y3 = y; + double x4 = x3 - dy; + double y4 = y3 + dx; + + double den = (y4-y3) * (x2-x1) - (x4-x3) * (y2-y1); + double u1 = ((x4-x3) * (y1-y3) - (y4-y3) * (x1-x3)) / den; + + double xi = x1 + u1 * (x2 - x1); + double yi = y1 + u1 * (y2 - y1); + + dx = xi - x; + dy = yi - y; + + if (u1 > 0.0 && u1 < 1.0 && sqrt(dx*dx + dy*dy) <= m_point_radius) + { + ret = true; + } + } + return ret; + } + + + + bool polygon_ctrl_impl::in_rect(double x, double y) const + { + return false; + } + + + bool polygon_ctrl_impl::on_mouse_button_down(double x, double y) + { + unsigned i; + bool ret = false; + m_node = -1; + m_edge = -1; + inverse_transform_xy(&x, &y); + for (i = 0; i < m_num_points; i++) + { + if(sqrt( (x-xn(i)) * (x-xn(i)) + (y-yn(i)) * (y-yn(i)) ) < m_point_radius) + { + m_dx = x - xn(i); + m_dy = y - yn(i); + m_node = int(i); + ret = true; + break; + } + } + + if(!ret) + { + for (i = 0; i < m_num_points; i++) + { + if(check_edge(i, x, y)) + { + m_dx = x; + m_dy = y; + m_edge = int(i); + ret = true; + break; + } + } + } + + if(!ret) + { + if(point_in_polygon(x, y)) + { + m_dx = x; + m_dy = y; + m_node = int(m_num_points); + ret = true; + } + } + return ret; + } + + + bool polygon_ctrl_impl::on_mouse_move(double x, double y, bool button_flag) + { + bool ret = false; + double dx; + double dy; + inverse_transform_xy(&x, &y); + if(m_node == int(m_num_points)) + { + dx = x - m_dx; + dy = y - m_dy; + unsigned i; + for(i = 0; i < m_num_points; i++) + { + xn(i) += dx; + yn(i) += dy; + } + m_dx = x; + m_dy = y; + ret = true; + } + else + { + if(m_edge >= 0) + { + unsigned n1 = m_edge; + unsigned n2 = (n1 + m_num_points - 1) % m_num_points; + dx = x - m_dx; + dy = y - m_dy; + xn(n1) += dx; + yn(n1) += dy; + xn(n2) += dx; + yn(n2) += dy; + m_dx = x; + m_dy = y; + ret = true; + } + else + { + if(m_node >= 0) + { + xn(m_node) = x - m_dx; + yn(m_node) = y - m_dy; + ret = true; + } + } + } + return ret; + } + + bool polygon_ctrl_impl::on_mouse_button_up(double x, double y) + { + bool ret = (m_node >= 0) || (m_edge >= 0); + m_node = -1; + m_edge = -1; + return ret; + } + + + bool polygon_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up) + { + return false; + } + + + //======= Crossings Multiply algorithm of InsideTest ======================== + // + // By Eric Haines, 3D/Eye Inc, erich@eye.com + // + // This version is usually somewhat faster than the original published in + // Graphics Gems IV; by turning the division for testing the X axis crossing + // into a tricky multiplication test this part of the test became faster, + // which had the additional effect of making the test for "both to left or + // both to right" a bit slower for triangles than simply computing the + // intersection each time. The main increase is in triangle testing speed, + // which was about 15% faster; all other polygon complexities were pretty much + // the same as before. On machines where division is very expensive (not the + // case on the HP 9000 series on which I tested) this test should be much + // faster overall than the old code. Your mileage may (in fact, will) vary, + // depending on the machine and the test data, but in general I believe this + // code is both shorter and faster. This test was inspired by unpublished + // Graphics Gems submitted by Joseph Samosky and Mark Haigh-Hutchinson. + // Related work by Samosky is in: + // + // Samosky, Joseph, "SectionView: A system for interactively specifying and + // visualizing sections through three-dimensional medical image data", + // M.S. Thesis, Department of Electrical Engineering and Computer Science, + // Massachusetts Institute of Technology, 1993. + // + // Shoot a test ray along +X axis. The strategy is to compare vertex Y values + // to the testing point's Y and quickly discard edges which are entirely to one + // side of the test ray. Note that CONVEX and WINDING code can be added as + // for the CrossingsTest() code; it is left out here for clarity. + // + // Input 2D polygon _pgon_ with _numverts_ number of vertices and test point + // _point_, returns 1 if inside, 0 if outside. + bool polygon_ctrl_impl::point_in_polygon(double tx, double ty) const + { + if(m_num_points < 3) return false; + if(!m_in_polygon_check) return false; + + unsigned j; + int yflag0, yflag1, inside_flag; + double vtx0, vty0, vtx1, vty1; + + vtx0 = xn(m_num_points - 1); + vty0 = yn(m_num_points - 1); + + // get test bit for above/below X axis + yflag0 = (vty0 >= ty); + + vtx1 = xn(0); + vty1 = yn(0); + + inside_flag = 0; + for (j = 1; j <= m_num_points; ++j) + { + yflag1 = (vty1 >= ty); + // Check if endpoints straddle (are on opposite sides) of X axis + // (i.e. the Y's differ); if so, +X ray could intersect this edge. + // The old test also checked whether the endpoints are both to the + // right or to the left of the test point. However, given the faster + // intersection point computation used below, this test was found to + // be a break-even proposition for most polygons and a loser for + // triangles (where 50% or more of the edges which survive this test + // will cross quadrants and so have to have the X intersection computed + // anyway). I credit Joseph Samosky with inspiring me to try dropping + // the "both left or both right" part of my code. + if (yflag0 != yflag1) + { + // Check intersection of pgon segment with +X ray. + // Note if >= point's X; if so, the ray hits it. + // The division operation is avoided for the ">=" test by checking + // the sign of the first vertex wrto the test point; idea inspired + // by Joseph Samosky's and Mark Haigh-Hutchinson's different + // polygon inclusion tests. + if ( ((vty1-ty) * (vtx0-vtx1) >= + (vtx1-tx) * (vty0-vty1)) == yflag1 ) + { + inside_flag ^= 1; + } + } + + // Move to the next pair of vertices, retaining info as possible. + yflag0 = yflag1; + vtx0 = vtx1; + vty0 = vty1; + + unsigned k = (j >= m_num_points) ? j - m_num_points : j; + vtx1 = xn(k); + vty1 = yn(k); + } + return inside_flag != 0; + } +} + diff --git a/jni/desmume/src/android/agg/src/ctrl/agg_rbox_ctrl.cpp b/jni/desmume/src/android/agg/src/ctrl/agg_rbox_ctrl.cpp new file mode 100755 index 0000000..3262fec --- /dev/null +++ b/jni/desmume/src/android/agg/src/ctrl/agg_rbox_ctrl.cpp @@ -0,0 +1,330 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <string.h> +#include "ctrl/agg_rbox_ctrl.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + rbox_ctrl_impl::rbox_ctrl_impl(double x1, double y1, + double x2, double y2, bool flip_y) : + ctrl(x1, y1, x2, y2, flip_y), + m_border_width(1.0), + m_border_extra(0.0), + m_text_thickness(1.5), + m_text_height(9.0), + m_text_width(0.0), + m_num_items(0), + m_cur_item(-1), + m_ellipse_poly(m_ellipse), + m_text_poly(m_text), + m_idx(0), + m_vertex(0) + { + calc_rbox(); + } + + + //------------------------------------------------------------------------ + void rbox_ctrl_impl::calc_rbox() + { + m_xs1 = m_x1 + m_border_width; + m_ys1 = m_y1 + m_border_width; + m_xs2 = m_x2 - m_border_width; + m_ys2 = m_y2 - m_border_width; + } + + + //------------------------------------------------------------------------ + void rbox_ctrl_impl::add_item(const char* text) + { + if(m_num_items < 32) + { + m_items[m_num_items].resize(strlen(text) + 1); + strcpy(&m_items[m_num_items][0], text); + m_num_items++; + } + } + + + //------------------------------------------------------------------------ + void rbox_ctrl_impl::border_width(double t, double extra) + { + m_border_width = t; + m_border_extra = extra; + calc_rbox(); + } + + + //------------------------------------------------------------------------ + void rbox_ctrl_impl::text_size(double h, double w) + { + m_text_width = w; + m_text_height = h; + } + + + + //------------------------------------------------------------------------ + void rbox_ctrl_impl::rewind(unsigned idx) + { + m_idx = idx; + m_dy = m_text_height * 2.0; + m_draw_item = 0; + + switch(idx) + { + default: + + case 0: // Background + m_vertex = 0; + m_vx[0] = m_x1 - m_border_extra; + m_vy[0] = m_y1 - m_border_extra; + m_vx[1] = m_x2 + m_border_extra; + m_vy[1] = m_y1 - m_border_extra; + m_vx[2] = m_x2 + m_border_extra; + m_vy[2] = m_y2 + m_border_extra; + m_vx[3] = m_x1 - m_border_extra; + m_vy[3] = m_y2 + m_border_extra; + break; + + case 1: // Border + m_vertex = 0; + m_vx[0] = m_x1; + m_vy[0] = m_y1; + m_vx[1] = m_x2; + m_vy[1] = m_y1; + m_vx[2] = m_x2; + m_vy[2] = m_y2; + m_vx[3] = m_x1; + m_vy[3] = m_y2; + m_vx[4] = m_x1 + m_border_width; + m_vy[4] = m_y1 + m_border_width; + m_vx[5] = m_x1 + m_border_width; + m_vy[5] = m_y2 - m_border_width; + m_vx[6] = m_x2 - m_border_width; + m_vy[6] = m_y2 - m_border_width; + m_vx[7] = m_x2 - m_border_width; + m_vy[7] = m_y1 + m_border_width; + break; + + case 2: // Text + m_text.text(&m_items[0][0]); + m_text.start_point(m_xs1 + m_dy * 1.5, m_ys1 + m_dy / 2.0); + m_text.size(m_text_height, m_text_width); + m_text_poly.width(m_text_thickness); + m_text_poly.line_join(round_join); + m_text_poly.line_cap(round_cap); + m_text_poly.rewind(0); + break; + + case 3: // Inactive items + m_ellipse.init(m_xs1 + m_dy / 1.3, + m_ys1 + m_dy / 1.3, + m_text_height / 1.5, + m_text_height / 1.5, 32); + m_ellipse_poly.width(m_text_thickness); + m_ellipse_poly.rewind(0); + break; + + + case 4: // Active Item + if(m_cur_item >= 0) + { + m_ellipse.init(m_xs1 + m_dy / 1.3, + m_ys1 + m_dy * m_cur_item + m_dy / 1.3, + m_text_height / 2.0, + m_text_height / 2.0, 32); + m_ellipse.rewind(0); + } + break; + + } + } + + + //------------------------------------------------------------------------ + unsigned rbox_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + switch(m_idx) + { + case 0: + if(m_vertex == 0) cmd = path_cmd_move_to; + if(m_vertex >= 4) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 1: + if(m_vertex == 0 || m_vertex == 4) cmd = path_cmd_move_to; + if(m_vertex >= 8) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 2: + cmd = m_text_poly.vertex(x, y); + if(is_stop(cmd)) + { + m_draw_item++; + if(m_draw_item >= m_num_items) + { + break; + } + else + { + m_text.text(&m_items[m_draw_item][0]); + m_text.start_point(m_xs1 + m_dy * 1.5, + m_ys1 + m_dy * (m_draw_item + 1) - m_dy / 2.0); + + m_text_poly.rewind(0); + cmd = m_text_poly.vertex(x, y); + } + } + break; + + case 3: + cmd = m_ellipse_poly.vertex(x, y); + if(is_stop(cmd)) + { + m_draw_item++; + if(m_draw_item >= m_num_items) + { + break; + } + else + { + m_ellipse.init(m_xs1 + m_dy / 1.3, + m_ys1 + m_dy * m_draw_item + m_dy / 1.3, + m_text_height / 1.5, + m_text_height / 1.5, 32); + m_ellipse_poly.rewind(0); + cmd = m_ellipse_poly.vertex(x, y); + } + } + break; + + + case 4: + if(m_cur_item >= 0) + { + cmd = m_ellipse.vertex(x, y); + } + else + { + cmd = path_cmd_stop; + } + break; + + default: + cmd = path_cmd_stop; + break; + } + + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + + return cmd; + } + + + //------------------------------------------------------------------------ + bool rbox_ctrl_impl::in_rect(double x, double y) const + { + inverse_transform_xy(&x, &y); + return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2; + } + + + + //------------------------------------------------------------------------ + bool rbox_ctrl_impl::on_mouse_button_down(double x, double y) + { + inverse_transform_xy(&x, &y); + unsigned i; + for(i = 0; i < m_num_items; i++) + { + double xp = m_xs1 + m_dy / 1.3; + double yp = m_ys1 + m_dy * i + m_dy / 1.3; + if(calc_distance(x, y, xp, yp) <= m_text_height / 1.5) + { + m_cur_item = int(i); + return true; + } + } + return false; + } + + + //------------------------------------------------------------------------ + bool rbox_ctrl_impl::on_mouse_move(double, double, bool) + { + return false; + } + + //------------------------------------------------------------------------ + bool rbox_ctrl_impl::on_mouse_button_up(double, double) + { + return false; + } + + //------------------------------------------------------------------------ + bool rbox_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up) + { + if(m_cur_item >= 0) + { + if(up || right) + { + m_cur_item++; + if(m_cur_item >= int(m_num_items)) + { + m_cur_item = 0; + } + return true; + } + + if(down || left) + { + m_cur_item--; + if(m_cur_item < 0) + { + m_cur_item = m_num_items - 1; + } + return true; + } + } + return false; + } + + +} + + diff --git a/jni/desmume/src/android/agg/src/ctrl/agg_scale_ctrl.cpp b/jni/desmume/src/android/agg/src/ctrl/agg_scale_ctrl.cpp new file mode 100755 index 0000000..4d9e9fb --- /dev/null +++ b/jni/desmume/src/android/agg/src/ctrl/agg_scale_ctrl.cpp @@ -0,0 +1,459 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include "ctrl/agg_scale_ctrl.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + scale_ctrl_impl::scale_ctrl_impl(double x1, double y1, + double x2, double y2, bool flip_y) : + ctrl(x1, y1, x2, y2, flip_y), + m_border_thickness(1.0), + m_border_extra((fabs(x2 - x1) > fabs(y2 - y1)) ? (y2 - y1) / 2 : (x2 - x1) / 2), + m_pdx(0.0), + m_pdy(0.0), + m_move_what(move_nothing), + m_value1(0.3), + m_value2(0.7), + m_min_d(0.01) + { + calc_box(); + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::calc_box() + { + m_xs1 = m_x1 + m_border_thickness; + m_ys1 = m_y1 + m_border_thickness; + m_xs2 = m_x2 - m_border_thickness; + m_ys2 = m_y2 - m_border_thickness; + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::border_thickness(double t, double extra) + { + m_border_thickness = t; + m_border_extra = extra; + calc_box(); + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::resize(double x1, double y1, double x2, double y2) + { + m_x1 = x1; + m_y1 = y1; + m_x2 = x2; + m_y2 = y2; + calc_box(); + m_border_extra = (fabs(x2 - x1) > fabs(y2 - y1)) ? + (y2 - y1) / 2 : + (x2 - x1) / 2; + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::value1(double value) + { + if(value < 0.0) value = 0.0; + if(value > 1.0) value = 1.0; + if(m_value2 - value < m_min_d) value = m_value2 - m_min_d; + m_value1 = value; + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::value2(double value) + { + if(value < 0.0) value = 0.0; + if(value > 1.0) value = 1.0; + if(m_value1 + value < m_min_d) value = m_value1 + m_min_d; + m_value2 = value; + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::move(double d) + { + m_value1 += d; + m_value2 += d; + if(m_value1 < 0.0) + { + m_value2 -= m_value1; + m_value1 = 0.0; + } + if(m_value2 > 1.0) + { + m_value1 -= m_value2 - 1.0; + m_value2 = 1.0; + } + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::rewind(unsigned idx) + { + m_idx = idx; + + switch(idx) + { + default: + + case 0: // Background + m_vertex = 0; + m_vx[0] = m_x1 - m_border_extra; + m_vy[0] = m_y1 - m_border_extra; + m_vx[1] = m_x2 + m_border_extra; + m_vy[1] = m_y1 - m_border_extra; + m_vx[2] = m_x2 + m_border_extra; + m_vy[2] = m_y2 + m_border_extra; + m_vx[3] = m_x1 - m_border_extra; + m_vy[3] = m_y2 + m_border_extra; + break; + + case 1: // Border + m_vertex = 0; + m_vx[0] = m_x1; + m_vy[0] = m_y1; + m_vx[1] = m_x2; + m_vy[1] = m_y1; + m_vx[2] = m_x2; + m_vy[2] = m_y2; + m_vx[3] = m_x1; + m_vy[3] = m_y2; + m_vx[4] = m_x1 + m_border_thickness; + m_vy[4] = m_y1 + m_border_thickness; + m_vx[5] = m_x1 + m_border_thickness; + m_vy[5] = m_y2 - m_border_thickness; + m_vx[6] = m_x2 - m_border_thickness; + m_vy[6] = m_y2 - m_border_thickness; + m_vx[7] = m_x2 - m_border_thickness; + m_vy[7] = m_y1 + m_border_thickness; + break; + + case 2: // pointer1 + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + m_ellipse.init(m_xs1 + (m_xs2 - m_xs1) * m_value1, + (m_ys1 + m_ys2) / 2.0, + m_y2 - m_y1, + m_y2 - m_y1, + 32); + } + else + { + m_ellipse.init((m_xs1 + m_xs2) / 2.0, + m_ys1 + (m_ys2 - m_ys1) * m_value1, + m_x2 - m_x1, + m_x2 - m_x1, + 32); + } + m_ellipse.rewind(0); + break; + + case 3: // pointer2 + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + m_ellipse.init(m_xs1 + (m_xs2 - m_xs1) * m_value2, + (m_ys1 + m_ys2) / 2.0, + m_y2 - m_y1, + m_y2 - m_y1, + 32); + } + else + { + m_ellipse.init((m_xs1 + m_xs2) / 2.0, + m_ys1 + (m_ys2 - m_ys1) * m_value2, + m_x2 - m_x1, + m_x2 - m_x1, + 32); + } + m_ellipse.rewind(0); + break; + + case 4: // slider + m_vertex = 0; + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + m_vx[0] = m_xs1 + (m_xs2 - m_xs1) * m_value1; + m_vy[0] = m_y1 - m_border_extra / 2.0; + m_vx[1] = m_xs1 + (m_xs2 - m_xs1) * m_value2; + m_vy[1] = m_vy[0]; + m_vx[2] = m_vx[1]; + m_vy[2] = m_y2 + m_border_extra / 2.0; + m_vx[3] = m_vx[0]; + m_vy[3] = m_vy[2]; + } + else + { + m_vx[0] = m_x1 - m_border_extra / 2.0; + m_vy[0] = m_ys1 + (m_ys2 - m_ys1) * m_value1; + m_vx[1] = m_vx[0]; + m_vy[1] = m_ys1 + (m_ys2 - m_ys1) * m_value2; + m_vx[2] = m_x2 + m_border_extra / 2.0; + m_vy[2] = m_vy[1]; + m_vx[3] = m_vx[2]; + m_vy[3] = m_vy[0]; + } + break; + } + } + + + //------------------------------------------------------------------------ + unsigned scale_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + switch(m_idx) + { + case 0: + case 4: + if(m_vertex == 0) cmd = path_cmd_move_to; + if(m_vertex >= 4) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 1: + if(m_vertex == 0 || m_vertex == 4) cmd = path_cmd_move_to; + if(m_vertex >= 8) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 2: + case 3: + cmd = m_ellipse.vertex(x, y); + break; + + default: + cmd = path_cmd_stop; + break; + } + + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + + return cmd; + } + + + + //------------------------------------------------------------------------ + bool scale_ctrl_impl::in_rect(double x, double y) const + { + inverse_transform_xy(&x, &y); + return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2; + } + + + //------------------------------------------------------------------------ + bool scale_ctrl_impl::on_mouse_button_down(double x, double y) + { + inverse_transform_xy(&x, &y); + + double xp1; + double xp2; + double ys1; + double ys2; + double xp; + double yp; + + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + xp1 = m_xs1 + (m_xs2 - m_xs1) * m_value1; + xp2 = m_xs1 + (m_xs2 - m_xs1) * m_value2; + ys1 = m_y1 - m_border_extra / 2.0; + ys2 = m_y2 + m_border_extra / 2.0; + yp = (m_ys1 + m_ys2) / 2.0; + + if(x > xp1 && y > ys1 && x < xp2 && y < ys2) + { + m_pdx = xp1 - x; + m_move_what = move_slider; + return true; + } + + //if(x < xp1 && calc_distance(x, y, xp1, yp) <= m_y2 - m_y1) + if(calc_distance(x, y, xp1, yp) <= m_y2 - m_y1) + { + m_pdx = xp1 - x; + m_move_what = move_value1; + return true; + } + + //if(x > xp2 && calc_distance(x, y, xp2, yp) <= m_y2 - m_y1) + if(calc_distance(x, y, xp2, yp) <= m_y2 - m_y1) + { + m_pdx = xp2 - x; + m_move_what = move_value2; + return true; + } + } + else + { + xp1 = m_x1 - m_border_extra / 2.0; + xp2 = m_x2 + m_border_extra / 2.0; + ys1 = m_ys1 + (m_ys2 - m_ys1) * m_value1; + ys2 = m_ys1 + (m_ys2 - m_ys1) * m_value2; + xp = (m_xs1 + m_xs2) / 2.0; + + if(x > xp1 && y > ys1 && x < xp2 && y < ys2) + { + m_pdy = ys1 - y; + m_move_what = move_slider; + return true; + } + + //if(y < ys1 && calc_distance(x, y, xp, ys1) <= m_x2 - m_x1) + if(calc_distance(x, y, xp, ys1) <= m_x2 - m_x1) + { + m_pdy = ys1 - y; + m_move_what = move_value1; + return true; + } + + //if(y > ys2 && calc_distance(x, y, xp, ys2) <= m_x2 - m_x1) + if(calc_distance(x, y, xp, ys2) <= m_x2 - m_x1) + { + m_pdy = ys2 - y; + m_move_what = move_value2; + return true; + } + } + + return false; + } + + + //------------------------------------------------------------------------ + bool scale_ctrl_impl::on_mouse_move(double x, double y, bool button_flag) + { + inverse_transform_xy(&x, &y); + if(!button_flag) + { + return on_mouse_button_up(x, y); + } + + double xp = x + m_pdx; + double yp = y + m_pdy; + double dv; + + switch(m_move_what) + { + case move_value1: + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + m_value1 = (xp - m_xs1) / (m_xs2 - m_xs1); + } + else + { + m_value1 = (yp - m_ys1) / (m_ys2 - m_ys1); + } + if(m_value1 < 0.0) m_value1 = 0.0; + if(m_value1 > m_value2 - m_min_d) m_value1 = m_value2 - m_min_d; + return true; + + case move_value2: + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + m_value2 = (xp - m_xs1) / (m_xs2 - m_xs1); + } + else + { + m_value2 = (yp - m_ys1) / (m_ys2 - m_ys1); + } + if(m_value2 > 1.0) m_value2 = 1.0; + if(m_value2 < m_value1 + m_min_d) m_value2 = m_value1 + m_min_d; + return true; + + case move_slider: + dv = m_value2 - m_value1; + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + m_value1 = (xp - m_xs1) / (m_xs2 - m_xs1); + } + else + { + m_value1 = (yp - m_ys1) / (m_ys2 - m_ys1); + } + m_value2 = m_value1 + dv; + if(m_value1 < 0.0) + { + dv = m_value2 - m_value1; + m_value1 = 0.0; + m_value2 = m_value1 + dv; + } + if(m_value2 > 1.0) + { + dv = m_value2 - m_value1; + m_value2 = 1.0; + m_value1 = m_value2 - dv; + } + return true; + } + + return false; + } + + + //------------------------------------------------------------------------ + bool scale_ctrl_impl::on_mouse_button_up(double, double) + { + m_move_what = move_nothing; + return false; + } + + + //------------------------------------------------------------------------ + bool scale_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up) + { +/* + if(right || up) + { + m_value += 0.005; + if(m_value > 1.0) m_value = 1.0; + return true; + } + + if(left || down) + { + m_value -= 0.005; + if(m_value < 0.0) m_value = 0.0; + return true; + } +*/ + return false; + } + +} + diff --git a/jni/desmume/src/android/agg/src/ctrl/agg_slider_ctrl.cpp b/jni/desmume/src/android/agg/src/ctrl/agg_slider_ctrl.cpp new file mode 100755 index 0000000..a71a12b --- /dev/null +++ b/jni/desmume/src/android/agg/src/ctrl/agg_slider_ctrl.cpp @@ -0,0 +1,354 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <string.h> +#include <stdio.h> +#include "ctrl/agg_slider_ctrl.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + slider_ctrl_impl::slider_ctrl_impl(double x1, double y1, + double x2, double y2, bool flip_y) : + ctrl(x1, y1, x2, y2, flip_y), + m_border_width(1.0), + m_border_extra((y2 - y1) / 2), + m_text_thickness(1.0), + m_pdx(0.0), + m_mouse_move(false), + m_value(0.5), + m_preview_value(0.5), + m_min(0.0), + m_max(1.0), + m_num_steps(0), + m_descending(false), + m_text_poly(m_text) + { + m_label[0] = 0; + calc_box(); + } + + + //------------------------------------------------------------------------ + void slider_ctrl_impl::calc_box() + { + m_xs1 = m_x1 + m_border_width; + m_ys1 = m_y1 + m_border_width; + m_xs2 = m_x2 - m_border_width; + m_ys2 = m_y2 - m_border_width; + } + + + //------------------------------------------------------------------------ + bool slider_ctrl_impl::normalize_value(bool preview_value_flag) + { + bool ret = true; + if(m_num_steps) + { + int step = int(m_preview_value * m_num_steps + 0.5); + ret = m_value != step / double(m_num_steps); + m_value = step / double(m_num_steps); + } + else + { + m_value = m_preview_value; + } + + if(preview_value_flag) + { + m_preview_value = m_value; + } + return ret; + } + + + //------------------------------------------------------------------------ + void slider_ctrl_impl::border_width(double t, double extra) + { + m_border_width = t; + m_border_extra = extra; + calc_box(); + } + + + //------------------------------------------------------------------------ + void slider_ctrl_impl::value(double value) + { + m_preview_value = (value - m_min) / (m_max - m_min); + if(m_preview_value > 1.0) m_preview_value = 1.0; + if(m_preview_value < 0.0) m_preview_value = 0.0; + normalize_value(true); + } + + //------------------------------------------------------------------------ + void slider_ctrl_impl::label(const char* fmt) + { + m_label[0] = 0; + if(fmt) + { + unsigned len = strlen(fmt); + if(len > 63) len = 63; + memcpy(m_label, fmt, len); + m_label[len] = 0; + } + } + + //------------------------------------------------------------------------ + void slider_ctrl_impl::rewind(unsigned idx) + { + m_idx = idx; + + switch(idx) + { + default: + + case 0: // Background + m_vertex = 0; + m_vx[0] = m_x1 - m_border_extra; + m_vy[0] = m_y1 - m_border_extra; + m_vx[1] = m_x2 + m_border_extra; + m_vy[1] = m_y1 - m_border_extra; + m_vx[2] = m_x2 + m_border_extra; + m_vy[2] = m_y2 + m_border_extra; + m_vx[3] = m_x1 - m_border_extra; + m_vy[3] = m_y2 + m_border_extra; + break; + + case 1: // Triangle + m_vertex = 0; + if(m_descending) + { + m_vx[0] = m_x1; + m_vy[0] = m_y1; + m_vx[1] = m_x2; + m_vy[1] = m_y1; + m_vx[2] = m_x1; + m_vy[2] = m_y2; + m_vx[3] = m_x1; + m_vy[3] = m_y1; + } + else + { + m_vx[0] = m_x1; + m_vy[0] = m_y1; + m_vx[1] = m_x2; + m_vy[1] = m_y1; + m_vx[2] = m_x2; + m_vy[2] = m_y2; + m_vx[3] = m_x1; + m_vy[3] = m_y1; + } + break; + + case 2: + m_text.text(m_label); + if(m_label[0]) + { + char buf[256]; + sprintf(buf, m_label, value()); + m_text.text(buf); + } + m_text.start_point(m_x1, m_y1); + m_text.size((m_y2 - m_y1) * 1.2, m_y2 - m_y1); + m_text_poly.width(m_text_thickness); + m_text_poly.line_join(round_join); + m_text_poly.line_cap(round_cap); + m_text_poly.rewind(0); + break; + + case 3: // pointer preview + m_ellipse.init(m_xs1 + (m_xs2 - m_xs1) * m_preview_value, + (m_ys1 + m_ys2) / 2.0, + m_y2 - m_y1, + m_y2 - m_y1, + 32); + break; + + + case 4: // pointer + normalize_value(false); + m_ellipse.init(m_xs1 + (m_xs2 - m_xs1) * m_value, + (m_ys1 + m_ys2) / 2.0, + m_y2 - m_y1, + m_y2 - m_y1, + 32); + m_ellipse.rewind(0); + break; + + case 5: + m_storage.remove_all(); + if(m_num_steps) + { + unsigned i; + double d = (m_xs2 - m_xs1) / m_num_steps; + if(d > 0.004) d = 0.004; + for(i = 0; i < m_num_steps + 1; i++) + { + double x = m_xs1 + (m_xs2 - m_xs1) * i / m_num_steps; + m_storage.move_to(x, m_y1); + m_storage.line_to(x - d * (m_x2 - m_x1), m_y1 - m_border_extra); + m_storage.line_to(x + d * (m_x2 - m_x1), m_y1 - m_border_extra); + } + } + } + } + + + //------------------------------------------------------------------------ + unsigned slider_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + switch(m_idx) + { + case 0: + if(m_vertex == 0) cmd = path_cmd_move_to; + if(m_vertex >= 4) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 1: + if(m_vertex == 0) cmd = path_cmd_move_to; + if(m_vertex >= 4) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 2: + cmd = m_text_poly.vertex(x, y); + break; + + case 3: + case 4: + cmd = m_ellipse.vertex(x, y); + break; + + case 5: + cmd = m_storage.vertex(x, y); + break; + + default: + cmd = path_cmd_stop; + break; + } + + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + + return cmd; + } + + + + //------------------------------------------------------------------------ + bool slider_ctrl_impl::in_rect(double x, double y) const + { + inverse_transform_xy(&x, &y); + return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2; + } + + + //------------------------------------------------------------------------ + bool slider_ctrl_impl::on_mouse_button_down(double x, double y) + { + inverse_transform_xy(&x, &y); + + double xp = m_xs1 + (m_xs2 - m_xs1) * m_value; + double yp = (m_ys1 + m_ys2) / 2.0; + + if(calc_distance(x, y, xp, yp) <= m_y2 - m_y1) + { + m_pdx = xp - x; + m_mouse_move = true; + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + bool slider_ctrl_impl::on_mouse_move(double x, double y, bool button_flag) + { + inverse_transform_xy(&x, &y); + if(!button_flag) + { + on_mouse_button_up(x, y); + return false; + } + + if(m_mouse_move) + { + double xp = x + m_pdx; + m_preview_value = (xp - m_xs1) / (m_xs2 - m_xs1); + if(m_preview_value < 0.0) m_preview_value = 0.0; + if(m_preview_value > 1.0) m_preview_value = 1.0; + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + bool slider_ctrl_impl::on_mouse_button_up(double, double) + { + m_mouse_move = false; + normalize_value(true); + return true; + } + + + //------------------------------------------------------------------------ + bool slider_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up) + { + double d = 0.005; + if(m_num_steps) + { + d = 1.0 / m_num_steps; + } + + if(right || up) + { + m_preview_value += d; + if(m_preview_value > 1.0) m_preview_value = 1.0; + normalize_value(true); + return true; + } + + if(left || down) + { + m_preview_value -= d; + if(m_preview_value < 0.0) m_preview_value = 0.0; + normalize_value(true); + return true; + } + return false; + } + +} + diff --git a/jni/desmume/src/android/agg/src/ctrl/agg_spline_ctrl.cpp b/jni/desmume/src/android/agg/src/ctrl/agg_spline_ctrl.cpp new file mode 100755 index 0000000..10847cb --- /dev/null +++ b/jni/desmume/src/android/agg/src/ctrl/agg_spline_ctrl.cpp @@ -0,0 +1,412 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include "ctrl/agg_spline_ctrl.h" + + +namespace agg +{ + + //------------------------------------------------------------------------ + spline_ctrl_impl::spline_ctrl_impl(double x1, double y1, double x2, double y2, + unsigned num_pnt, bool flip_y) : + ctrl(x1, y1, x2, y2, flip_y), + m_num_pnt(num_pnt), + m_border_width(1.0), + m_border_extra(0.0), + m_curve_width(1.0), + m_point_size(3.0), + m_curve_poly(m_curve_pnt), + m_idx(0), + m_vertex(0), + m_active_pnt(-1), + m_move_pnt(-1), + m_pdx(0.0), + m_pdy(0.0) + { + if(m_num_pnt < 4) m_num_pnt = 4; + if(m_num_pnt > 32) m_num_pnt = 32; + + unsigned i; + for(i = 0; i < m_num_pnt; i++) + { + m_xp[i] = double(i) / double(m_num_pnt - 1); + m_yp[i] = 0.5; + } + calc_spline_box(); + update_spline(); + } + + + //------------------------------------------------------------------------ + void spline_ctrl_impl::border_width(double t, double extra) + { + m_border_width = t; + m_border_extra = extra; + calc_spline_box(); + } + + + //------------------------------------------------------------------------ + void spline_ctrl_impl::calc_spline_box() + { + m_xs1 = m_x1 + m_border_width; + m_ys1 = m_y1 + m_border_width; + m_xs2 = m_x2 - m_border_width; + m_ys2 = m_y2 - m_border_width; + } + + + //------------------------------------------------------------------------ + void spline_ctrl_impl::update_spline() + { + int i; + m_spline.init(m_num_pnt, m_xp, m_yp); + for(i = 0; i < 256; i++) + { + m_spline_values[i] = m_spline.get(double(i) / 255.0); + if(m_spline_values[i] < 0.0) m_spline_values[i] = 0.0; + if(m_spline_values[i] > 1.0) m_spline_values[i] = 1.0; + m_spline_values8[i] = (int8u)(m_spline_values[i] * 255.0); + } + } + + + //------------------------------------------------------------------------ + void spline_ctrl_impl::calc_curve() + { + int i; + m_curve_pnt.remove_all(); + m_curve_pnt.move_to(m_xs1, m_ys1 + (m_ys2 - m_ys1) * m_spline_values[0]); + for(i = 1; i < 256; i++) + { + m_curve_pnt.line_to(m_xs1 + (m_xs2 - m_xs1) * double(i) / 255.0, + m_ys1 + (m_ys2 - m_ys1) * m_spline_values[i]); + } + } + + + //------------------------------------------------------------------------ + double spline_ctrl_impl::calc_xp(unsigned idx) + { + return m_xs1 + (m_xs2 - m_xs1) * m_xp[idx]; + } + + + //------------------------------------------------------------------------ + double spline_ctrl_impl::calc_yp(unsigned idx) + { + return m_ys1 + (m_ys2 - m_ys1) * m_yp[idx]; + } + + + //------------------------------------------------------------------------ + void spline_ctrl_impl::set_xp(unsigned idx, double val) + { + if(val < 0.0) val = 0.0; + if(val > 1.0) val = 1.0; + + if(idx == 0) + { + val = 0.0; + } + else if(idx == m_num_pnt - 1) + { + val = 1.0; + } + else + { + if(val < m_xp[idx - 1] + 0.001) val = m_xp[idx - 1] + 0.001; + if(val > m_xp[idx + 1] - 0.001) val = m_xp[idx + 1] - 0.001; + } + m_xp[idx] = val; + } + + //------------------------------------------------------------------------ + void spline_ctrl_impl::set_yp(unsigned idx, double val) + { + if(val < 0.0) val = 0.0; + if(val > 1.0) val = 1.0; + m_yp[idx] = val; + } + + + //------------------------------------------------------------------------ + void spline_ctrl_impl::point(unsigned idx, double x, double y) + { + if(idx < m_num_pnt) + { + set_xp(idx, x); + set_yp(idx, y); + } + } + + + //------------------------------------------------------------------------ + void spline_ctrl_impl::value(unsigned idx, double y) + { + if(idx < m_num_pnt) + { + set_yp(idx, y); + } + } + + //------------------------------------------------------------------------ + double spline_ctrl_impl::value(double x) const + { + x = m_spline.get(x); + if(x < 0.0) x = 0.0; + if(x > 1.0) x = 1.0; + return x; + } + + + //------------------------------------------------------------------------ + void spline_ctrl_impl::rewind(unsigned idx) + { + unsigned i; + + m_idx = idx; + + switch(idx) + { + default: + + case 0: // Background + m_vertex = 0; + m_vx[0] = m_x1 - m_border_extra; + m_vy[0] = m_y1 - m_border_extra; + m_vx[1] = m_x2 + m_border_extra; + m_vy[1] = m_y1 - m_border_extra; + m_vx[2] = m_x2 + m_border_extra; + m_vy[2] = m_y2 + m_border_extra; + m_vx[3] = m_x1 - m_border_extra; + m_vy[3] = m_y2 + m_border_extra; + break; + + case 1: // Border + m_vertex = 0; + m_vx[0] = m_x1; + m_vy[0] = m_y1; + m_vx[1] = m_x2; + m_vy[1] = m_y1; + m_vx[2] = m_x2; + m_vy[2] = m_y2; + m_vx[3] = m_x1; + m_vy[3] = m_y2; + m_vx[4] = m_x1 + m_border_width; + m_vy[4] = m_y1 + m_border_width; + m_vx[5] = m_x1 + m_border_width; + m_vy[5] = m_y2 - m_border_width; + m_vx[6] = m_x2 - m_border_width; + m_vy[6] = m_y2 - m_border_width; + m_vx[7] = m_x2 - m_border_width; + m_vy[7] = m_y1 + m_border_width; + break; + + case 2: // Curve + calc_curve(); + m_curve_poly.width(m_curve_width); + m_curve_poly.rewind(0); + break; + + + case 3: // Inactive points + m_curve_pnt.remove_all(); + for(i = 0; i < m_num_pnt; i++) + { + if(int(i) != m_active_pnt) + { + m_ellipse.init(calc_xp(i), calc_yp(i), + m_point_size, m_point_size, 32); + m_curve_pnt.concat_path(m_ellipse); + } + } + m_curve_poly.rewind(0); + break; + + + case 4: // Active point + m_curve_pnt.remove_all(); + if(m_active_pnt >= 0) + { + m_ellipse.init(calc_xp(m_active_pnt), calc_yp(m_active_pnt), + m_point_size, m_point_size, 32); + + m_curve_pnt.concat_path(m_ellipse); + } + m_curve_poly.rewind(0); + break; + + } + } + + + //------------------------------------------------------------------------ + unsigned spline_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + switch(m_idx) + { + case 0: + if(m_vertex == 0) cmd = path_cmd_move_to; + if(m_vertex >= 4) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 1: + if(m_vertex == 0 || m_vertex == 4) cmd = path_cmd_move_to; + if(m_vertex >= 8) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 2: + cmd = m_curve_poly.vertex(x, y); + break; + + case 3: + case 4: + cmd = m_curve_pnt.vertex(x, y); + break; + + default: + cmd = path_cmd_stop; + break; + } + + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + + return cmd; + } + + + + //------------------------------------------------------------------------ + void spline_ctrl_impl::active_point(int i) + { + m_active_pnt = i; + } + + + //------------------------------------------------------------------------ + bool spline_ctrl_impl::in_rect(double x, double y) const + { + inverse_transform_xy(&x, &y); + return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2; + } + + + //------------------------------------------------------------------------ + bool spline_ctrl_impl::on_mouse_button_down(double x, double y) + { + inverse_transform_xy(&x, &y); + unsigned i; + for(i = 0; i < m_num_pnt; i++) + { + double xp = calc_xp(i); + double yp = calc_yp(i); + if(calc_distance(x, y, xp, yp) <= m_point_size + 1) + { + m_pdx = xp - x; + m_pdy = yp - y; + m_active_pnt = m_move_pnt = int(i); + return true; + } + } + return false; + } + + + //------------------------------------------------------------------------ + bool spline_ctrl_impl::on_mouse_button_up(double, double) + { + if(m_move_pnt >= 0) + { + m_move_pnt = -1; + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + bool spline_ctrl_impl::on_mouse_move(double x, double y, bool button_flag) + { + inverse_transform_xy(&x, &y); + if(!button_flag) + { + return on_mouse_button_up(x, y); + } + + if(m_move_pnt >= 0) + { + double xp = x + m_pdx; + double yp = y + m_pdy; + + set_xp(m_move_pnt, (xp - m_xs1) / (m_xs2 - m_xs1)); + set_yp(m_move_pnt, (yp - m_ys1) / (m_ys2 - m_ys1)); + + update_spline(); + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + bool spline_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up) + { + double kx = 0.0; + double ky = 0.0; + bool ret = false; + if(m_active_pnt >= 0) + { + kx = m_xp[m_active_pnt]; + ky = m_yp[m_active_pnt]; + if(left) { kx -= 0.001; ret = true; } + if(right) { kx += 0.001; ret = true; } + if(down) { ky -= 0.001; ret = true; } + if(up) { ky += 0.001; ret = true; } + } + if(ret) + { + set_xp(m_active_pnt, kx); + set_yp(m_active_pnt, ky); + update_spline(); + } + return ret; + } + + + + +} + diff --git a/jni/desmume/src/android/agg/src/install b/jni/desmume/src/android/agg/src/install new file mode 100755 index 0000000..e69de29 diff --git a/jni/desmume/src/android/agg/src/news b/jni/desmume/src/android/agg/src/news new file mode 100755 index 0000000..e69de29 diff --git a/jni/desmume/src/android/agg/src/platform/AmigaOS/Makefile.am b/jni/desmume/src/android/agg/src/platform/AmigaOS/Makefile.am new file mode 100755 index 0000000..474153c --- /dev/null +++ b/jni/desmume/src/android/agg/src/platform/AmigaOS/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST=agg_platform_support.cpp diff --git a/jni/desmume/src/android/agg/src/platform/AmigaOS/agg_platform_support.cpp b/jni/desmume/src/android/agg/src/platform/AmigaOS/agg_platform_support.cpp new file mode 100755 index 0000000..eed9a6e --- /dev/null +++ b/jni/desmume/src/android/agg/src/platform/AmigaOS/agg_platform_support.cpp @@ -0,0 +1,983 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Copyright (C) 2004 Steven Solie +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include "platform/agg_platform_support.h" +#include "util/agg_color_conv_rgb8.h" + +#include <sys/time.h> +#include <cstring> + +#include <classes/requester.h> +#include <classes/window.h> +#include <datatypes/pictureclass.h> +#include <proto/exec.h> +#include <proto/datatypes.h> +#include <proto/dos.h> +#include <proto/graphics.h> +#include <proto/intuition.h> +#include <proto/keymap.h> +#include <proto/Picasso96API.h> +#include <proto/utility.h> + +Library* DataTypesBase = 0; +Library* GraphicsBase = 0; +Library* IntuitionBase = 0; +Library* KeymapBase = 0; +Library* P96Base = 0; + +DataTypesIFace* IDataTypes = 0; +GraphicsIFace* IGraphics = 0; +IntuitionIFace* IIntuition = 0; +KeymapIFace* IKeymap = 0; +P96IFace* IP96 = 0; + +Class* RequesterClass = 0; +Class* WindowClass = 0; + + +namespace agg +{ + void handle_idcmp(Hook* hook, APTR win, IntuiMessage* msg); + + //------------------------------------------------------------------------ + class platform_specific + { + public: + platform_specific(platform_support& support, pix_format_e format, + bool flip_y); + ~platform_specific(); + bool handle_input(); + bool load_img(const char* file, unsigned idx, rendering_buffer* rbuf); + bool create_img(unsigned idx, rendering_buffer* rbuf, unsigned width, + unsigned height); + bool make_bitmap(); + public: + platform_support& m_support; + RGBFTYPE m_ftype; + pix_format_e m_format; + unsigned m_bpp; + BitMap* m_bitmap; + bool m_flip_y; + uint16 m_width; + uint16 m_height; + APTR m_window_obj; + Window* m_window; + Hook* m_idcmp_hook; + unsigned m_input_flags; + bool m_dragging; + double m_start_time; + uint16 m_last_key; + BitMap* m_img_bitmaps[platform_support::max_images]; + }; + + //------------------------------------------------------------------------ + platform_specific::platform_specific(platform_support& support, + pix_format_e format, bool flip_y) : + m_support(support), + m_ftype(RGBFB_NONE), + m_format(format), + m_bpp(0), + m_bitmap(0), + m_flip_y(flip_y), + m_width(0), + m_height(0), + m_window_obj(0), + m_window(0), + m_idcmp_hook(0), + m_input_flags(0), + m_dragging(false), + m_start_time(0.0), + m_last_key(0) + { + switch ( format ) + { + case pix_format_gray8: + // Not supported. + break; + case pix_format_rgb555: + m_ftype = RGBFB_R5G5B5; + m_bpp = 15; + break; + case pix_format_rgb565: + m_ftype = RGBFB_R5G6B5; + m_bpp = 16; + break; + case pix_format_rgb24: + m_ftype = RGBFB_R8G8B8; + m_bpp = 24; + break; + case pix_format_bgr24: + m_ftype = RGBFB_B8G8R8; + m_bpp = 24; + break; + case pix_format_bgra32: + m_ftype = RGBFB_B8G8R8A8; + m_bpp = 32; + break; + case pix_format_abgr32: + m_ftype = RGBFB_A8B8G8R8; + m_bpp = 32; + break; + case pix_format_argb32: + m_ftype = RGBFB_A8R8G8B8; + m_bpp = 32; + break; + case pix_format_rgba32: + m_ftype = RGBFB_R8G8B8A8; + m_bpp = 32; + break; + } + + for ( unsigned i = 0; i < platform_support::max_images; ++i ) + { + m_img_bitmaps[i] = 0; + } + } + + //------------------------------------------------------------------------ + platform_specific::~platform_specific() + { + IIntuition->DisposeObject(m_window_obj); + + IP96->p96FreeBitMap(m_bitmap); + + for ( unsigned i = 0; i < platform_support::max_images; ++i ) + { + IP96->p96FreeBitMap(m_img_bitmaps[i]); + } + + if ( m_idcmp_hook != 0 ) + { + IExec->FreeSysObject(ASOT_HOOK, m_idcmp_hook); + } + } + + //------------------------------------------------------------------------ + bool platform_specific::handle_input() + { + int16 code = 0; + uint32 result = 0; + Object* obj = reinterpret_cast<Object*>(m_window_obj); + + while ( (result = IIntuition->IDoMethod(obj, WM_HANDLEINPUT, + &code)) != WMHI_LASTMSG ) + { + switch ( result & WMHI_CLASSMASK ) + { + case WMHI_CLOSEWINDOW: + return true; + break; + case WMHI_INTUITICK: + if ( !m_support.wait_mode() ) + { + m_support.on_idle(); + } + break; + case WMHI_NEWSIZE: + if ( make_bitmap() ) + { + m_support.trans_affine_resizing(m_width, m_height); + m_support.on_resize(m_width, m_height); + m_support.force_redraw(); + } + break; + } + } + + return false; + } + + //------------------------------------------------------------------------ + bool platform_specific::load_img(const char* file, unsigned idx, + rendering_buffer* rbuf) + { + if ( m_img_bitmaps[idx] != 0 ) + { + IP96->p96FreeBitMap(m_img_bitmaps[idx]); + m_img_bitmaps[idx] = 0; + } + + bool result = false; + + Object* picture = IDataTypes->NewDTObject(const_cast<STRPTR>(file), + DTA_GroupID, GID_PICTURE, + PDTA_DestMode, PMODE_V43, + PDTA_Remap, FALSE, + TAG_END); + if ( picture != 0 ) + { + gpLayout layout; + layout.MethodID = DTM_PROCLAYOUT; + layout.gpl_GInfo = 0; + layout.gpl_Initial = 1; + ULONG loaded = IDataTypes->DoDTMethodA(picture, 0, 0, + reinterpret_cast<Msg>(&layout)); + if ( loaded != 0 ) + { + BitMap* src_bitmap = 0; + IDataTypes->GetDTAttrs(picture, + PDTA_ClassBitMap, &src_bitmap, + TAG_END); + + bool supported = false; + + RGBFTYPE ftype = static_cast<RGBFTYPE>(IP96->p96GetBitMapAttr( + src_bitmap, P96BMA_RGBFORMAT)); + + switch ( ftype ) + { + case RGBFB_R8G8B8: + supported = true; + break; + default: + m_support.message("File uses unsupported graphics mode."); + break; + } + + if ( supported ) { + uint16 width = IP96->p96GetBitMapAttr(src_bitmap, + P96BMA_WIDTH); + uint16 height = IP96->p96GetBitMapAttr(src_bitmap, + P96BMA_HEIGHT); + + m_img_bitmaps[idx] = IP96->p96AllocBitMap(width, height, + m_bpp, BMF_USERPRIVATE, 0, m_ftype); + if ( m_img_bitmaps[idx] != 0 ) + { + int8u* buf = reinterpret_cast<int8u*>( + IP96->p96GetBitMapAttr(m_img_bitmaps[idx], + P96BMA_MEMORY)); + int bpr = IP96->p96GetBitMapAttr(m_img_bitmaps[idx], + P96BMA_BYTESPERROW); + int stride = (m_flip_y) ? -bpr : bpr; + rbuf->attach(buf, width, height, stride); + + // P96 sets the alpha to zero so it can't be used to + // color convert true color modes. + if ( m_bpp == 32 ) + { + RenderInfo ri; + int32 lock = IP96->p96LockBitMap(src_bitmap, + reinterpret_cast<uint8*>(&ri), + sizeof(RenderInfo)); + + rendering_buffer rbuf_src; + rbuf_src.attach( + reinterpret_cast<int8u*>(ri.Memory), + width, height, (m_flip_y) ? + -ri.BytesPerRow : ri.BytesPerRow); + + switch ( m_format ) + { + case pix_format_bgra32: + color_conv(rbuf, &rbuf_src, + color_conv_rgb24_to_bgra32()); + break; + case pix_format_abgr32: + color_conv(rbuf, &rbuf_src, + color_conv_rgb24_to_abgr32()); + break; + case pix_format_argb32: + color_conv(rbuf, &rbuf_src, + color_conv_rgb24_to_argb32()); + break; + case pix_format_rgba32: + color_conv(rbuf, &rbuf_src, + color_conv_rgb24_to_rgba32()); + break; + } + + IP96->p96UnlockBitMap(src_bitmap, lock); + } + else + { + IGraphics->BltBitMap(src_bitmap, 0, 0, + m_img_bitmaps[idx], 0, 0, width, height, + ABC|ABNC, 0xFF, 0); + } + + result = true; + } + } + } + } + + IGraphics->WaitBlit(); + IDataTypes->DisposeDTObject(picture); + + return result; + } + + //------------------------------------------------------------------------ + bool platform_specific::create_img(unsigned idx, rendering_buffer* rbuf, + unsigned width, unsigned height) + { + if ( m_img_bitmaps[idx] != 0 ) + { + IP96->p96FreeBitMap(m_img_bitmaps[idx]); + m_img_bitmaps[idx] = 0; + } + + m_img_bitmaps[idx] = IP96->p96AllocBitMap(width, height, + m_bpp, BMF_USERPRIVATE, m_bitmap, m_ftype); + if ( m_img_bitmaps[idx] != 0 ) + { + int8u* buf = reinterpret_cast<int8u*>( + IP96->p96GetBitMapAttr(m_img_bitmaps[idx], + P96BMA_MEMORY)); + int bpr = IP96->p96GetBitMapAttr(m_img_bitmaps[idx], + P96BMA_BYTESPERROW); + int stride = (m_flip_y) ? -bpr : bpr; + + rbuf->attach(buf, width, height, stride); + + return true; + } + + return false; + } + + //------------------------------------------------------------------------ + bool platform_specific::make_bitmap() + { + uint32 width = 0; + uint32 height = 0; + IIntuition->GetWindowAttrs(m_window, + WA_InnerWidth, &width, + WA_InnerHeight, &height, + TAG_END); + + BitMap* bm = IP96->p96AllocBitMap(width, height, m_bpp, + BMF_USERPRIVATE|BMF_CLEAR, 0, m_ftype); + if ( bm == 0 ) + { + return false; + } + + int8u* buf = reinterpret_cast<int8u*>( + IP96->p96GetBitMapAttr(bm, P96BMA_MEMORY)); + int bpr = IP96->p96GetBitMapAttr(bm, P96BMA_BYTESPERROW); + int stride = (m_flip_y) ? -bpr : bpr; + + m_support.rbuf_window().attach(buf, width, height, stride); + + if ( m_bitmap != 0 ) + { + IP96->p96FreeBitMap(m_bitmap); + m_bitmap = 0; + } + + m_bitmap = bm; + m_width = width; + m_height = height; + + return true; + } + + //------------------------------------------------------------------------ + platform_support::platform_support(pix_format_e format, bool flip_y) : + m_specific(new platform_specific(*this, format, flip_y)), + m_format(format), + m_bpp(m_specific->m_bpp), + m_window_flags(0), + m_wait_mode(true), + m_flip_y(flip_y), + m_initial_width(10), + m_initial_height(10) + { + std::strncpy(m_caption, "Anti-Grain Geometry", 256); + } + + //------------------------------------------------------------------------ + platform_support::~platform_support() + { + delete m_specific; + } + + //------------------------------------------------------------------------ + void platform_support::caption(const char* cap) + { + std::strncpy(m_caption, cap, 256); + if ( m_specific->m_window != 0 ) + { + const char* ignore = reinterpret_cast<const char*>(-1); + IIntuition->SetWindowAttr(m_specific->m_window, + WA_Title, m_caption, sizeof(char*)); + } + } + + //------------------------------------------------------------------------ + void platform_support::start_timer() + { + timeval tv; + gettimeofday(&tv, 0); + m_specific->m_start_time = tv.tv_secs + tv.tv_micro/1e6; + } + + //------------------------------------------------------------------------ + double platform_support::elapsed_time() const + { + timeval tv; + gettimeofday(&tv, 0); + double end_time = tv.tv_secs + tv.tv_micro/1e6; + + double elasped_seconds = end_time - m_specific->m_start_time; + double elasped_millis = elasped_seconds*1e3; + + return elasped_millis; + } + + //------------------------------------------------------------------------ + void* platform_support::raw_display_handler() + { + return 0; // Not available. + } + + //------------------------------------------------------------------------ + void platform_support::message(const char* msg) + { + APTR req = IIntuition->NewObject(RequesterClass, 0, + REQ_TitleText, "Anti-Grain Geometry", + REQ_Image, REQIMAGE_INFO, + REQ_BodyText, msg, + REQ_GadgetText, "_Ok", + TAG_END); + if ( req == 0 ) + { + IDOS->Printf("Message: %s\n", msg); + return; + } + + orRequest reqmsg; + reqmsg.MethodID = RM_OPENREQ; + reqmsg.or_Attrs = 0; + reqmsg.or_Window = m_specific->m_window; + reqmsg.or_Screen = 0; + + IIntuition->IDoMethodA(reinterpret_cast<Object*>(req), + reinterpret_cast<Msg>(&reqmsg)); + IIntuition->DisposeObject(req); + } + + //------------------------------------------------------------------------ + bool platform_support::init(unsigned width, unsigned height, + unsigned flags) + { + if( m_specific->m_ftype == RGBFB_NONE ) + { + message("Unsupported mode requested."); + return false; + } + + m_window_flags = flags; + + m_specific->m_idcmp_hook = reinterpret_cast<Hook*>( + IExec->AllocSysObjectTags(ASOT_HOOK, + ASOHOOK_Entry, handle_idcmp, + ASOHOOK_Data, this, + TAG_END)); + if ( m_specific->m_idcmp_hook == 0 ) + { + return false; + } + + m_specific->m_window_obj = IIntuition->NewObject(WindowClass, 0, + WA_Title, m_caption, + WA_AutoAdjustDClip, TRUE, + WA_InnerWidth, width, + WA_InnerHeight, height, + WA_Activate, TRUE, + WA_SmartRefresh, TRUE, + WA_NoCareRefresh, TRUE, + WA_CloseGadget, TRUE, + WA_DepthGadget, TRUE, + WA_SizeGadget, (flags & agg::window_resize) ? TRUE : FALSE, + WA_DragBar, TRUE, + WA_AutoAdjust, TRUE, + WA_ReportMouse, TRUE, + WA_RMBTrap, TRUE, + WA_MouseQueue, 1, + WA_IDCMP, + IDCMP_NEWSIZE | + IDCMP_MOUSEBUTTONS | + IDCMP_MOUSEMOVE | + IDCMP_RAWKEY | + IDCMP_INTUITICKS, + WINDOW_IDCMPHook, m_specific->m_idcmp_hook, + WINDOW_IDCMPHookBits, + IDCMP_MOUSEBUTTONS | + IDCMP_MOUSEMOVE | + IDCMP_RAWKEY, + TAG_END); + if ( m_specific->m_window_obj == 0 ) + { + return false; + } + + Object* obj = reinterpret_cast<Object*>(m_specific->m_window_obj); + m_specific->m_window = + reinterpret_cast<Window*>(IIntuition->IDoMethod(obj, WM_OPEN)); + if ( m_specific->m_window == 0 ) + { + return false; + } + + RGBFTYPE ftype = static_cast<RGBFTYPE>(IP96->p96GetBitMapAttr( + m_specific->m_window->RPort->BitMap, P96BMA_RGBFORMAT)); + + switch ( ftype ) + { + case RGBFB_A8R8G8B8: + case RGBFB_B8G8R8A8: + case RGBFB_R5G6B5PC: + break; + default: + message("Unsupported screen mode.\n"); + return false; + } + + if ( !m_specific->make_bitmap() ) + { + return false; + } + + m_initial_width = width; + m_initial_height = height; + + on_init(); + on_resize(width, height); + force_redraw(); + + return true; + } + + //------------------------------------------------------------------------ + int platform_support::run() + { + uint32 window_mask = 0; + IIntuition->GetAttr(WINDOW_SigMask, m_specific->m_window_obj, + &window_mask); + uint32 wait_mask = window_mask | SIGBREAKF_CTRL_C; + + bool done = false; + + while ( !done ) + { + uint32 sig_mask = IExec->Wait(wait_mask); + if ( sig_mask & SIGBREAKF_CTRL_C ) + { + done = true; + } + else + { + done = m_specific->handle_input(); + } + } + + return 0; + } + + //------------------------------------------------------------------------ + const char* platform_support::img_ext() const + { + return ".bmp"; + } + + //------------------------------------------------------------------------ + const char* platform_support::full_file_name(const char* file_name) + { + return file_name; + } + + //------------------------------------------------------------------------ + bool platform_support::load_img(unsigned idx, const char* file) + { + if ( idx < max_images ) + { + static char fn[1024]; + std::strncpy(fn, file, 1024); + int len = std::strlen(fn); + if ( len < 4 || std::strcmp(fn + len - 4, ".bmp") != 0 ) + { + std::strncat(fn, ".bmp", 1024); + } + + return m_specific->load_img(fn, idx, &m_rbuf_img[idx]); + } + + return false; + } + + //------------------------------------------------------------------------ + bool platform_support::save_img(unsigned idx, const char* file) + { + message("Not supported"); + return false; + } + + //------------------------------------------------------------------------ + bool platform_support::create_img(unsigned idx, unsigned width, + unsigned height) + { + if ( idx < max_images ) + { + if ( width == 0 ) + { + width = m_specific->m_width; + } + + if ( height == 0 ) + { + height = m_specific->m_height; + } + + return m_specific->create_img(idx, &m_rbuf_img[idx], width, + height); + } + + return false; + } + + //------------------------------------------------------------------------ + void platform_support::force_redraw() + { + on_draw(); + update_window(); + } + + //------------------------------------------------------------------------ + void platform_support::update_window() + { + // Note this function does automatic color conversion. + IGraphics->BltBitMapRastPort(m_specific->m_bitmap, 0, 0, + m_specific->m_window->RPort, m_specific->m_window->BorderLeft, + m_specific->m_window->BorderTop, m_specific->m_width, + m_specific->m_height, ABC|ABNC); + } + + //------------------------------------------------------------------------ + void platform_support::on_init() {} + void platform_support::on_resize(int sx, int sy) {} + void platform_support::on_idle() {} + void platform_support::on_mouse_move(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {} + void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {} + void platform_support::on_ctrl_change() {} + void platform_support::on_draw() {} + void platform_support::on_post_draw(void* raw_handler) {} + + //------------------------------------------------------------------------ + void handle_idcmp(Hook* hook, APTR obj, IntuiMessage* msg) + { + platform_support* app = + reinterpret_cast<platform_support*>(hook->h_Data); + Window* window = app->m_specific->m_window; + + int16 x = msg->MouseX - window->BorderLeft; + + int16 y = 0; + if ( app->flip_y() ) + { + y = window->Height - window->BorderBottom - msg->MouseY; + } + else + { + y = msg->MouseY - window->BorderTop; + } + + switch ( msg->Class ) + { + case IDCMP_MOUSEBUTTONS: + if ( msg->Code & IECODE_UP_PREFIX ) + { + if ( msg->Code == SELECTUP ) + { + app->m_specific->m_input_flags = mouse_left; + app->m_specific->m_dragging = false; + } + else if ( msg->Code == MENUUP ) + { + app->m_specific->m_input_flags = mouse_right; + app->m_specific->m_dragging = false; + } + else + { + return; + } + + + if ( app->m_ctrls.on_mouse_button_up(x, y) ) + { + app->on_ctrl_change(); + app->force_redraw(); + } + + app->on_mouse_button_up(x, y, app->m_specific->m_input_flags); + } + else + { + if ( msg->Code == SELECTDOWN ) + { + app->m_specific->m_input_flags = mouse_left; + app->m_specific->m_dragging = true; + } + else if ( msg->Code == MENUDOWN ) + { + app->m_specific->m_input_flags = mouse_right; + app->m_specific->m_dragging = true; + } + else + { + return; + } + + app->m_ctrls.set_cur(x, y); + if ( app->m_ctrls.on_mouse_button_down(x, y) ) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + if ( app->m_ctrls.in_rect(x, y) ) + { + if ( app->m_ctrls.set_cur(x, y) ) + { + app->on_ctrl_change(); + app->force_redraw(); + } + } + else + { + app->on_mouse_button_down(x, y, + app->m_specific->m_input_flags); + } + } + } + break; + case IDCMP_MOUSEMOVE: + if ( app->m_specific->m_dragging ) { + if ( app->m_ctrls.on_mouse_move(x, y, + app->m_specific->m_input_flags & mouse_left) != 0 ) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + if ( !app->m_ctrls.in_rect(x, y) ) + { + app->on_mouse_move(x, y, + app->m_specific->m_input_flags); + } + } + } + break; + case IDCMP_RAWKEY: + { + static InputEvent ie = { 0 }; + ie.ie_Class = IECLASS_RAWKEY; + ie.ie_Code = msg->Code; + ie.ie_Qualifier = msg->Qualifier; + + static const unsigned BUF_SIZE = 16; + static char key_buf[BUF_SIZE]; + int16 num_chars = IKeymap->MapRawKey(&ie, key_buf, BUF_SIZE, 0); + + uint32 code = 0x00000000; + switch ( num_chars ) + { + case 1: + code = key_buf[0]; + break; + case 2: + code = key_buf[0]<<8 | key_buf[1]; + break; + case 3: + code = key_buf[0]<<16 | key_buf[1]<<8 | key_buf[2]; + break; + } + + uint16 key_code = 0; + + if ( num_chars == 1 ) + { + if ( code >= IECODE_ASCII_FIRST && code <= IECODE_ASCII_LAST ) + { + key_code = code; + } + } + + if ( key_code == 0 ) + { + switch ( code ) + { + case 0x00000008: key_code = key_backspace; break; + case 0x00000009: key_code = key_tab; break; + case 0x0000000D: key_code = key_return; break; + case 0x0000001B: key_code = key_escape; break; + case 0x0000007F: key_code = key_delete; break; + case 0x00009B41: + case 0x00009B54: key_code = key_up; break; + case 0x00009B42: + case 0x00009B53: key_code = key_down; break; + case 0x00009B43: + case 0x009B2040: key_code = key_right; break; + case 0x00009B44: + case 0x009B2041: key_code = key_left; break; + case 0x009B307E: key_code = key_f1; break; + case 0x009B317E: key_code = key_f2; break; + case 0x009B327E: key_code = key_f3; break; + case 0x009B337E: key_code = key_f4; break; + case 0x009B347E: key_code = key_f5; break; + case 0x009B357E: key_code = key_f6; break; + case 0x009B367E: key_code = key_f7; break; + case 0x009B377E: key_code = key_f8; break; + case 0x009B387E: key_code = key_f9; break; + case 0x009B397E: key_code = key_f10; break; + case 0x009B3F7E: key_code = key_scrollock; break; + } + } + + if ( ie.ie_Code & IECODE_UP_PREFIX ) + { + if ( app->m_specific->m_last_key != 0 ) + { + bool left = (key_code == key_left) ? true : false; + bool right = (key_code == key_right) ? true : false; + bool down = (key_code == key_down) ? true : false; + bool up = (key_code == key_up) ? true : false; + + if ( app->m_ctrls.on_arrow_keys(left, right, down, up) ) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + app->on_key(x, y, app->m_specific->m_last_key, 0); + } + + app->m_specific->m_last_key = 0; + } + } + else + { + app->m_specific->m_last_key = key_code; + } + break; + } + default: + break; + } + } +} + +//---------------------------------------------------------------------------- +int agg_main(int argc, char* argv[]); +bool open_libs(); +void close_libs(); + +//---------------------------------------------------------------------------- +bool open_libs() +{ + DataTypesBase = IExec->OpenLibrary("datatypes.library", 51); + GraphicsBase = IExec->OpenLibrary("graphics.library", 51); + IntuitionBase = IExec->OpenLibrary("intuition.library", 51); + KeymapBase = IExec->OpenLibrary("keymap.library", 51); + P96Base = IExec->OpenLibrary("Picasso96API.library", 2); + + IDataTypes = reinterpret_cast<DataTypesIFace*>( + IExec->GetInterface(DataTypesBase, "main", 1, 0)); + IGraphics = reinterpret_cast<GraphicsIFace*>( + IExec->GetInterface(GraphicsBase, "main", 1, 0)); + IIntuition = reinterpret_cast<IntuitionIFace*>( + IExec->GetInterface(IntuitionBase, "main", 1, 0)); + IKeymap = reinterpret_cast<KeymapIFace*>( + IExec->GetInterface(KeymapBase, "main", 1, 0)); + IP96 = reinterpret_cast<P96IFace*>( + IExec->GetInterface(P96Base, "main", 1, 0)); + + if ( IDataTypes == 0 || + IGraphics == 0 || + IIntuition == 0 || + IKeymap == 0 || + IP96 == 0 ) + { + close_libs(); + return false; + } + else + { + return true; + } +} + +//---------------------------------------------------------------------------- +void close_libs() +{ + IExec->DropInterface(reinterpret_cast<Interface*>(IP96)); + IExec->DropInterface(reinterpret_cast<Interface*>(IKeymap)); + IExec->DropInterface(reinterpret_cast<Interface*>(IIntuition)); + IExec->DropInterface(reinterpret_cast<Interface*>(IGraphics)); + IExec->DropInterface(reinterpret_cast<Interface*>(IDataTypes)); + + IExec->CloseLibrary(P96Base); + IExec->CloseLibrary(KeymapBase); + IExec->CloseLibrary(IntuitionBase); + IExec->CloseLibrary(GraphicsBase); + IExec->CloseLibrary(DataTypesBase); +} + +//---------------------------------------------------------------------------- +int main(int argc, char* argv[]) +{ + if ( !open_libs() ) { + IDOS->Printf("Can't open libraries.\n"); + return -1; + } + + ClassLibrary* requester = + IIntuition->OpenClass("requester.class", 51, &RequesterClass); + ClassLibrary* window = + IIntuition->OpenClass("window.class", 51, &WindowClass); + if ( requester == 0 || window == 0 ) + { + IDOS->Printf("Can't open classes.\n"); + IIntuition->CloseClass(requester); + IIntuition->CloseClass(window); + close_libs(); + return -1; + } + + int rc = agg_main(argc, argv); + + IIntuition->CloseClass(window); + IIntuition->CloseClass(requester); + close_libs(); + + return rc; +} diff --git a/jni/desmume/src/android/agg/src/platform/BeOS/Makefile.am b/jni/desmume/src/android/agg/src/platform/BeOS/Makefile.am new file mode 100755 index 0000000..474153c --- /dev/null +++ b/jni/desmume/src/android/agg/src/platform/BeOS/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST=agg_platform_support.cpp diff --git a/jni/desmume/src/android/agg/src/platform/BeOS/agg_platform_support.cpp b/jni/desmume/src/android/agg/src/platform/BeOS/agg_platform_support.cpp new file mode 100755 index 0000000..c5f53d3 --- /dev/null +++ b/jni/desmume/src/android/agg/src/platform/BeOS/agg_platform_support.cpp @@ -0,0 +1,998 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Copyright (C) 2004 Stephan Assmus (superstippi@gmx.de) +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <new> +#include <stdio.h> + +#include <Alert.h> +#include <Application.h> +#include <Bitmap.h> +#include <Message.h> +#include <MessageRunner.h> +#include <Messenger.h> +#include <Path.h> +#include <Roster.h> +#include <TranslationUtils.h> +#include <View.h> +#include <Window.h> + +#include <string.h> +#include "platform/agg_platform_support.h" +#include "util/agg_color_conv_rgb8.h" + +using std::nothrow; + + +static void +attach_buffer_to_BBitmap(agg::rendering_buffer& buffer, BBitmap* bitmap, bool flipY) +{ + uint8* bits = (uint8*)bitmap->Bits(); + uint32 width = bitmap->Bounds().IntegerWidth() + 1; + uint32 height = bitmap->Bounds().IntegerHeight() + 1; + int32 bpr = bitmap->BytesPerRow(); + if (flipY) { +// XXX: why don't I have to do this?!? +// bits += bpr * (height - 1); + bpr = -bpr; + } + buffer.attach(bits, width, height, bpr); +} + + +static color_space +pix_format_to_color_space(agg::pix_format_e format) +{ + color_space bitmapFormat = B_NO_COLOR_SPACE; + switch (format) { + case agg::pix_format_rgb555: + + bitmapFormat = B_RGB15; + break; + + case agg::pix_format_rgb565: + + bitmapFormat = B_RGB16; + break; + + case agg::pix_format_rgb24: + case agg::pix_format_bgr24: + + bitmapFormat = B_RGB24; + break; + + case agg::pix_format_rgba32: + case agg::pix_format_argb32: + case agg::pix_format_abgr32: + case agg::pix_format_bgra32: + + bitmapFormat = B_RGBA32; + break; + } + return bitmapFormat; +} + + +// #pragma mark - + + +class AGGView : public BView { + public: + AGGView(BRect frame, agg::platform_support* agg, + agg::pix_format_e format, bool flipY); + virtual ~AGGView(); + + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + + virtual void MessageReceived(BMessage* message); + virtual void Draw(BRect updateRect); + virtual void FrameResized(float width, float height); + + virtual void KeyDown(const char* bytes, int32 numBytes); + + virtual void MouseDown(BPoint where); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMesage); + virtual void MouseUp(BPoint where); + + BBitmap* Bitmap() const; + + uint8 LastKeyDown() const; + uint32 MouseButtons(); + + void Update(); + void ForceRedraw(); + + unsigned GetKeyFlags(); + + private: + BBitmap* fBitmap; + agg::pix_format_e fFormat; + bool fFlipY; + + agg::platform_support* fAGG; + + uint32 fMouseButtons; + int32 fMouseX; + int32 fMouseY; + + uint8 fLastKeyDown; + + bool fRedraw; + + BMessageRunner* fPulse; + bigtime_t fLastPulse; + bool fEnableTicks; +}; + +AGGView::AGGView(BRect frame, + agg::platform_support* agg, + agg::pix_format_e format, + bool flipY) + : BView(frame, "AGG View", B_FOLLOW_ALL, + B_FRAME_EVENTS | B_WILL_DRAW), + fFormat(format), + fFlipY(flipY), + + fAGG(agg), + + fMouseButtons(0), + fMouseX(-1), + fMouseY(-1), + + fLastKeyDown(0), + + fRedraw(true), + + fPulse(NULL), + fLastPulse(0), + fEnableTicks(true) +{ + SetViewColor(B_TRANSPARENT_32_BIT); + + frame.OffsetTo(0.0, 0.0); + fBitmap = new BBitmap(frame, 0, pix_format_to_color_space(fFormat)); + if (fBitmap->IsValid()) { + attach_buffer_to_BBitmap(fAGG->rbuf_window(), fBitmap, fFlipY); + } else { + delete fBitmap; + fBitmap = NULL; + } +} + + +AGGView::~AGGView() +{ + delete fBitmap; + delete fPulse; +} + + +void +AGGView::AttachedToWindow() +{ + BMessage message('tick'); + BMessenger target(this, Looper()); + delete fPulse; +// BScreen screen; +// TODO: calc screen retrace + fPulse = new BMessageRunner(target, &message, 40000); + + // make sure we call this once + fAGG->on_resize(Bounds().IntegerWidth() + 1, + Bounds().IntegerHeight() + 1); + MakeFocus(); +} + + +void +AGGView::DetachedFromWindow() +{ + delete fPulse; + fPulse = NULL; +} + + +void +AGGView::MessageReceived(BMessage* message) +{ + bigtime_t now = system_time(); + switch (message->what) { + case 'tick': + // drop messages that have piled up + if (/*now - fLastPulse > 30000*/fEnableTicks) { + fLastPulse = now; + if (!fAGG->wait_mode()) + fAGG->on_idle(); + Window()->PostMessage('entk', this); + fEnableTicks = false; + } else { +// printf("dropping tick message (%lld)\n", now - fLastPulse); + } + break; + case 'entk': + fEnableTicks = true; + if (now - fLastPulse > 30000) { + fLastPulse = now; + if (!fAGG->wait_mode()) + fAGG->on_idle(); + } + break; + default: + BView::MessageReceived(message); + break; + } +} + + +void +AGGView::Draw(BRect updateRect) +{ + if (fBitmap) { + if (fRedraw) { + fAGG->on_draw(); + fRedraw = false; + } + if (fFormat == agg::pix_format_bgra32) { + DrawBitmap(fBitmap, updateRect, updateRect); + } else { + BBitmap* bitmap = new BBitmap(fBitmap->Bounds(), 0, B_RGBA32); + + agg::rendering_buffer rbufSrc; + attach_buffer_to_BBitmap(rbufSrc, fBitmap, false); + + agg::rendering_buffer rbufDst; + attach_buffer_to_BBitmap(rbufDst, bitmap, false); + + switch(fFormat) { + case agg::pix_format_rgb555: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_rgb555_to_bgra32()); + break; + case agg::pix_format_rgb565: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_rgb565_to_bgra32()); + break; + case agg::pix_format_rgb24: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_rgb24_to_bgra32()); + break; + case agg::pix_format_bgr24: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_bgr24_to_bgra32()); + break; + case agg::pix_format_rgba32: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_rgba32_to_bgra32()); + break; + case agg::pix_format_argb32: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_argb32_to_bgra32()); + break; + case agg::pix_format_abgr32: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_abgr32_to_bgra32()); + break; + case agg::pix_format_bgra32: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_bgra32_to_bgra32()); + break; + } + DrawBitmap(bitmap, updateRect, updateRect); + delete bitmap; + } + } else { + FillRect(updateRect); + } +} + + +void +AGGView::FrameResized(float width, float height) +{ + BRect r(0.0, 0.0, width, height); + BBitmap* bitmap = new BBitmap(r, 0, pix_format_to_color_space(fFormat)); + if (bitmap->IsValid()) { + delete fBitmap; + fBitmap = bitmap; + attach_buffer_to_BBitmap(fAGG->rbuf_window(), fBitmap, fFlipY); + + fAGG->trans_affine_resizing((int)width + 1, + (int)height + 1); + + // pass the event on to AGG + fAGG->on_resize((int)width + 1, (int)height + 1); + + fRedraw = true; + Invalidate(); + } else + delete bitmap; +} + + +void +AGGView::KeyDown(const char* bytes, int32 numBytes) +{ + if (bytes && numBytes > 0) { + fLastKeyDown = bytes[0]; + + bool left = false; + bool up = false; + bool right = false; + bool down = false; + + switch (fLastKeyDown) { + + case B_LEFT_ARROW: + left = true; + break; + + case B_UP_ARROW: + up = true; + break; + + case B_RIGHT_ARROW: + right = true; + break; + + case B_DOWN_ARROW: + down = true; + break; + } + +/* case key_f2: +fAGG->copy_window_to_img(agg::platform_support::max_images - 1); +fAGG->save_img(agg::platform_support::max_images - 1, "screenshot"); +break; +}*/ + + + if (fAGG->m_ctrls.on_arrow_keys(left, right, down, up)) { + fAGG->on_ctrl_change(); + fAGG->force_redraw(); + } else { + fAGG->on_key(fMouseX, fMouseY, fLastKeyDown, GetKeyFlags()); + } +// fAGG->on_key(fMouseX, fMouseY, fLastKeyDown, GetKeyFlags()); + + } +} + + +void +AGGView::MouseDown(BPoint where) +{ + BMessage* currentMessage = Window()->CurrentMessage(); + if (currentMessage) { + if (currentMessage->FindInt32("buttons", (int32*)&fMouseButtons) < B_OK) + fMouseButtons = B_PRIMARY_MOUSE_BUTTON; + } else + fMouseButtons = B_PRIMARY_MOUSE_BUTTON; + + fMouseX = (int)where.x; + fMouseY = fFlipY ? (int)(Bounds().Height() - where.y) : (int)where.y; + + // pass the event on to AGG + if (fMouseButtons == B_PRIMARY_MOUSE_BUTTON) { + // left mouse button -> see if to handle in controls + fAGG->m_ctrls.set_cur(fMouseX, fMouseY); + if (fAGG->m_ctrls.on_mouse_button_down(fMouseX, fMouseY)) { + fAGG->on_ctrl_change(); + fAGG->force_redraw(); + } else { + if (fAGG->m_ctrls.in_rect(fMouseX, fMouseY)) { + if (fAGG->m_ctrls.set_cur(fMouseX, fMouseY)) { + fAGG->on_ctrl_change(); + fAGG->force_redraw(); + } + } else { + fAGG->on_mouse_button_down(fMouseX, fMouseY, GetKeyFlags()); + } + } + } else if (fMouseButtons & B_SECONDARY_MOUSE_BUTTON) { + // right mouse button -> simple + fAGG->on_mouse_button_down(fMouseX, fMouseY, GetKeyFlags()); + } + SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); +} + + +void +AGGView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMesage) +{ + // workarround missed mouse up events + // (if we react too slowly, app_server might have dropped events) + BMessage* currentMessage = Window()->CurrentMessage(); + int32 buttons = 0; + if (currentMessage->FindInt32("buttons", &buttons) < B_OK) { + buttons = 0; + } + if (!buttons) + MouseUp(where); + + fMouseX = (int)where.x; + fMouseY = fFlipY ? (int)(Bounds().Height() - where.y) : (int)where.y; + + // pass the event on to AGG + if (fAGG->m_ctrls.on_mouse_move(fMouseX, fMouseY, + (GetKeyFlags() & agg::mouse_left) != 0)) { + fAGG->on_ctrl_change(); + fAGG->force_redraw(); + } else { + if (!fAGG->m_ctrls.in_rect(fMouseX, fMouseY)) { + fAGG->on_mouse_move(fMouseX, fMouseY, GetKeyFlags()); + } + } +} + + +void +AGGView::MouseUp(BPoint where) +{ + fMouseX = (int)where.x; + fMouseY = fFlipY ? (int)(Bounds().Height() - where.y) : (int)where.y; + + // pass the event on to AGG + if (fMouseButtons == B_PRIMARY_MOUSE_BUTTON) { + fMouseButtons = 0; + + if (fAGG->m_ctrls.on_mouse_button_up(fMouseX, fMouseY)) { + fAGG->on_ctrl_change(); + fAGG->force_redraw(); + } + fAGG->on_mouse_button_up(fMouseX, fMouseY, GetKeyFlags()); + } else if (fMouseButtons == B_SECONDARY_MOUSE_BUTTON) { + fMouseButtons = 0; + + fAGG->on_mouse_button_up(fMouseX, fMouseY, GetKeyFlags()); + } +} + + +BBitmap* +AGGView::Bitmap() const +{ + return fBitmap; +} + + +uint8 +AGGView::LastKeyDown() const +{ + return fLastKeyDown; +} + + +uint32 +AGGView::MouseButtons() +{ + uint32 buttons = 0; + if (LockLooper()) { + buttons = fMouseButtons; + UnlockLooper(); + } + return buttons; +} + + +void +AGGView::Update() +{ + // trigger display update + if (LockLooper()) { + Invalidate(); + UnlockLooper(); + } +} + + +void +AGGView::ForceRedraw() +{ + // force a redraw (fRedraw = true;) + // and trigger display update + if (LockLooper()) { + fRedraw = true; + Invalidate(); + UnlockLooper(); + } +} + + +unsigned +AGGView::GetKeyFlags() +{ + uint32 buttons = fMouseButtons; + uint32 mods = modifiers(); + unsigned flags = 0; + if (buttons & B_PRIMARY_MOUSE_BUTTON) flags |= agg::mouse_left; + if (buttons & B_SECONDARY_MOUSE_BUTTON) flags |= agg::mouse_right; + if (mods & B_SHIFT_KEY) flags |= agg::kbd_shift; + if (mods & B_COMMAND_KEY) flags |= agg::kbd_ctrl; + return flags; +} + +// #pragma mark - + + +class AGGWindow : public BWindow { + public: + AGGWindow() + : BWindow(BRect(-50.0, -50.0, -10.0, -10.0), + "AGG Application", B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS) + { + } + + virtual bool QuitRequested() + { + be_app->PostMessage(B_QUIT_REQUESTED); + return true; + } + + bool Init(BRect frame, agg::platform_support* agg, agg::pix_format_e format, + bool flipY, uint32 flags) + { + MoveTo(frame.LeftTop()); + ResizeTo(frame.Width(), frame.Height()); + + SetFlags(flags); + + frame.OffsetTo(0.0, 0.0); + fView = new AGGView(frame, agg, format, flipY); + AddChild(fView); + + return fView->Bitmap() != NULL; + } + + + AGGView* View() const + { + return fView; + } + private: + AGGView* fView; +}; + +// #pragma mark - + + +class AGGApplication : public BApplication { + public: + AGGApplication() + : BApplication("application/x-vnd.AGG-AGG") + { + fWindow = new AGGWindow(); + } + + virtual void ReadyToRun() + { + if (fWindow) { + fWindow->Show(); + } + } + + virtual bool Init(agg::platform_support* agg, int width, int height, + agg::pix_format_e format, bool flipY, uint32 flags) + { + BRect r(50.0, 50.0, + 50.0 + width - 1.0, + 50.0 + height - 1.0); + uint32 windowFlags = B_ASYNCHRONOUS_CONTROLS; + if (!(flags & agg::window_resize)) + windowFlags |= B_NOT_RESIZABLE; + + return fWindow->Init(r, agg, format, flipY, windowFlags);; + } + + + AGGWindow* Window() const + { + return fWindow; + } + + private: + AGGWindow* fWindow; +}; + + +// #pragma mark - + + +namespace agg +{ + +class platform_specific { + public: + platform_specific(agg::platform_support* agg, + agg::pix_format_e format, bool flip_y) + : fAGG(agg), + fApp(NULL), + fFormat(format), + fFlipY(flip_y), + fTimerStart(system_time()) + { + memset(fImages, 0, sizeof(fImages)); + fApp = new AGGApplication(); + fAppPath[0] = 0; + // figure out where we're running from + app_info info; + status_t ret = fApp->GetAppInfo(&info); + if (ret >= B_OK) { + BPath path(&info.ref); + ret = path.InitCheck(); + if (ret >= B_OK) { + ret = path.GetParent(&path); + if (ret >= B_OK) { + sprintf(fAppPath, "%s", path.Path()); + } else { + fprintf(stderr, "getting app parent folder failed: %s\n", strerror(ret)); + } + } else { + fprintf(stderr, "making app path failed: %s\n", strerror(ret)); + } + } else { + fprintf(stderr, "GetAppInfo() failed: %s\n", strerror(ret)); + } + } + ~platform_specific() + { + for (int32 i = 0; i < agg::platform_support::max_images; i++) + delete fImages[i]; + delete fApp; + } + + bool Init(int width, int height, unsigned flags) + { + return fApp->Init(fAGG, width, height, fFormat, fFlipY, flags); + } + + int Run() + { + status_t ret = B_NO_INIT; + if (fApp) { + fApp->Run(); + ret = B_OK; + } + return ret; + } + + void SetTitle(const char* title) + { + if (fApp && fApp->Window() && fApp->Window()->Lock()) { + fApp->Window()->SetTitle(title); + fApp->Window()->Unlock(); + } + } + void StartTimer() + { + fTimerStart = system_time(); + } + double ElapsedTime() const + { + return (system_time() - fTimerStart) / 1000.0; + } + + void ForceRedraw() + { + fApp->Window()->View()->ForceRedraw(); + } + void UpdateWindow() + { + fApp->Window()->View()->Update(); + } + + + agg::platform_support* fAGG; + AGGApplication* fApp; + agg::pix_format_e fFormat; + bool fFlipY; + bigtime_t fTimerStart; + BBitmap* fImages[agg::platform_support::max_images]; + + char fAppPath[B_PATH_NAME_LENGTH]; + char fFilePath[B_PATH_NAME_LENGTH]; +}; + + + //------------------------------------------------------------------------ + platform_support::platform_support(pix_format_e format, bool flip_y) : + m_specific(new platform_specific(this, format, flip_y)), + m_format(format), + m_bpp(32/*m_specific->m_bpp*/), + m_window_flags(0), + m_wait_mode(true), + m_flip_y(flip_y), + m_initial_width(10), + m_initial_height(10) + { + strcpy(m_caption, "Anti-Grain Geometry Application"); + } + + + //------------------------------------------------------------------------ + platform_support::~platform_support() + { + delete m_specific; + } + + //------------------------------------------------------------------------ + void platform_support::caption(const char* cap) + { + strcpy(m_caption, cap); + m_specific->SetTitle(cap); + } + + //------------------------------------------------------------------------ + void platform_support::start_timer() + { + m_specific->StartTimer(); + } + + //------------------------------------------------------------------------ + double platform_support::elapsed_time() const + { + return m_specific->ElapsedTime(); + } + + //------------------------------------------------------------------------ + void* platform_support::raw_display_handler() + { + // TODO: if we ever support BDirectWindow here, that would + // be the frame buffer pointer with offset to the window top left + return NULL; + } + + //------------------------------------------------------------------------ + void platform_support::message(const char* msg) + { + BAlert* alert = new BAlert("AGG Message", msg, "Ok"); + alert->Go(/*NULL*/); + } + + + //------------------------------------------------------------------------ + bool platform_support::init(unsigned width, unsigned height, unsigned flags) + { + m_initial_width = width; + m_initial_height = height; + m_window_flags = flags; + + if (m_specific->Init(width, height, flags)) { + on_init(); + return true; + } + + return false; + } + + + //------------------------------------------------------------------------ + int platform_support::run() + { + return m_specific->Run(); + } + + + //------------------------------------------------------------------------ + const char* platform_support::img_ext() const { return ".ppm"; } + + + const char* platform_support::full_file_name(const char* file_name) + { + sprintf(m_specific->fFilePath, "%s/%s", m_specific->fAppPath, file_name); + return m_specific->fFilePath; + } + + + //------------------------------------------------------------------------ + bool platform_support::load_img(unsigned idx, const char* file) + { + if (idx < max_images) + { + char path[B_PATH_NAME_LENGTH]; + sprintf(path, "%s/%s%s", m_specific->fAppPath, file, img_ext()); + BBitmap* transBitmap = BTranslationUtils::GetBitmap(path); + if (transBitmap && transBitmap->IsValid()) { + if(transBitmap->ColorSpace() != B_RGB32 && transBitmap->ColorSpace() != B_RGBA32) { + // ups we got a smart ass Translator making our live harder + delete transBitmap; + return false; + } + + color_space format = B_RGB24; + + switch (m_format) { + case pix_format_gray8: + format = B_GRAY8; + break; + case pix_format_rgb555: + format = B_RGB15; + break; + case pix_format_rgb565: + format = B_RGB16; + break; + case pix_format_rgb24: + format = B_RGB24_BIG; + break; + case pix_format_bgr24: + format = B_RGB24; + break; + case pix_format_abgr32: + case pix_format_argb32: + case pix_format_bgra32: + format = B_RGB32; + break; + case pix_format_rgba32: + format = B_RGB32_BIG; + break; + } + BBitmap* bitmap = new (nothrow) BBitmap(transBitmap->Bounds(), 0, format); + if (!bitmap || !bitmap->IsValid()) { + fprintf(stderr, "failed to allocate temporary bitmap!\n"); + delete transBitmap; + delete bitmap; + return false; + } + + delete m_specific->fImages[idx]; + + rendering_buffer rbuf_tmp; + attach_buffer_to_BBitmap(rbuf_tmp, transBitmap, m_flip_y); + + m_specific->fImages[idx] = bitmap; + + attach_buffer_to_BBitmap(m_rbuf_img[idx], bitmap, m_flip_y); + + rendering_buffer* dst = &m_rbuf_img[idx]; + + switch(m_format) + { + case pix_format_gray8: + return false; +// color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_gray8()); break; + break; + + case pix_format_rgb555: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb555()); break; + break; + + case pix_format_rgb565: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb565()); break; + break; + + case pix_format_rgb24: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb24()); break; + break; + + case pix_format_bgr24: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_bgr24()); break; + break; + + case pix_format_abgr32: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_abgr32()); break; + break; + + case pix_format_argb32: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_argb32()); break; + break; + + case pix_format_bgra32: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_bgra32()); break; + break; + + case pix_format_rgba32: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgba32()); break; + break; + } + delete transBitmap; + + return true; + + } else { + fprintf(stderr, "failed to load bitmap: '%s'\n", full_file_name(file)); + } + } + return false; + } + + + + //------------------------------------------------------------------------ + bool platform_support::save_img(unsigned idx, const char* file) + { + // TODO: implement using BTranslatorRoster and friends + return false; + } + + + + //------------------------------------------------------------------------ + bool platform_support::create_img(unsigned idx, unsigned width, unsigned height) + { + if(idx < max_images) + { + if(width == 0) width = m_specific->fApp->Window()->View()->Bitmap()->Bounds().IntegerWidth() + 1; + if(height == 0) height = m_specific->fApp->Window()->View()->Bitmap()->Bounds().IntegerHeight() + 1; + BBitmap* bitmap = new BBitmap(BRect(0.0, 0.0, width - 1, height - 1), 0, B_RGBA32);; + if (bitmap && bitmap->IsValid()) { + delete m_specific->fImages[idx]; + m_specific->fImages[idx] = bitmap; + attach_buffer_to_BBitmap(m_rbuf_img[idx], bitmap, m_flip_y); + return true; + } else { + delete bitmap; + } + } + return false; + } + + + //------------------------------------------------------------------------ + void platform_support::force_redraw() + { + m_specific->ForceRedraw(); + } + + + + //------------------------------------------------------------------------ + void platform_support::update_window() + { + m_specific->UpdateWindow(); + } + + + //------------------------------------------------------------------------ + void platform_support::on_init() {} + void platform_support::on_resize(int sx, int sy) {} + void platform_support::on_idle() {} + void platform_support::on_mouse_move(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {} + void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {} + void platform_support::on_ctrl_change() {} + void platform_support::on_draw() {} + void platform_support::on_post_draw(void* raw_handler) {} +} + + + + + + +//---------------------------------------------------------------------------- +int agg_main(int argc, char* argv[]); + + + +int +main(int argc, char* argv[]) +{ + return agg_main(argc, argv); +} + + + + diff --git a/jni/desmume/src/android/agg/src/platform/Makefile.am b/jni/desmume/src/android/agg/src/platform/Makefile.am new file mode 100755 index 0000000..ebe5e7e --- /dev/null +++ b/jni/desmume/src/android/agg/src/platform/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = X11 sdl win32 AmigaOS BeOS mac diff --git a/jni/desmume/src/android/agg/src/platform/X11/Makefile.am b/jni/desmume/src/android/agg/src/platform/X11/Makefile.am new file mode 100755 index 0000000..da5757f --- /dev/null +++ b/jni/desmume/src/android/agg/src/platform/X11/Makefile.am @@ -0,0 +1,8 @@ +if ENABLE_X11 +lib_LTLIBRARIES = libaggplatformX11.la + +libaggplatformX11_la_LDFLAGS = -version-info @AGG_LIB_VERSION@ -L@x_libraries@ +libaggplatformX11_la_SOURCES = agg_platform_support.cpp +libaggplatformX11_la_CXXFLAGS = -I$(top_srcdir)/include -I@x_includes@ +libaggplatformX11_la_LIBADD = -lX11 +endif diff --git a/jni/desmume/src/android/agg/src/platform/X11/agg_platform_support.cpp b/jni/desmume/src/android/agg/src/platform/X11/agg_platform_support.cpp new file mode 100755 index 0000000..986304d --- /dev/null +++ b/jni/desmume/src/android/agg/src/platform/X11/agg_platform_support.cpp @@ -0,0 +1,1303 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <ctype.h> +#include <time.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> +#include <X11/keysym.h> +#include "agg_basics.h" +#include "util/agg_color_conv_rgb8.h" +#include "platform/agg_platform_support.h" + + +namespace agg +{ + //------------------------------------------------------------------------ + class platform_specific + { + public: + platform_specific(pix_format_e format, bool flip_y); + ~platform_specific(); + + void caption(const char* capt); + void put_image(const rendering_buffer* src); + + pix_format_e m_format; + pix_format_e m_sys_format; + int m_byte_order; + bool m_flip_y; + unsigned m_bpp; + unsigned m_sys_bpp; + Display* m_display; + int m_screen; + int m_depth; + Visual* m_visual; + Window m_window; + GC m_gc; + XImage* m_ximg_window; + XSetWindowAttributes m_window_attributes; + Atom m_close_atom; + unsigned char* m_buf_window; + unsigned char* m_buf_img[platform_support::max_images]; + unsigned m_keymap[256]; + + bool m_update_flag; + bool m_resize_flag; + bool m_initialized; + //bool m_wait_mode; + clock_t m_sw_start; + }; + + + + //------------------------------------------------------------------------ + platform_specific::platform_specific(pix_format_e format, bool flip_y) : + m_format(format), + m_sys_format(pix_format_undefined), + m_byte_order(LSBFirst), + m_flip_y(flip_y), + m_bpp(0), + m_sys_bpp(0), + m_display(0), + m_screen(0), + m_depth(0), + m_visual(0), + m_window(0), + m_gc(0), + m_ximg_window(0), + m_close_atom(0), + + m_buf_window(0), + + m_update_flag(true), + m_resize_flag(true), + m_initialized(false) + //m_wait_mode(true) + { + memset(m_buf_img, 0, sizeof(m_buf_img)); + + unsigned i; + for(i = 0; i < 256; i++) + { + m_keymap[i] = i; + } + + m_keymap[XK_Pause&0xFF] = key_pause; + m_keymap[XK_Clear&0xFF] = key_clear; + + m_keymap[XK_KP_0&0xFF] = key_kp0; + m_keymap[XK_KP_1&0xFF] = key_kp1; + m_keymap[XK_KP_2&0xFF] = key_kp2; + m_keymap[XK_KP_3&0xFF] = key_kp3; + m_keymap[XK_KP_4&0xFF] = key_kp4; + m_keymap[XK_KP_5&0xFF] = key_kp5; + m_keymap[XK_KP_6&0xFF] = key_kp6; + m_keymap[XK_KP_7&0xFF] = key_kp7; + m_keymap[XK_KP_8&0xFF] = key_kp8; + m_keymap[XK_KP_9&0xFF] = key_kp9; + + m_keymap[XK_KP_Insert&0xFF] = key_kp0; + m_keymap[XK_KP_End&0xFF] = key_kp1; + m_keymap[XK_KP_Down&0xFF] = key_kp2; + m_keymap[XK_KP_Page_Down&0xFF] = key_kp3; + m_keymap[XK_KP_Left&0xFF] = key_kp4; + m_keymap[XK_KP_Begin&0xFF] = key_kp5; + m_keymap[XK_KP_Right&0xFF] = key_kp6; + m_keymap[XK_KP_Home&0xFF] = key_kp7; + m_keymap[XK_KP_Up&0xFF] = key_kp8; + m_keymap[XK_KP_Page_Up&0xFF] = key_kp9; + m_keymap[XK_KP_Delete&0xFF] = key_kp_period; + m_keymap[XK_KP_Decimal&0xFF] = key_kp_period; + m_keymap[XK_KP_Divide&0xFF] = key_kp_divide; + m_keymap[XK_KP_Multiply&0xFF] = key_kp_multiply; + m_keymap[XK_KP_Subtract&0xFF] = key_kp_minus; + m_keymap[XK_KP_Add&0xFF] = key_kp_plus; + m_keymap[XK_KP_Enter&0xFF] = key_kp_enter; + m_keymap[XK_KP_Equal&0xFF] = key_kp_equals; + + m_keymap[XK_Up&0xFF] = key_up; + m_keymap[XK_Down&0xFF] = key_down; + m_keymap[XK_Right&0xFF] = key_right; + m_keymap[XK_Left&0xFF] = key_left; + m_keymap[XK_Insert&0xFF] = key_insert; + m_keymap[XK_Home&0xFF] = key_delete; + m_keymap[XK_End&0xFF] = key_end; + m_keymap[XK_Page_Up&0xFF] = key_page_up; + m_keymap[XK_Page_Down&0xFF] = key_page_down; + + m_keymap[XK_F1&0xFF] = key_f1; + m_keymap[XK_F2&0xFF] = key_f2; + m_keymap[XK_F3&0xFF] = key_f3; + m_keymap[XK_F4&0xFF] = key_f4; + m_keymap[XK_F5&0xFF] = key_f5; + m_keymap[XK_F6&0xFF] = key_f6; + m_keymap[XK_F7&0xFF] = key_f7; + m_keymap[XK_F8&0xFF] = key_f8; + m_keymap[XK_F9&0xFF] = key_f9; + m_keymap[XK_F10&0xFF] = key_f10; + m_keymap[XK_F11&0xFF] = key_f11; + m_keymap[XK_F12&0xFF] = key_f12; + m_keymap[XK_F13&0xFF] = key_f13; + m_keymap[XK_F14&0xFF] = key_f14; + m_keymap[XK_F15&0xFF] = key_f15; + + m_keymap[XK_Num_Lock&0xFF] = key_numlock; + m_keymap[XK_Caps_Lock&0xFF] = key_capslock; + m_keymap[XK_Scroll_Lock&0xFF] = key_scrollock; + + switch(m_format) + { + default: break; + case pix_format_gray8: + m_bpp = 8; + break; + + case pix_format_rgb565: + case pix_format_rgb555: + m_bpp = 16; + break; + + case pix_format_rgb24: + case pix_format_bgr24: + m_bpp = 24; + break; + + case pix_format_bgra32: + case pix_format_abgr32: + case pix_format_argb32: + case pix_format_rgba32: + m_bpp = 32; + break; + } + m_sw_start = clock(); + } + + //------------------------------------------------------------------------ + platform_specific::~platform_specific() + { + } + + //------------------------------------------------------------------------ + void platform_specific::caption(const char* capt) + { + //XTextProperty tp; + //tp.value = (unsigned char *)capt; + //tp.encoding = XA_WM_NAME; + //tp.format = 8; + //tp.nitems = strlen(capt); + //XSetWMName(m_display, m_window, &tp); + //XStoreName(m_display, m_window, capt); + //XSetIconName(m_display, m_window, capt); + //XSetWMIconName(m_display, m_window, &tp); + // Fixed by Enno Fennema + XStoreName(m_display, m_window, capt); + XSetIconName(m_display, m_window, capt); + } + + + //------------------------------------------------------------------------ + void platform_specific::put_image(const rendering_buffer* src) + { + if(m_ximg_window == 0) return; + m_ximg_window->data = (char*)m_buf_window; + + if(m_format == m_sys_format) + { + XPutImage(m_display, + m_window, + m_gc, + m_ximg_window, + 0, 0, 0, 0, + src->width(), + src->height()); + } + else + { + int row_len = src->width() * m_sys_bpp / 8; + unsigned char* buf_tmp = + new unsigned char[row_len * src->height()]; + + rendering_buffer rbuf_tmp; + rbuf_tmp.attach(buf_tmp, + src->width(), + src->height(), + m_flip_y ? -row_len : row_len); + + switch(m_sys_format) + { + default: break; + case pix_format_rgb555: + switch(m_format) + { + default: break; + case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_rgb555()); break; + case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgb555()); break; + case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_rgb555()); break; + case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_rgb555()); break; + case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_rgb555()); break; + case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_rgb555()); break; + case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_rgb555()); break; + case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_rgb555()); break; + } + break; + + case pix_format_rgb565: + switch(m_format) + { + default: break; + case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_rgb565()); break; + case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgb565()); break; + case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_rgb565()); break; + case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_rgb565()); break; + case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_rgb565()); break; + case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_rgb565()); break; + case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_rgb565()); break; + case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_rgb565()); break; + } + break; + + case pix_format_rgba32: + switch(m_format) + { + default: break; + case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_rgba32()); break; + case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgba32()); break; + case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_rgba32()); break; + case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_rgba32()); break; + case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_rgba32()); break; + case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_rgba32()); break; + case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_rgba32()); break; + case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_rgba32()); break; + } + break; + + case pix_format_abgr32: + switch(m_format) + { + default: break; + case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_abgr32()); break; + case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_abgr32()); break; + case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_abgr32()); break; + case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_abgr32()); break; + case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_abgr32()); break; + case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_abgr32()); break; + case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_abgr32()); break; + case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_abgr32()); break; + } + break; + + case pix_format_argb32: + switch(m_format) + { + default: break; + case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_argb32()); break; + case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_argb32()); break; + case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_argb32()); break; + case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_argb32()); break; + case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_argb32()); break; + case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_argb32()); break; + case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_argb32()); break; + case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_argb32()); break; + } + break; + + case pix_format_bgra32: + switch(m_format) + { + default: break; + case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_bgra32()); break; + case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_bgra32()); break; + case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_bgra32()); break; + case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_bgra32()); break; + case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_bgra32()); break; + case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_bgra32()); break; + case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_bgra32()); break; + case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_bgra32()); break; + } + break; + } + + m_ximg_window->data = (char*)buf_tmp; + XPutImage(m_display, + m_window, + m_gc, + m_ximg_window, + 0, 0, 0, 0, + src->width(), + src->height()); + + delete [] buf_tmp; + } + } + + + //------------------------------------------------------------------------ + platform_support::platform_support(pix_format_e format, bool flip_y) : + m_specific(new platform_specific(format, flip_y)), + m_format(format), + m_bpp(m_specific->m_bpp), + m_window_flags(0), + m_wait_mode(true), + m_flip_y(flip_y), + m_initial_width(10), + m_initial_height(10) + { + strcpy(m_caption, "AGG Application"); + } + + //------------------------------------------------------------------------ + platform_support::~platform_support() + { + delete m_specific; + } + + + + //------------------------------------------------------------------------ + void platform_support::caption(const char* cap) + { + strcpy(m_caption, cap); + if(m_specific->m_initialized) + { + m_specific->caption(cap); + } + } + + + //------------------------------------------------------------------------ + enum xevent_mask_e + { + xevent_mask = + PointerMotionMask| + ButtonPressMask| + ButtonReleaseMask| + ExposureMask| + KeyPressMask| + StructureNotifyMask + }; + + + //------------------------------------------------------------------------ + bool platform_support::init(unsigned width, unsigned height, unsigned flags) + { + m_window_flags = flags; + + m_specific->m_display = XOpenDisplay(NULL); + if(m_specific->m_display == 0) + { + fprintf(stderr, "Unable to open DISPLAY!\n"); + return false; + } + + m_specific->m_screen = XDefaultScreen(m_specific->m_display); + m_specific->m_depth = XDefaultDepth(m_specific->m_display, + m_specific->m_screen); + m_specific->m_visual = XDefaultVisual(m_specific->m_display, + m_specific->m_screen); + unsigned long r_mask = m_specific->m_visual->red_mask; + unsigned long g_mask = m_specific->m_visual->green_mask; + unsigned long b_mask = m_specific->m_visual->blue_mask; + +//printf("depth=%d, red=%08x, green=%08x, blue=%08x\n", +// m_specific->m_depth, +// m_specific->m_visual->red_mask, +// m_specific->m_visual->green_mask, +// m_specific->m_visual->blue_mask); + + +// // NOT COMPLETED YET! +// // Try to find an appropriate Visual if the default doesn't fit. +// if(m_specific->m_depth < 15 || +// r_mask == 0 || g_mask == 0 || b_mask == 0) +// { +// +// // This is an attempt to find an appropriate Visual if +// // the default one doesn't match the minumum requirements +// static int depth[] = { 32, 24, 16, 15 }; +// int i; +// for(int i = 0; i < 4; i++) +// { +// XVisualInfo vi; +// if(XMatchVisualInfo(m_specific->m_display, +// m_specific->m_screen, +// depth[i], +// TrueColor, +// &vi)) +// { +// // printf("TrueColor depth=%d, red=%08x, green=%08x, blue=%08x, bits=%d\n", +// // vi.depth, +// // vi.visual->red_mask, +// // vi.visual->green_mask, +// // vi.visual->blue_mask, +// // vi.bits_per_rgb); +// m_specific->m_depth = vi.depth; +// m_specific->m_visual = vi.visual; +// r_mask = m_specific->m_visual->red_mask; +// g_mask = m_specific->m_visual->green_mask; +// b_mask = m_specific->m_visual->blue_mask; +// break; +// } +// if(XMatchVisualInfo(m_specific->m_display, +// m_specific->m_screen, +// depth[i], +// DirectColor, +// &vi)) +// { +// // printf("DirectColor depth=%d, red=%08x, green=%08x, blue=%08x, bits=%d\n", +// // vi.depth, +// // vi.visual->red_mask, +// // vi.visual->green_mask, +// // vi.visual->blue_mask, +// // vi.bits_per_rgb); +// m_specific->m_depth = vi.depth; +// m_specific->m_visual = vi.visual; +// r_mask = m_specific->m_visual->red_mask; +// g_mask = m_specific->m_visual->green_mask; +// b_mask = m_specific->m_visual->blue_mask; +// break; +// } +// } +// } + + if(m_specific->m_depth < 15 || + r_mask == 0 || g_mask == 0 || b_mask == 0) + { + fprintf(stderr, + "There's no Visual compatible with minimal AGG requirements:\n" + "At least 15-bit color depth and True- or DirectColor class.\n\n"); + XCloseDisplay(m_specific->m_display); + return false; + } + + int t = 1; + int hw_byte_order = LSBFirst; + if(*(char*)&t == 0) hw_byte_order = MSBFirst; + + // Perceive SYS-format by mask + switch(m_specific->m_depth) + { + case 15: + m_specific->m_sys_bpp = 16; + if(r_mask == 0x7C00 && g_mask == 0x3E0 && b_mask == 0x1F) + { + m_specific->m_sys_format = pix_format_rgb555; + m_specific->m_byte_order = hw_byte_order; + } + break; + + case 16: + m_specific->m_sys_bpp = 16; + if(r_mask == 0xF800 && g_mask == 0x7E0 && b_mask == 0x1F) + { + m_specific->m_sys_format = pix_format_rgb565; + m_specific->m_byte_order = hw_byte_order; + } + break; + + case 24: + case 32: + m_specific->m_sys_bpp = 32; + if(g_mask == 0xFF00) + { + if(r_mask == 0xFF && b_mask == 0xFF0000) + { + switch(m_specific->m_format) + { + case pix_format_rgba32: + m_specific->m_sys_format = pix_format_rgba32; + m_specific->m_byte_order = LSBFirst; + break; + + case pix_format_abgr32: + m_specific->m_sys_format = pix_format_abgr32; + m_specific->m_byte_order = MSBFirst; + break; + + default: + m_specific->m_byte_order = hw_byte_order; + m_specific->m_sys_format = + (hw_byte_order == LSBFirst) ? + pix_format_rgba32 : + pix_format_abgr32; + break; + } + } + + if(r_mask == 0xFF0000 && b_mask == 0xFF) + { + switch(m_specific->m_format) + { + case pix_format_argb32: + m_specific->m_sys_format = pix_format_argb32; + m_specific->m_byte_order = MSBFirst; + break; + + case pix_format_bgra32: + m_specific->m_sys_format = pix_format_bgra32; + m_specific->m_byte_order = LSBFirst; + break; + + default: + m_specific->m_byte_order = hw_byte_order; + m_specific->m_sys_format = + (hw_byte_order == MSBFirst) ? + pix_format_argb32 : + pix_format_bgra32; + break; + } + } + } + break; + } + + if(m_specific->m_sys_format == pix_format_undefined) + { + fprintf(stderr, + "RGB masks are not compatible with AGG pixel formats:\n" + "R=%08x, R=%08x, B=%08x\n", r_mask, g_mask, b_mask); + XCloseDisplay(m_specific->m_display); + return false; + } + + + + memset(&m_specific->m_window_attributes, + 0, + sizeof(m_specific->m_window_attributes)); + + m_specific->m_window_attributes.border_pixel = + XBlackPixel(m_specific->m_display, m_specific->m_screen); + + m_specific->m_window_attributes.background_pixel = + XWhitePixel(m_specific->m_display, m_specific->m_screen); + + m_specific->m_window_attributes.override_redirect = 0; + + unsigned long window_mask = CWBackPixel | CWBorderPixel; + + m_specific->m_window = + XCreateWindow(m_specific->m_display, + XDefaultRootWindow(m_specific->m_display), + 0, 0, + width, + height, + 0, + m_specific->m_depth, + InputOutput, + CopyFromParent, + window_mask, + &m_specific->m_window_attributes); + + + m_specific->m_gc = XCreateGC(m_specific->m_display, + m_specific->m_window, + 0, 0); + m_specific->m_buf_window = + new unsigned char[width * height * (m_bpp / 8)]; + + memset(m_specific->m_buf_window, 255, width * height * (m_bpp / 8)); + + m_rbuf_window.attach(m_specific->m_buf_window, + width, + height, + m_flip_y ? -width * (m_bpp / 8) : width * (m_bpp / 8)); + + m_specific->m_ximg_window = + XCreateImage(m_specific->m_display, + m_specific->m_visual, //CopyFromParent, + m_specific->m_depth, + ZPixmap, + 0, + (char*)m_specific->m_buf_window, + width, + height, + m_specific->m_sys_bpp, + width * (m_specific->m_sys_bpp / 8)); + m_specific->m_ximg_window->byte_order = m_specific->m_byte_order; + + m_specific->caption(m_caption); + m_initial_width = width; + m_initial_height = height; + + if(!m_specific->m_initialized) + { + on_init(); + m_specific->m_initialized = true; + } + + trans_affine_resizing(width, height); + on_resize(width, height); + m_specific->m_update_flag = true; + + XSizeHints *hints = XAllocSizeHints(); + if(hints) + { + if(flags & window_resize) + { + hints->min_width = 32; + hints->min_height = 32; + hints->max_width = 4096; + hints->max_height = 4096; + } + else + { + hints->min_width = width; + hints->min_height = height; + hints->max_width = width; + hints->max_height = height; + } + hints->flags = PMaxSize | PMinSize; + + XSetWMNormalHints(m_specific->m_display, + m_specific->m_window, + hints); + + XFree(hints); + } + + + XMapWindow(m_specific->m_display, + m_specific->m_window); + + XSelectInput(m_specific->m_display, + m_specific->m_window, + xevent_mask); + + + m_specific->m_close_atom = XInternAtom(m_specific->m_display, + "WM_DELETE_WINDOW", + false); + + XSetWMProtocols(m_specific->m_display, + m_specific->m_window, + &m_specific->m_close_atom, + 1); + + return true; + } + + + + //------------------------------------------------------------------------ + void platform_support::update_window() + { + m_specific->put_image(&m_rbuf_window); + + // When m_wait_mode is true we can discard all the events + // came while the image is being drawn. In this case + // the X server does not accumulate mouse motion events. + // When m_wait_mode is false, i.e. we have some idle drawing + // we cannot afford to miss any events + XSync(m_specific->m_display, m_wait_mode); + } + + + //------------------------------------------------------------------------ + int platform_support::run() + { + XFlush(m_specific->m_display); + + bool quit = false; + unsigned flags; + int cur_x; + int cur_y; + + while(!quit) + { + if(m_specific->m_update_flag) + { + on_draw(); + update_window(); + m_specific->m_update_flag = false; + } + + if(!m_wait_mode) + { + if(XPending(m_specific->m_display) == 0) + { + on_idle(); + continue; + } + } + + XEvent x_event; + XNextEvent(m_specific->m_display, &x_event); + + // In the Idle mode discard all intermediate MotionNotify events + if(!m_wait_mode && x_event.type == MotionNotify) + { + XEvent te = x_event; + for(;;) + { + if(XPending(m_specific->m_display) == 0) break; + XNextEvent(m_specific->m_display, &te); + if(te.type != MotionNotify) break; + } + x_event = te; + } + + switch(x_event.type) + { + case ConfigureNotify: + { + if(x_event.xconfigure.width != int(m_rbuf_window.width()) || + x_event.xconfigure.height != int(m_rbuf_window.height())) + { + int width = x_event.xconfigure.width; + int height = x_event.xconfigure.height; + + delete [] m_specific->m_buf_window; + m_specific->m_ximg_window->data = 0; + XDestroyImage(m_specific->m_ximg_window); + + m_specific->m_buf_window = + new unsigned char[width * height * (m_bpp / 8)]; + + m_rbuf_window.attach(m_specific->m_buf_window, + width, + height, + m_flip_y ? + -width * (m_bpp / 8) : + width * (m_bpp / 8)); + + m_specific->m_ximg_window = + XCreateImage(m_specific->m_display, + m_specific->m_visual, //CopyFromParent, + m_specific->m_depth, + ZPixmap, + 0, + (char*)m_specific->m_buf_window, + width, + height, + m_specific->m_sys_bpp, + width * (m_specific->m_sys_bpp / 8)); + m_specific->m_ximg_window->byte_order = m_specific->m_byte_order; + + trans_affine_resizing(width, height); + on_resize(width, height); + on_draw(); + update_window(); + } + } + break; + + case Expose: + m_specific->put_image(&m_rbuf_window); + XFlush(m_specific->m_display); + XSync(m_specific->m_display, false); + break; + + case KeyPress: + { + KeySym key = XLookupKeysym(&x_event.xkey, 0); + flags = 0; + if(x_event.xkey.state & Button1Mask) flags |= mouse_left; + if(x_event.xkey.state & Button3Mask) flags |= mouse_right; + if(x_event.xkey.state & ShiftMask) flags |= kbd_shift; + if(x_event.xkey.state & ControlMask) flags |= kbd_ctrl; + + bool left = false; + bool up = false; + bool right = false; + bool down = false; + + switch(m_specific->m_keymap[key & 0xFF]) + { + case key_left: + left = true; + break; + + case key_up: + up = true; + break; + + case key_right: + right = true; + break; + + case key_down: + down = true; + break; + + case key_f2: + copy_window_to_img(max_images - 1); + save_img(max_images - 1, "screenshot"); + break; + } + + if(m_ctrls.on_arrow_keys(left, right, down, up)) + { + on_ctrl_change(); + force_redraw(); + } + else + { + on_key(x_event.xkey.x, + m_flip_y ? + m_rbuf_window.height() - x_event.xkey.y : + x_event.xkey.y, + m_specific->m_keymap[key & 0xFF], + flags); + } + } + break; + + + case ButtonPress: + { + flags = 0; + if(x_event.xbutton.state & ShiftMask) flags |= kbd_shift; + if(x_event.xbutton.state & ControlMask) flags |= kbd_ctrl; + if(x_event.xbutton.button == Button1) flags |= mouse_left; + if(x_event.xbutton.button == Button3) flags |= mouse_right; + + cur_x = x_event.xbutton.x; + cur_y = m_flip_y ? m_rbuf_window.height() - x_event.xbutton.y : + x_event.xbutton.y; + + if(flags & mouse_left) + { + if(m_ctrls.on_mouse_button_down(cur_x, cur_y)) + { + m_ctrls.set_cur(cur_x, cur_y); + on_ctrl_change(); + force_redraw(); + } + else + { + if(m_ctrls.in_rect(cur_x, cur_y)) + { + if(m_ctrls.set_cur(cur_x, cur_y)) + { + on_ctrl_change(); + force_redraw(); + } + } + else + { + on_mouse_button_down(cur_x, cur_y, flags); + } + } + } + if(flags & mouse_right) + { + on_mouse_button_down(cur_x, cur_y, flags); + } + //m_specific->m_wait_mode = m_wait_mode; + //m_wait_mode = true; + } + break; + + + case MotionNotify: + { + flags = 0; + if(x_event.xmotion.state & Button1Mask) flags |= mouse_left; + if(x_event.xmotion.state & Button3Mask) flags |= mouse_right; + if(x_event.xmotion.state & ShiftMask) flags |= kbd_shift; + if(x_event.xmotion.state & ControlMask) flags |= kbd_ctrl; + + cur_x = x_event.xbutton.x; + cur_y = m_flip_y ? m_rbuf_window.height() - x_event.xbutton.y : + x_event.xbutton.y; + + if(m_ctrls.on_mouse_move(cur_x, cur_y, (flags & mouse_left) != 0)) + { + on_ctrl_change(); + force_redraw(); + } + else + { + if(!m_ctrls.in_rect(cur_x, cur_y)) + { + on_mouse_move(cur_x, cur_y, flags); + } + } + } + break; + + case ButtonRelease: + { + flags = 0; + if(x_event.xbutton.state & ShiftMask) flags |= kbd_shift; + if(x_event.xbutton.state & ControlMask) flags |= kbd_ctrl; + if(x_event.xbutton.button == Button1) flags |= mouse_left; + if(x_event.xbutton.button == Button3) flags |= mouse_right; + + cur_x = x_event.xbutton.x; + cur_y = m_flip_y ? m_rbuf_window.height() - x_event.xbutton.y : + x_event.xbutton.y; + + if(flags & mouse_left) + { + if(m_ctrls.on_mouse_button_up(cur_x, cur_y)) + { + on_ctrl_change(); + force_redraw(); + } + } + if(flags & (mouse_left | mouse_right)) + { + on_mouse_button_up(cur_x, cur_y, flags); + } + } + //m_wait_mode = m_specific->m_wait_mode; + break; + + case ClientMessage: + if((x_event.xclient.format == 32) && + (x_event.xclient.data.l[0] == int(m_specific->m_close_atom))) + { + quit = true; + } + break; + } + } + + + unsigned i = platform_support::max_images; + while(i--) + { + if(m_specific->m_buf_img[i]) + { + delete [] m_specific->m_buf_img[i]; + } + } + + delete [] m_specific->m_buf_window; + m_specific->m_ximg_window->data = 0; + XDestroyImage(m_specific->m_ximg_window); + XFreeGC(m_specific->m_display, m_specific->m_gc); + XDestroyWindow(m_specific->m_display, m_specific->m_window); + XCloseDisplay(m_specific->m_display); + + return 0; + } + + + + //------------------------------------------------------------------------ + const char* platform_support::img_ext() const { return ".ppm"; } + + //------------------------------------------------------------------------ + const char* platform_support::full_file_name(const char* file_name) + { + return file_name; + } + + //------------------------------------------------------------------------ + bool platform_support::load_img(unsigned idx, const char* file) + { + if(idx < max_images) + { + char buf[1024]; + strcpy(buf, file); + int len = strlen(buf); + if(len < 4 || strcasecmp(buf + len - 4, ".ppm") != 0) + { + strcat(buf, ".ppm"); + } + + FILE* fd = fopen(buf, "rb"); + if(fd == 0) return false; + + if((len = fread(buf, 1, 1022, fd)) == 0) + { + fclose(fd); + return false; + } + buf[len] = 0; + + if(buf[0] != 'P' && buf[1] != '6') + { + fclose(fd); + return false; + } + + char* ptr = buf + 2; + + while(*ptr && !isdigit(*ptr)) ptr++; + if(*ptr == 0) + { + fclose(fd); + return false; + } + + unsigned width = atoi(ptr); + if(width == 0 || width > 4096) + { + fclose(fd); + return false; + } + while(*ptr && isdigit(*ptr)) ptr++; + while(*ptr && !isdigit(*ptr)) ptr++; + if(*ptr == 0) + { + fclose(fd); + return false; + } + unsigned height = atoi(ptr); + if(height == 0 || height > 4096) + { + fclose(fd); + return false; + } + while(*ptr && isdigit(*ptr)) ptr++; + while(*ptr && !isdigit(*ptr)) ptr++; + if(atoi(ptr) != 255) + { + fclose(fd); + return false; + } + while(*ptr && isdigit(*ptr)) ptr++; + if(*ptr == 0) + { + fclose(fd); + return false; + } + ptr++; + fseek(fd, long(ptr - buf), SEEK_SET); + + create_img(idx, width, height); + bool ret = true; + + if(m_format == pix_format_rgb24) + { + fread(m_specific->m_buf_img[idx], 1, width * height * 3, fd); + } + else + { + unsigned char* buf_img = new unsigned char [width * height * 3]; + rendering_buffer rbuf_img; + rbuf_img.attach(buf_img, + width, + height, + m_flip_y ? + -width * 3 : + width * 3); + + fread(buf_img, 1, width * height * 3, fd); + + switch(m_format) + { + case pix_format_rgb555: + color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_rgb555()); + break; + + case pix_format_rgb565: + color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_rgb565()); + break; + + case pix_format_bgr24: + color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_bgr24()); + break; + + case pix_format_rgba32: + color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_rgba32()); + break; + + case pix_format_argb32: + color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_argb32()); + break; + + case pix_format_bgra32: + color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_bgra32()); + break; + + case pix_format_abgr32: + color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_abgr32()); + break; + + default: + ret = false; + } + delete [] buf_img; + } + + fclose(fd); + return ret; + } + return false; + } + + + + + //------------------------------------------------------------------------ + bool platform_support::save_img(unsigned idx, const char* file) + { + if(idx < max_images && rbuf_img(idx).buf()) + { + char buf[1024]; + strcpy(buf, file); + int len = strlen(buf); + if(len < 4 || strcasecmp(buf + len - 4, ".ppm") != 0) + { + strcat(buf, ".ppm"); + } + + FILE* fd = fopen(buf, "wb"); + if(fd == 0) return false; + + unsigned w = rbuf_img(idx).width(); + unsigned h = rbuf_img(idx).height(); + + fprintf(fd, "P6\n%d %d\n255\n", w, h); + + unsigned y; + unsigned char* tmp_buf = new unsigned char [w * 3]; + for(y = 0; y < rbuf_img(idx).height(); y++) + { + const unsigned char* src = rbuf_img(idx).row_ptr(m_flip_y ? h - 1 - y : y); + switch(m_format) + { + default: break; + case pix_format_rgb555: + color_conv_row(tmp_buf, src, w, color_conv_rgb555_to_rgb24()); + break; + + case pix_format_rgb565: + color_conv_row(tmp_buf, src, w, color_conv_rgb565_to_rgb24()); + break; + + case pix_format_bgr24: + color_conv_row(tmp_buf, src, w, color_conv_bgr24_to_rgb24()); + break; + + case pix_format_rgb24: + color_conv_row(tmp_buf, src, w, color_conv_rgb24_to_rgb24()); + break; + + case pix_format_rgba32: + color_conv_row(tmp_buf, src, w, color_conv_rgba32_to_rgb24()); + break; + + case pix_format_argb32: + color_conv_row(tmp_buf, src, w, color_conv_argb32_to_rgb24()); + break; + + case pix_format_bgra32: + color_conv_row(tmp_buf, src, w, color_conv_bgra32_to_rgb24()); + break; + + case pix_format_abgr32: + color_conv_row(tmp_buf, src, w, color_conv_abgr32_to_rgb24()); + break; + } + fwrite(tmp_buf, 1, w * 3, fd); + } + delete [] tmp_buf; + fclose(fd); + return true; + } + return false; + } + + + + //------------------------------------------------------------------------ + bool platform_support::create_img(unsigned idx, unsigned width, unsigned height) + { + if(idx < max_images) + { + if(width == 0) width = rbuf_window().width(); + if(height == 0) height = rbuf_window().height(); + delete [] m_specific->m_buf_img[idx]; + m_specific->m_buf_img[idx] = + new unsigned char[width * height * (m_bpp / 8)]; + + m_rbuf_img[idx].attach(m_specific->m_buf_img[idx], + width, + height, + m_flip_y ? + -width * (m_bpp / 8) : + width * (m_bpp / 8)); + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + void platform_support::force_redraw() + { + m_specific->m_update_flag = true; + } + + + //------------------------------------------------------------------------ + void platform_support::message(const char* msg) + { + fprintf(stderr, "%s\n", msg); + } + + //------------------------------------------------------------------------ + void platform_support::start_timer() + { + m_specific->m_sw_start = clock(); + } + + //------------------------------------------------------------------------ + double platform_support::elapsed_time() const + { + clock_t stop = clock(); + return double(stop - m_specific->m_sw_start) * 1000.0 / CLOCKS_PER_SEC; + } + + + //------------------------------------------------------------------------ + void platform_support::on_init() {} + void platform_support::on_resize(int sx, int sy) {} + void platform_support::on_idle() {} + void platform_support::on_mouse_move(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {} + void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {} + void platform_support::on_ctrl_change() {} + void platform_support::on_draw() {} + void platform_support::on_post_draw(void* raw_handler) {} + + + +} + + +int agg_main(int argc, char* argv[]); + + +int main(int argc, char* argv[]) +{ + return agg_main(argc, argv); +} + + + + + + diff --git a/jni/desmume/src/android/agg/src/platform/mac/Makefile.am b/jni/desmume/src/android/agg/src/platform/mac/Makefile.am new file mode 100755 index 0000000..6f1b860 --- /dev/null +++ b/jni/desmume/src/android/agg/src/platform/mac/Makefile.am @@ -0,0 +1,11 @@ +if ENABLE_OSX +lib_LTLIBRARIES = libaggplatformmac.la +libaggplatformmac_la_LDFLAGS=-version-info @AGG_LIB_VERSION@ +libaggplatformmac_la_SOURCES=agg_mac_pmap.cpp \ + agg_platform_support.cpp + +libaggplatformmac_la_CXXFLAGS = -I$(top_srcdir)/include @OSX_CFLAGS@ +libaggplatformmac_la_LIBADD = @OSX_LIBS@ $(top_builddir)/src/libagg.la + + +endif diff --git a/jni/desmume/src/android/agg/src/platform/mac/agg_mac_pmap.cpp b/jni/desmume/src/android/agg/src/platform/mac/agg_mac_pmap.cpp new file mode 100755 index 0000000..dc85fd6 --- /dev/null +++ b/jni/desmume/src/android/agg/src/platform/mac/agg_mac_pmap.cpp @@ -0,0 +1,298 @@ +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// Contact: mcseemagg@yahoo.com +// baer@karto.baug.ethz.ch +//---------------------------------------------------------------------------- +// +// class pixel_map +// +//---------------------------------------------------------------------------- + +#include <string.h> +#include <Carbon.h> +#include <QuickTimeComponents.h> +#include <ImageCompression.h> +#include "platform/mac/agg_mac_pmap.h" +#include "agg_basics.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + pixel_map::~pixel_map() + { + destroy(); + } + + + //------------------------------------------------------------------------ + pixel_map::pixel_map() : + m_pmap(0), + m_buf(0), + m_bpp(0), + m_img_size(0) + + { + } + + + //------------------------------------------------------------------------ + void pixel_map::destroy() + { + delete[] m_buf; + m_buf = NULL; + if (m_pmap != nil) + { + DisposeGWorld(m_pmap); + m_pmap = nil; + } + } + + + //------------------------------------------------------------------------ + void pixel_map::create(unsigned width, + unsigned height, + org_e org, + unsigned clear_val) + { + destroy(); + if(width == 0) width = 1; + if(height == 0) height = 1; + m_bpp = org; + + Rect r; + int row_bytes = calc_row_len (width, m_bpp); + MacSetRect(&r, 0, 0, width, height); + m_buf = new unsigned char[m_img_size = row_bytes * height]; + // The Quicktime version for creating GWorlds is more flexible than the classical function. + QTNewGWorldFromPtr (&m_pmap, m_bpp, &r, nil, nil, 0, m_buf, row_bytes); + + // create_gray_scale_palette(m_pmap); I didn't care about gray scale palettes so far. + if(clear_val <= 255) + { + memset(m_buf, clear_val, m_img_size); + } + } + + + + //------------------------------------------------------------------------ + void pixel_map::clear(unsigned clear_val) + { + if(m_buf) memset(m_buf, clear_val, m_img_size); + } + + + //static + //This function is just copied from the Win32 plattform support. + //Is also seems to be appropriate for MacOS as well, but it is not + //thouroughly tested so far. + //------------------------------------------------------------------------ + + unsigned pixel_map::calc_row_len(unsigned width, unsigned bits_per_pixel) + { + unsigned n = width; + unsigned k; + + switch(bits_per_pixel) + { + case 1: k = n; + n = n >> 3; + if(k & 7) n++; + break; + + case 4: k = n; + n = n >> 1; + if(k & 3) n++; + break; + + case 8: + break; + + case 16: n = n << 1; + break; + + case 24: n = (n << 1) + n; + break; + + case 32: n = n << 2; + break; + + default: n = 0; + break; + } + return ((n + 3) >> 2) << 2; + } + + + + + //------------------------------------------------------------------------ + void pixel_map::draw(WindowRef window, const Rect *device_rect, const Rect *pmap_rect) const + { + if(m_pmap == nil || m_buf == NULL) return; + + PixMapHandle pm = GetGWorldPixMap (m_pmap); + CGrafPtr port = GetWindowPort (window); + Rect dest_rect; + + // Again, I used the Quicktime version. + // Good old 'CopyBits' does better interpolation when scaling + // but does not support all pixel depths. + MacSetRect (&dest_rect, 0, 0, this->width(), this->height()); + ImageDescriptionHandle image_description; + MakeImageDescriptionForPixMap (pm, &image_description); + if (image_description != nil) + { + DecompressImage (GetPixBaseAddr (pm), image_description, GetPortPixMap (port), nil, &dest_rect, ditherCopy, nil); + DisposeHandle ((Handle) image_description); + } + } + + + //------------------------------------------------------------------------ + void pixel_map::draw(WindowRef window, int x, int y, double scale) const + { + if(m_pmap == nil || m_buf == NULL) return; + unsigned width = (unsigned)(this->width() * scale); + unsigned height = (unsigned)(this->height() * scale); + Rect rect; + SetRect (&rect, x, y, x + width, y + height); + draw(window, &rect); + } + + + + //------------------------------------------------------------------------ + void pixel_map::blend(WindowRef window, const Rect *device_rect, const Rect *bmp_rect) const + { + draw (window, device_rect, bmp_rect); // currently just mapped to drawing method + } + + + //------------------------------------------------------------------------ + void pixel_map::blend(WindowRef window, int x, int y, double scale) const + { + draw(window, x, y, scale); // currently just mapped to drawing method + } + + + // I let Quicktime handle image import since it supports most popular + // image formats such as: + // *.psd, *.bmp, *.tif, *.png, *.jpg, *.gif, *.pct, *.pcx + //------------------------------------------------------------------------ + bool pixel_map::load_from_qt(const char *filename) + { + FSSpec fss; + OSErr err; + + // get file specification to application directory + err = HGetVol(nil, &fss.vRefNum, &fss.parID); + if (err == noErr) + { + CopyCStringToPascal(filename, fss.name); + GraphicsImportComponent gi; + err = GetGraphicsImporterForFile (&fss, &gi); + if (err == noErr) + { + ImageDescriptionHandle desc; + GraphicsImportGetImageDescription(gi, &desc); +// For simplicity, all images are currently converted to 32 bit. + // create an empty pixelmap + short depth = 32; + create ((**desc).width, (**desc).height, (org_e)depth, 0xff); + DisposeHandle ((Handle)desc); + // let Quicktime draw to pixelmap + GraphicsImportSetGWorld(gi, m_pmap, nil); + GraphicsImportDraw(gi); +// Well, this is a hack. The graphics importer sets the alpha channel of the pixelmap to 0x00 +// for imported images without alpha channel but this would cause agg to draw an invisible image. + // set alpha channel to 0xff + unsigned char * buf = m_buf; + for (unsigned int size = 0; size < m_img_size; size += 4) + { + *buf = 0xff; + buf += 4; + } + } + } + return err == noErr; + } + + + + //------------------------------------------------------------------------ + bool pixel_map::save_as_qt(const char *filename) const + { + FSSpec fss; + OSErr err; + + // get file specification to application directory + err = HGetVol(nil, &fss.vRefNum, &fss.parID); + if (err == noErr) + { + GraphicsExportComponent ge; + CopyCStringToPascal(filename, fss.name); + // I decided to use PNG as output image file type. + // There are a number of other available formats. + // Should I check the file suffix to choose the image file format? + err = OpenADefaultComponent(GraphicsExporterComponentType, kQTFileTypePNG, &ge); + if (err == noErr) + { + err = GraphicsExportSetInputGWorld(ge, m_pmap); + if (err == noErr) + { + err = GraphicsExportSetOutputFile (ge, &fss); + if (err == noErr) + { + GraphicsExportDoExport(ge, nil); + } + } + CloseComponent(ge); + } + } + + return err == noErr; + } + + //------------------------------------------------------------------------ + unsigned char* pixel_map::buf() + { + return m_buf; + } + + //------------------------------------------------------------------------ + unsigned pixel_map::width() const + { + if(m_pmap == nil) return 0; + PixMapHandle pm = GetGWorldPixMap (m_pmap); + Rect bounds; + GetPixBounds (pm, &bounds); + return bounds.right - bounds.left; + } + + //------------------------------------------------------------------------ + unsigned pixel_map::height() const + { + if(m_pmap == nil) return 0; + PixMapHandle pm = GetGWorldPixMap (m_pmap); + Rect bounds; + GetPixBounds (pm, &bounds); + return bounds.bottom - bounds.top; + } + + //------------------------------------------------------------------------ + int pixel_map::row_bytes() const + { + if(m_pmap == nil) return 0; + PixMapHandle pm = GetGWorldPixMap (m_pmap); + return calc_row_len(width(), GetPixDepth(pm)); + } + + + +} + + + diff --git a/jni/desmume/src/android/agg/src/platform/mac/agg_platform_support.cpp b/jni/desmume/src/android/agg/src/platform/mac/agg_platform_support.cpp new file mode 100755 index 0000000..36a9929 --- /dev/null +++ b/jni/desmume/src/android/agg/src/platform/mac/agg_platform_support.cpp @@ -0,0 +1,1057 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Copyright (C) 2003 Hansruedi Baer (MacOS support, baer@karto.baug.eth.ch) +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- +// +// Note from Hansruedi Baer: +// I tried to retain the original structure for the Win32 platform as far +// as possible. Currently, not all features are implemented but the examples +// should work properly. +// HB +//---------------------------------------------------------------------------- + +#include <Carbon.h> +#if defined(__MWERKS__) +#include "console.h" +#endif +#include <string.h> +#include <unistd.h> +#include "platform/agg_platform_support.h" +#include "platform/mac/agg_mac_pmap.h" +#include "util/agg_color_conv_rgb8.h" + + +namespace agg +{ + +pascal OSStatus DoWindowClose (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData); +pascal OSStatus DoWindowDrawContent (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData); +pascal OSStatus DoAppQuit (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData); +pascal OSStatus DoMouseDown (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData); +pascal OSStatus DoMouseUp (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData); +pascal OSStatus DoMouseDragged (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData); +pascal OSStatus DoKeyDown (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData); +pascal OSStatus DoKeyUp (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData); +pascal void DoPeriodicTask (EventLoopTimerRef theTimer, void* userData); + + + //------------------------------------------------------------------------ + class platform_specific + { + public: + platform_specific(pix_format_e format, bool flip_y); + + void create_pmap(unsigned width, unsigned height, + rendering_buffer* wnd); + + void display_pmap(WindowRef window, const rendering_buffer* src); + bool load_pmap(const char* fn, unsigned idx, + rendering_buffer* dst); + + bool save_pmap(const char* fn, unsigned idx, + const rendering_buffer* src); + + unsigned translate(unsigned keycode); + + pix_format_e m_format; + pix_format_e m_sys_format; + bool m_flip_y; + unsigned m_bpp; + unsigned m_sys_bpp; + WindowRef m_window; + pixel_map m_pmap_window; + pixel_map m_pmap_img[platform_support::max_images]; + unsigned m_keymap[256]; + unsigned m_last_translated_key; + int m_cur_x; + int m_cur_y; + unsigned m_input_flags; + bool m_redraw_flag; + UnsignedWide m_sw_freq; + UnsignedWide m_sw_start; + }; + + + //------------------------------------------------------------------------ + platform_specific::platform_specific(pix_format_e format, bool flip_y) : + m_format(format), + m_sys_format(pix_format_undefined), + m_flip_y(flip_y), + m_bpp(0), + m_sys_bpp(0), + m_window(nil), + m_last_translated_key(0), + m_cur_x(0), + m_cur_y(0), + m_input_flags(0), + m_redraw_flag(true) + { + memset(m_keymap, 0, sizeof(m_keymap)); + + //Keyboard input is not yet fully supported nor tested + //m_keymap[VK_PAUSE] = key_pause; + m_keymap[kClearCharCode] = key_clear; + + //m_keymap[VK_NUMPAD0] = key_kp0; + //m_keymap[VK_NUMPAD1] = key_kp1; + //m_keymap[VK_NUMPAD2] = key_kp2; + //m_keymap[VK_NUMPAD3] = key_kp3; + //m_keymap[VK_NUMPAD4] = key_kp4; + //m_keymap[VK_NUMPAD5] = key_kp5; + //m_keymap[VK_NUMPAD6] = key_kp6; + //m_keymap[VK_NUMPAD7] = key_kp7; + //m_keymap[VK_NUMPAD8] = key_kp8; + //m_keymap[VK_NUMPAD9] = key_kp9; + //m_keymap[VK_DECIMAL] = key_kp_period; + //m_keymap[VK_DIVIDE] = key_kp_divide; + //m_keymap[VK_MULTIPLY] = key_kp_multiply; + //m_keymap[VK_SUBTRACT] = key_kp_minus; + //m_keymap[VK_ADD] = key_kp_plus; + + m_keymap[kUpArrowCharCode] = key_up; + m_keymap[kDownArrowCharCode] = key_down; + m_keymap[kRightArrowCharCode] = key_right; + m_keymap[kLeftArrowCharCode] = key_left; + //m_keymap[VK_INSERT] = key_insert; + m_keymap[kDeleteCharCode] = key_delete; + m_keymap[kHomeCharCode] = key_home; + m_keymap[kEndCharCode] = key_end; + m_keymap[kPageUpCharCode] = key_page_up; + m_keymap[kPageDownCharCode] = key_page_down; + + //m_keymap[VK_F1] = key_f1; + //m_keymap[VK_F2] = key_f2; + //m_keymap[VK_F3] = key_f3; + //m_keymap[VK_F4] = key_f4; + //m_keymap[VK_F5] = key_f5; + //m_keymap[VK_F6] = key_f6; + //m_keymap[VK_F7] = key_f7; + //m_keymap[VK_F8] = key_f8; + //m_keymap[VK_F9] = key_f9; + //m_keymap[VK_F10] = key_f10; + //m_keymap[VK_F11] = key_f11; + //m_keymap[VK_F12] = key_f12; + //m_keymap[VK_F13] = key_f13; + //m_keymap[VK_F14] = key_f14; + //m_keymap[VK_F15] = key_f15; + + //m_keymap[VK_NUMLOCK] = key_numlock; + //m_keymap[VK_CAPITAL] = key_capslock; + //m_keymap[VK_SCROLL] = key_scrollock; + + switch(m_format) + { + case pix_format_gray8: + m_sys_format = pix_format_gray8; + m_bpp = 8; + m_sys_bpp = 8; + break; + + case pix_format_rgb565: + case pix_format_rgb555: + m_sys_format = pix_format_rgb555; + m_bpp = 16; + m_sys_bpp = 16; + break; + + case pix_format_rgb24: + case pix_format_bgr24: + m_sys_format = pix_format_rgb24; + m_bpp = 24; + m_sys_bpp = 24; + break; + + case pix_format_bgra32: + case pix_format_abgr32: + case pix_format_argb32: + case pix_format_rgba32: + m_sys_format = pix_format_argb32; + m_bpp = 32; + m_sys_bpp = 32; + break; + } + ::Microseconds(&m_sw_freq); + ::Microseconds(&m_sw_start); + } + + + //------------------------------------------------------------------------ + void platform_specific::create_pmap(unsigned width, + unsigned height, + rendering_buffer* wnd) + { + m_pmap_window.create(width, height, org_e(m_bpp)); + wnd->attach(m_pmap_window.buf(), + m_pmap_window.width(), + m_pmap_window.height(), + m_flip_y ? + -m_pmap_window.row_bytes() : + m_pmap_window.row_bytes()); + } + + + //------------------------------------------------------------------------ + void platform_specific::display_pmap(WindowRef window, const rendering_buffer* src) + { + if(m_sys_format == m_format) + { + m_pmap_window.draw(window); + } + else + { + pixel_map pmap_tmp; + pmap_tmp.create(m_pmap_window.width(), + m_pmap_window.height(), + org_e(m_sys_bpp)); + + rendering_buffer rbuf_tmp; + rbuf_tmp.attach(pmap_tmp.buf(), + pmap_tmp.width(), + pmap_tmp.height(), + m_flip_y ? + -pmap_tmp.row_bytes() : + pmap_tmp.row_bytes()); + + switch(m_format) + { + case pix_format_gray8: + return; + + case pix_format_rgb565: + color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgb555()); + break; + + case pix_format_bgr24: + color_conv(&rbuf_tmp, src, color_conv_bgr24_to_rgb24()); + break; + + case pix_format_abgr32: + color_conv(&rbuf_tmp, src, color_conv_abgr32_to_argb32()); + break; + + case pix_format_bgra32: + color_conv(&rbuf_tmp, src, color_conv_bgra32_to_argb32()); + break; + + case pix_format_rgba32: + color_conv(&rbuf_tmp, src, color_conv_rgba32_to_argb32()); + break; + } + pmap_tmp.draw(window); + } + } + + + //------------------------------------------------------------------------ + bool platform_specific::save_pmap(const char* fn, unsigned idx, + const rendering_buffer* src) + { + if(m_sys_format == m_format) + { + return m_pmap_img[idx].save_as_qt(fn); + } + else + { + pixel_map pmap_tmp; + pmap_tmp.create(m_pmap_img[idx].width(), + m_pmap_img[idx].height(), + org_e(m_sys_bpp)); + + rendering_buffer rbuf_tmp; + rbuf_tmp.attach(pmap_tmp.buf(), + pmap_tmp.width(), + pmap_tmp.height(), + m_flip_y ? + -pmap_tmp.row_bytes() : + pmap_tmp.row_bytes()); + switch(m_format) + { + case pix_format_gray8: + return false; + + case pix_format_rgb565: + color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgb555()); + break; + + case pix_format_rgb24: + color_conv(&rbuf_tmp, src, color_conv_rgb24_to_bgr24()); + break; + + case pix_format_abgr32: + color_conv(&rbuf_tmp, src, color_conv_abgr32_to_bgra32()); + break; + + case pix_format_argb32: + color_conv(&rbuf_tmp, src, color_conv_argb32_to_bgra32()); + break; + + case pix_format_rgba32: + color_conv(&rbuf_tmp, src, color_conv_rgba32_to_bgra32()); + break; + } + return pmap_tmp.save_as_qt(fn); + } + return true; + } + + + + //------------------------------------------------------------------------ + bool platform_specific::load_pmap(const char* fn, unsigned idx, + rendering_buffer* dst) + { + pixel_map pmap_tmp; + if(!pmap_tmp.load_from_qt(fn)) return false; + + rendering_buffer rbuf_tmp; + rbuf_tmp.attach(pmap_tmp.buf(), + pmap_tmp.width(), + pmap_tmp.height(), + m_flip_y ? + -pmap_tmp.row_bytes() : + pmap_tmp.row_bytes()); + + m_pmap_img[idx].create(pmap_tmp.width(), + pmap_tmp.height(), + org_e(m_bpp), + 0); + + dst->attach(m_pmap_img[idx].buf(), + m_pmap_img[idx].width(), + m_pmap_img[idx].height(), + m_flip_y ? + -m_pmap_img[idx].row_bytes() : + m_pmap_img[idx].row_bytes()); + + switch(m_format) + { + case pix_format_gray8: + return false; + break; + + case pix_format_rgb555: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb555()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_rgb555()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_rgb555()); break; + } + break; + + case pix_format_rgb565: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb565()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_rgb565()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_rgb565()); break; + } + break; + + case pix_format_rgb24: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb24()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_rgb24()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_rgb24()); break; + } + break; + + case pix_format_bgr24: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_bgr24()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_bgr24()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_bgr24()); break; + } + break; + + case pix_format_abgr32: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_abgr32()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_abgr32()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_abgr32()); break; + } + break; + + case pix_format_argb32: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_argb32()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_argb32()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_argb32()); break; + } + break; + + case pix_format_bgra32: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_bgra32()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_bgra32()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_bgra32()); break; + } + break; + + case pix_format_rgba32: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgba32()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_rgba32()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_rgba32()); break; + } + break; + } + + return true; + } + + + + + + + + + //------------------------------------------------------------------------ + unsigned platform_specific::translate(unsigned keycode) + { + return m_last_translated_key = (keycode > 255) ? 0 : m_keymap[keycode]; + } + + + + //------------------------------------------------------------------------ + platform_support::platform_support(pix_format_e format, bool flip_y) : + m_specific(new platform_specific(format, flip_y)), + m_format(format), + m_bpp(m_specific->m_bpp), + m_window_flags(0), + m_wait_mode(true), + m_flip_y(flip_y), + m_initial_width(10), + m_initial_height(10) + { + strcpy(m_caption, "Anti-Grain Geometry Application"); + } + + + //------------------------------------------------------------------------ + platform_support::~platform_support() + { + delete m_specific; + } + + + + //------------------------------------------------------------------------ + void platform_support::caption(const char* cap) + { + strcpy(m_caption, cap); + if(m_specific->m_window) + { + SetWindowTitleWithCFString (m_specific->m_window, CFStringCreateWithCStringNoCopy (nil, cap, kCFStringEncodingASCII, nil)); + } + } + + + + //------------------------------------------------------------------------ + static unsigned get_key_flags(UInt32 wflags) + { + unsigned flags = 0; + + if(wflags & shiftKey) flags |= kbd_shift; + if(wflags & controlKey) flags |= kbd_ctrl; + + return flags; + } + + + //------------------------------------------------------------------------ + void platform_support::message(const char* msg) + { + SInt16 item; + Str255 p_msg; + + ::CopyCStringToPascal (msg, p_msg); + ::StandardAlert (kAlertPlainAlert, (const unsigned char*) "\013AGG Message", p_msg, NULL, &item); + //::StandardAlert (kAlertPlainAlert, (const unsigned char*) "\pAGG Message", p_msg, NULL, &item); + } + + + //------------------------------------------------------------------------ + void platform_support::start_timer() + { + ::Microseconds (&(m_specific->m_sw_start)); + } + + + //------------------------------------------------------------------------ + double platform_support::elapsed_time() const + { + UnsignedWide stop; + ::Microseconds(&stop); + return double(stop.lo - + m_specific->m_sw_start.lo) * 1e6 / + double(m_specific->m_sw_freq.lo); + } + + + //------------------------------------------------------------------------ + bool platform_support::init(unsigned width, unsigned height, unsigned flags) + { + if(m_specific->m_sys_format == pix_format_undefined) + { + return false; + } + + m_window_flags = flags; + + // application + EventTypeSpec eventType; + EventHandlerUPP handlerUPP; + + eventType.eventClass = kEventClassApplication; + eventType.eventKind = kEventAppQuit; + + handlerUPP = NewEventHandlerUPP(DoAppQuit); + + InstallApplicationEventHandler (handlerUPP, 1, &eventType, nil, nil); + + eventType.eventClass = kEventClassMouse; + eventType.eventKind = kEventMouseDown; + handlerUPP = NewEventHandlerUPP(DoMouseDown); + InstallApplicationEventHandler (handlerUPP, 1, &eventType, this, nil); + + eventType.eventKind = kEventMouseUp; + handlerUPP = NewEventHandlerUPP(DoMouseUp); + InstallApplicationEventHandler (handlerUPP, 1, &eventType, this, nil); + + eventType.eventKind = kEventMouseDragged; + handlerUPP = NewEventHandlerUPP(DoMouseDragged); + InstallApplicationEventHandler (handlerUPP, 1, &eventType, this, nil); + + eventType.eventClass = kEventClassKeyboard; + eventType.eventKind = kEventRawKeyDown; + handlerUPP = NewEventHandlerUPP(DoKeyDown); + InstallApplicationEventHandler (handlerUPP, 1, &eventType, this, nil); + + eventType.eventKind = kEventRawKeyUp; + handlerUPP = NewEventHandlerUPP(DoKeyUp); + InstallApplicationEventHandler (handlerUPP, 1, &eventType, this, nil); + + eventType.eventKind = kEventRawKeyRepeat; + handlerUPP = NewEventHandlerUPP(DoKeyDown); // 'key repeat' is translated to 'key down' + InstallApplicationEventHandler (handlerUPP, 1, &eventType, this, nil); + + WindowAttributes windowAttrs; + Rect bounds; + + // window + windowAttrs = kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute | kWindowStandardHandlerAttribute; + SetRect (&bounds, 0, 0, width, height); + OffsetRect (&bounds, 100, 100); + CreateNewWindow (kDocumentWindowClass, windowAttrs, &bounds, &m_specific->m_window); + + if(m_specific->m_window == nil) + { + return false; + } + + // I assume the text is ASCII. + // Change to kCFStringEncodingMacRoman, kCFStringEncodingISOLatin1, kCFStringEncodingUTF8 or what else you need. + SetWindowTitleWithCFString (m_specific->m_window, CFStringCreateWithCStringNoCopy (nil, m_caption, kCFStringEncodingASCII, nil)); + + eventType.eventClass = kEventClassWindow; + eventType.eventKind = kEventWindowClose; + + handlerUPP = NewEventHandlerUPP(DoWindowClose); + InstallWindowEventHandler (m_specific->m_window, handlerUPP, 1, &eventType, this, NULL); + + eventType.eventKind = kEventWindowDrawContent; + handlerUPP = NewEventHandlerUPP(DoWindowDrawContent); + InstallWindowEventHandler (m_specific->m_window, handlerUPP, 1, &eventType, this, NULL); + + // Periodic task + // Instead of an idle function I use the Carbon event timer. + // You may decide to change the wait value which is currently 50 milliseconds. + EventLoopRef mainLoop; + EventLoopTimerUPP timerUPP; + EventLoopTimerRef theTimer; + + mainLoop = GetMainEventLoop(); + timerUPP = NewEventLoopTimerUPP (DoPeriodicTask); + InstallEventLoopTimer (mainLoop, 0, 50 * kEventDurationMillisecond, timerUPP, this, &theTimer); + + m_specific->create_pmap(width, height, &m_rbuf_window); + m_initial_width = width; + m_initial_height = height; + on_init(); + on_resize(width, height); + m_specific->m_redraw_flag = true; + + ShowWindow (m_specific->m_window); + SetPortWindowPort (m_specific->m_window); + + return true; + } + + + //------------------------------------------------------------------------ + int platform_support::run() + { + + RunApplicationEventLoop (); + return true; + } + + + //------------------------------------------------------------------------ + const char* platform_support::img_ext() const { return ".bmp"; } + + //------------------------------------------------------------------------ + const char* platform_support::full_file_name(const char* file_name) + { + return file_name; + } + + //------------------------------------------------------------------------ + bool platform_support::load_img(unsigned idx, const char* file) + { + if(idx < max_images) + { + char fn[1024]; + strcpy(fn, file); + int len = strlen(fn); +#if defined(__MWERKS__) + if(len < 4 || stricmp(fn + len - 4, ".BMP") != 0) +#else + if(len < 4 || strncasecmp(fn + len - 4, ".BMP", 4) != 0) +#endif + { + strcat(fn, ".bmp"); + } + return m_specific->load_pmap(fn, idx, &m_rbuf_img[idx]); + } + return true; + } + + + + //------------------------------------------------------------------------ + bool platform_support::save_img(unsigned idx, const char* file) + { + if(idx < max_images) + { + char fn[1024]; + strcpy(fn, file); + int len = strlen(fn); +#if defined(__MWERKS__) + if(len < 4 || stricmp(fn + len - 4, ".BMP") != 0) +#else + if(len < 4 || strncasecmp(fn + len - 4, ".BMP", 4) != 0) +#endif + { + strcat(fn, ".bmp"); + } + return m_specific->save_pmap(fn, idx, &m_rbuf_img[idx]); + } + return true; + } + + + + //------------------------------------------------------------------------ + bool platform_support::create_img(unsigned idx, unsigned width, unsigned height) + { + if(idx < max_images) + { + if(width == 0) width = m_specific->m_pmap_window.width(); + if(height == 0) height = m_specific->m_pmap_window.height(); + m_specific->m_pmap_img[idx].create(width, height, org_e(m_specific->m_bpp)); + m_rbuf_img[idx].attach(m_specific->m_pmap_img[idx].buf(), + m_specific->m_pmap_img[idx].width(), + m_specific->m_pmap_img[idx].height(), + m_flip_y ? + -m_specific->m_pmap_img[idx].row_bytes() : + m_specific->m_pmap_img[idx].row_bytes()); + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + void platform_support::force_redraw() + { + Rect bounds; + + m_specific->m_redraw_flag = true; + // on_ctrl_change (); + on_draw(); + + SetRect(&bounds, 0, 0, m_rbuf_window.width(), m_rbuf_window.height()); + InvalWindowRect(m_specific->m_window, &bounds); + } + + + + //------------------------------------------------------------------------ + void platform_support::update_window() + { + m_specific->display_pmap(m_specific->m_window, &m_rbuf_window); + } + + + //------------------------------------------------------------------------ + void platform_support::on_init() {} + void platform_support::on_resize(int sx, int sy) {} + void platform_support::on_idle() {} + void platform_support::on_mouse_move(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {} + void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {} + void platform_support::on_ctrl_change() {} + void platform_support::on_draw() {} + void platform_support::on_post_draw(void* raw_handler) {} + + +//------------------------------------------------------------------------ +pascal OSStatus DoWindowClose (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) +{ + userData; + + QuitApplicationEventLoop (); + + return CallNextEventHandler (nextHandler, theEvent); +} + + +//------------------------------------------------------------------------ +pascal OSStatus DoAppQuit (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) +{ + userData; + + return CallNextEventHandler (nextHandler, theEvent); +} + + +//------------------------------------------------------------------------ +pascal OSStatus DoMouseDown (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) +{ + Point wheresMyMouse; + UInt32 modifier; + + GetEventParameter (theEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &wheresMyMouse); + GlobalToLocal (&wheresMyMouse); + GetEventParameter (theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifier); + + platform_support * app = reinterpret_cast<platform_support*>(userData); + + app->m_specific->m_cur_x = wheresMyMouse.h; + if(app->flip_y()) + { + app->m_specific->m_cur_y = app->rbuf_window().height() - wheresMyMouse.v; + } + else + { + app->m_specific->m_cur_y = wheresMyMouse.v; + } + app->m_specific->m_input_flags = mouse_left | get_key_flags(modifier); + + app->m_ctrls.set_cur(app->m_specific->m_cur_x, + app->m_specific->m_cur_y); + if(app->m_ctrls.on_mouse_button_down(app->m_specific->m_cur_x, + app->m_specific->m_cur_y)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + if(app->m_ctrls.in_rect(app->m_specific->m_cur_x, + app->m_specific->m_cur_y)) + { + if(app->m_ctrls.set_cur(app->m_specific->m_cur_x, + app->m_specific->m_cur_y)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + } + else + { + app->on_mouse_button_down(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_input_flags); + } + } + + return CallNextEventHandler (nextHandler, theEvent); +} + + +//------------------------------------------------------------------------ +pascal OSStatus DoMouseUp (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) +{ + Point wheresMyMouse; + UInt32 modifier; + + GetEventParameter (theEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &wheresMyMouse); + GlobalToLocal (&wheresMyMouse); + GetEventParameter (theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifier); + + platform_support * app = reinterpret_cast<platform_support*>(userData); + + app->m_specific->m_cur_x = wheresMyMouse.h; + if(app->flip_y()) + { + app->m_specific->m_cur_y = app->rbuf_window().height() - wheresMyMouse.v; + } + else + { + app->m_specific->m_cur_y = wheresMyMouse.v; + } + app->m_specific->m_input_flags = mouse_left | get_key_flags(modifier); + + if(app->m_ctrls.on_mouse_button_up(app->m_specific->m_cur_x, + app->m_specific->m_cur_y)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + app->on_mouse_button_up(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_input_flags); + + return CallNextEventHandler (nextHandler, theEvent); +} + + +//------------------------------------------------------------------------ +pascal OSStatus DoMouseDragged (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) +{ + Point wheresMyMouse; + UInt32 modifier; + + GetEventParameter (theEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &wheresMyMouse); + GlobalToLocal (&wheresMyMouse); + GetEventParameter (theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifier); + + platform_support * app = reinterpret_cast<platform_support*>(userData); + + app->m_specific->m_cur_x = wheresMyMouse.h; + if(app->flip_y()) + { + app->m_specific->m_cur_y = app->rbuf_window().height() - wheresMyMouse.v; + } + else + { + app->m_specific->m_cur_y = wheresMyMouse.v; + } + app->m_specific->m_input_flags = mouse_left | get_key_flags(modifier); + + + if(app->m_ctrls.on_mouse_move( + app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + (app->m_specific->m_input_flags & mouse_left) != 0)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + app->on_mouse_move(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_input_flags); + } + + return CallNextEventHandler (nextHandler, theEvent); +} + + +//------------------------------------------------------------------------ +pascal OSStatus DoKeyDown (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) +{ + char key_code; + UInt32 modifier; + + GetEventParameter (theEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &key_code); + GetEventParameter (theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifier); + + platform_support * app = reinterpret_cast<platform_support*>(userData); + + app->m_specific->m_last_translated_key = 0; + switch(modifier) + { + case controlKey: + app->m_specific->m_input_flags |= kbd_ctrl; + break; + + case shiftKey: + app->m_specific->m_input_flags |= kbd_shift; + break; + + default: + app->m_specific->translate(key_code); + break; + } + + if(app->m_specific->m_last_translated_key) + { + bool left = false; + bool up = false; + bool right = false; + bool down = false; + + switch(app->m_specific->m_last_translated_key) + { + case key_left: + left = true; + break; + + case key_up: + up = true; + break; + + case key_right: + right = true; + break; + + case key_down: + down = true; + break; + + //On a Mac, screenshots are handled by the system. + case key_f2: + app->copy_window_to_img(agg::platform_support::max_images - 1); + app->save_img(agg::platform_support::max_images - 1, "screenshot"); + break; + } + + + if(app->m_ctrls.on_arrow_keys(left, right, down, up)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + app->on_key(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_last_translated_key, + app->m_specific->m_input_flags); + } + } + + return CallNextEventHandler (nextHandler, theEvent); +} + + +//------------------------------------------------------------------------ +pascal OSStatus DoKeyUp (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) +{ + char key_code; + UInt32 modifier; + + GetEventParameter (theEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &key_code); + GetEventParameter (theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifier); + + platform_support * app = reinterpret_cast<platform_support*>(userData); + + app->m_specific->m_last_translated_key = 0; + switch(modifier) + { + case controlKey: + app->m_specific->m_input_flags &= ~kbd_ctrl; + break; + + case shiftKey: + app->m_specific->m_input_flags &= ~kbd_shift; + break; + } + + return CallNextEventHandler (nextHandler, theEvent); +} + + +//------------------------------------------------------------------------ +pascal OSStatus DoWindowDrawContent (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) +{ + platform_support * app = reinterpret_cast<platform_support*>(userData); + + if(app) + { + if(app->m_specific->m_redraw_flag) + { + app->on_draw(); + app->m_specific->m_redraw_flag = false; + } + app->m_specific->display_pmap(app->m_specific->m_window, &app->rbuf_window()); + } + + return CallNextEventHandler (nextHandler, theEvent); +} + + +//------------------------------------------------------------------------ +pascal void DoPeriodicTask (EventLoopTimerRef theTimer, void* userData) +{ + platform_support * app = reinterpret_cast<platform_support*>(userData); + + if(!app->wait_mode()) + app->on_idle(); +} + + +} + + + + +//---------------------------------------------------------------------------- +int agg_main(int argc, char* argv[]); + + +// Hm. Classic MacOS does not know command line input. +// CodeWarrior provides a way to mimic command line input. +// The function 'ccommand' can be used to get the command +// line arguments. +//---------------------------------------------------------------------------- +int main(int argc, char* argv[]) +{ +#if defined(__MWERKS__) + // argc = ccommand (&argv); +#endif + + // Check if we are launched by double-clicking under OSX + // Get rid of extra argument, this will confuse the standard argument parsing + // calls used in the examples to get the name of the image file to be used + if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { + argc = 1; + } + +launch: + return agg_main(argc, argv); +} \ No newline at end of file diff --git a/jni/desmume/src/android/agg/src/platform/sdl/Makefile.am b/jni/desmume/src/android/agg/src/platform/sdl/Makefile.am new file mode 100755 index 0000000..590ef82 --- /dev/null +++ b/jni/desmume/src/android/agg/src/platform/sdl/Makefile.am @@ -0,0 +1,10 @@ +if ENABLE_SDL + +lib_LTLIBRARIES = libaggplatformsdl.la + +libaggplatformsdl_la_LDFLAGS = -version-info @AGG_LIB_VERSION@ +libaggplatformsdl_la_SOURCES = agg_platform_support.cpp +libaggplatformsdl_la_CXXFLAGS = -I$(top_srcdir)/include @SDL_CFLAGS@ +libaggplatformsdl_la_LIBADD = @SDL_LIBS@ +endif + diff --git a/jni/desmume/src/android/agg/src/platform/sdl/agg_platform_support.cpp b/jni/desmume/src/android/agg/src/platform/sdl/agg_platform_support.cpp new file mode 100755 index 0000000..091361b --- /dev/null +++ b/jni/desmume/src/android/agg/src/platform/sdl/agg_platform_support.cpp @@ -0,0 +1,714 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Copyright (C) 2004 Mauricio Piacentini (SDL Support) +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <string.h> +#include "platform/agg_platform_support.h" +#include "SDL.h" +#include "SDL_byteorder.h" + + +namespace agg +{ + + //------------------------------------------------------------------------ + class platform_specific + { + public: + platform_specific(pix_format_e format, bool flip_y); + ~platform_specific(); + + pix_format_e m_format; + pix_format_e m_sys_format; + bool m_flip_y; + unsigned m_bpp; + unsigned m_sys_bpp; + unsigned m_rmask; + unsigned m_gmask; + unsigned m_bmask; + unsigned m_amask; + bool m_update_flag; + bool m_resize_flag; + bool m_initialized; + SDL_Surface* m_surf_screen; + SDL_Surface* m_surf_window; + SDL_Surface* m_surf_img[platform_support::max_images]; + int m_cur_x; + int m_cur_y; + int m_sw_start; + }; + + + + //------------------------------------------------------------------------ + platform_specific::platform_specific(pix_format_e format, bool flip_y) : + m_format(format), + m_sys_format(pix_format_undefined), + m_flip_y(flip_y), + m_bpp(0), + m_sys_bpp(0), + m_update_flag(true), + m_resize_flag(true), + m_initialized(false), + m_surf_screen(0), + m_surf_window(0), + m_cur_x(0), + m_cur_y(0) + { + memset(m_surf_img, 0, sizeof(m_surf_img)); + + switch(m_format) + { + case pix_format_gray8: + m_bpp = 8; + break; + + case pix_format_rgb565: + m_rmask = 0xF800; + m_gmask = 0x7E0; + m_bmask = 0x1F; + m_amask = 0; + m_bpp = 16; + break; + + case pix_format_rgb555: + m_rmask = 0x7C00; + m_gmask = 0x3E0; + m_bmask = 0x1F; + m_amask = 0; + m_bpp = 16; + break; + +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + case pix_format_rgb24: + m_rmask = 0xFF; + m_gmask = 0xFF00; + m_bmask = 0xFF0000; + m_amask = 0; + m_bpp = 24; + break; + + case pix_format_bgr24: + m_rmask = 0xFF0000; + m_gmask = 0xFF00; + m_bmask = 0xFF; + m_amask = 0; + m_bpp = 24; + break; + + case pix_format_bgra32: + m_rmask = 0xFF0000; + m_gmask = 0xFF00; + m_bmask = 0xFF; + m_amask = 0xFF000000; + m_bpp = 32; + break; + + case pix_format_abgr32: + m_rmask = 0xFF000000; + m_gmask = 0xFF0000; + m_bmask = 0xFF00; + m_amask = 0xFF; + m_bpp = 32; + break; + + case pix_format_argb32: + m_rmask = 0xFF00; + m_gmask = 0xFF0000; + m_bmask = 0xFF000000; + m_amask = 0xFF; + m_bpp = 32; + break; + + case pix_format_rgba32: + m_rmask = 0xFF; + m_gmask = 0xFF00; + m_bmask = 0xFF0000; + m_amask = 0xFF000000; + m_bpp = 32; + break; +#else //SDL_BIG_ENDIAN (PPC) + case pix_format_rgb24: + m_rmask = 0xFF0000; + m_gmask = 0xFF00; + m_bmask = 0xFF; + m_amask = 0; + m_bpp = 24; + break; + + case pix_format_bgr24: + m_rmask = 0xFF; + m_gmask = 0xFF00; + m_bmask = 0xFF0000; + m_amask = 0; + m_bpp = 24; + break; + + case pix_format_bgra32: + m_rmask = 0xFF00; + m_gmask = 0xFF0000; + m_bmask = 0xFF000000; + m_amask = 0xFF; + m_bpp = 32; + break; + + case pix_format_abgr32: + m_rmask = 0xFF; + m_gmask = 0xFF00; + m_bmask = 0xFF0000; + m_amask = 0xFF000000; + m_bpp = 32; + break; + + case pix_format_argb32: + m_rmask = 0xFF0000; + m_gmask = 0xFF00; + m_bmask = 0xFF; + m_amask = 0xFF000000; + m_bpp = 32; + break; + + case pix_format_rgba32: + m_rmask = 0xFF000000; + m_gmask = 0xFF0000; + m_bmask = 0xFF00; + m_amask = 0xFF; + m_bpp = 32; + break; +#endif + } + } + + //------------------------------------------------------------------------ + platform_specific::~platform_specific() + { + int i; + for(i = platform_support::max_images - 1; i >= 0; --i) + { + if(m_surf_img[i]) SDL_FreeSurface(m_surf_img[i]); + } + if(m_surf_window) SDL_FreeSurface(m_surf_window); + if(m_surf_screen) SDL_FreeSurface(m_surf_screen); + } + + + + //------------------------------------------------------------------------ + platform_support::platform_support(pix_format_e format, bool flip_y) : + m_specific(new platform_specific(format, flip_y)), + m_format(format), + m_bpp(m_specific->m_bpp), + m_window_flags(0), + m_wait_mode(true), + m_flip_y(flip_y) + { + SDL_Init(SDL_INIT_VIDEO); + strcpy(m_caption, "Anti-Grain Geometry Application"); + } + + + //------------------------------------------------------------------------ + platform_support::~platform_support() + { + delete m_specific; + } + + + + //------------------------------------------------------------------------ + void platform_support::caption(const char* cap) + { + strcpy(m_caption, cap); + if(m_specific->m_initialized) + { + SDL_WM_SetCaption(cap, 0); + } + } + + + + + + //------------------------------------------------------------------------ + bool platform_support::init(unsigned width, unsigned height, unsigned flags) + { + m_window_flags = flags; + unsigned wflags = SDL_SWSURFACE; + + if(m_window_flags & window_hw_buffer) + { + wflags = SDL_HWSURFACE; + } + + if(m_window_flags & window_resize) + { + wflags |= SDL_RESIZABLE; + } + + if(m_specific->m_surf_screen) SDL_FreeSurface(m_specific->m_surf_screen); + + m_specific->m_surf_screen = SDL_SetVideoMode(width, height, m_bpp, wflags); + if(m_specific->m_surf_screen == 0) + { + fprintf(stderr, + "Unable to set %dx%d %d bpp video: %s\n", + width, + height, + m_bpp, + ::SDL_GetError()); + return false; + } + + SDL_WM_SetCaption(m_caption, 0); + + if(m_specific->m_surf_window) SDL_FreeSurface(m_specific->m_surf_window); + + m_specific->m_surf_window = + SDL_CreateRGBSurface(SDL_HWSURFACE, + m_specific->m_surf_screen->w, + m_specific->m_surf_screen->h, + m_specific->m_surf_screen->format->BitsPerPixel, + m_specific->m_rmask, + m_specific->m_gmask, + m_specific->m_bmask, + m_specific->m_amask); + + if(m_specific->m_surf_window == 0) + { + fprintf(stderr, + "Unable to create image buffer %dx%d %d bpp: %s\n", + width, + height, + m_bpp, + SDL_GetError()); + return false; + } + + m_rbuf_window.attach((unsigned char*)m_specific->m_surf_window->pixels, + m_specific->m_surf_window->w, + m_specific->m_surf_window->h, + m_flip_y ? -m_specific->m_surf_window->pitch : + m_specific->m_surf_window->pitch); + + if(!m_specific->m_initialized) + { + m_initial_width = width; + m_initial_height = height; + on_init(); + m_specific->m_initialized = true; + } + on_resize(m_rbuf_window.width(), m_rbuf_window.height()); + m_specific->m_update_flag = true; + return true; + } + + + + //------------------------------------------------------------------------ + void platform_support::update_window() + { + SDL_BlitSurface(m_specific->m_surf_window, 0, m_specific->m_surf_screen, 0); + SDL_UpdateRect(m_specific->m_surf_screen, 0, 0, 0, 0); + } + + + //------------------------------------------------------------------------ + int platform_support::run() + { + SDL_Event event; + bool ev_flag = false; + + for(;;) + { + if(m_specific->m_update_flag) + { + on_draw(); + update_window(); + m_specific->m_update_flag = false; + } + + ev_flag = false; + if(m_wait_mode) + { + SDL_WaitEvent(&event); + ev_flag = true; + } + else + { + if(SDL_PollEvent(&event)) + { + ev_flag = true; + } + else + { + on_idle(); + } + } + + if(ev_flag) + { + if(event.type == SDL_QUIT) + { + break; + } + + int y; + unsigned flags = 0; + + switch (event.type) + { + case SDL_VIDEORESIZE: + if(!init(event.resize.w, event.resize.h, m_window_flags)) return false; + on_resize(m_rbuf_window.width(), m_rbuf_window.height()); + trans_affine_resizing(event.resize.w, event.resize.h); + m_specific->m_update_flag = true; + break; + + case SDL_KEYDOWN: + { + flags = 0; + if(event.key.keysym.mod & KMOD_SHIFT) flags |= kbd_shift; + if(event.key.keysym.mod & KMOD_CTRL) flags |= kbd_ctrl; + + bool left = false; + bool up = false; + bool right = false; + bool down = false; + + switch(event.key.keysym.sym) + { + case key_left: + left = true; + break; + + case key_up: + up = true; + break; + + case key_right: + right = true; + break; + + case key_down: + down = true; + break; + } + + if(m_ctrls.on_arrow_keys(left, right, down, up)) + { + on_ctrl_change(); + force_redraw(); + } + else + { + on_key(m_specific->m_cur_x, + m_specific->m_cur_y, + event.key.keysym.sym, + flags); + } + } + break; + + case SDL_MOUSEMOTION: + y = m_flip_y ? + m_rbuf_window.height() - event.motion.y : + event.motion.y; + + m_specific->m_cur_x = event.motion.x; + m_specific->m_cur_y = y; + flags = 0; + if(event.motion.state & SDL_BUTTON_LMASK) flags |= mouse_left; + if(event.motion.state & SDL_BUTTON_RMASK) flags |= mouse_right; + + if(m_ctrls.on_mouse_move(m_specific->m_cur_x, + m_specific->m_cur_y, + (flags & mouse_left) != 0)) + { + on_ctrl_change(); + force_redraw(); + } + else + { + on_mouse_move(m_specific->m_cur_x, + m_specific->m_cur_y, + flags); + } + SDL_Event eventtrash; + while (SDL_PeepEvents(&eventtrash, 1, SDL_GETEVENT, SDL_EVENTMASK(SDL_MOUSEMOTION))!=0){;} + break; + + case SDL_MOUSEBUTTONDOWN: + y = m_flip_y + ? m_rbuf_window.height() - event.button.y + : event.button.y; + + m_specific->m_cur_x = event.button.x; + m_specific->m_cur_y = y; + flags = 0; + switch(event.button.button) + { + case SDL_BUTTON_LEFT: + { + flags = mouse_left; + +if(m_ctrls.on_mouse_button_down(m_specific->m_cur_x, + m_specific->m_cur_y)) + { + m_ctrls.set_cur(m_specific->m_cur_x, + m_specific->m_cur_y); + on_ctrl_change(); + force_redraw(); + } + else + { + if(m_ctrls.in_rect(m_specific->m_cur_x, + m_specific->m_cur_y)) + { + if(m_ctrls.set_cur(m_specific->m_cur_x, + m_specific->m_cur_y)) + { + on_ctrl_change(); + force_redraw(); + } + } + else + { + on_mouse_button_down(m_specific->m_cur_x, + m_specific->m_cur_y, + flags); + } + } + } + break; + case SDL_BUTTON_RIGHT: + flags = mouse_right; + on_mouse_button_down(m_specific->m_cur_x, + m_specific->m_cur_y, + flags); + break; + } //switch(event.button.button) + break; + + case SDL_MOUSEBUTTONUP: + y = m_flip_y + ? m_rbuf_window.height() - event.button.y + : event.button.y; + + m_specific->m_cur_x = event.button.x; + m_specific->m_cur_y = y; + flags = 0; + if(m_ctrls.on_mouse_button_up(m_specific->m_cur_x, + m_specific->m_cur_y)) + { + on_ctrl_change(); + force_redraw(); + } + on_mouse_button_up(m_specific->m_cur_x, + m_specific->m_cur_y, + flags); + break; + } + } + } + return 0; + } + + + + //------------------------------------------------------------------------ + const char* platform_support::img_ext() const { return ".bmp"; } + + //------------------------------------------------------------------------ + const char* platform_support::full_file_name(const char* file_name) + { + return file_name; + } + + //------------------------------------------------------------------------ + bool platform_support::load_img(unsigned idx, const char* file) + { + if(idx < max_images) + { + if(m_specific->m_surf_img[idx]) SDL_FreeSurface(m_specific->m_surf_img[idx]); + + char fn[1024]; + strcpy(fn, file); + int len = strlen(fn); + if(len < 4 || strcmp(fn + len - 4, ".bmp") != 0) + { + strcat(fn, ".bmp"); + } + + SDL_Surface* tmp_surf = SDL_LoadBMP(fn); + if (tmp_surf == 0) + { + fprintf(stderr, "Couldn't load %s: %s\n", fn, SDL_GetError()); + return false; + } + + SDL_PixelFormat format; + format.palette = 0; + format.BitsPerPixel = m_bpp; + format.BytesPerPixel = m_bpp >> 8; + format.Rmask = m_specific->m_rmask; + format.Gmask = m_specific->m_gmask; + format.Bmask = m_specific->m_bmask; + format.Amask = m_specific->m_amask; + format.Rshift = 0; + format.Gshift = 0; + format.Bshift = 0; + format.Ashift = 0; + format.Rloss = 0; + format.Gloss = 0; + format.Bloss = 0; + format.Aloss = 0; + format.colorkey = 0; + format.alpha = 0; + + m_specific->m_surf_img[idx] = + SDL_ConvertSurface(tmp_surf, + &format, + SDL_SWSURFACE); + + SDL_FreeSurface(tmp_surf); + + if(m_specific->m_surf_img[idx] == 0) return false; + + m_rbuf_img[idx].attach((unsigned char*)m_specific->m_surf_img[idx]->pixels, + m_specific->m_surf_img[idx]->w, + m_specific->m_surf_img[idx]->h, + m_flip_y ? -m_specific->m_surf_img[idx]->pitch : + m_specific->m_surf_img[idx]->pitch); + return true; + + } + return false; + } + + + + + //------------------------------------------------------------------------ + bool platform_support::save_img(unsigned idx, const char* file) + { + if(idx < max_images && m_specific->m_surf_img[idx]) + { + char fn[1024]; + strcpy(fn, file); + int len = strlen(fn); + if(len < 4 || strcmp(fn + len - 4, ".bmp") != 0) + { + strcat(fn, ".bmp"); + } + return SDL_SaveBMP(m_specific->m_surf_img[idx], fn) == 0; + } + return false; + } + + + + //------------------------------------------------------------------------ + bool platform_support::create_img(unsigned idx, unsigned width, unsigned height) + { + if(idx < max_images) + { + + if(m_specific->m_surf_img[idx]) SDL_FreeSurface(m_specific->m_surf_img[idx]); + + m_specific->m_surf_img[idx] = + SDL_CreateRGBSurface(SDL_SWSURFACE, + width, + height, + m_specific->m_surf_screen->format->BitsPerPixel, + m_specific->m_rmask, + m_specific->m_gmask, + m_specific->m_bmask, + m_specific->m_amask); + if(m_specific->m_surf_img[idx] == 0) + { + fprintf(stderr, "Couldn't create image: %s\n", SDL_GetError()); + return false; + } + + m_rbuf_img[idx].attach((unsigned char*)m_specific->m_surf_img[idx]->pixels, + m_specific->m_surf_img[idx]->w, + m_specific->m_surf_img[idx]->h, + m_flip_y ? -m_specific->m_surf_img[idx]->pitch : + m_specific->m_surf_img[idx]->pitch); + + return true; + } + + return false; + } + + //------------------------------------------------------------------------ + void platform_support::start_timer() + { + m_specific->m_sw_start = SDL_GetTicks(); + } + + //------------------------------------------------------------------------ + double platform_support::elapsed_time() const + { + int stop = SDL_GetTicks(); + return double(stop - m_specific->m_sw_start); + } + + //------------------------------------------------------------------------ + void platform_support::message(const char* msg) + { + fprintf(stderr, "%s\n", msg); + } + + //------------------------------------------------------------------------ + void platform_support::force_redraw() + { + m_specific->m_update_flag = true; + } + + + //------------------------------------------------------------------------ + void platform_support::on_init() {} + void platform_support::on_resize(int sx, int sy) {} + void platform_support::on_idle() {} + void platform_support::on_mouse_move(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {} + void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {} + void platform_support::on_ctrl_change() {} + void platform_support::on_draw() {} + void platform_support::on_post_draw(void* raw_handler) {} + + +} + + +int agg_main(int argc, char* argv[]); + +int main(int argc, char* argv[]) +{ + return agg_main(argc, argv); +} + diff --git a/jni/desmume/src/android/agg/src/platform/win32/Makefile.am b/jni/desmume/src/android/agg/src/platform/win32/Makefile.am new file mode 100755 index 0000000..df7a675 --- /dev/null +++ b/jni/desmume/src/android/agg/src/platform/win32/Makefile.am @@ -0,0 +1,13 @@ + + +if ENABLE_WIN32 +lib_LTLIBRARIES = libaggplatformwin32.la + +libaggplatformwin32_la_LDFLAGS = -version-info @AGG_LIB_VERSION@ +libaggplatformwin32_la_SOURCES = agg_platform_support.cpp \ + agg_win32_bmp.cpp + +libaggplatformwin32_la_CXXFLAGS = -I$(top_srcdir)/include @WINDOWS_CFLAGS@ +libaggplatformwin32_la_LIBADD = @WINDOWS_LIBS@ $(top_builddir)/src/libagg.la +endif + diff --git a/jni/desmume/src/android/agg/src/platform/win32/agg_platform_support.cpp b/jni/desmume/src/android/agg/src/platform/win32/agg_platform_support.cpp new file mode 100755 index 0000000..2e9e51b --- /dev/null +++ b/jni/desmume/src/android/agg/src/platform/win32/agg_platform_support.cpp @@ -0,0 +1,1478 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG 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. +// +// AGG 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 AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <windows.h> +#include <string.h> +#include "platform/agg_platform_support.h" +#include "platform/win32/agg_win32_bmp.h" +#include "util/agg_color_conv_rgb8.h" +#include "util/agg_color_conv_rgb16.h" + + +namespace agg +{ + + //------------------------------------------------------------------------ + HINSTANCE g_windows_instance = 0; + int g_windows_cmd_show = 0; + + + //------------------------------------------------------------------------ + class platform_specific + { + public: + platform_specific(pix_format_e format, bool flip_y); + + void create_pmap(unsigned width, unsigned height, + rendering_buffer* wnd); + + void display_pmap(HDC dc, const rendering_buffer* src); + bool load_pmap(const char* fn, unsigned idx, + rendering_buffer* dst); + + bool save_pmap(const char* fn, unsigned idx, + const rendering_buffer* src); + + unsigned translate(unsigned keycode); + + pix_format_e m_format; + pix_format_e m_sys_format; + bool m_flip_y; + unsigned m_bpp; + unsigned m_sys_bpp; + HWND m_hwnd; + pixel_map m_pmap_window; + pixel_map m_pmap_img[platform_support::max_images]; + unsigned m_keymap[256]; + unsigned m_last_translated_key; + int m_cur_x; + int m_cur_y; + unsigned m_input_flags; + bool m_redraw_flag; + HDC m_current_dc; + LARGE_INTEGER m_sw_freq; + LARGE_INTEGER m_sw_start; + }; + + + //------------------------------------------------------------------------ + platform_specific::platform_specific(pix_format_e format, bool flip_y) : + m_format(format), + m_sys_format(pix_format_undefined), + m_flip_y(flip_y), + m_bpp(0), + m_sys_bpp(0), + m_hwnd(0), + m_last_translated_key(0), + m_cur_x(0), + m_cur_y(0), + m_input_flags(0), + m_redraw_flag(true), + m_current_dc(0) + { + memset(m_keymap, 0, sizeof(m_keymap)); + + m_keymap[VK_PAUSE] = key_pause; + m_keymap[VK_CLEAR] = key_clear; + + m_keymap[VK_NUMPAD0] = key_kp0; + m_keymap[VK_NUMPAD1] = key_kp1; + m_keymap[VK_NUMPAD2] = key_kp2; + m_keymap[VK_NUMPAD3] = key_kp3; + m_keymap[VK_NUMPAD4] = key_kp4; + m_keymap[VK_NUMPAD5] = key_kp5; + m_keymap[VK_NUMPAD6] = key_kp6; + m_keymap[VK_NUMPAD7] = key_kp7; + m_keymap[VK_NUMPAD8] = key_kp8; + m_keymap[VK_NUMPAD9] = key_kp9; + m_keymap[VK_DECIMAL] = key_kp_period; + m_keymap[VK_DIVIDE] = key_kp_divide; + m_keymap[VK_MULTIPLY] = key_kp_multiply; + m_keymap[VK_SUBTRACT] = key_kp_minus; + m_keymap[VK_ADD] = key_kp_plus; + + m_keymap[VK_UP] = key_up; + m_keymap[VK_DOWN] = key_down; + m_keymap[VK_RIGHT] = key_right; + m_keymap[VK_LEFT] = key_left; + m_keymap[VK_INSERT] = key_insert; + m_keymap[VK_DELETE] = key_delete; + m_keymap[VK_HOME] = key_home; + m_keymap[VK_END] = key_end; + m_keymap[VK_PRIOR] = key_page_up; + m_keymap[VK_NEXT] = key_page_down; + + m_keymap[VK_F1] = key_f1; + m_keymap[VK_F2] = key_f2; + m_keymap[VK_F3] = key_f3; + m_keymap[VK_F4] = key_f4; + m_keymap[VK_F5] = key_f5; + m_keymap[VK_F6] = key_f6; + m_keymap[VK_F7] = key_f7; + m_keymap[VK_F8] = key_f8; + m_keymap[VK_F9] = key_f9; + m_keymap[VK_F10] = key_f10; + m_keymap[VK_F11] = key_f11; + m_keymap[VK_F12] = key_f12; + m_keymap[VK_F13] = key_f13; + m_keymap[VK_F14] = key_f14; + m_keymap[VK_F15] = key_f15; + + m_keymap[VK_NUMLOCK] = key_numlock; + m_keymap[VK_CAPITAL] = key_capslock; + m_keymap[VK_SCROLL] = key_scrollock; + + + switch(m_format) + { + case pix_format_bw: + m_sys_format = pix_format_bw; + m_bpp = 1; + m_sys_bpp = 1; + break; + + case pix_format_gray8: + m_sys_format = pix_format_gray8; + m_bpp = 8; + m_sys_bpp = 8; + break; + + case pix_format_gray16: + m_sys_format = pix_format_gray8; + m_bpp = 16; + m_sys_bpp = 8; + break; + + case pix_format_rgb565: + case pix_format_rgb555: + m_sys_format = pix_format_rgb555; + m_bpp = 16; + m_sys_bpp = 16; + break; + + case pix_format_rgbAAA: + case pix_format_bgrAAA: + case pix_format_rgbBBA: + case pix_format_bgrABB: + m_sys_format = pix_format_bgr24; + m_bpp = 32; + m_sys_bpp = 24; + break; + + case pix_format_rgb24: + case pix_format_bgr24: + m_sys_format = pix_format_bgr24; + m_bpp = 24; + m_sys_bpp = 24; + break; + + case pix_format_rgb48: + case pix_format_bgr48: + m_sys_format = pix_format_bgr24; + m_bpp = 48; + m_sys_bpp = 24; + break; + + case pix_format_bgra32: + case pix_format_abgr32: + case pix_format_argb32: + case pix_format_rgba32: + m_sys_format = pix_format_bgra32; + m_bpp = 32; + m_sys_bpp = 32; + break; + + case pix_format_bgra64: + case pix_format_abgr64: + case pix_format_argb64: + case pix_format_rgba64: + m_sys_format = pix_format_bgra32; + m_bpp = 64; + m_sys_bpp = 32; + break; + } + ::QueryPerformanceFrequency(&m_sw_freq); + ::QueryPerformanceCounter(&m_sw_start); + } + + + //------------------------------------------------------------------------ + void platform_specific::create_pmap(unsigned width, + unsigned height, + rendering_buffer* wnd) + { + m_pmap_window.create(width, height, org_e(m_bpp)); + wnd->attach(m_pmap_window.buf(), + m_pmap_window.width(), + m_pmap_window.height(), + m_flip_y ? + m_pmap_window.stride() : + -m_pmap_window.stride()); + } + + + //------------------------------------------------------------------------ + static void convert_pmap(rendering_buffer* dst, + const rendering_buffer* src, + pix_format_e format) + { + switch(format) + { + case pix_format_gray8: + break; + + case pix_format_gray16: + color_conv(dst, src, color_conv_gray16_to_gray8()); + break; + + case pix_format_rgb565: + color_conv(dst, src, color_conv_rgb565_to_rgb555()); + break; + + case pix_format_rgbAAA: + color_conv(dst, src, color_conv_rgbAAA_to_bgr24()); + break; + + case pix_format_bgrAAA: + color_conv(dst, src, color_conv_bgrAAA_to_bgr24()); + break; + + case pix_format_rgbBBA: + color_conv(dst, src, color_conv_rgbBBA_to_bgr24()); + break; + + case pix_format_bgrABB: + color_conv(dst, src, color_conv_bgrABB_to_bgr24()); + break; + + case pix_format_rgb24: + color_conv(dst, src, color_conv_rgb24_to_bgr24()); + break; + + case pix_format_rgb48: + color_conv(dst, src, color_conv_rgb48_to_bgr24()); + break; + + case pix_format_bgr48: + color_conv(dst, src, color_conv_bgr48_to_bgr24()); + break; + + case pix_format_abgr32: + color_conv(dst, src, color_conv_abgr32_to_bgra32()); + break; + + case pix_format_argb32: + color_conv(dst, src, color_conv_argb32_to_bgra32()); + break; + + case pix_format_rgba32: + color_conv(dst, src, color_conv_rgba32_to_bgra32()); + break; + + case pix_format_bgra64: + color_conv(dst, src, color_conv_bgra64_to_bgra32()); + break; + + case pix_format_abgr64: + color_conv(dst, src, color_conv_abgr64_to_bgra32()); + break; + + case pix_format_argb64: + color_conv(dst, src, color_conv_argb64_to_bgra32()); + break; + + case pix_format_rgba64: + color_conv(dst, src, color_conv_rgba64_to_bgra32()); + break; + } + } + + + //------------------------------------------------------------------------ + void platform_specific::display_pmap(HDC dc, const rendering_buffer* src) + { + if(m_sys_format == m_format) + { + m_pmap_window.draw(dc); + } + else + { + pixel_map pmap_tmp; + pmap_tmp.create(m_pmap_window.width(), + m_pmap_window.height(), + org_e(m_sys_bpp)); + + rendering_buffer rbuf_tmp; + rbuf_tmp.attach(pmap_tmp.buf(), + pmap_tmp.width(), + pmap_tmp.height(), + m_flip_y ? + pmap_tmp.stride() : + -pmap_tmp.stride()); + + convert_pmap(&rbuf_tmp, src, m_format); + pmap_tmp.draw(dc); + } + } + + + + //------------------------------------------------------------------------ + bool platform_specific::save_pmap(const char* fn, unsigned idx, + const rendering_buffer* src) + { + if(m_sys_format == m_format) + { + return m_pmap_img[idx].save_as_bmp(fn); + } + + pixel_map pmap_tmp; + pmap_tmp.create(m_pmap_img[idx].width(), + m_pmap_img[idx].height(), + org_e(m_sys_bpp)); + + rendering_buffer rbuf_tmp; + rbuf_tmp.attach(pmap_tmp.buf(), + pmap_tmp.width(), + pmap_tmp.height(), + m_flip_y ? + pmap_tmp.stride() : + -pmap_tmp.stride()); + + convert_pmap(&rbuf_tmp, src, m_format); + return pmap_tmp.save_as_bmp(fn); + } + + + + //------------------------------------------------------------------------ + bool platform_specific::load_pmap(const char* fn, unsigned idx, + rendering_buffer* dst) + { + pixel_map pmap_tmp; + if(!pmap_tmp.load_from_bmp(fn)) return false; + + rendering_buffer rbuf_tmp; + rbuf_tmp.attach(pmap_tmp.buf(), + pmap_tmp.width(), + pmap_tmp.height(), + m_flip_y ? + pmap_tmp.stride() : + -pmap_tmp.stride()); + + m_pmap_img[idx].create(pmap_tmp.width(), + pmap_tmp.height(), + org_e(m_bpp), + 0); + + dst->attach(m_pmap_img[idx].buf(), + m_pmap_img[idx].width(), + m_pmap_img[idx].height(), + m_flip_y ? + m_pmap_img[idx].stride() : + -m_pmap_img[idx].stride()); + + switch(m_format) + { + case pix_format_gray8: + switch(pmap_tmp.bpp()) + { + //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_gray8()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_gray8()); break; + //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_gray8()); break; + } + break; + + case pix_format_gray16: + switch(pmap_tmp.bpp()) + { + //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_gray16()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_gray16()); break; + //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_gray16()); break; + } + break; + + case pix_format_rgb555: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb555()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_rgb555()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb555()); break; + } + break; + + case pix_format_rgb565: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb565()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_rgb565()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb565()); break; + } + break; + + case pix_format_rgb24: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb24()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_rgb24()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb24()); break; + } + break; + + case pix_format_bgr24: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_bgr24()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_bgr24()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_bgr24()); break; + } + break; + + case pix_format_rgb48: + switch(pmap_tmp.bpp()) + { + //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb48()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_rgb48()); break; + //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb48()); break; + } + break; + + case pix_format_bgr48: + switch(pmap_tmp.bpp()) + { + //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_bgr48()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_bgr48()); break; + //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_bgr48()); break; + } + break; + + case pix_format_abgr32: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_abgr32()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_abgr32()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_abgr32()); break; + } + break; + + case pix_format_argb32: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_argb32()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_argb32()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_argb32()); break; + } + break; + + case pix_format_bgra32: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_bgra32()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_bgra32()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_bgra32()); break; + } + break; + + case pix_format_rgba32: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgba32()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_rgba32()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgba32()); break; + } + break; + + case pix_format_abgr64: + switch(pmap_tmp.bpp()) + { + //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_abgr64()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_abgr64()); break; + //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_abgr64()); break; + } + break; + + case pix_format_argb64: + switch(pmap_tmp.bpp()) + { + //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_argb64()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_argb64()); break; + //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_argb64()); break; + } + break; + + case pix_format_bgra64: + switch(pmap_tmp.bpp()) + { + //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_bgra64()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_bgra64()); break; + //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_bgra64()); break; + } + break; + + case pix_format_rgba64: + switch(pmap_tmp.bpp()) + { + //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgba64()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_rgba64()); break; + //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgba64()); break; + } + break; + + } + + return true; + } + + + + + + + + + //------------------------------------------------------------------------ + unsigned platform_specific::translate(unsigned keycode) + { + return m_last_translated_key = (keycode > 255) ? 0 : m_keymap[keycode]; + } + + + + //------------------------------------------------------------------------ + platform_support::platform_support(pix_format_e format, bool flip_y) : + m_specific(new platform_specific(format, flip_y)), + m_format(format), + m_bpp(m_specific->m_bpp), + m_window_flags(0), + m_wait_mode(true), + m_flip_y(flip_y), + m_initial_width(10), + m_initial_height(10) + { + strcpy(m_caption, "Anti-Grain Geometry Application"); + } + + + //------------------------------------------------------------------------ + platform_support::~platform_support() + { + delete m_specific; + } + + + + //------------------------------------------------------------------------ + void platform_support::caption(const char* cap) + { + strcpy(m_caption, cap); + if(m_specific->m_hwnd) + { + SetWindowText(m_specific->m_hwnd, m_caption); + } + } + + //------------------------------------------------------------------------ + void platform_support::start_timer() + { + ::QueryPerformanceCounter(&(m_specific->m_sw_start)); + } + + //------------------------------------------------------------------------ + double platform_support::elapsed_time() const + { + LARGE_INTEGER stop; + ::QueryPerformanceCounter(&stop); + return double(stop.QuadPart - + m_specific->m_sw_start.QuadPart) * 1000.0 / + double(m_specific->m_sw_freq.QuadPart); + } + + + + //------------------------------------------------------------------------ + static unsigned get_key_flags(int wflags) + { + unsigned flags = 0; + if(wflags & MK_LBUTTON) flags |= mouse_left; + if(wflags & MK_RBUTTON) flags |= mouse_right; + if(wflags & MK_SHIFT) flags |= kbd_shift; + if(wflags & MK_CONTROL) flags |= kbd_ctrl; + return flags; + } + + + void* platform_support::raw_display_handler() + { + return m_specific->m_current_dc; + } + + + //------------------------------------------------------------------------ + LRESULT CALLBACK window_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + PAINTSTRUCT ps; + HDC paintDC; + + + void* user_data = reinterpret_cast<void*>(::GetWindowLong(hWnd, GWL_USERDATA)); + platform_support* app = 0; + + if(user_data) + { + app = reinterpret_cast<platform_support*>(user_data); + } + + if(app == 0) + { + if(msg == WM_DESTROY) + { + ::PostQuitMessage(0); + return 0; + } + return ::DefWindowProc(hWnd, msg, wParam, lParam); + } + + HDC dc = ::GetDC(app->m_specific->m_hwnd); + app->m_specific->m_current_dc = dc; + LRESULT ret = 0; + + switch(msg) + { + //-------------------------------------------------------------------- + case WM_CREATE: + break; + + //-------------------------------------------------------------------- + case WM_SIZE: + app->m_specific->create_pmap(LOWORD(lParam), + HIWORD(lParam), + &app->rbuf_window()); + + app->trans_affine_resizing(LOWORD(lParam), HIWORD(lParam)); + app->on_resize(LOWORD(lParam), HIWORD(lParam)); + app->force_redraw(); + break; + + //-------------------------------------------------------------------- + case WM_ERASEBKGND: + break; + + //-------------------------------------------------------------------- + case WM_LBUTTONDOWN: + ::SetCapture(app->m_specific->m_hwnd); + app->m_specific->m_cur_x = int16(LOWORD(lParam)); + if(app->flip_y()) + { + app->m_specific->m_cur_y = app->rbuf_window().height() - int16(HIWORD(lParam)); + } + else + { + app->m_specific->m_cur_y = int16(HIWORD(lParam)); + } + app->m_specific->m_input_flags = mouse_left | get_key_flags(wParam); + + app->m_ctrls.set_cur(app->m_specific->m_cur_x, + app->m_specific->m_cur_y); + if(app->m_ctrls.on_mouse_button_down(app->m_specific->m_cur_x, + app->m_specific->m_cur_y)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + if(app->m_ctrls.in_rect(app->m_specific->m_cur_x, + app->m_specific->m_cur_y)) + { + if(app->m_ctrls.set_cur(app->m_specific->m_cur_x, + app->m_specific->m_cur_y)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + } + else + { + app->on_mouse_button_down(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_input_flags); + } + } +/* + if(!app->wait_mode()) + { + app->on_idle(); + } +*/ + break; + + //-------------------------------------------------------------------- + case WM_LBUTTONUP: + ::ReleaseCapture(); + app->m_specific->m_cur_x = int16(LOWORD(lParam)); + if(app->flip_y()) + { + app->m_specific->m_cur_y = app->rbuf_window().height() - int16(HIWORD(lParam)); + } + else + { + app->m_specific->m_cur_y = int16(HIWORD(lParam)); + } + app->m_specific->m_input_flags = mouse_left | get_key_flags(wParam); + + if(app->m_ctrls.on_mouse_button_up(app->m_specific->m_cur_x, + app->m_specific->m_cur_y)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + app->on_mouse_button_up(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_input_flags); +/* + if(!app->wait_mode()) + { + app->on_idle(); + } +*/ + break; + + + //-------------------------------------------------------------------- + case WM_RBUTTONDOWN: + ::SetCapture(app->m_specific->m_hwnd); + app->m_specific->m_cur_x = int16(LOWORD(lParam)); + if(app->flip_y()) + { + app->m_specific->m_cur_y = app->rbuf_window().height() - int16(HIWORD(lParam)); + } + else + { + app->m_specific->m_cur_y = int16(HIWORD(lParam)); + } + app->m_specific->m_input_flags = mouse_right | get_key_flags(wParam); + app->on_mouse_button_down(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_input_flags); +/* + if(!app->wait_mode()) + { + app->on_idle(); + } +*/ + break; + + //-------------------------------------------------------------------- + case WM_RBUTTONUP: + ::ReleaseCapture(); + app->m_specific->m_cur_x = int16(LOWORD(lParam)); + if(app->flip_y()) + { + app->m_specific->m_cur_y = app->rbuf_window().height() - int16(HIWORD(lParam)); + } + else + { + app->m_specific->m_cur_y = int16(HIWORD(lParam)); + } + app->m_specific->m_input_flags = mouse_right | get_key_flags(wParam); + app->on_mouse_button_up(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_input_flags); +/* + if(!app->wait_mode()) + { + app->on_idle(); + } +*/ + break; + + //-------------------------------------------------------------------- + case WM_MOUSEMOVE: + app->m_specific->m_cur_x = int16(LOWORD(lParam)); + if(app->flip_y()) + { + app->m_specific->m_cur_y = app->rbuf_window().height() - int16(HIWORD(lParam)); + } + else + { + app->m_specific->m_cur_y = int16(HIWORD(lParam)); + } + app->m_specific->m_input_flags = get_key_flags(wParam); + + + if(app->m_ctrls.on_mouse_move( + app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + (app->m_specific->m_input_flags & mouse_left) != 0)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + if(!app->m_ctrls.in_rect(app->m_specific->m_cur_x, + app->m_specific->m_cur_y)) + { + app->on_mouse_move(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_input_flags); + } + } +/* + if(!app->wait_mode()) + { + app->on_idle(); + } +*/ + break; + + //-------------------------------------------------------------------- + case WM_SYSKEYDOWN: + case WM_KEYDOWN: + app->m_specific->m_last_translated_key = 0; + switch(wParam) + { + case VK_CONTROL: + app->m_specific->m_input_flags |= kbd_ctrl; + break; + + case VK_SHIFT: + app->m_specific->m_input_flags |= kbd_shift; + break; + + default: + app->m_specific->translate(wParam); + break; + } + + if(app->m_specific->m_last_translated_key) + { + bool left = false; + bool up = false; + bool right = false; + bool down = false; + + switch(app->m_specific->m_last_translated_key) + { + case key_left: + left = true; + break; + + case key_up: + up = true; + break; + + case key_right: + right = true; + break; + + case key_down: + down = true; + break; + + case key_f2: + app->copy_window_to_img(agg::platform_support::max_images - 1); + app->save_img(agg::platform_support::max_images - 1, "screenshot"); + break; + } + + if(app->window_flags() & window_process_all_keys) + { + app->on_key(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_last_translated_key, + app->m_specific->m_input_flags); + } + else + { + if(app->m_ctrls.on_arrow_keys(left, right, down, up)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + app->on_key(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_last_translated_key, + app->m_specific->m_input_flags); + } + } + } +/* + if(!app->wait_mode()) + { + app->on_idle(); + } +*/ + break; + + //-------------------------------------------------------------------- + case WM_SYSKEYUP: + case WM_KEYUP: + app->m_specific->m_last_translated_key = 0; + switch(wParam) + { + case VK_CONTROL: + app->m_specific->m_input_flags &= ~kbd_ctrl; + break; + + case VK_SHIFT: + app->m_specific->m_input_flags &= ~kbd_shift; + break; + } + break; + + //-------------------------------------------------------------------- + case WM_CHAR: + case WM_SYSCHAR: + if(app->m_specific->m_last_translated_key == 0) + { + app->on_key(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + wParam, + app->m_specific->m_input_flags); + } + break; + + //-------------------------------------------------------------------- + case WM_PAINT: + paintDC = ::BeginPaint(hWnd, &ps); + app->m_specific->m_current_dc = paintDC; + if(app->m_specific->m_redraw_flag) + { + app->on_draw(); + app->m_specific->m_redraw_flag = false; + } + app->m_specific->display_pmap(paintDC, &app->rbuf_window()); + app->on_post_draw(paintDC); + app->m_specific->m_current_dc = 0; + ::EndPaint(hWnd, &ps); + break; + + //-------------------------------------------------------------------- + case WM_COMMAND: + break; + + //-------------------------------------------------------------------- + case WM_DESTROY: + ::PostQuitMessage(0); + break; + + //-------------------------------------------------------------------- + default: + ret = ::DefWindowProc(hWnd, msg, wParam, lParam); + break; + } + app->m_specific->m_current_dc = 0; + ::ReleaseDC(app->m_specific->m_hwnd, dc); + return ret; + } + + + //------------------------------------------------------------------------ + void platform_support::message(const char* msg) + { + ::MessageBox(m_specific->m_hwnd, msg, "AGG Message", MB_OK); + } + + + //------------------------------------------------------------------------ + bool platform_support::init(unsigned width, unsigned height, unsigned flags) + { + if(m_specific->m_sys_format == pix_format_undefined) + { + return false; + } + + m_window_flags = flags; + + int wflags = CS_OWNDC | CS_VREDRAW | CS_HREDRAW; + + WNDCLASS wc; + wc.lpszClassName = "AGGAppClass"; + wc.lpfnWndProc = window_proc; + wc.style = wflags; + wc.hInstance = g_windows_instance; + wc.hIcon = LoadIcon(0, IDI_APPLICATION); + wc.hCursor = LoadCursor(0, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wc.lpszMenuName = "AGGAppMenu"; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + ::RegisterClass(&wc); + + wflags = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; + + if(m_window_flags & window_resize) + { + wflags |= WS_THICKFRAME | WS_MAXIMIZEBOX; + } + + m_specific->m_hwnd = ::CreateWindow("AGGAppClass", + m_caption, + wflags, + 100, + 100, + width, + height, + 0, + 0, + g_windows_instance, + 0); + + if(m_specific->m_hwnd == 0) + { + return false; + } + + + RECT rct; + ::GetClientRect(m_specific->m_hwnd, &rct); + + ::MoveWindow(m_specific->m_hwnd, // handle to window + 100, // horizontal position + 100, // vertical position + width + (width - (rct.right - rct.left)), + height + (height - (rct.bottom - rct.top)), + FALSE); + + ::SetWindowLong(m_specific->m_hwnd, GWL_USERDATA, (LONG)this); + m_specific->create_pmap(width, height, &m_rbuf_window); + m_initial_width = width; + m_initial_height = height; + on_init(); + m_specific->m_redraw_flag = true; + ::ShowWindow(m_specific->m_hwnd, g_windows_cmd_show); + return true; + } + + + + //------------------------------------------------------------------------ + int platform_support::run() + { + MSG msg; + + for(;;) + { + if(m_wait_mode) + { + if(!::GetMessage(&msg, 0, 0, 0)) + { + break; + } + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + else + { + if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { + ::TranslateMessage(&msg); + if(msg.message == WM_QUIT) + { + break; + } + ::DispatchMessage(&msg); + } + else + { + on_idle(); + } + } + } + return (int)msg.wParam; + } + + + //------------------------------------------------------------------------ + const char* platform_support::img_ext() const { return ".bmp"; } + + + //------------------------------------------------------------------------ + const char* platform_support::full_file_name(const char* file_name) + { + return file_name; + } + + //------------------------------------------------------------------------ + bool platform_support::load_img(unsigned idx, const char* file) + { + if(idx < max_images) + { + char fn[1024]; + strcpy(fn, file); + int len = strlen(fn); + if(len < 4 || stricmp(fn + len - 4, ".BMP") != 0) + { + strcat(fn, ".bmp"); + } + return m_specific->load_pmap(fn, idx, &m_rbuf_img[idx]); + } + return true; + } + + + + //------------------------------------------------------------------------ + bool platform_support::save_img(unsigned idx, const char* file) + { + if(idx < max_images) + { + char fn[1024]; + strcpy(fn, file); + int len = strlen(fn); + if(len < 4 || stricmp(fn + len - 4, ".BMP") != 0) + { + strcat(fn, ".bmp"); + } + return m_specific->save_pmap(fn, idx, &m_rbuf_img[idx]); + } + return true; + } + + + + //------------------------------------------------------------------------ + bool platform_support::create_img(unsigned idx, unsigned width, unsigned height) + { + if(idx < max_images) + { + if(width == 0) width = m_specific->m_pmap_window.width(); + if(height == 0) height = m_specific->m_pmap_window.height(); + m_specific->m_pmap_img[idx].create(width, height, org_e(m_specific->m_bpp)); + m_rbuf_img[idx].attach(m_specific->m_pmap_img[idx].buf(), + m_specific->m_pmap_img[idx].width(), + m_specific->m_pmap_img[idx].height(), + m_flip_y ? + m_specific->m_pmap_img[idx].stride() : + -m_specific->m_pmap_img[idx].stride()); + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + void platform_support::force_redraw() + { + m_specific->m_redraw_flag = true; + ::InvalidateRect(m_specific->m_hwnd, 0, FALSE); + } + + + + //------------------------------------------------------------------------ + void platform_support::update_window() + { + HDC dc = ::GetDC(m_specific->m_hwnd); + m_specific->display_pmap(dc, &m_rbuf_window); + ::ReleaseDC(m_specific->m_hwnd, dc); + } + + + //------------------------------------------------------------------------ + void platform_support::on_init() {} + void platform_support::on_resize(int sx, int sy) {} + void platform_support::on_idle() {} + void platform_support::on_mouse_move(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {} + void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {} + void platform_support::on_ctrl_change() {} + void platform_support::on_draw() {} + void platform_support::on_post_draw(void* raw_handler) {} +} + + + + +namespace agg +{ + // That's ridiculous. I have to parse the command line by myself + // because Windows doesn't provide a method of getting the command + // line arguments in a form of argc, argv. Of course, there's + // CommandLineToArgv() but first, it returns Unicode that I don't + // need to deal with, but most of all, it's not compatible with Win98. + //----------------------------------------------------------------------- + class tokenizer + { + public: + enum sep_flag + { + single, + multiple, + whole_str + }; + + struct token + { + const char* ptr; + unsigned len; + }; + + public: + tokenizer(const char* sep, + const char* trim=0, + const char* quote="\"", + char mask_chr='\\', + sep_flag sf=multiple); + + void set_str(const char* str); + token next_token(); + + private: + int check_chr(const char *str, char chr); + + private: + const char* m_src_string; + int m_start; + const char* m_sep; + const char* m_trim; + const char* m_quote; + char m_mask_chr; + unsigned m_sep_len; + sep_flag m_sep_flag; + }; + + + + //----------------------------------------------------------------------- + inline void tokenizer::set_str(const char* str) + { + m_src_string = str; + m_start = 0; + } + + + //----------------------------------------------------------------------- + inline int tokenizer::check_chr(const char *str, char chr) + { + return int(strchr(str, chr)); + } + + + //----------------------------------------------------------------------- + tokenizer::tokenizer(const char* sep, + const char* trim, + const char* quote, + char mask_chr, + sep_flag sf) : + m_src_string(0), + m_start(0), + m_sep(sep), + m_trim(trim), + m_quote(quote), + m_mask_chr(mask_chr), + m_sep_len(sep ? strlen(sep) : 0), + m_sep_flag(sep ? sf : single) + { + } + + + //----------------------------------------------------------------------- + tokenizer::token tokenizer::next_token() + { + unsigned count = 0; + char quote_chr = 0; + token tok; + + tok.ptr = 0; + tok.len = 0; + if(m_src_string == 0 || m_start == -1) return tok; + + register const char *pstr = m_src_string + m_start; + + if(*pstr == 0) + { + m_start = -1; + return tok; + } + + int sep_len = 1; + if(m_sep_flag == whole_str) sep_len = m_sep_len; + + if(m_sep_flag == multiple) + { + //Pass all the separator symbols at the begin of the string + while(*pstr && check_chr(m_sep, *pstr)) + { + ++pstr; + ++m_start; + } + } + + if(*pstr == 0) + { + m_start = -1; + return tok; + } + + for(count = 0;; ++count) + { + char c = *pstr; + int found = 0; + + //We are outside of qotation: find one of separator symbols + if(quote_chr == 0) + { + if(sep_len == 1) + { + found = check_chr(m_sep, c); + } + else + { + found = strncmp(m_sep, pstr, m_sep_len) == 0; + } + } + + ++pstr; + + if(c == 0 || found) + { + if(m_trim) + { + while(count && + check_chr(m_trim, m_src_string[m_start])) + { + ++m_start; + --count; + } + + while(count && + check_chr(m_trim, m_src_string[m_start + count - 1])) + { + --count; + } + } + + tok.ptr = m_src_string + m_start; + tok.len = count; + + //Next time it will be the next separator character + //But we must check, whether it is NOT the end of the string. + m_start += count; + if(c) + { + m_start += sep_len; + if(m_sep_flag == multiple) + { + //Pass all the separator symbols + //after the end of the string + while(check_chr(m_sep, m_src_string[m_start])) + { + ++m_start; + } + } + } + break; + } + + //Switch quote. If it is not a quote yet, try to check any of + //quote symbols. Otherwise quote must be finished with quote_symb + if(quote_chr == 0) + { + if(check_chr(m_quote, c)) + { + quote_chr = c; + continue; + } + } + else + { + //We are inside quote: pass all the mask symbols + if(m_mask_chr && c == m_mask_chr) + { + if(*pstr) + { + ++count; + ++pstr; + } + continue; + } + if(c == quote_chr) + { + quote_chr = 0; + continue; + } + } + } + return tok; + } + + +} + + + +//---------------------------------------------------------------------------- +int agg_main(int argc, char* argv[]); + + + +//---------------------------------------------------------------------------- +int PASCAL WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpszCmdLine, + int nCmdShow) +{ + agg::g_windows_instance = hInstance; + agg::g_windows_cmd_show = nCmdShow; + + char* argv_str = new char [strlen(lpszCmdLine) + 3]; + char* argv_ptr = argv_str; + + char* argv[64]; + memset(argv, 0, sizeof(argv)); + + agg::tokenizer cmd_line(" ", "\"' ", "\"'", '\\', agg::tokenizer::multiple); + cmd_line.set_str(lpszCmdLine); + + int argc = 0; + argv[argc++] = argv_ptr; + *argv_ptr++ = 0; + + while(argc < 64) + { + agg::tokenizer::token tok = cmd_line.next_token(); + if(tok.ptr == 0) break; + if(tok.len) + { + memcpy(argv_ptr, tok.ptr, tok.len); + argv[argc++] = argv_ptr; + argv_ptr += tok.len; + *argv_ptr++ = 0; + } + } + + int ret = agg_main(argc, argv); + delete [] argv_str; + + return ret; +} + + + + diff --git a/jni/desmume/src/android/agg/src/platform/win32/agg_win32_bmp.cpp b/jni/desmume/src/android/agg/src/platform/win32/agg_win32_bmp.cpp new file mode 100755 index 0000000..9a03d43 --- /dev/null +++ b/jni/desmume/src/android/agg/src/platform/win32/agg_win32_bmp.cpp @@ -0,0 +1,625 @@ +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// Contact: mcseemagg@yahoo.com +//---------------------------------------------------------------------------- +// +// class pixel_map +// +//---------------------------------------------------------------------------- + +#include "platform/win32/agg_win32_bmp.h" +#include "agg_basics.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + pixel_map::~pixel_map() + { + destroy(); + } + + + //------------------------------------------------------------------------ + pixel_map::pixel_map() : + m_bmp(0), + m_buf(0), + m_bpp(0), + m_is_internal(false), + m_img_size(0), + m_full_size(0) + + { + } + + + //------------------------------------------------------------------------ + void pixel_map::destroy() + { + if(m_bmp && m_is_internal) delete [] (unsigned char*)m_bmp; + m_bmp = 0; + m_is_internal = false; + m_buf = 0; + } + + + //------------------------------------------------------------------------ + void pixel_map::create(unsigned width, + unsigned height, + org_e org, + unsigned clear_val) + { + destroy(); + if(width == 0) width = 1; + if(height == 0) height = 1; + m_bpp = org; + create_from_bmp(create_bitmap_info(width, height, m_bpp)); + create_gray_scale_palette(m_bmp); + m_is_internal = true; + if(clear_val <= 255) + { + memset(m_buf, clear_val, m_img_size); + } + } + + + //------------------------------------------------------------------------ + HBITMAP pixel_map::create_dib_section(HDC h_dc, + unsigned width, + unsigned height, + org_e org, + unsigned clear_val) + { + destroy(); + if(width == 0) width = 1; + if(height == 0) height = 1; + m_bpp = org; + HBITMAP h_bitmap = create_dib_section_from_args(h_dc, width, height, m_bpp); + create_gray_scale_palette(m_bmp); + m_is_internal = true; + if(clear_val <= 255) + { + memset(m_buf, clear_val, m_img_size); + } + return h_bitmap; + } + + + + //------------------------------------------------------------------------ + void pixel_map::clear(unsigned clear_val) + { + if(m_buf) memset(m_buf, clear_val, m_img_size); + } + + + //------------------------------------------------------------------------ + void pixel_map::attach_to_bmp(BITMAPINFO *bmp) + { + if(bmp) + { + destroy(); + create_from_bmp(bmp); + m_is_internal = false; + } + } + + + + //static + //------------------------------------------------------------------------ + unsigned pixel_map::calc_full_size(BITMAPINFO *bmp) + { + if(bmp == 0) return 0; + + return sizeof(BITMAPINFOHEADER) + + sizeof(RGBQUAD) * calc_palette_size(bmp) + + bmp->bmiHeader.biSizeImage; + } + + //static + //------------------------------------------------------------------------ + unsigned pixel_map::calc_header_size(BITMAPINFO *bmp) + { + if(bmp == 0) return 0; + return sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * calc_palette_size(bmp); + } + + + //static + //------------------------------------------------------------------------ + unsigned pixel_map::calc_palette_size(unsigned clr_used, unsigned bits_per_pixel) + { + int palette_size = 0; + + if(bits_per_pixel <= 8) + { + palette_size = clr_used; + if(palette_size == 0) + { + palette_size = 1 << bits_per_pixel; + } + } + return palette_size; + } + + //static + //------------------------------------------------------------------------ + unsigned pixel_map::calc_palette_size(BITMAPINFO *bmp) + { + if(bmp == 0) return 0; + return calc_palette_size(bmp->bmiHeader.biClrUsed, bmp->bmiHeader.biBitCount); + } + + + //static + //------------------------------------------------------------------------ + unsigned char * pixel_map::calc_img_ptr(BITMAPINFO *bmp) + { + if(bmp == 0) return 0; + return ((unsigned char*)bmp) + calc_header_size(bmp); + } + + //static + //------------------------------------------------------------------------ + BITMAPINFO* pixel_map::create_bitmap_info(unsigned width, + unsigned height, + unsigned bits_per_pixel) + { + unsigned line_len = calc_row_len(width, bits_per_pixel); + unsigned img_size = line_len * height; + unsigned rgb_size = calc_palette_size(0, bits_per_pixel) * sizeof(RGBQUAD); + unsigned full_size = sizeof(BITMAPINFOHEADER) + rgb_size + img_size; + + BITMAPINFO *bmp = (BITMAPINFO *) new unsigned char[full_size]; + + bmp->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmp->bmiHeader.biWidth = width; + bmp->bmiHeader.biHeight = height; + bmp->bmiHeader.biPlanes = 1; + bmp->bmiHeader.biBitCount = (unsigned short)bits_per_pixel; + bmp->bmiHeader.biCompression = 0; + bmp->bmiHeader.biSizeImage = img_size; + bmp->bmiHeader.biXPelsPerMeter = 0; + bmp->bmiHeader.biYPelsPerMeter = 0; + bmp->bmiHeader.biClrUsed = 0; + bmp->bmiHeader.biClrImportant = 0; + + return bmp; + } + + + //static + //------------------------------------------------------------------------ + void pixel_map::create_gray_scale_palette(BITMAPINFO *bmp) + { + if(bmp == 0) return; + + unsigned rgb_size = calc_palette_size(bmp); + RGBQUAD *rgb = (RGBQUAD*)(((unsigned char*)bmp) + sizeof(BITMAPINFOHEADER)); + unsigned brightness; + unsigned i; + + for(i = 0; i < rgb_size; i++) + { + brightness = (255 * i) / (rgb_size - 1); + rgb->rgbBlue = + rgb->rgbGreen = + rgb->rgbRed = (unsigned char)brightness; + rgb->rgbReserved = 0; + rgb++; + } + } + + + + //static + //------------------------------------------------------------------------ + unsigned pixel_map::calc_row_len(unsigned width, unsigned bits_per_pixel) + { + unsigned n = width; + unsigned k; + + switch(bits_per_pixel) + { + case 1: k = n; + n = n >> 3; + if(k & 7) n++; + break; + + case 4: k = n; + n = n >> 1; + if(k & 3) n++; + break; + + case 8: + break; + + case 16: n *= 2; + break; + + case 24: n *= 3; + break; + + case 32: n *= 4; + break; + + case 48: n *= 6; + break; + + case 64: n *= 8; + break; + + default: n = 0; + break; + } + return ((n + 3) >> 2) << 2; + } + + + + + + //------------------------------------------------------------------------ + void pixel_map::draw(HDC h_dc, const RECT *device_rect, const RECT *bmp_rect) const + { + if(m_bmp == 0 || m_buf == 0) return; + + unsigned bmp_x = 0; + unsigned bmp_y = 0; + unsigned bmp_width = m_bmp->bmiHeader.biWidth; + unsigned bmp_height = m_bmp->bmiHeader.biHeight; + unsigned dvc_x = 0; + unsigned dvc_y = 0; + unsigned dvc_width = m_bmp->bmiHeader.biWidth; + unsigned dvc_height = m_bmp->bmiHeader.biHeight; + + if(bmp_rect) + { + bmp_x = bmp_rect->left; + bmp_y = bmp_rect->top; + bmp_width = bmp_rect->right - bmp_rect->left; + bmp_height = bmp_rect->bottom - bmp_rect->top; + } + + dvc_x = bmp_x; + dvc_y = bmp_y; + dvc_width = bmp_width; + dvc_height = bmp_height; + + if(device_rect) + { + dvc_x = device_rect->left; + dvc_y = device_rect->top; + dvc_width = device_rect->right - device_rect->left; + dvc_height = device_rect->bottom - device_rect->top; + } + + if(dvc_width != bmp_width || dvc_height != bmp_height) + { + ::SetStretchBltMode(h_dc, COLORONCOLOR); + ::StretchDIBits( + h_dc, // handle of device context + dvc_x, // x-coordinate of upper-left corner of source rect. + dvc_y, // y-coordinate of upper-left corner of source rect. + dvc_width, // width of source rectangle + dvc_height, // height of source rectangle + bmp_x, + bmp_y, // x, y -coordinates of upper-left corner of dest. rect. + bmp_width, // width of destination rectangle + bmp_height, // height of destination rectangle + m_buf, // address of bitmap bits + m_bmp, // address of bitmap data + DIB_RGB_COLORS, // usage + SRCCOPY // raster operation code + ); + } + else + { + ::SetDIBitsToDevice( + h_dc, // handle to device context + dvc_x, // x-coordinate of upper-left corner of + dvc_y, // y-coordinate of upper-left corner of + dvc_width, // source rectangle width + dvc_height, // source rectangle height + bmp_x, // x-coordinate of lower-left corner of + bmp_y, // y-coordinate of lower-left corner of + 0, // first scan line in array + bmp_height, // number of scan lines + m_buf, // address of array with DIB bits + m_bmp, // address of structure with bitmap info. + DIB_RGB_COLORS // RGB or palette indexes + ); + } + } + + + //------------------------------------------------------------------------ + void pixel_map::draw(HDC h_dc, int x, int y, double scale) const + { + if(m_bmp == 0 || m_buf == 0) return; + + unsigned width = unsigned(m_bmp->bmiHeader.biWidth * scale); + unsigned height = unsigned(m_bmp->bmiHeader.biHeight * scale); + RECT rect; + rect.left = x; + rect.top = y; + rect.right = x + width; + rect.bottom = y + height; + draw(h_dc, &rect); + } + + + + + //------------------------------------------------------------------------ + void pixel_map::blend(HDC h_dc, const RECT *device_rect, const RECT *bmp_rect) const + { +#if !defined(AGG_BMP_ALPHA_BLEND) + draw(h_dc, device_rect, bmp_rect); + return; +#else + if(m_bpp != 32) + { + draw(h_dc, device_rect, bmp_rect); + return; + } + + if(m_bmp == 0 || m_buf == 0) return; + + unsigned bmp_x = 0; + unsigned bmp_y = 0; + unsigned bmp_width = m_bmp->bmiHeader.biWidth; + unsigned bmp_height = m_bmp->bmiHeader.biHeight; + unsigned dvc_x = 0; + unsigned dvc_y = 0; + unsigned dvc_width = m_bmp->bmiHeader.biWidth; + unsigned dvc_height = m_bmp->bmiHeader.biHeight; + + if(bmp_rect) + { + bmp_x = bmp_rect->left; + bmp_y = bmp_rect->top; + bmp_width = bmp_rect->right - bmp_rect->left; + bmp_height = bmp_rect->bottom - bmp_rect->top; + } + + dvc_x = bmp_x; + dvc_y = bmp_y; + dvc_width = bmp_width; + dvc_height = bmp_height; + + if(device_rect) + { + dvc_x = device_rect->left; + dvc_y = device_rect->top; + dvc_width = device_rect->right - device_rect->left; + dvc_height = device_rect->bottom - device_rect->top; + } + + HDC mem_dc = ::CreateCompatibleDC(h_dc); + void* buf = 0; + HBITMAP bmp = ::CreateDIBSection( + mem_dc, + m_bmp, + DIB_RGB_COLORS, + &buf, + 0, + 0 + ); + memcpy(buf, m_buf, m_bmp->bmiHeader.biSizeImage); + + HBITMAP temp = (HBITMAP)::SelectObject(mem_dc, bmp); + + BLENDFUNCTION blend; + blend.BlendOp = AC_SRC_OVER; + blend.BlendFlags = 0; + +#if defined(AC_SRC_ALPHA) + blend.AlphaFormat = AC_SRC_ALPHA; +//#elif defined(AC_SRC_NO_PREMULT_ALPHA) +// blend.AlphaFormat = AC_SRC_NO_PREMULT_ALPHA; +#else +#error "No appropriate constant for alpha format. Check version of wingdi.h, There must be AC_SRC_ALPHA or AC_SRC_NO_PREMULT_ALPHA" +#endif + + blend.SourceConstantAlpha = 255; + ::AlphaBlend( + h_dc, + dvc_x, + dvc_y, + dvc_width, + dvc_height, + mem_dc, + bmp_x, + bmp_y, + bmp_width, + bmp_height, + blend + ); + + ::SelectObject(mem_dc, temp); + ::DeleteObject(bmp); + ::DeleteObject(mem_dc); +#endif //defined(AGG_BMP_ALPHA_BLEND) + } + + + //------------------------------------------------------------------------ + void pixel_map::blend(HDC h_dc, int x, int y, double scale) const + { + if(m_bmp == 0 || m_buf == 0) return; + unsigned width = unsigned(m_bmp->bmiHeader.biWidth * scale); + unsigned height = unsigned(m_bmp->bmiHeader.biHeight * scale); + RECT rect; + rect.left = x; + rect.top = y; + rect.right = x + width; + rect.bottom = y + height; + blend(h_dc, &rect); + } + + + //------------------------------------------------------------------------ + bool pixel_map::load_from_bmp(FILE *fd) + { + BITMAPFILEHEADER bmf; + BITMAPINFO *bmi = 0; + unsigned bmp_size; + + fread(&bmf, sizeof(bmf), 1, fd); + if(bmf.bfType != 0x4D42) goto bmperr; + + bmp_size = bmf.bfSize - sizeof(BITMAPFILEHEADER); + + bmi = (BITMAPINFO*) new unsigned char [bmp_size]; + if(fread(bmi, 1, bmp_size, fd) != bmp_size) goto bmperr; + destroy(); + m_bpp = bmi->bmiHeader.biBitCount; + create_from_bmp(bmi); + m_is_internal = 1; + return true; + + bmperr: + if(bmi) delete [] (unsigned char*) bmi; + return false; + } + + + + //------------------------------------------------------------------------ + bool pixel_map::load_from_bmp(const char *filename) + { + FILE *fd = fopen(filename, "rb"); + bool ret = false; + if(fd) + { + ret = load_from_bmp(fd); + fclose(fd); + } + return ret; + } + + + + //------------------------------------------------------------------------ + bool pixel_map::save_as_bmp(FILE *fd) const + { + if(m_bmp == 0) return 0; + + BITMAPFILEHEADER bmf; + + bmf.bfType = 0x4D42; + bmf.bfOffBits = calc_header_size(m_bmp) + sizeof(bmf); + bmf.bfSize = bmf.bfOffBits + m_img_size; + bmf.bfReserved1 = 0; + bmf.bfReserved2 = 0; + + fwrite(&bmf, sizeof(bmf), 1, fd); + fwrite(m_bmp, m_full_size, 1, fd); + return true; + } + + + + //------------------------------------------------------------------------ + bool pixel_map::save_as_bmp(const char *filename) const + { + FILE *fd = fopen(filename, "wb"); + bool ret = false; + if(fd) + { + ret = save_as_bmp(fd); + fclose(fd); + } + return ret; + } + + + //------------------------------------------------------------------------ + unsigned char* pixel_map::buf() + { + return m_buf; + } + + //------------------------------------------------------------------------ + unsigned pixel_map::width() const + { + return m_bmp->bmiHeader.biWidth; + } + + //------------------------------------------------------------------------ + unsigned pixel_map::height() const + { + return m_bmp->bmiHeader.biHeight; + } + + //------------------------------------------------------------------------ + int pixel_map::stride() const + { + return calc_row_len(m_bmp->bmiHeader.biWidth, + m_bmp->bmiHeader.biBitCount); + } + + + //private + //------------------------------------------------------------------------ + void pixel_map::create_from_bmp(BITMAPINFO *bmp) + { + if(bmp) + { + m_img_size = calc_row_len(bmp->bmiHeader.biWidth, + bmp->bmiHeader.biBitCount) * + bmp->bmiHeader.biHeight; + + m_full_size = calc_full_size(bmp); + m_bmp = bmp; + m_buf = calc_img_ptr(bmp); + } + } + + + //private + //------------------------------------------------------------------------ + HBITMAP pixel_map::create_dib_section_from_args(HDC h_dc, + unsigned width, + unsigned height, + unsigned bits_per_pixel) + { + unsigned line_len = calc_row_len(width, bits_per_pixel); + unsigned img_size = line_len * height; + unsigned rgb_size = calc_palette_size(0, bits_per_pixel) * sizeof(RGBQUAD); + unsigned full_size = sizeof(BITMAPINFOHEADER) + rgb_size; + + BITMAPINFO *bmp = (BITMAPINFO *) new unsigned char[full_size]; + + bmp->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmp->bmiHeader.biWidth = width; + bmp->bmiHeader.biHeight = height; + bmp->bmiHeader.biPlanes = 1; + bmp->bmiHeader.biBitCount = (unsigned short)bits_per_pixel; + bmp->bmiHeader.biCompression = 0; + bmp->bmiHeader.biSizeImage = img_size; + bmp->bmiHeader.biXPelsPerMeter = 0; + bmp->bmiHeader.biYPelsPerMeter = 0; + bmp->bmiHeader.biClrUsed = 0; + bmp->bmiHeader.biClrImportant = 0; + + void* img_ptr = 0; + HBITMAP h_bitmap = ::CreateDIBSection(h_dc, bmp, DIB_RGB_COLORS, &img_ptr, NULL, 0); + + if(img_ptr) + { + m_img_size = calc_row_len(width, bits_per_pixel) * height; + m_full_size = 0; + m_bmp = bmp; + m_buf = (unsigned char *) img_ptr; + } + + return h_bitmap; + } +} + + + diff --git a/jni/desmume/src/android/agg/src/readme b/jni/desmume/src/android/agg/src/readme new file mode 100755 index 0000000..232260e --- /dev/null +++ b/jni/desmume/src/android/agg/src/readme @@ -0,0 +1,5 @@ +Use automake to build the library. + +If automake is not available you still can use the old make. +There is a very simple Makefile that can be used. Note that +if you use automake it will overwrite Makefile. diff --git a/jni/desmume/src/android/main.cpp b/jni/desmume/src/android/main.cpp new file mode 100755 index 0000000..710fee6 --- /dev/null +++ b/jni/desmume/src/android/main.cpp @@ -0,0 +1,622 @@ +/* + Copyright (C) 2012 Jeffrey Quesnelle + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <jni.h> +#include <errno.h> + +#include <EGL/egl.h> +#include <GLES/gl.h> +#include <android/sensor.h> +#include <android/bitmap.h> + +#include "main.h" +#include "../OGLRender.h" +#include "../rasterize.h" +#include "../SPU.h" +#include "../debug.h" +#include "../NDSSystem.h" +#include "../path.h" +#include "../GPU_OSD.h" +#include "../addons.h" +#include "../slot1.h" +#include "../saves.h" +#include "throttle.h" +#include "video.h" +#ifdef HAVE_NEON +#include "neontest.h" +#endif + +#define JNI(X,...) Java_com_opendoorstudios_ds4droid_DeSmuME_##X(JNIEnv* env, jclass* clazz, __VA_ARGS__) +#define JNI_NOARGS(X) Java_com_opendoorstudios_ds4droid_DeSmuME_##X(JNIEnv* env, jclass* clazz) + + + +GPU3DInterface *core3DList[] = { + &gpu3DNull, + &gpu3Dgl, + &gpu3DRasterize, + NULL +}; + +SoundInterface_struct *SNDCoreList[] = { + &SNDDummy, + NULL +}; + +int scanline_filter_a = 2, scanline_filter_b = 4; +volatile bool execute = false; +volatile bool paused = true; +volatile BOOL pausedByMinimize = FALSE; +bool autoframeskipenab=1; +int frameskiprate=1; +int lastskiprate=0; +int emu_paused = 0; +bool frameAdvance = false; +bool continuousframeAdvancing = false; +bool staterewindingenabled = false; +struct NDS_fw_config_data fw_config; +bool FrameLimit = true; +AndroidBitmapInfo bitmapInfo; +EGLSurface surface; +EGLContext context; +const char* IniName = NULL; + +extern "C" { + +void logCallback(const Logger& logger, const char* message) +{ + if(message) + LOGI("%s", message); +} + +struct MainLoopData +{ + u64 freq; + int framestoskip; + int framesskipped; + int skipnextframe; + u64 lastticks; + u64 curticks; + u64 diffticks; + u64 fpsticks; + int fps; + int fps3d; + int fpsframecount; + int toolframecount; +} mainLoopData = {0}; + +VideoInfo video; + +/** + * Initialize an EGL context for the current display. + */ +static bool android_opengl_init() { + //call back into java here? + + const EGLint attribs[] = { + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_DEPTH_SIZE, 16, + EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, + EGL_RENDERABLE_TYPE, 1, + EGL_NONE + }; + EGLint w, h, dummy, format; + EGLint numConfigs; + EGLConfig config; + EGLSurface surface; + EGLContext context; + + EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + + eglInitialize(display, 0, 0); + + /* Here, the application chooses the configuration it desires. In this + * sample, we have a very simplified selection process, where we pick + * the first EGLConfig that matches our criteria */ + eglChooseConfig(display, attribs, &config, 1, &numConfigs); + + const EGLint surfaceAttribs[] = { + EGL_WIDTH, 256, + EGL_HEIGHT, 384, + EGL_LARGEST_PBUFFER, 0, + EGL_NONE + }; + + surface = eglCreatePbufferSurface(display, config, surfaceAttribs); + context = eglCreateContext(display, config, NULL, NULL); + + if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) { + LOGW("Unable to eglMakeCurrent"); + return false; + } + + INFO("Created OpenGL"); + return true; +} + + + +void nds4droid_displayFrame() +{ +} + +static void DoDisplay_DrawHud() +{ + osd->update(); + DrawHUD(); + osd->clear(); +} + +float triangles[] = { + 0, 0, 0, + 0, 200, 0, + 100, 200, 0, +}; + +void JNI(draw, jobject bitmap) +{ + video.srcBuffer = (u8*)GPU_screen; + + //convert pixel format to 32bpp for compositing + //why do we do this over and over? well, we are compositing to + //filteredbuffer32bpp, and it needs to get refreshed each frame.. + const int size = video.size(); + u16* src = (u16*)video.srcBuffer; + for(int i=0;i<size;i++) + video.buffer[i] = RGB15TO32(src[i], 0xFF); + + + aggDraw.hud->attach((u8*)video.buffer, 256, 384, 1024); + DoDisplay_DrawHud(); + + + video.filter(); + + //here the magic happens + void* pixels = NULL; + if(AndroidBitmap_lockPixels(env,bitmap,&pixels) >= 0) + { + u32* src = (u32*)video.finalBuffer(); + u8* dest = (u8*)pixels; + int height = video.height; + int width = video.width; + int stride = bitmapInfo.stride; + for(int y = 0 ; y < height ; ++y) + { + memcpy(dest, &src[y * width], width * sizeof(u32)); + dest += bitmapInfo.stride; + } + AndroidBitmap_unlockPixels(env, bitmap); + } +} + +bool NDS_Pause(bool showMsg = true) +{ + if(paused) return false; + + emu_halt(); + paused = TRUE; + SPU_Pause(1); + while (!paused) {} + if (showMsg) INFO("Emulation paused\n"); + + return true; +} + +void NDS_UnPause(bool showMsg = true) +{ + if (/*romloaded &&*/ paused) + { + paused = FALSE; + pausedByMinimize = FALSE; + execute = TRUE; + SPU_Pause(0); + if (showMsg) INFO("Emulation unpaused\n"); + + } +} + +static void nds4droid_throttle(bool allowSleep = true, int forceFrameSkip = -1) +{ + int skipRate = (forceFrameSkip < 0) ? frameskiprate : forceFrameSkip; + int ffSkipRate = (forceFrameSkip < 0) ? 9 : forceFrameSkip; + + if(lastskiprate != skipRate) + { + lastskiprate = skipRate; + mainLoopData.framestoskip = 0; // otherwise switches to lower frameskip rates will lag behind + } + + if(!mainLoopData.skipnextframe || forceFrameSkip == 0 || frameAdvance || (continuousframeAdvancing && !FastForward)) + { + mainLoopData.framesskipped = 0; + + if (mainLoopData.framestoskip > 0) + mainLoopData.skipnextframe = 1; + } + else + { + mainLoopData.framestoskip--; + + if (mainLoopData.framestoskip < 1) + mainLoopData.skipnextframe = 0; + else + mainLoopData.skipnextframe = 1; + + mainLoopData.framesskipped++; + + NDS_SkipNextFrame(); + } + + if(FastForward) + { + if(mainLoopData.framesskipped < ffSkipRate) + { + mainLoopData.skipnextframe = 1; + mainLoopData.framestoskip = 1; + } + if (mainLoopData.framestoskip < 1) + mainLoopData.framestoskip += ffSkipRate; + } + else if((/*autoframeskipenab && frameskiprate ||*/ FrameLimit) && allowSleep) + { + SpeedThrottle(); + } + + if (autoframeskipenab && frameskiprate) + { + if(!frameAdvance && !continuousframeAdvancing) + { + AutoFrameSkip_NextFrame(); + if (mainLoopData.framestoskip < 1) + mainLoopData.framestoskip += AutoFrameSkip_GetSkipAmount(0,skipRate); + } + } + else + { + if (mainLoopData.framestoskip < 1) + mainLoopData.framestoskip += skipRate; + } + + if (frameAdvance && allowSleep) + { + frameAdvance = false; + emu_halt(); + SPU_Pause(1); + } + if(execute && emu_paused && !frameAdvance) + { + // safety net against running out of control in case this ever happens. + NDS_UnPause(); NDS_Pause(); + } + + //ServiceDisplayThreadInvocations(); +} + +void nds4droid_user() +{ + const int kFramesPerToolUpdate = 1; + + Hud.fps = mainLoopData.fps; + Hud.fps3d = mainLoopData.fps3d; + + //nds4droid_display(); + + gfx3d.frameCtrRaw++; + if(gfx3d.frameCtrRaw == 60) { + mainLoopData.fps3d = gfx3d.frameCtr; + gfx3d.frameCtrRaw = 0; + gfx3d.frameCtr = 0; + } + + + mainLoopData.toolframecount++; + if (mainLoopData.toolframecount == kFramesPerToolUpdate) + { + //if(SoundView_IsOpened()) SoundView_Refresh(); + //RefreshAllToolWindows(); + + mainLoopData.toolframecount = 0; + } + + //Update_RAM_Search(); // Update_RAM_Watch() is also called. + + mainLoopData.fpsframecount++; + mainLoopData.curticks = GetTickCount(); + bool oneSecond = mainLoopData.curticks >= mainLoopData.fpsticks + mainLoopData.freq; + if(oneSecond) // TODO: print fps on screen in DDraw + { + mainLoopData.fps = mainLoopData.fpsframecount; + mainLoopData.fpsframecount = 0; + mainLoopData.fpsticks = GetTickCount(); + } + + if(nds.idleFrameCounter==0 || oneSecond) + { + //calculate a 16 frame arm9 load average + for(int cpu=0;cpu<2;cpu++) + { + int load = 0; + //printf("%d: ",cpu); + for(int i=0;i<16;i++) + { + //blend together a few frames to keep low-framerate games from having a jittering load average + //(they will tend to work 100% for a frame and then sleep for a while) + //4 frames should handle even the slowest of games + s32 sample = + nds.runCycleCollector[cpu][(i+0+nds.idleFrameCounter)&15] + + nds.runCycleCollector[cpu][(i+1+nds.idleFrameCounter)&15] + + nds.runCycleCollector[cpu][(i+2+nds.idleFrameCounter)&15] + + nds.runCycleCollector[cpu][(i+3+nds.idleFrameCounter)&15]; + sample /= 4; + load = load/8 + sample*7/8; + } + //printf("\n"); + load = std::min(100,std::max(0,(int)(load*100/1120380))); + Hud.cpuload[cpu] = load; + } + } + + Hud.cpuloopIterationCount = nds.cpuloopIterationCount; +} + +void nds4droid_core() +{ + NDS_beginProcessingInput(); + NDS_endProcessingInput(); + NDS_exec<false>(); + //disable sound + //SPU_Emulate_user(); + +} + + + +void nds4droid_unpause() +{ + if(!execute) NDS_Pause(false); + if (emu_paused && autoframeskipenab && frameskiprate) AutoFrameSkip_IgnorePreviousDelay(); + NDS_UnPause(); +} + +bool nds4droid_loadrom(const char* path) +{ + if(NDS_LoadROM(path, path) >= 0) + { + INFO("Loading %s was successful\n",path); + nds4droid_unpause(); + if (autoframeskipenab && frameskiprate) AutoFrameSkip_IgnorePreviousDelay(); + return true; + } + return false; +} + +void JNI(resize, jobject bitmap, int width, int height) +{ + osd->singleScreen = (video.layout == 2); + video.width = width; + video.height = height; + //video.setfilter(VideoInfo::SUPER2XSAI); + AndroidBitmap_getInfo(env, bitmap, &bitmapInfo); +} + +int JNI_NOARGS(runCore) +{ + if(execute) + { + nds4droid_core(); + return mainLoopData.fps > 0 ? mainLoopData.fps : 1; + } + return 1; + +} + +void JNI_NOARGS(runOther) +{ + if(execute) + { + nds4droid_user(); + nds4droid_throttle(); + } +} + +void JNI(saveState, int slot) +{ + savestate_slot(slot); +} + +void JNI(restoreState, int slot) +{ + loadstate_slot(slot); +} + +void JNI(init, jobject _inst) +{ +#ifdef HAVE_NEON + //neontest(); +#endif + INFO(""); + for(std::vector<Logger*>::iterator it = Logger::channels.begin() ; it != Logger::channels.end() ; ++it) + (*it)->setCallback(logCallback); + + extern bool windows_opengl_init(); + oglrender_init = android_opengl_init; + + CommonSettings.num_cores = 1; + CommonSettings.advanced_timing = false; + path.ReadPathSettings(); + + CommonSettings.cheatsDisable = GetPrivateProfileBool(env,"General", "cheatsDisable", false, IniName); + CommonSettings.autodetectBackupMethod = GetPrivateProfileInt(env,"General", "autoDetectMethod", 0, IniName); + video.rotation = GetPrivateProfileInt(env,"Video","Window Rotate", 0, IniName); + video.rotation_userset = GetPrivateProfileInt(env,"Video","Window Rotate Set", video.rotation, IniName); + video.layout_old = video.layout = GetPrivateProfileInt(env,"Video", "LCDsLayout", 0, IniName); + if (video.layout > 2) + { + video.layout = video.layout_old = 0; + } + video.swap = GetPrivateProfileInt(env,"Video", "LCDsSwap", 0, IniName); + CommonSettings.hud.FpsDisplay = GetPrivateProfileBool(env,"Display","Display Fps", true, IniName); + CommonSettings.hud.FrameCounterDisplay = GetPrivateProfileBool(env,"Display","FrameCounter", false, IniName); + CommonSettings.hud.ShowInputDisplay = GetPrivateProfileBool(env,"Display","Display Input", false, IniName); + CommonSettings.hud.ShowGraphicalInputDisplay = GetPrivateProfileBool(env,"Display","Display Graphical Input", false, IniName); + CommonSettings.hud.ShowLagFrameCounter = GetPrivateProfileBool(env,"Display","Display Lag Counter", false, IniName); + CommonSettings.hud.ShowMicrophone = GetPrivateProfileBool(env,"Display","Display Microphone", false, IniName); + CommonSettings.hud.ShowRTC = GetPrivateProfileBool(env,"Display","Display RTC", false, IniName); + CommonSettings.micMode = (TCommonSettings::MicMode)GetPrivateProfileInt(env,"MicSettings", "MicMode", (int)TCommonSettings::InternalNoise, IniName); + video.screengap = GetPrivateProfileInt(env,"Display", "ScreenGap", 0, IniName); + CommonSettings.showGpu.main = GetPrivateProfileInt(env,"Display", "MainGpu", 1, IniName) != 0; + CommonSettings.showGpu.sub = GetPrivateProfileInt(env,"Display", "SubGpu", 1, IniName) != 0; + CommonSettings.spu_advanced = GetPrivateProfileBool(env,"Sound", "SpuAdvanced", false, IniName); + CommonSettings.advanced_timing = GetPrivateProfileBool(env,"Emulation", "AdvancedTiming", false, IniName); + CommonSettings.GFX3D_Zelda_Shadow_Depth_Hack = GetPrivateProfileInt(env,"3D", "ZeldaShadowDepthHack", 0, IniName); + + Desmume_InitOnce(); + //gpu_SetRotateScreen(video.rotation); + NDS_FillDefaultFirmwareConfigData(&fw_config); + Hud.reset(); + + INFO("Init NDS"); + + switch (slot1_device_type) + { + case NDS_SLOT1_NONE: + case NDS_SLOT1_RETAIL: + case NDS_SLOT1_R4: + case NDS_SLOT1_RETAIL_NAND: + break; + default: + slot1_device_type = NDS_SLOT1_RETAIL; + break; + } + + switch (addon_type) + { + case NDS_ADDON_NONE: + break; + case NDS_ADDON_CFLASH: + break; + case NDS_ADDON_RUMBLEPAK: + break; + case NDS_ADDON_GBAGAME: + if (!strlen(GBAgameName)) + { + addon_type = NDS_ADDON_NONE; + break; + } + // TODO: check for file exist + break; + case NDS_ADDON_GUITARGRIP: + break; + case NDS_ADDON_EXPMEMORY: + break; + case NDS_ADDON_PIANO: + break; + case NDS_ADDON_PADDLE: + break; + default: + addon_type = NDS_ADDON_NONE; + break; + } + + slot1Change((NDS_SLOT1_TYPE)slot1_device_type); + addonsChangePak(addon_type); + + CommonSettings.wifi.mode = GetPrivateProfileInt(env,"Wifi", "Mode", 0, IniName); + CommonSettings.wifi.infraBridgeAdapter = GetPrivateProfileInt(env,"Wifi", "BridgeAdapter", 0, IniName); + + NDS_Init(); + + osd->singleScreen = true; + NDS_3D_ChangeCore(cur3DCore = 1); //OpenGL + + LOG("Init sound core\n"); + + static const char* nickname = "emozilla"; + fw_config.nickname_len = strlen(nickname); + for(int i = 0 ; i < fw_config.nickname_len ; ++i) + fw_config.nickname[i] = nickname[i]; + + static const char* message = "ds4droid makes you happy!"; + fw_config.message_len = strlen(message); + for(int i = 0 ; i < fw_config.message_len ; ++i) + fw_config.message[i] = message[i]; + + video.setfilter(GetPrivateProfileInt(env,"Video", "Filter", video.NONE, IniName)); + + NDS_CreateDummyFirmware(&fw_config); + + InitSpeedThrottle(); + + mainLoopData.freq = 1000; + mainLoopData.lastticks = GetTickCount(); +} + +jboolean JNI(loadRom, jstring path) +{ + jboolean isCopy; + const char* szPath = env->GetStringUTFChars(path, &isCopy); + bool ret = nds4droid_loadrom(szPath); + env->ReleaseStringUTFChars(path, szPath); + return ret ? JNI_TRUE : JNI_FALSE; +} + +void JNI(setWorkingDir, jstring path) +{ + jboolean isCopy; + const char* szPath = env->GetStringUTFChars(path, &isCopy); + strncpy(PathInfo::pathToModule, szPath, MAX_PATH); + env->ReleaseStringUTFChars(path, szPath); +} + +void JNI(touchScreenTouch, int x, int y) +{ + if(x<0) x = 0; else if(x>255) x = 255; + if(y<0) y = 0; else if(y>192) y = 192; + NDS_setTouchPos(x,y); +} + +void JNI_NOARGS(touchScreenRelease) +{ + NDS_releaseTouch(); +} + +void JNI(setButtons, int l, int r, int up, int down, int left, int right, int a, int b, int x, int y, int start, int select) +{ + NDS_setPad(right, left, down, up, select, start, b, a, y, x, l, r, false, false); +} + +} //end extern "C" + +unsigned int GetPrivateProfileInt(JNIEnv* env, const char* lpAppName, const char* lpKeyName, int nDefault, const char* lpFileName) +{ + jclass javaClass = env->FindClass("com/opendoorstudios/ds4droid/DeSmuME"); + if(!javaClass) + return nDefault; + jmethodID getSettingInt = env->GetStaticMethodID(javaClass, "getSettingInt","(Ljava/lang/String;I)I"); + jstring key = env->NewStringUTF(lpKeyName); + int ret = env->CallStaticIntMethod(javaClass, getSettingInt, key, nDefault); + return ret; +} + +bool GetPrivateProfileBool(JNIEnv* env, const char* lpAppName, const char* lpKeyName, bool bDefault, const char* lpFileName) +{ + return GetPrivateProfileInt(env, lpAppName, lpKeyName, bDefault ? 1 : 0, lpFileName); +} \ No newline at end of file diff --git a/jni/desmume/src/android/main.h b/jni/desmume/src/android/main.h new file mode 100755 index 0000000..643f17f --- /dev/null +++ b/jni/desmume/src/android/main.h @@ -0,0 +1,46 @@ +/* + Copyright (C) 2012 Jeffrey Quesnelle + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _MAIN_H +#define _MAIN_H + +#include <jni.h> +#include <android/log.h> + +unsigned int GetPrivateProfileInt(JNIEnv* env, const char* lpAppName, const char* lpKeyName, int nDefault, const char* lpFileName); +unsigned int GetTickCount(); + +#ifdef __cplusplus +bool GetPrivateProfileBool(JNIEnv* env, const char* lpAppName, const char* lpKeyName, bool bDefault, const char* lpFileName); + +extern "C" { +#endif + +#define APPNAME "nds4droid" + +#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, APPNAME, __VA_ARGS__)) +#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, APPNAME, __VA_ARGS__)) +#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, APPNAME, __VA_ARGS__)) + + +//JNI callbacks go here + +#ifdef __cplusplus +} //end extern "C" +#endif + +#endif \ No newline at end of file diff --git a/jni/desmume/src/android/math-neon/Android.mk b/jni/desmume/src/android/math-neon/Android.mk new file mode 100755 index 0000000..b1a0880 --- /dev/null +++ b/jni/desmume/src/android/math-neon/Android.mk @@ -0,0 +1,45 @@ +# Android ndk for math-neon +# http://code.google.com/p/math-neon/ + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := libmathneon +LOCAL_SRC_FILES := math_acosf.c \ + math_ceilf.c \ + math_expf.c \ + math_frexpf.c \ + math_logf.c \ + math_modf.c \ + math_sinf.c \ + math_sqrtfv.c \ + math_vec3.c \ + math_asinf.c \ + math_cosf.c \ + math_fabsf.c \ + math_invsqrtf.c \ + math_mat2.c \ + math_powf.c \ + math_sinfv.c \ + math_tanf.c \ + math_vec4.c \ + math_atan2f.c \ + math_coshf.c \ + math_floorf.c \ + math_ldexpf.c \ + math_mat3.c \ + math_runfast.c \ + math_sinhf.c \ + math_tanhf.c \ + math_atanf.c \ + math_debug.c \ + math_fmodf.c \ + math_log10f.c \ + math_mat4.c \ + math_sincosf.c \ + math_sqrtf.c \ + math_vec2.c +LOCAL_ARM_NEON := true +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := -std=gnu99 -DHAVE_NEON=1 -march=armv6 -marm -mfloat-abi=softfp -mfpu=neon +include $(BUILD_STATIC_LIBRARY) \ No newline at end of file diff --git a/jni/desmume/src/android/math-neon/COPYING b/jni/desmume/src/android/math-neon/COPYING new file mode 100755 index 0000000..cca7fc2 --- /dev/null +++ b/jni/desmume/src/android/math-neon/COPYING @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser 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 +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/jni/desmume/src/android/math-neon/README b/jni/desmume/src/android/math-neon/README new file mode 100755 index 0000000..b738b1e --- /dev/null +++ b/jni/desmume/src/android/math-neon/README @@ -0,0 +1,36 @@ + +Library: MATH-NEON +By: Lachlan Tychsen - Smith AKA Adventus +Licence: GPLv3 +======================================================================================= +This project implements the cmath functions and some optimised matrix functions +with the aim of increasing the floating point performance of ARM Cortex A-8 +based platforms. As well as implementing the functions in ARM NEON assembly, +they sacrifice error checking and some accuracy to achieve better performance. + +Function Errors: +======================================================================================= +The measurement and characterisations of the inaccuracies present within these +functions is really a field within itself. For the benchmark i provide the +maximum absolute, maximum relative and root mean squared error compared to the +cmath implementations over the specified range. However these values can be +misleading, especially for functions which quickly go to infinity. So its always a +good idea to test it within your actual program. In general, this library will not +be as accurate as cmath, however for many functions it is close enough to be +negilible. + +Notes: +======================================================================================= +- The *_c functions are c implementations of the *_neon code. +- Like cmath, The errors present in the functions are very dependent on the + range which your operating in. So you should test them first. +- Look in the "math_neon.h" file for discriptions of the functions. In some + function files there are also notes on the specific implementation. +- The *_neon functions make certain assumptions about the location of arguments + that is incompatible with inlining. + +Contact: +======================================================================================= +Name: Lachlan Tychsen - Smith +Email: lachlan.ts@gmail.com +Forum: I also regularly check my GP32X.com forum messages, so you can PM "Adventus". \ No newline at end of file diff --git a/jni/desmume/src/android/math-neon/math_acosf.c b/jni/desmume/src/android/math-neon/math_acosf.c new file mode 100755 index 0000000..024074f --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_acosf.c @@ -0,0 +1,63 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "math.h" +#include "math_neon.h" + +/* +Test func : acosf(x) +Test Range: -1.0 < x < 1.0 +Peak Error: ~0.005% +RMS Error: ~0.001% +*/ + +const float __acosf_pi_2 = M_PI_2; + +float acosf_c(float x) +{ + return __acosf_pi_2 - asinf_c(x); +} + + +float acosf_neon_hfp(float x) +{ +#ifdef __MATH_NEON + asinf_neon_hfp(x); + asm volatile ( + "vdup.f32 d1, %0 \n\t" //d1 = {pi/2, pi/2}; + "vsub.f32 d0, d1, d0 \n\t" //d0 = d1 - d0; + ::"r"(__acosf_pi_2): + ); +#endif +} + +float acosf_neon_sfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ("vmov.f32 s0, r0 \n\t"); + acosf_neon_hfp(x); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return acosf_c(x); +#endif +} + + + diff --git a/jni/desmume/src/android/math-neon/math_asinf.c b/jni/desmume/src/android/math-neon/math_asinf.c new file mode 100755 index 0000000..2edabbf --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_asinf.c @@ -0,0 +1,179 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "math.h" +#include "math_neon.h" + +/* +Test func : asinf(x) +Test Range: -1.0 < x < 1.0 +Peak Error: ~0.005% +RMS Error: ~0.001% +*/ + + +const float __asinf_lut[4] = { + 0.105312459675071, //p7 + 0.169303418571894, //p3 + 0.051599985887214, //p5 + 0.999954835104825 //p1 +}; + +const float __asinf_pi_2 = M_PI_2; + +float asinf_c(float x) +{ + + float a, b, c, d, r, ax; + int m; + + union { + float f; + int i; + } xx; + + ax = fabs(x); + d = 0.5; + d = d - ax*0.5; + + //fast invsqrt approx + xx.f = d; + xx.i = 0x5F3759DF - (xx.i >> 1); //VRSQRTE + c = d * xx.f; + b = (3.0f - c * xx.f) * 0.5; //VRSQRTS + xx.f = xx.f * b; + c = d * xx.f; + b = (3.0f - c * xx.f) * 0.5; + xx.f = xx.f * b; + + //fast inverse approx + d = xx.f; + m = 0x3F800000 - (xx.i & 0x7F800000); + xx.i = xx.i + m; + xx.f = 1.41176471f - 0.47058824f * xx.f; + xx.i = xx.i + m; + b = 2.0 - xx.f * d; + xx.f = xx.f * b; + b = 2.0 - xx.f * d; + xx.f = xx.f * b; + + //if |x|>0.5 -> x = sqrt((1-x)/2) + xx.f = xx.f - ax; + a = (ax > 0.5f); + d = __asinf_pi_2 * a; + c = 1.0f - 3.0f * a; + ax = ax + xx.f * a; + + //polynomial evaluation + xx.f = ax * ax; + a = (__asinf_lut[0] * ax) * xx.f + (__asinf_lut[2] * ax); + b = (__asinf_lut[1] * ax) * xx.f + (__asinf_lut[3] * ax); + xx.f = xx.f * xx.f; + r = b + a * xx.f; + r = d + c * r; + + a = r + r; + b = (x < 0.0f); + r = r - a * b; + return r; +} + + +float asinf_neon_hfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ( + + "vdup.f32 d0, d0[0] \n\t" //d0 = {x, x}; + "vdup.f32 d4, %1 \n\t" //d4 = {pi/2, pi/2}; + "vmov.f32 d6, d0 \n\t" //d6 = d0; + "vabs.f32 d0, d0 \n\t" //d0 = fabs(d0) ; + + "vmov.f32 d5, #0.5 \n\t" //d5 = 0.5; + "vmls.f32 d5, d0, d5 \n\t" //d5 = d5 - d0*d5; + + //fast invsqrt approx + "vmov.f32 d1, d5 \n\t" //d1 = d5 + "vrsqrte.f32 d5, d5 \n\t" //d5 = ~ 1.0 / sqrt(d5) + "vmul.f32 d2, d5, d1 \n\t" //d2 = d5 * d1 + "vrsqrts.f32 d3, d2, d5 \n\t" //d3 = (3 - d5 * d2) / 2 + "vmul.f32 d5, d5, d3 \n\t" //d5 = d5 * d3 + "vmul.f32 d2, d5, d1 \n\t" //d2 = d5 * d1 + "vrsqrts.f32 d3, d2, d5 \n\t" //d3 = (3 - d5 * d3) / 2 + "vmul.f32 d5, d5, d3 \n\t" //d5 = d5 * d3 + + //fast reciporical approximation + "vrecpe.f32 d1, d5 \n\t" //d1 = ~ 1 / d5; + "vrecps.f32 d2, d1, d5 \n\t" //d2 = 2.0 - d1 * d5; + "vmul.f32 d1, d1, d2 \n\t" //d1 = d1 * d2; + "vrecps.f32 d2, d1, d5 \n\t" //d2 = 2.0 - d1 * d5; + "vmul.f32 d5, d1, d2 \n\t" //d5 = d1 * d2; + + //if |x| > 0.5 -> ax = sqrt((1-ax)/2), r = pi/2 + "vsub.f32 d5, d0, d5 \n\t" //d5 = d0 - d5; + "vmov.f32 d2, #0.5 \n\t" //d2 = 0.5; + "vcgt.f32 d3, d0, d2 \n\t" //d3 = (d0 > d2); + "vmov.f32 d1, #3.0 \n\t" //d5 = 3.0; + "vshr.u32 d3, #31 \n\t" //d3 = d3 >> 31; + "vmov.f32 d16, #1.0 \n\t" //d16 = 1.0; + "vcvt.f32.u32 d3, d3 \n\t" //d3 = (float) d3; + "vmls.f32 d0, d5, d3[0] \n\t" //d0 = d0 - d5 * d3[0]; + "vmul.f32 d7, d4, d3[0] \n\t" //d7 = d5 * d4; + "vmls.f32 d16, d1, d3[0] \n\t" //d16 = d16 - d1 * d3; + + //polynomial: + "vmul.f32 d2, d0, d0 \n\t" //d2 = d0*d0 = {ax^2, ax^2} + "vld1.32 {d4, d5}, [%0] \n\t" //d4 = {p7, p3}, d5 = {p5, p1} + "vmul.f32 d3, d2, d2 \n\t" //d3 = d2*d2 = {x^4, x^4} + "vmul.f32 q0, q2, d0[0] \n\t" //q0 = q2 * d0[0] = {p7x, p3x, p5x, p1x} + "vmla.f32 d1, d0, d2[0] \n\t" //d1 = d1 + d0*d2[0] = {p5x + p7x^3, p1x + p3x^3} + "vmla.f32 d1, d3, d1[0] \n\t" //d1 = d1 + d3*d1[0] = {..., p1x + p3x^3 + p5x^5 + p7x^7} + + "vmla.f32 d7, d1, d16 \n\t" //d7 = d7 + d1*d16 + + "vadd.f32 d2, d7, d7 \n\t" //d2 = d7 + d7 + "vclt.f32 d3, d6, #0 \n\t" //d3 = (d6 < 0) + "vshr.u32 d3, #31 \n\t" //d3 = d3 >> 31; + "vcvt.f32.u32 d3, d3 \n\t" //d3 = (float) d3 + "vmls.f32 d7, d2, d3[0] \n\t" //d7 = d7 - d2 * d3[0]; + + "vmov.f32 s0, s15 \n\t" //s0 = s3 + + :: "r"(__asinf_lut), "r"(__asinf_pi_2) + : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7" + ); +#endif +} + + +float asinf_neon_sfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ("vmov.f32 s0, r0 \n\t"); + asinf_neon_hfp(x); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return asinf_c(x); +#endif +} + + + + diff --git a/jni/desmume/src/android/math-neon/math_atan2f.c b/jni/desmume/src/android/math-neon/math_atan2f.c new file mode 100755 index 0000000..8eaae32 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_atan2f.c @@ -0,0 +1,166 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "math.h" +#include "math_neon.h" + +const float __atan2f_lut[4] = { + -0.0443265554792128, //p7 + -0.3258083974640975, //p3 + +0.1555786518463281, //p5 + +0.9997878412794807 //p1 +}; + +const float __atan2f_pi_2 = M_PI_2; + +float atan2f_c(float y, float x) +{ + float a, b, c, r, xx; + int m; + union { + float f; + int i; + } xinv; + + //fast inverse approximation (2x newton) + xx = fabs(x); + xinv.f = xx; + m = 0x3F800000 - (xinv.i & 0x7F800000); + xinv.i = xinv.i + m; + xinv.f = 1.41176471f - 0.47058824f * xinv.f; + xinv.i = xinv.i + m; + b = 2.0 - xinv.f * xx; + xinv.f = xinv.f * b; + b = 2.0 - xinv.f * xx; + xinv.f = xinv.f * b; + + c = fabs(y * xinv.f); + + //fast inverse approximation (2x newton) + xinv.f = c; + m = 0x3F800000 - (xinv.i & 0x7F800000); + xinv.i = xinv.i + m; + xinv.f = 1.41176471f - 0.47058824f * xinv.f; + xinv.i = xinv.i + m; + b = 2.0 - xinv.f * c; + xinv.f = xinv.f * b; + b = 2.0 - xinv.f * c; + xinv.f = xinv.f * b; + + //if |x| > 1.0 -> ax = -1/ax, r = pi/2 + xinv.f = xinv.f + c; + a = (c > 1.0f); + c = c - a * xinv.f; + r = a * __atan2f_pi_2; + + //polynomial evaluation + xx = c * c; + a = (__atan2f_lut[0] * c) * xx + (__atan2f_lut[2] * c); + b = (__atan2f_lut[1] * c) * xx + (__atan2f_lut[3] * c); + xx = xx * xx; + r = r + a * xx; + r = r + b; + + //determine quadrant and test for small x. + b = M_PI; + b = b - 2.0f * r; + r = r + (x < 0.0f) * b; + b = (fabs(x) < 0.000001f); + c = !b; + r = c * r; + r = r + __atan2f_pi_2 * b; + b = r + r; + r = r - (y < 0.0f) * b; + + return r; +} + +float atan2f_neon_hfp(float y, float x) +{ +#ifdef __MATH_NEON + asm volatile ( + + "vdup.f32 d17, d0[1] \n\t" //d17 = {x, x}; + "vdup.f32 d16, d0[0] \n\t" //d16 = {y, y}; + + //1.0 / x + "vrecpe.f32 d18, d17 \n\t" //d16 = ~ 1 / d1; + "vrecps.f32 d19, d18, d17 \n\t" //d17 = 2.0 - d16 * d1; + "vmul.f32 d18, d18, d19 \n\t" //d16 = d16 * d17; + "vrecps.f32 d19, d18, d17 \n\t" //d17 = 2.0 - d16 * d1; + "vmul.f32 d18, d18, d19 \n\t" //d16 = d16 * d17; + + //y * (1.0 /x) + "vmul.f32 d0, d16, d18 \n\t" //d0 = d16 * d18; + + + "vdup.f32 d4, %1 \n\t" //d4 = {pi/2, pi/2}; + "vmov.f32 d6, d0 \n\t" //d6 = d0; + "vabs.f32 d0, d0 \n\t" //d0 = fabs(d0) ; + + //fast reciporical approximation + "vrecpe.f32 d1, d0 \n\t" //d1 = ~ 1 / d0; + "vrecps.f32 d2, d1, d0 \n\t" //d2 = 2.0 - d1 * d0; + "vmul.f32 d1, d1, d2 \n\t" //d1 = d1 * d2; + "vrecps.f32 d2, d1, d0 \n\t" //d2 = 2.0 - d1 * d0; + "vmul.f32 d1, d1, d2 \n\t" //d1 = d1 * d2; + + //if |x| > 1.0 -> ax = 1/ax, r = pi/2 + "vadd.f32 d1, d1, d0 \n\t" //d1 = d1 + d0; + "vmov.f32 d2, #1.0 \n\t" //d2 = 1.0; + "vcgt.f32 d3, d0, d2 \n\t" //d3 = (d0 > d2); + "vcvt.f32.u32 d3, d3 \n\t" //d3 = (float) d3; + "vmls.f32 d0, d1, d3 \n\t" //d0 = d0 - d1 * d3; + "vmul.f32 d7, d3, d4 \n\t" //d7 = d3 * d4; + + //polynomial: + "vmul.f32 d2, d0, d0 \n\t" //d2 = d0*d0 = {ax^2, ax^2} + "vld1.32 {d4, d5}, [%0] \n\t" //d4 = {p7, p3}, d5 = {p5, p1} + "vmul.f32 d3, d2, d2 \n\t" //d3 = d2*d2 = {x^4, x^4} + "vmul.f32 q0, q2, d0[0] \n\t" //q0 = q2 * d0[0] = {p7x, p3x, p5x, p1x} + "vmla.f32 d1, d0, d2[0] \n\t" //d1 = d1 + d0*d2[0] = {p5x + p7x^3, p1x + p3x^3} + "vmla.f32 d1, d3, d1[0] \n\t" //d1 = d1 + d3*d1[0] = {..., p1x + p3x^3 + p5x^5 + p7x^7} + "vadd.f32 d1, d1, d7 \n\t" //d1 = d1 + d7 + + "vadd.f32 d2, d1, d1 \n\t" //d2 = d1 + d1 + "vclt.f32 d3, d6, #0 \n\t" //d3 = (d6 < 0) + "vcvt.f32.u32 d3, d3 \n\t" //d3 = (float) d3 + "vmls.f32 d1, d3, d2 \n\t" //d1 = d1 - d2 * d3; + + "vmov.f32 s0, s3 \n\t" //s0 = s3 + + :: "r"(__atan2f_lut), "r"(__atan2f_pi_2) + : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7" + ); +#endif +} + + +float atan2f_neon_sfp(float x, float y) +{ +#ifdef __MATH_NEON + asm volatile ("vmov.f32 s0, r0 \n\t"); + asm volatile ("vmov.f32 s1, r1 \n\t"); + atan2f_neon_hfp(x, y); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return atan2f_c(y, x); +#endif +}; diff --git a/jni/desmume/src/android/math-neon/math_atanf.c b/jni/desmume/src/android/math-neon/math_atanf.c new file mode 100755 index 0000000..fa0c632 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_atanf.c @@ -0,0 +1,145 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "math.h" +#include "math_neon.h" + +const float __atanf_lut[4] = { + -0.0443265554792128, //p7 + -0.3258083974640975, //p3 + +0.1555786518463281, //p5 + +0.9997878412794807 //p1 +}; + +const float __atanf_pi_2 = M_PI_2; + +float atanf_c(float x) +{ + + float a, b, r, xx; + int m; + + union { + float f; + int i; + } xinv, ax; + + ax.f = fabs(x); + + //fast inverse approximation (2x newton) + xinv.f = ax.f; + m = 0x3F800000 - (xinv.i & 0x7F800000); + xinv.i = xinv.i + m; + xinv.f = 1.41176471f - 0.47058824f * xinv.f; + xinv.i = xinv.i + m; + b = 2.0 - xinv.f * ax.f; + xinv.f = xinv.f * b; + b = 2.0 - xinv.f * ax.f; + xinv.f = xinv.f * b; + + //if |x| > 1.0 -> ax = -1/ax, r = pi/2 + xinv.f = xinv.f + ax.f; + a = (ax.f > 1.0f); + ax.f = ax.f - a * xinv.f; + r = a * __atanf_pi_2; + + //polynomial evaluation + xx = ax.f * ax.f; + a = (__atanf_lut[0] * ax.f) * xx + (__atanf_lut[2] * ax.f); + b = (__atanf_lut[1] * ax.f) * xx + (__atanf_lut[3] * ax.f); + xx = xx * xx; + b = b + a * xx; + r = r + b; + + //if x < 0 -> r = -r + a = 2 * r; + b = (x < 0.0f); + r = r - a * b; + + return r; +} + + +float atanf_neon_hfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ( + + "vdup.f32 d0, d0[0] \n\t" //d0 = {x, x}; + + "vdup.f32 d4, %1 \n\t" //d4 = {pi/2, pi/2}; + "vmov.f32 d6, d0 \n\t" //d6 = d0; + "vabs.f32 d0, d0 \n\t" //d0 = fabs(d0) ; + + //fast reciporical approximation + "vrecpe.f32 d1, d0 \n\t" //d1 = ~ 1 / d0; + "vrecps.f32 d2, d1, d0 \n\t" //d2 = 2.0 - d1 * d0; + "vmul.f32 d1, d1, d2 \n\t" //d1 = d1 * d2; + "vrecps.f32 d2, d1, d0 \n\t" //d2 = 2.0 - d1 * d0; + "vmul.f32 d1, d1, d2 \n\t" //d1 = d1 * d2; + + + //if |x| > 1.0 -> ax = -1/ax, r = pi/2 + "vadd.f32 d1, d1, d0 \n\t" //d1 = d1 + d0; + "vmov.f32 d2, #1.0 \n\t" //d2 = 1.0; + "vcgt.f32 d3, d0, d2 \n\t" //d3 = (d0 > d2); + "vshr.u32 d3, #31 \n\t" //d3 = (d0 > d2); + "vcvt.f32.u32 d3, d3 \n\t" //d5 = (float) d3; + "vmls.f32 d0, d1, d3[0] \n\t" //d0 = d0 - d1 * d3[0]; + "vmul.f32 d7, d4, d3[0] \n\t" //d7 = d5 * d4; + + //polynomial: + "vmul.f32 d2, d0, d0 \n\t" //d2 = d0*d0 = {ax^2, ax^2} + "vld1.32 {d4, d5}, [%0] \n\t" //d4 = {p7, p3}, d5 = {p5, p1} + "vmul.f32 d3, d2, d2 \n\t" //d3 = d2*d2 = {x^4, x^4} + "vmul.f32 q0, q2, d0[0] \n\t" //q0 = q2 * d0[0] = {p7x, p3x, p5x, p1x} + "vmla.f32 d1, d0, d2[0] \n\t" //d1 = d1 + d0*d2[0] = {p5x + p7x^3, p1x + p3x^3} + "vmla.f32 d1, d3, d1[0] \n\t" //d1 = d1 + d3*d1[0] = {..., p1x + p3x^3 + p5x^5 + p7x^7} + "vadd.f32 d1, d1, d7 \n\t" //d1 = d1 + d7 + + "vadd.f32 d2, d1, d1 \n\t" //d2 = d1 + d1 + "vclt.f32 d3, d6, #0 \n\t" //d3 = (d6 < 0) + "vshr.u32 d3, #31 \n\t" //d3 = (d0 > d2); + "vcvt.f32.u32 d3, d3 \n\t" //d3 = (float) d3 + "vmls.f32 d1, d3, d2 \n\t" //d1 = d1 - d2 * d3; + + "vmov.f32 s0, s3 \n\t" //s0 = s3 + + :: "r"(__atanf_lut), "r"(__atanf_pi_2) + : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7" + ); + +#endif +} + + +float atanf_neon_sfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ("vdup.f32 d0, r0 \n\t"); + atanf_neon_hfp(x); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return atanf_c(x); +#endif +}; + + + diff --git a/jni/desmume/src/android/math-neon/math_ceilf.c b/jni/desmume/src/android/math-neon/math_ceilf.c new file mode 100755 index 0000000..aa85999 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_ceilf.c @@ -0,0 +1,67 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* +Assumes the floating point value |x| < 2147483648 +*/ + +#include "math.h" +#include "math_neon.h" + +float ceilf_c(float x) +{ + int n; + float r; + n = (int) x; + r = (float) n; + r = r + (x > r); + return r; +} + +float ceilf_neon_hfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ( + + "vcvt.s32.f32 d1, d0 \n\t" //d1 = (int) d0; + "vcvt.f32.s32 d1, d1 \n\t" //d1 = (float) d1; + "vcgt.f32 d0, d0, d1 \n\t" //d0 = (d0 > d1); + "vshr.u32 d0, #31 \n\t" //d0 = d0 >> 31; + "vcvt.f32.u32 d0, d0 \n\t" //d0 = (float) d0; + "vadd.f32 d0, d1, d0 \n\t" //d0 = d1 + d0; + + ::: "d0", "d1" + ); + +#endif +} + +float ceilf_neon_sfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ("vmov.f32 s0, r0 \n\t"); + ceilf_neon_hfp(x); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return ceilf_c(x); +#endif +}; + + diff --git a/jni/desmume/src/android/math-neon/math_cosf.c b/jni/desmume/src/android/math-neon/math_cosf.c new file mode 100755 index 0000000..9d3f640 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_cosf.c @@ -0,0 +1,46 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "math_neon.h" + +float cosf_c(float x) +{ + return sinf_c(x + M_PI_2); +} + +float cosf_neon_hfp(float x) +{ +#ifdef __MATH_NEON + float xx = x + M_PI_2; + return sinf_neon_hfp(xx); +#endif +} + +float cosf_neon_sfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ("vdup.f32 d0, r0 \n\t"); + cosf_neon_hfp(x); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return cosf_c(x); +#endif +}; + diff --git a/jni/desmume/src/android/math-neon/math_coshf.c b/jni/desmume/src/android/math-neon/math_coshf.c new file mode 100755 index 0000000..911491f --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_coshf.c @@ -0,0 +1,116 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "math.h" +#include "math_neon.h" + +const float __coshf_rng[2] = { + 1.442695041f, + 0.693147180f +}; + +const float __coshf_lut[16] = { + 0.00019578093328483123, //p7 + 0.00019578093328483123, //p7 + 0.0014122663401803872, //p6 + 0.0014122663401803872, //p6 + 0.008336936973260111, //p5 + 0.008336936973260111, //p5 + 0.04165989275009526, //p4 + 0.04165989275009526, //p4 + 0.16666570253074878, //p3 + 0.16666570253074878, //p3 + 0.5000006143673624, //p2 + 0.5000006143673624, //p2 + 1.000000059694879, //p1 + 1.000000059694879, //p1 + 0.9999999916728642, //p0 + 0.9999999916728642 //p0 +}; + + +float coshf_c(float x) +{ + float a, b, xx; + xx = -x; + a = expf_c(x); + b = expf_c(xx); + a = a * 0.5f; + a = a + 0.5f * b; + return a; +} + + +float coshf_neon_hfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ( + "vdup.f32 d0, d0[0] \n\t" //d0 = {x, x} + "fnegs s1, s1 \n\t" //s1 = -s1 + + //Range Reduction: + "vld1.32 d2, [%0] \n\t" //d2 = {invrange, range} + "vld1.32 {d16, d17}, [%1]! \n\t" + "vmul.f32 d6, d0, d2[0] \n\t" //d6 = d0 * d2[0] + "vcvt.s32.f32 d6, d6 \n\t" //d6 = (int) d6 + "vld1.32 {d18}, [%1]! \n\t" + "vcvt.f32.s32 d1, d6 \n\t" //d1 = (float) d6 + "vld1.32 {d19}, [%1]! \n\t" + "vmls.f32 d0, d1, d2[1] \n\t" //d0 = d0 - d1 * d2[1] + "vld1.32 {d20}, [%1]! \n\t" + + //polynomial: + "vmla.f32 d17, d16, d0 \n\t" //d17 = d17 + d16 * d0; + "vld1.32 {d21}, [%1]! \n\t" + "vmla.f32 d18, d17, d0 \n\t" //d18 = d18 + d17 * d0; + "vld1.32 {d22}, [%1]! \n\t" + "vmla.f32 d19, d18, d0 \n\t" //d19 = d19 + d18 * d0; + "vld1.32 {d23}, [%1]! \n\t" + "vmla.f32 d20, d19, d0 \n\t" //d20 = d20 + d19 * d0; + "vmla.f32 d21, d20, d0 \n\t" //d21 = d21 + d20 * d0; + "vmla.f32 d22, d21, d0 \n\t" //d22 = d22 + d21 * d0; + "vmla.f32 d23, d22, d0 \n\t" //d23 = d23 + d22 * d0; + + //multiply by 2 ^ m + "vshl.i32 d6, d6, #23 \n\t" //d6 = d6 << 23 + "vadd.i32 d0, d23, d6 \n\t" //d0 = d22 + d6 + + "vdup.f32 d2, d0[1] \n\t" //d2 = s1 + "vmov.f32 d1, #0.5 \n\t" //d1 = 0.5 + "vadd.f32 d0, d0, d2 \n\t" //d0 = d0 + d2 + "vmul.f32 d0, d1 \n\t" //d0 = d0 * d1 + + :: "r"(__coshf_rng), "r"(__coshf_lut) + : "d0", "d1", "q1", "q2", "d6" + ); + +#endif +} + +float coshf_neon_sfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ("vmov.f32 s0, r0 \n\t"); + coshf_neon_hfp(x); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return coshf_c(x); +#endif +}; diff --git a/jni/desmume/src/android/math-neon/math_debug.c b/jni/desmume/src/android/math-neon/math_debug.c new file mode 100755 index 0000000..d036d6e --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_debug.c @@ -0,0 +1,724 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "math_neon.h" +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <time.h> +#ifdef WIN32 +#include <time.h> +#else +#include <sys/time.h> +#include <sys/resource.h> +#endif + +#define randf() (rand() / (RAND_MAX + 1.0f)) + +#ifdef ANDROID +#include "../main.h" +#include "../neontest.h" +#define printf LOGI +#endif + +struct test1_s { + const char* name; + float (*func)(float); //the function + float (*bench)(float); //the function to benchmark against. + float rng0, rng1; + int num; + float emaxabs; + float xmaxabs; + float emaxrel; + float xmaxrel; + float erms; + int time; //time to execute num functions; +}; + +struct test2_s { + const char* name; + float (*func)(float, float); //the function + float (*bench)(float, float); //the function to benchmark against. + float rng0, rng1; + int num; + float emaxabs; + float xmaxabs; + float emaxrel; + float xmaxrel; + float erms; + int time; //time to execute num functions; +}; + + +float invsqrtf(float x){ + return (1.0f / sqrtf(x)); +} + +typedef struct test1_s test1_t; +typedef struct test2_s test2_t; + +test1_t test1[51] = +{ + {"sinf ", sinf, sinf, -M_PI, M_PI, 500000}, + {"sinf_c ", sinf_c, sinf, -M_PI, M_PI, 500000}, + {"sinf_neon ", sinf_neon, sinf, -M_PI, M_PI, 500000}, + + {"cosf ", cosf, cosf, -M_PI, M_PI, 500000}, + {"cosf_c ", cosf_c, cosf, -M_PI, M_PI, 500000}, + {"cosf_neon ", cosf_neon, cosf, -M_PI, M_PI, 500000}, + + {"tanf ", tanf, tanf, -M_PI_4, M_PI_4, 500000, 0, 0, 0}, + {"tanf_c ", tanf_c, tanf, -M_PI_4, M_PI_4, 500000, 0, 0, 0}, + {"tanf_neon ", tanf_neon, tanf, -M_PI_4, M_PI_4, 500000, 0, 0, 0}, + + {"asinf ", asinf, asinf, -1, 1, 500000, 0, 0, 0}, + {"asinf_c ", asinf_c, asinf, -1, 1, 500000, 0, 0, 0}, + {"asinf_neon ", asinf_neon, asinf, -1, 1, 500000, 0, 0, 0}, + + {"acosf ", acosf, acosf, -1, 1, 500000, 0, 0, 0}, + {"acosf_c ", acosf_c, acosf, -1, 1, 500000, 0, 0, 0}, + {"acosf_neon ", acosf_neon, acosf, -1, 1, 500000, 0, 0, 0}, + + {"atanf ", atanf, atanf, -1, 1, 500000, 0, 0, 0}, + {"atanf_c ", atanf_c, atanf, -1, 1, 500000, 0, 0, 0}, + {"atanf_neon ", atanf_neon, atanf, -1, 1, 500000, 0, 0, 0}, + + {"sinhf ", sinhf, sinhf, -M_PI, M_PI, 500000, 0, 0, 0}, + {"sinhf_c ", sinhf_c, sinhf, -M_PI, M_PI, 500000, 0, 0, 0}, + {"sinhf_neon ", sinhf_neon, sinhf, -M_PI, M_PI, 500000, 0, 0, 0}, + + {"coshf ", coshf, coshf, -M_PI, M_PI, 500000, 0, 0, 0}, + {"coshf_c ", coshf_c, coshf, -M_PI, M_PI, 500000, 0, 0, 0}, + {"coshf_neon ", coshf_neon, coshf, -M_PI, M_PI, 500000, 0, 0, 0}, + + {"tanhf ", tanhf, tanhf, -M_PI, M_PI, 500000, 0, 0, 0}, + {"tanhf_c ", tanhf_c, tanhf, -M_PI, M_PI, 500000, 0, 0, 0}, + {"tanhf_neon ", tanhf_neon, tanhf, -M_PI, M_PI, 500000, 0, 0, 0}, + + {"expf ", expf, expf, 0, 10, 500000, 0, 0, 0}, + {"expf_c ", expf_c, expf, 0, 10, 500000, 0, 0, 0}, + {"expf_neon ", expf_neon, expf, 0, 10, 500000, 0, 0, 0}, + + {"logf ", logf, logf, 1, 1000, 500000, 0, 0, 0}, + {"logf_c ", logf_c, logf, 1, 1000, 500000, 0, 0, 0}, + {"logf_neon ", logf_neon, logf, 1, 1000, 500000, 0, 0, 0}, + + {"log10f ", log10f, log10f, 1, 1000, 500000, 0, 0, 0}, + {"log10f_c ", log10f_c, log10f, 1, 1000, 500000, 0, 0, 0}, + {"log10f_neon ", log10f_neon,log10f, 1, 1000, 500000, 0, 0, 0}, + + {"floorf ", floorf, floorf, 1, 1000, 5000000, 0, 0, 0}, + {"floorf_c ", floorf_c, floorf, 1, 1000, 5000000, 0, 0, 0}, + {"floorf_neon", floorf_neon,floorf, 1, 1000, 5000000, 0, 0, 0}, + + {"ceilf ", ceilf, ceilf, 1, 1000, 5000000, 0, 0, 0}, + {"ceilf_c ", ceilf_c, ceilf, 1, 1000, 5000000, 0, 0, 0}, + {"ceilf_neon", ceilf_neon, ceilf, 1, 1000, 5000000, 0, 0, 0}, + + {"fabsf ", fabsf, fabsf, 1, 1000, 5000000, 0, 0, 0}, + {"fabsf_c ", fabsf_c, fabsf, 1, 1000, 5000000, 0, 0, 0}, + {"fabsf_neon", fabsf_neon, fabsf, 1, 1000, 5000000, 0, 0, 0}, + + {"sqrtf ", sqrtf, sqrtf, 1, 1000, 500000, 0, 0, 0}, + {"sqrtf_c ", sqrtf_c, sqrtf, 1, 1000, 500000, 0, 0, 0}, + {"sqrtf_neon ", sqrtf_neon, sqrtf, 1, 1000, 500000, 0, 0, 0}, + + {"invsqrtf ", invsqrtf, invsqrtf, 1, 1000, 500000, 0, 0, 0}, + {"invsqrtf_c ", invsqrtf_c, invsqrtf, 1, 1000, 500000, 0, 0, 0}, + {"invsqrtf_neon ", invsqrtf_neon, invsqrtf, 1, 1000, 500000, 0, 0, 0}, +}; + +test2_t test2[9] = +{ + {"atan2f ", atan2f, atan2f, 0.1, 10, 10000, 0, 0, 0}, + {"atan2f_c ", atan2f_c, atan2f, 0.1, 10, 10000, 0, 0, 0}, + {"atan2f_neon ", atan2f_neon,atan2f, 0.1, 10, 10000, 0, 0, 0}, + + {"powf ", powf, powf, 1, 10, 10000, 0, 0, 0}, + {"powf_c ", powf_c, powf, 1, 10, 10000, 0, 0, 0}, + {"powf_neon ", powf_neon, powf, 1, 10, 10000, 0, 0, 0}, + + {"fmodf ", fmodf, fmodf, 1, 10, 10000, 0, 0, 0}, + {"fmodf_c ", fmodf_c, fmodf, 1, 10, 10000, 0, 0, 0}, + {"fmodf_neon ", fmodf_neon, fmodf, 1, 10, 10000, 0, 0, 0}, + +}; + + +void +test_mathfunc1(test1_t *tst) +{ + + float x; + float dx = (tst->rng1 - tst->rng0) / ((float)tst->num); +#ifndef WIN32 + struct rusage ru; +#endif + + tst->emaxabs = tst->xmaxabs = 0; + tst->emaxrel = tst->xmaxrel = 0; + tst->erms = 0; + for(x = tst->rng0; x < tst->rng1 ; x += dx){ + float r = (tst->func)((float)x); + float rr = (tst->bench)((float)x); + float dr = fabs(r - rr); + float drr = dr * (100.0f / rr); + tst->erms += dr*dr; + if (dr > tst->emaxabs){ + tst->emaxabs = dr; + tst->xmaxabs = x; + } + if (drr > tst->emaxrel){ + tst->emaxrel = drr; + tst->xmaxrel = x; + } + } + tst->erms = sqrt(tst->erms / ((float) tst->num)); + +#ifdef WIN32 + tst->time = (1000 * clock()) / (CLOCKS_PER_SEC / 1000); +#else + getrusage(RUSAGE_SELF, &ru); + tst->time = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; +#endif + + for(x = tst->rng0; x < tst->rng1 ; x += dx){ + (tst->func)((float)x); + } + +#ifdef WIN32 + tst->time = (1000 * clock()) / (CLOCKS_PER_SEC / 1000) - tst->time; +#else + getrusage(RUSAGE_SELF, &ru); + tst->time = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec - tst->time; +#endif + +} + +void +test_mathfunc2(test2_t *tst) +{ + float x, y; + float rng = tst->rng1 - tst->rng0; + float d = (rng * rng) / ((float) tst->num); +#ifndef WIN32 + struct rusage ru; +#endif + + tst->emaxabs = tst->xmaxabs = 0; + tst->emaxrel = tst->xmaxrel = 0; + for(y = (tst->rng0); y < (tst->rng1) ; y += d){ + for(x = (tst->rng0); x < (tst->rng1); x += d){ + float r = (tst->func)((float)x, y); + float rr = (tst->bench)((float)x, y); + float dr = fabs(r - rr); + float drr = dr * (100.0f / rr); + if (dr > tst->emaxabs){ + tst->emaxabs = dr; + tst->xmaxabs = x; + } + if (drr > tst->emaxrel && fabsf(rr) > 0.0001){ + tst->emaxrel = drr; + tst->xmaxrel = x; + } + } + } + +#ifdef WIN32 + tst->time = (1000 * clock()) / (CLOCKS_PER_SEC / 1000) ; +#else + getrusage(RUSAGE_SELF, &ru); + tst->time = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; +#endif + + for(y = tst->rng0; y < tst->rng1 ; y += d){ + for(x = tst->rng0; x < tst->rng1 ; x += d){ + (tst->func)((float)x, (float)y); + } + } + +#ifdef WIN32 + tst->time = (1000 * clock()) / (CLOCKS_PER_SEC / 1000) - tst->time; +#else + getrusage(RUSAGE_SELF, &ru); + tst->time = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec - tst->time; +#endif + +} + +void test_vectorfunc() +{ + float v0[4], v1[4], d[4]; + + for(int i=0;i<4;i++) + { + v0[i] = 10*randf() - 5; + v1[i] = 10*randf() - 5; + d[i] = 10*randf() - 5; + } + + int testnum = 5000000; + struct rusage ru; + int v2t[3], v3t[3], v4t[3]; + float r; + + printf("\n"); + + //dot 2 + /*getrusage(RUSAGE_SELF, &ru); + v2t[0] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(int i=0;i < testnum; i++) + { + r = dot2_c(v0, v1); + }; + getrusage(RUSAGE_SELF, &ru); + v2t[1] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(int i=0;i < testnum; i++) + { + r = dot2_neon(v0, v1); + }; + getrusage(RUSAGE_SELF, &ru); + v2t[2] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + + r = dot2_c(v0, v1); + printf("dot2_c = %f\n", r); + r = dot2_neon(v0, v1); + printf("dot2_neon = %f\n", r); + + printf("dot2: c=%i \t neon=%i \t rate=%.2f \n", v2t[1] - v2t[0], v2t[2] - v2t[1], + (float)(v2t[1] - v2t[0]) / (float)(v2t[2] - v2t[1]));*/ + + //normalize 2 + getrusage(RUSAGE_SELF, &ru); + v2t[0] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(int i=0;i < testnum; i++) + { + normalize2_c(v0, d); + }; + getrusage(RUSAGE_SELF, &ru); + v2t[1] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(int i=0;i < testnum; i++) + { + normalize2_neon(v0, d); + }; + getrusage(RUSAGE_SELF, &ru); + v2t[2] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + + + normalize2_c(v0, d); + printf("normalize2_c = [%.2f, %.2f]\n", d[0], d[1]); + normalize2_neon(v0, d); + printf("normalize2_neon = [%.2f, %.2f]\n", d[0], d[1]); + + printf("normalize2: c=%i \t neon=%i \t rate=%.2f \n", v2t[1] - v2t[0], v2t[2] - v2t[1], + (float)(v2t[1] - v2t[0]) / (float)(v2t[2] - v2t[1])); + printf("\n"); + + + //dot 3 + /*getrusage(RUSAGE_SELF, &ru); + v3t[0] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(int i=0;i < testnum; i++) + { + r = dot3_c(v0, v1); + }; + getrusage(RUSAGE_SELF, &ru); + v3t[1] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(int i=0;i < testnum; i++) + { + r = dot3_neon(v0, v1); + }; + getrusage(RUSAGE_SELF, &ru); + v3t[2] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + + r = dot3_c(v0, v1); + printf("dot3_c = %f\n", r); + r = dot3_neon(v0, v1); + printf("dot3_neon = %f\n", r); + + printf("dot3: c=%i \t neon=%i \t rate=%.2f \n", v3t[1] - v3t[0], v3t[2] - v3t[1], + (float)(v3t[1] - v3t[0]) / (float)(v3t[2] - v3t[1]));*/ + + //normalize 3 + getrusage(RUSAGE_SELF, &ru); + v3t[0] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(int i=0;i < testnum; i++) + { + normalize3_c(v0, d); + }; + getrusage(RUSAGE_SELF, &ru); + v3t[1] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(int i=0;i < testnum; i++) + { + normalize3_neon(v0, d); + }; + getrusage(RUSAGE_SELF, &ru); + v3t[2] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + + + normalize3_c(v0, d); + printf("normalize3_c = [%.2f, %.2f, %.2f]\n", d[0], d[1], d[2]); + normalize3_neon(v0, d); + printf("normalize3_neon = [%.2f, %.2f, %.2f]\n", d[0], d[1], d[2]); + + printf("normalize3: c=%i \t neon=%i \t rate=%.2f \n", v3t[1] - v3t[0], v3t[2] - v3t[1], + (float)(v3t[1] - v3t[0]) / (float)(v3t[2] - v3t[1])); + + //cross 3 + getrusage(RUSAGE_SELF, &ru); + v3t[0] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(int i=0;i < testnum; i++) + { + cross3_c(v0, v1, d); + }; + getrusage(RUSAGE_SELF, &ru); + v3t[1] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(int i=0;i < testnum; i++) + { + cross3_neon(v0, v1, d); + }; + getrusage(RUSAGE_SELF, &ru); + v3t[2] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + + + cross3_c(v0, v1, d); + printf("cross3_c = [%.2f, %.2f, %.2f]\n", d[0], d[1], d[2]); + cross3_neon(v0, v1, d); + printf("cross3_neon = [%.2f, %.2f, %.2f]\n", d[0], d[1], d[2]); + + printf("cross3: c=%i \t neon=%i \t rate=%.2f \n", v3t[1] - v3t[0], v3t[2] - v3t[1], + (float)(v3t[1] - v3t[0]) / (float)(v3t[2] - v3t[1])); + printf("\n"); + + + //dot 4 + /*getrusage(RUSAGE_SELF, &ru); + v4t[0] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(int i=0;i < testnum; i++) + { + r = dot4_c(v0, v1); + }; + getrusage(RUSAGE_SELF, &ru); + v4t[1] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(int i=0;i < testnum; i++) + { + r = dot4_neon(v0, v1); + }; + getrusage(RUSAGE_SELF, &ru); + v4t[2] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + + r = dot4_c(v0, v1); + printf("dot4_c = %f\n", r); + r = dot4_neon(v0, v1); + printf("dot4_neon = %f\n", r); + + printf("dot4: c=%i \t neon=%i \t rate=%.2f \n", v4t[1] - v4t[0], v4t[2] - v4t[1], + (float)(v4t[1] - v4t[0]) / (float)(v4t[2] - v4t[1]));*/ + + //normalize 4 + getrusage(RUSAGE_SELF, &ru); + v4t[0] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(int i=0;i < testnum; i++) + { + normalize4_c(v0, d); + }; + getrusage(RUSAGE_SELF, &ru); + v4t[1] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(int i=0;i < testnum; i++) + { + normalize4_neon(v0, d); + }; + getrusage(RUSAGE_SELF, &ru); + v4t[2] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + + + normalize4_c(v0, d); + printf("normalize4_c = [%.2f, %.2f, %.2f, %.2f]\n", d[0], d[1], d[2], d[3]); + normalize4_neon(v0, d); + printf("normalize4_neon = [%.2f, %.2f, %.2f, %.2f]\n", d[0], d[1], d[2], d[3]); + + printf("normalize4: c=%i \t neon=%i \t rate=%.2f \n", v4t[1] - v4t[0], v4t[2] - v4t[1], + (float)(v4t[1] - v4t[0]) / (float)(v4t[2] - v4t[1])); + printf("\n"); + + +} + + + +void test_matrixfunc() +{ + float m0[16], m1[16], m2[16]; + int m2t[3], m3t[3], m4t[3]; + + int i; + int testnum = 1000000; + struct rusage ru; + + for(int i=0;i<16;i++) + { + m0[i] = 10.0f * randf() - 5.0f; + m1[i] = 10.0f * randf() - 5.0f; + m2[i] = 10.0f * randf() - 5.0f; + } + + + //matmul2 + getrusage(RUSAGE_SELF, &ru); + m2t[0] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(i = 0; i < testnum; i++){ + matmul2_c(m0, m1, m2); + } + getrusage(RUSAGE_SELF, &ru); + m2t[1] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(i = 0; i < testnum; i++){ + matmul2_neon(m0, m1, m2); + } + getrusage(RUSAGE_SELF, &ru); + m2t[2] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + + matmul2_c(m0, m1, m2); + printf("matmul2_c = \n"); + printf("\t\t\t|%.2f, %.2f|\n", m2[0], m2[2]); + printf("\t\t\t|%.2f, %.2f|\n", m2[1], m2[3]); + + matmul2_neon(m0, m1, m2); + printf("matmul2_neon = \n"); + printf("\t\t\t|%.2f, %.2f|\n", m2[0], m2[2]); + printf("\t\t\t|%.2f, %.2f|\n", m2[1], m2[3]); + + printf("matmul2: c=%i \t neon=%i \t rate=%.2f \n", m2t[1] - m2t[0], m2t[2] - m2t[1], + (float)(m2t[1] - m2t[0]) / (float)(m2t[2] - m2t[1])); + + + //matvec2 + getrusage(RUSAGE_SELF, &ru); + m2t[0] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(i = 0; i < testnum; i++){ + matvec2_c(m0, m1, m2); + } + getrusage(RUSAGE_SELF, &ru); + m2t[1] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(i = 0; i < testnum; i++){ + matvec2_neon(m0, m1, m2); + } + getrusage(RUSAGE_SELF, &ru); + m2t[2] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + + memset(m2, 0, 4*sizeof(float)); + matvec2_c(m0, m1, m2); + printf("matvec2_c = |%.2f, %.2f|\n", m2[0], m2[1]); + + memset(m2, 0, 4*sizeof(float)); + matvec2_neon(m0, m1, m2); + printf("matvec2_neon = |%.2f, %.2f|\n", m2[0], m2[1]); + + printf("matvec2: c=%i \t neon=%i \t rate=%.2f \n", m2t[1] - m2t[0], m2t[2] - m2t[1], + (float)(m2t[1] - m2t[0]) / (float)(m2t[2] - m2t[1])); + + //MAT3 + getrusage(RUSAGE_SELF, &ru); + m3t[0] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(i = 0; i < testnum; i++){ + matmul3_c(m0, m1, m2); + } + getrusage(RUSAGE_SELF, &ru); + m3t[1] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(i = 0; i < testnum; i++){ + matmul3_neon(m0, m1, m2); + } + getrusage(RUSAGE_SELF, &ru); + m3t[2] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + + memset(m2, 0, 9*sizeof(float)); + matmul3_c(m0, m1, m2); + printf("matmul3_c =\n"); + printf("\t\t\t|%.2f, %.2f, %.2f|\n", m2[0], m2[3], m2[6]); + printf("\t\t\t|%.2f, %.2f, %.2f|\n", m2[1], m2[4], m2[7]); + printf("\t\t\t|%.2f, %.2f, %.2f|\n", m2[2], m2[5], m2[8]); + + memset(m2, 0, 9*sizeof(float)); + matmul3_neon(m0, m1, m2); + printf("matmul3_neon =\n"); + printf("\t\t\t|%.2f, %.2f, %.2f|\n", m2[0], m2[3], m2[6]); + printf("\t\t\t|%.2f, %.2f, %.2f|\n", m2[1], m2[4], m2[7]); + printf("\t\t\t|%.2f, %.2f, %.2f|\n", m2[2], m2[5], m2[8]); + + printf("matmul3: c=%i \t neon=%i \t rate=%.2f \n", m3t[1] - m3t[0], m3t[2] - m3t[1], + (float)(m3t[1] - m3t[0]) / (float)(m3t[2] - m3t[1])); + + //matvec3 + getrusage(RUSAGE_SELF, &ru); + m3t[0] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(i = 0; i < testnum; i++){ + matvec3_c(m0, m1, m2); + } + getrusage(RUSAGE_SELF, &ru); + m3t[1] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(i = 0; i < testnum; i++){ + matvec3_neon(m0, m1, m2); + } + getrusage(RUSAGE_SELF, &ru); + m3t[2] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + + memset(m2, 0, 4*sizeof(float)); + matvec3_c(m0, m1, m2); + printf("matvec3_c = |%.2f, %.2f, %.2f|\n", m2[0], m2[1], m2[2]); + + memset(m2, 0, 4*sizeof(float)); + matvec3_neon(m0, m1, m2); + printf("matvec3_neon = |%.2f, %.2f, %.2f|\n", m2[0], m2[1], m2[2]); + + printf("matvec3: c=%i \t neon=%i \t rate=%.2f \n", m2t[1] - m2t[0], m2t[2] - m2t[1], + (float)(m2t[1] - m2t[0]) / (float)(m2t[2] - m2t[1])); + + //MAT4 + getrusage(RUSAGE_SELF, &ru); + m4t[0] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(i = 0; i < testnum; i++){ + matmul4_c(m0, m1, m2); + } + getrusage(RUSAGE_SELF, &ru); + m4t[1] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(i = 0; i < testnum; i++){ + matmul4_neon(m0, m1, m2); + } + getrusage(RUSAGE_SELF, &ru); + m4t[2] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + + memset(m2, 0, 16*sizeof(float)); + matmul4_c(m0, m1, m2); + printf("matmul4_c =\n"); + printf("\t\t\t|%.2f, %.2f, %.2f, %.2f|\n", m2[0], m2[4], m2[8], m2[12]); + printf("\t\t\t|%.2f, %.2f, %.2f, %.2f|\n", m2[1], m2[5], m2[9], m2[13]); + printf("\t\t\t|%.2f, %.2f, %.2f, %.2f|\n", m2[2], m2[6], m2[10], m2[14]); + printf("\t\t\t|%.2f, %.2f, %.2f, %.2f|\n", m2[3], m2[7], m2[11], m2[15]); + + memset(m2, 0, 16*sizeof(float)); + matmul4_neon(m0, m1, m2); + printf("matmul4_neon =\n"); + printf("\t\t\t|%.2f, %.2f, %.2f, %.2f|\n", m2[0], m2[4], m2[8], m2[12]); + printf("\t\t\t|%.2f, %.2f, %.2f, %.2f|\n", m2[1], m2[5], m2[9], m2[13]); + printf("\t\t\t|%.2f, %.2f, %.2f, %.2f|\n", m2[2], m2[6], m2[10], m2[14]); + printf("\t\t\t|%.2f, %.2f, %.2f, %.2f|\n", m2[3], m2[7], m2[11], m2[15]); + + printf("matmul4: c=%i \t neon=%i \t rate=%.2f \n", m4t[1] - m4t[0], m4t[2] - m4t[1], + (float)(m4t[1] - m4t[0]) / (float)(m4t[2] - m4t[1])); + + //matvec4 + getrusage(RUSAGE_SELF, &ru); + m4t[0] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(i = 0; i < testnum; i++){ + matvec4_c(m0, m1, m2); + } + getrusage(RUSAGE_SELF, &ru); + m4t[1] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + for(i = 0; i < testnum; i++){ + matvec4_neon(m0, m1, m2); + } + getrusage(RUSAGE_SELF, &ru); + m4t[2] = ru.ru_utime.tv_sec * 1000000 + ru.ru_utime.tv_usec; + + memset(m2, 0, 4*sizeof(float)); + matvec4_c(m0, m1, m2); + printf("matvec4_c = |%.2f, %.2f, %.2f, %f|\n", m2[0], m2[1], m2[2], m2[3]); + + memset(m2, 0, 4*sizeof(float)); + matvec4_neon(m0, m1, m2); + printf("matvec4_neon = |%.2f, %.2f, %.2f, %f|\n", m2[0], m2[1], m2[2], m2[3]); + + printf("matvec4: c=%i \t neon=%i \t rate=%.2f \n", m2t[1] - m2t[0], m2t[2] - m2t[1], + (float)(m2t[1] - m2t[0]) / (float)(m2t[2] - m2t[1])); + + +} + +int math_debug_main(int argc, char** argv) +{ + + int i, ii; + if (argc > 1 && strcmp(argv[1], "-norunfast") == 0){ + printf("RUNFAST: Disabled \n"); + }else { + printf("RUNFAST: Enabled \n"); + enable_runfast(); + } + + srand(time(NULL)); + +#if 1 + //test single argument functions: + printf("------------------------------------------------------------------------------------------------------\n"); + printf("MATRIX FUNCTION TESTS \n"); + printf("------------------------------------------------------------------------------------------------------\n"); + + test_matrixfunc(); + test_vectorfunc(); + + printf("------------------------------------------------------------------------------------------------------\n"); + printf("CMATH FUNCTION TESTS \n"); + printf("------------------------------------------------------------------------------------------------------\n"); + printf("Function\tRange\t\tNumber\tABS Max Error\tREL Max Error\tRMS Error\tTime\tRate\n"); + printf("------------------------------------------------------------------------------------------------------\n"); + for(i = 0; i < 51; i++){ + test_mathfunc1(&test1[i]); + + ii = i - (i % 3); + printf("%s\t", test1[i].name); + printf("[%.2f, %.2f]\t", test1[i].rng0, test1[i].rng1); + printf("%i\t", test1[i].num); + printf("%.2e\t", test1[i].emaxabs); + printf("%.2e%%\t", test1[i].emaxrel); + printf("%.2e\t", test1[i].erms); + printf("%i\t", test1[i].time); + printf("x%.2f\t", (float)test1[ii].time / test1[i].time); + printf("\n"); + } + for(i = 0; i < 9; i++){ + test_mathfunc2(&test2[i]); + + ii = i - (i % 3); + + printf("%s\t", test2[i].name); + printf("[%.2f, %.2f]\t", test2[i].rng0, test2[i].rng1); + printf("%i\t", test2[i].num); + printf("%.2e\t", test2[i].emaxabs); + printf("%.2e%%\t", test2[i].emaxrel); + printf("%.2e\t", test2[i].erms); + printf("%i\t", test2[i].time); + printf("x%.2f\t", (float)test2[ii].time / test2[i].time); + printf("\n"); + } + +#else + + + float x = 0; + for(x = -M_PI_2; x < M_PI_2; x+= 0.01) + { + printf("x=%.2f\t in=%.2f\t c=%.2f\t neon=%.2f \n", x, sinhf(x), sinhf_c(x), sinhf_neon(x)); + } + +#endif + + return 0; +} diff --git a/jni/desmume/src/android/math-neon/math_expf.c b/jni/desmume/src/android/math-neon/math_expf.c new file mode 100755 index 0000000..be2e2be --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_expf.c @@ -0,0 +1,133 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* +Based on: + + e ^ x = (1+m) * (2^n) + x = log(1+m) + n * log(2) + n = (int) (x * 1.0 / log(2)) + (1+m) = e ^ (x - n * log(2)) + (1+m) = Poly(x - n * log(2)) + + where Poly(x) is the Minimax approximation of e ^ x over the + range [-Log(2), Log(2)] + +Test func : expf(x) +Test Range: 0 < x < 50 +Peak Error: ~0.00024% +RMS Error: ~0.00007% +*/ + + + +#include "math.h" +#include "math_neon.h" + +const float __expf_rng[2] = { + 1.442695041f, + 0.693147180f +}; + +const float __expf_lut[8] = { + 0.9999999916728642, //p0 + 0.04165989275009526, //p4 + 0.5000006143673624, //p2 + 0.0014122663401803872, //p6 + 1.000000059694879, //p1 + 0.008336936973260111, //p5 + 0.16666570253074878, //p3 + 0.00019578093328483123 //p7 +}; + +float expf_c(float x) +{ + float a, b, c, d, xx; + int m; + + union { + float f; + int i; + } r; + + //Range Reduction: + m = (int) (x * __expf_rng[0]); + x = x - ((float) m) * __expf_rng[1]; + + //Taylor Polynomial (Estrins) + a = (__expf_lut[4] * x) + (__expf_lut[0]); + b = (__expf_lut[6] * x) + (__expf_lut[2]); + c = (__expf_lut[5] * x) + (__expf_lut[1]); + d = (__expf_lut[7] * x) + (__expf_lut[3]); + xx = x * x; + a = a + b * xx; + c = c + d * xx; + xx = xx* xx; + r.f = a + c * xx; + + //multiply by 2 ^ m + m = m << 23; + r.i = r.i + m; + + return r.f; +} + +float expf_neon_hfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ( + "vdup.f32 d0, d0[0] \n\t" //d0 = {x, x} + + //Range Reduction: + "vld1.32 d2, [%0] \n\t" //d2 = {invrange, range} + "vmul.f32 d6, d0, d2[0] \n\t" //d6 = d0 * d2[0] + "vcvt.s32.f32 d6, d6 \n\t" //d6 = (int) d6 + "vcvt.f32.s32 d1, d6 \n\t" //d1 = (float) d6 + "vmls.f32 d0, d1, d2[1] \n\t" //d0 = d0 - d1 * d2[1] + + //polynomial: + "vmul.f32 d1, d0, d0 \n\t" //d1 = d0*d0 = {x^2, x^2} + "vld1.32 {d2, d3, d4, d5}, [%1] \n\t" //q1 = {p0, p4, p2, p6}, q2 = {p1, p5, p3, p7} ; + "vmla.f32 q1, q2, d0[0] \n\t" //q1 = q1 + q2 * d0[0] + "vmla.f32 d2, d3, d1[0] \n\t" //d2 = d2 + d3 * d1[0] + "vmul.f32 d1, d1, d1 \n\t" //d1 = d1 * d1 = {x^4, x^4} + "vmla.f32 d2, d1, d2[1] \n\t" //d2 = d2 + d1 * d2[1] + + //multiply by 2 ^ m + "vshl.i32 d6, d6, #23 \n\t" //d6 = d6 << 23 + "vadd.i32 d0, d2, d6 \n\t" //d0 = d2 + d6 + + :: "r"(__expf_rng), "r"(__expf_lut) + : "d0", "d1", "q1", "q2", "d6" + ); +#endif +} + +float expf_neon_sfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ("vmov.f32 s0, r0 \n\t"); + expf_neon_hfp(x); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return expf_c(x); +#endif +}; + diff --git a/jni/desmume/src/android/math-neon/math_fabsf.c b/jni/desmume/src/android/math-neon/math_fabsf.c new file mode 100755 index 0000000..fd73029 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_fabsf.c @@ -0,0 +1,54 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "math_neon.h" + + +float fabsf_c(float x) +{ + union { + int i; + float f; + } xx; + + xx.f = x; + xx.i = xx.i & 0x7FFFFFFF; + return xx.f; +} + +float fabsf_neon_hfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ( + "fabss s0, s0 \n\t" //s0 = fabs(s0) + ); +#endif +} + +float fabsf_neon_sfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ( + "bic r0, r0, #0x80000000 \n\t" //r0 = r0 & ~(1 << 31) + ); +#else + return fabsf_c(x); +#endif +} diff --git a/jni/desmume/src/android/math-neon/math_floorf.c b/jni/desmume/src/android/math-neon/math_floorf.c new file mode 100755 index 0000000..d44d0e7 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_floorf.c @@ -0,0 +1,62 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* +Assumes the floating point value |x| < 2147483648 +*/ + +#include "math.h" +#include "math_neon.h" + +float floorf_c(float x) +{ + int n; + float r; + n = (int) x; + r = (float) n; + r = r - (r > x); + return r; +} + +float floorf_neon_hfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ( + "vcvt.s32.f32 d1, d0 \n\t" //d1 = (int) d0; + "vcvt.f32.s32 d1, d1 \n\t" //d1 = (float) d1; + "vcgt.f32 d0, d1, d0 \n\t" //d0 = (d1 > d0); + "vshr.u32 d0, #31 \n\t" //d0 = d0 >> 31; + "vcvt.f32.u32 d0, d0 \n\t" //d0 = (float) d0; + "vsub.f32 d0, d1, d0 \n\t" //d0 = d1 - d0; + ::: "d0", "d1" + ); +#endif +} + +float floorf_neon_sfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ("vmov.f32 s0, r0 \n\t"); + floorf_neon_hfp(x); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return floorf_c(x); +#endif +}; diff --git a/jni/desmume/src/android/math-neon/math_fmodf.c b/jni/desmume/src/android/math-neon/math_fmodf.c new file mode 100755 index 0000000..4a5f003 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_fmodf.c @@ -0,0 +1,96 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* +Assumes the floating point value |x / y| < 2,147,483,648 +*/ + +#include "math_neon.h" + +float fmodf_c(float x, float y) +{ + int n; + union { + float f; + int i; + } yinv; + float a; + + //fast reciporical approximation (4x Newton) + yinv.f = y; + n = 0x3F800000 - (yinv.i & 0x7F800000); + yinv.i = yinv.i + n; + yinv.f = 1.41176471f - 0.47058824f * yinv.f; + yinv.i = yinv.i + n; + a = 2.0 - yinv.f * y; + yinv.f = yinv.f * a; + a = 2.0 - yinv.f * y; + yinv.f = yinv.f * a; + a = 2.0 - yinv.f * y; + yinv.f = yinv.f * a; + a = 2.0 - yinv.f * y; + yinv.f = yinv.f * a; + + n = (int)(x * yinv.f); + x = x - ((float)n) * y; + return x; +} + + +float fmodf_neon_hfp(float x, float y) +{ +#ifdef __MATH_NEON + asm volatile ( + "vdup.f32 d1, d0[1] \n\t" //d1[0] = y + "vdup.f32 d0, d0[0] \n\t" //d1[0] = y + + //fast reciporical approximation + "vrecpe.f32 d2, d1 \n\t" //d2 = ~1.0 / d1 + "vrecps.f32 d3, d2, d1 \n\t" //d3 = 2.0 - d2 * d1; + "vmul.f32 d2, d2, d3 \n\t" //d2 = d2 * d3; + "vrecps.f32 d3, d2, d1 \n\t" //d3 = 2.0 - d2 * d1; + "vmul.f32 d2, d2, d3 \n\t" //d2 = d2 * d3; + "vrecps.f32 d3, d2, d1 \n\t" //d3 = 2.0 - d2 * d1; + "vmul.f32 d2, d2, d3 \n\t" //d2 = d2 * d3; + "vrecps.f32 d3, d2, d1 \n\t" //d3 = 2.0 - d2 * d1; + "vmul.f32 d2, d2, d3 \n\t" //d2 = d2 * d3; + + "vmul.f32 d2, d2, d0 \n\t" //d2 = d2 * d0; + "vcvt.s32.f32 d2, d2 \n\t" //d2 = (int) d2; + "vcvt.f32.s32 d2, d2 \n\t" //d2 = (float) d2; + "vmls.f32 d0, d1, d2 \n\t" //d0 = d0 - d1 * d2; + + ::: "d0", "d1", "d2", "d3" + ); +#endif +} + + +float fmodf_neon_sfp(float x, float y) +{ +#ifdef __MATH_NEON + asm volatile ("vmov.f32 s0, r0 \n\t"); + asm volatile ("vmov.f32 s1, r1 \n\t"); + fmodf_neon_hfp(x, y); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return fmodf_c(x,y); +#endif +}; diff --git a/jni/desmume/src/android/math-neon/math_frexpf.c b/jni/desmume/src/android/math-neon/math_frexpf.c new file mode 100755 index 0000000..05875a6 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_frexpf.c @@ -0,0 +1,49 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "math.h" +#include "math_neon.h" + +float frexpf_c(float x, int *e) +{ + union { + float f; + int i; + } r; + int n; + + r.f = x; + n = r.i >> 23; + n = n & 0xFF; + n = n - 126; + r.i = r.i - (n << 23); + *e = n; + return r.f; +} + +float frexpf_neon_hfp(float x, int *e) +{ + return frexpf_c(x, e); +} + +float frexpf_neon_sfp(float x, int *e) +{ + return frexpf_c(x, e); +} \ No newline at end of file diff --git a/jni/desmume/src/android/math-neon/math_invsqrtf.c b/jni/desmume/src/android/math-neon/math_invsqrtf.c new file mode 100755 index 0000000..b2801e3 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_invsqrtf.c @@ -0,0 +1,75 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "math.h" +#include "math_neon.h" + +float invsqrtf_c(float x) +{ + + float b, c; + union { + float f; + int i; + } a; + + //fast invsqrt approx + a.f = x; + a.i = 0x5F3759DF - (a.i >> 1); //VRSQRTE + c = x * a.f; + b = (3.0f - c * a.f) * 0.5; //VRSQRTS + a.f = a.f * b; + c = x * a.f; + b = (3.0f - c * a.f) * 0.5; + a.f = a.f * b; + + return a.f; +} + +float invsqrtf_neon_hfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ( + + "vmov.f32 d1, d0 \n\t" //d1 = d0 + "vrsqrte.f32 d0, d0 \n\t" //d0 = ~ 1.0 / sqrt(d0) + "vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1 + "vrsqrts.f32 d3, d2, d0 \n\t" //d3 = (3 - d0 * d2) / 2 + "vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3 + "vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1 + "vrsqrts.f32 d3, d2, d0 \n\t" //d4 = (3 - d0 * d3) / 2 + "vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d4 + + ::: "d0", "d1", "d2", "d3" + ); +#endif +} + +float invsqrtf_neon_sfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ("vmov.f32 s0, r0 \n\t"); + invsqrtf_neon_hfp(x); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return invsqrtf_c(x); +#endif +}; + diff --git a/jni/desmume/src/android/math-neon/math_ldexpf.c b/jni/desmume/src/android/math-neon/math_ldexpf.c new file mode 100755 index 0000000..f5dcffd --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_ldexpf.c @@ -0,0 +1,63 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "math.h" +#include "math_neon.h" + +float ldexpf_c(float m, int e) +{ + union { + float f; + int i; + } r; + r.f = m; + r.i += (e << 23); + return r.f; +} + +float ldexpf_neon_hfp(float m, int e) +{ +#ifdef __MATH_NEON + float r; + asm volatile ( + "lsl r0, r0, #23 \n\t" //r0 = r0 << 23 + "vdup.i32 d1, r0 \n\t" //d1 = {r0, r0} + "vadd.i32 d0, d0, d1 \n\t" //d0 = d0 + d1 + ::: "d0", "d1" + ); +#endif +} + +float ldexpf_neon_sfp(float m, int e) +{ +#ifdef __MATH_NEON + float r; + asm volatile ( + "lsl r1, r1, #23 \n\t" //r1 = r1 << 23 + "vdup.f32 d0, r0 \n\t" //d0 = {r0, r0} + "vdup.i32 d1, r1 \n\t" //d1 = {r1, r1} + "vadd.i32 d0, d0, d1 \n\t" //d0 = d0 + d1 + "vmov.f32 r0, s0 \n\t" //r0 = s0 + ::: "d0", "d1" + ); +#else + return ldexpf_c(m,e); +#endif +} \ No newline at end of file diff --git a/jni/desmume/src/android/math-neon/math_log10f.c b/jni/desmume/src/android/math-neon/math_log10f.c new file mode 100755 index 0000000..ddd0695 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_log10f.c @@ -0,0 +1,131 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* +Based on: + + log10(x) = log10((1+m) * (2^n)) + log(x) = n * log10(2) + log10(1 + m) + log(1+m) = Poly(1+m) + + where Poly(x) is the Minimax approximation of log10(x) over the + range [1, 2] + +Test func : log10f(x) +Test Range: 1 < x < 10000 +Peak Error: ~0.000040% +RMS Error: ~0.000008% +*/ + +#include "math.h" +#include "math_neon.h" + +const float __log10f_rng = 0.3010299957f; + +const float __log10f_lut[8] = { + -0.99697286229624, //p0 + -1.07301643912502, //p4 + -2.46980061535534, //p2 + -0.07176870463131, //p6 + 2.247870219989470, //p1 + 0.366547581117400, //p5 + 1.991005185100089, //p3 + 0.006135635201050, //p7 +}; + +float log10f_c(float x) +{ + float a, b, c, d, xx; + int m; + + union { + float f; + int i; + } r; + + //extract exponent + r.f = x; + m = (r.i >> 23); + m = m - 127; + r.i = r.i - (m << 23); + + //Taylor Polynomial (Estrins) + xx = r.f * r.f; + a = (__log10f_lut[4] * r.f) + (__log10f_lut[0]); + b = (__log10f_lut[6] * r.f) + (__log10f_lut[2]); + c = (__log10f_lut[5] * r.f) + (__log10f_lut[1]); + d = (__log10f_lut[7] * r.f) + (__log10f_lut[3]); + a = a + b * xx; + c = c + d * xx; + xx = xx * xx; + r.f = a + c * xx; + + //add exponent + r.f = r.f + ((float) m) * __log10f_rng; + + return r.f; +} + +float log10f_neon_hfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ( + + "vdup.f32 d0, d0[0] \n\t" //d0 = {x,x}; + + //extract exponent + "vmov.i32 d2, #127 \n\t" //d2 = 127; + "vshr.u32 d6, d0, #23 \n\t" //d6 = d0 >> 23; + "vsub.i32 d6, d6, d2 \n\t" //d6 = d6 - d2; + "vshl.u32 d1, d6, #23 \n\t" //d1 = d6 << 23; + "vsub.i32 d0, d0, d1 \n\t" //d0 = d0 + d1; + + //polynomial: + "vmul.f32 d1, d0, d0 \n\t" //d1 = d0*d0 = {x^2, x^2} + "vld1.32 {d2, d3, d4, d5}, [%1] \n\t" //q1 = {p0, p4, p2, p6}, q2 = {p1, p5, p3, p7} ; + "vmla.f32 q1, q2, d0[0] \n\t" //q1 = q1 + q2 * d0[0] + "vmla.f32 d2, d3, d1[0] \n\t" //d2 = d2 + d3 * d1[0] + "vmul.f32 d1, d1, d1 \n\t" //d1 = d1 * d1 = {x^4, x^4} + "vmla.f32 d2, d1, d2[1] \n\t" //d2 = d2 + d1 * d2[1] + + //add exponent + "vdup.32 d7, %0 \n\t" //d7 = {rng, rng} + "vcvt.f32.s32 d6, d6 \n\t" //d6 = (float) d6 + "vmla.f32 d2, d6, d7 \n\t" //d2 = d2 + d6 * d7 + + "vmov.f32 s0, s4 \n\t" //s0 = s4 + + :: "r"(__log10f_rng), "r"(__log10f_lut) + : "d0", "d1", "q1", "q2", "d6", "d7" + ); +#endif +} + + +float log10f_neon_sfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ("vmov.f32 s0, r0 \n\t"); + log10f_neon_hfp(x); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return log10f_c(x); +#endif +}; diff --git a/jni/desmume/src/android/math-neon/math_logf.c b/jni/desmume/src/android/math-neon/math_logf.c new file mode 100755 index 0000000..9cd82d2 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_logf.c @@ -0,0 +1,131 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* +Based on: + + log(x) = log((1+m) * (2^n)) + log(x) = n * log(2) + log(1 + m) + log(1+m) = Poly(1+m) + + where Poly(x) is the Minimax approximation of log(x) over the + range [1, 2] + +Test func : logf(x) +Test Range: 1 < x < 10000 +Peak Error: ~0.000601% +RMS Error: ~0.000005% +*/ + +#include "math.h" +#include "math_neon.h" + +const float __logf_rng = 0.693147180f; + +const float __logf_lut[8] = { + -2.295614848256274, //p0 + -2.470711633419806, //p4 + -5.686926051100417, //p2 + -0.165253547131978, //p6 + +5.175912446351073, //p1 + +0.844006986174912, //p5 + +4.584458825456749, //p3 + +0.014127821926000 //p7 +}; + +float logf_c(float x) +{ + float a, b, c, d, xx; + int m; + + union { + float f; + int i; + } r; + + //extract exponent + r.f = x; + m = (r.i >> 23); + m = m - 127; + r.i = r.i - (m << 23); + + //Taylor Polynomial (Estrins) + xx = r.f * r.f; + a = (__logf_lut[4] * r.f) + (__logf_lut[0]); + b = (__logf_lut[6] * r.f) + (__logf_lut[2]); + c = (__logf_lut[5] * r.f) + (__logf_lut[1]); + d = (__logf_lut[7] * r.f) + (__logf_lut[3]); + a = a + b * xx; + c = c + d * xx; + xx = xx * xx; + r.f = a + c * xx; + + //add exponent + r.f = r.f + ((float) m) * __logf_rng; + + return r.f; +} + +float logf_neon_hfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ( + + "vdup.f32 d0, d0[0] \n\t" //d0 = {x,x}; + + //extract exponent + "vmov.i32 d2, #127 \n\t" //d2 = 127; + "vshr.u32 d6, d0, #23 \n\t" //d6 = d0 >> 23; + "vsub.i32 d6, d6, d2 \n\t" //d6 = d6 - d2; + "vshl.u32 d1, d6, #23 \n\t" //d1 = d6 << 23; + "vsub.i32 d0, d0, d1 \n\t" //d0 = d0 + d1; + + //polynomial: + "vmul.f32 d1, d0, d0 \n\t" //d1 = d0*d0 = {x^2, x^2} + "vld1.32 {d2, d3, d4, d5}, [%1] \n\t" //q1 = {p0, p4, p2, p6}, q2 = {p1, p5, p3, p7} ; + "vmla.f32 q1, q2, d0[0] \n\t" //q1 = q1 + q2 * d0[0] + "vmla.f32 d2, d3, d1[0] \n\t" //d2 = d2 + d3 * d1[0] + "vmul.f32 d1, d1, d1 \n\t" //d1 = d1 * d1 = {x^4, x^4} + "vmla.f32 d2, d1, d2[1] \n\t" //d2 = d2 + d1 * d2[1] + + //add exponent + "vdup.32 d7, %0 \n\t" //d7 = {rng, rng} + "vcvt.f32.s32 d6, d6 \n\t" //d6 = (float) d6 + "vmla.f32 d2, d6, d7 \n\t" //d2 = d2 + d6 * d7 + + "vmov.f32 s0, s4 \n\t" //s0 = s4 + + :: "r"(__logf_rng), "r"(__logf_lut) + : "d0", "d1", "q1", "q2", "d6", "d7" + ); +#endif +} + +float logf_neon_sfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ("vmov.f32 s0, r0 \n\t"); + logf_neon_hfp(x); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return logf_c(x); +#endif +}; + diff --git a/jni/desmume/src/android/math-neon/math_mat2.c b/jni/desmume/src/android/math-neon/math_mat2.c new file mode 100755 index 0000000..5b37aaf --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_mat2.c @@ -0,0 +1,91 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* +Matrices are specified in column major format: + +| a c | +| b d | + +therefore m[2] = c +*/ + +#include "math_neon.h" + +//matrix matrix multipication. d = m0 * m1; +void +matmul2_c(float m0[4], float m1[4], float d[4]) +{ + d[0] = m0[0]*m1[0] + m0[2]*m1[1]; + d[1] = m0[1]*m1[0] + m0[3]*m1[1]; + d[2] = m0[0]*m1[2] + m0[2]*m1[3]; + d[3] = m0[1]*m1[2] + m0[3]*m1[3]; +} + +void +matmul2_neon(float m0[4], float m1[4], float d[4]) +{ +#ifdef __MATH_NEON + asm volatile ( + "vld1.32 {d0, d1}, [%0] \n\t" //Q1 = m0 + "vld1.32 {d2, d3}, [%1] \n\t" //Q2 = m1 + + "vmul.f32 d4, d0, d2[0] \n\t" //D4 = D0*D2[0] + "vmul.f32 d5, d0, d3[0] \n\t" //D5 = D0*D3[0] + "vmla.f32 d4, d1, d2[1] \n\t" //D4 += D1*D2[1] + "vmla.f32 d5, d1, d3[1] \n\t" //D5 += D1*D3[1] + + "vst1.32 {d4, d5}, [%2] \n\t" //Q4 = m+12 + :: "r"(m0), "r"(m1), "r"(d) + : "q0", "q1", "q2", "memory" + ); +#else + matmul2_c(m0, m1, d); +#endif +} + + +//matrix vector multiplication. d = m * v +void +matvec2_c(float m[4], float v[2], float d[2]) +{ + d[0] = m[0]*v[0] + m[2]*v[1]; + d[1] = m[1]*v[0] + m[3]*v[1]; +} + +void +matvec2_neon(float m[4], float v[2], float d[2]) +{ +#ifdef __MATH_NEON + asm volatile ( + "vld1.32 d0, [%1] \n\t" //d0 = v + "vld1.32 {d1, d2}, [%0] \n\t" //Q1 = m + + "vmul.f32 d3, d1, d0[0] \n\t" //Q5 = Q1*d0[0] + "vmla.f32 d3, d2, d0[1] \n\t" //Q5 += Q1*d0[1] + + "vst1.32 d3, [%2] \n\t" //Q4 = m+12 + :: "r"(m), "r"(v), "r"(d) + : "d0", "d1", "d2","d3", "memory" + ); +#else + matvec2_c(m, v, d); +#endif +} diff --git a/jni/desmume/src/android/math-neon/math_mat3.c b/jni/desmume/src/android/math-neon/math_mat3.c new file mode 100755 index 0000000..044ce04 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_mat3.c @@ -0,0 +1,127 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* +Matrices are specified in row major format: + +| x0 x2 | +| x1 x3 | + +therefore m[2] = x2 + +*/ + +#include "math_neon.h" + +//matrix matrix multipication. d = m0 * m1; +void +matmul3_c(float m0[9], float m1[9], float d[9]) +{ + d[0] = m0[0]*m1[0] + m0[3]*m1[1] + m0[6]*m1[2]; + d[1] = m0[1]*m1[0] + m0[4]*m1[1] + m0[7]*m1[2]; + d[2] = m0[2]*m1[0] + m0[5]*m1[1] + m0[8]*m1[2]; + d[3] = m0[0]*m1[3] + m0[3]*m1[4] + m0[6]*m1[5]; + d[4] = m0[1]*m1[3] + m0[4]*m1[4] + m0[7]*m1[5]; + d[5] = m0[2]*m1[3] + m0[5]*m1[4] + m0[8]*m1[5]; + d[6] = m0[0]*m1[6] + m0[3]*m1[7] + m0[6]*m1[8]; + d[7] = m0[1]*m1[6] + m0[4]*m1[7] + m0[7]*m1[8]; + d[8] = m0[2]*m1[6] + m0[5]*m1[7] + m0[8]*m1[8]; +} + +void +matmul3_neon(float m0[9], float m1[9], float d[9]) +{ +#ifdef __MATH_NEON + asm volatile ( + "vld1.32 {d0, d1}, [%1]! \n\t" //q0 = m1 + "vld1.32 {d2, d3}, [%1]! \n\t" //q1 = m1+4 + "flds s8, [%1] \n\t" //q2 = m1+8 + + "vld1.32 {d6, d7}, [%0] \n\t" //q3[0] = m0 + "add %0, %0, #12 \n\t" //q3[0] = m0 + "vld1.32 {d8, d9}, [%0] \n\t" //q4[0] = m0+12 + "add %0, %0, #12 \n\t" //q3[0] = m0 + "vld1.32 {d10}, [%0] \n\t" //q5[0] = m0+24 + "add %0, %0, #8 \n\t" //q3[0] = m0 + "flds s22, [%0] \n\t" //q2 = m1+8 + + "vmul.f32 q6, q3, d0[0] \n\t" //q12 = q3 * d0[0] + "vmul.f32 q7, q3, d1[1] \n\t" //q13 = q3 * d2[0] + "vmul.f32 q8, q3, d3[0] \n\t" //q14 = q3 * d4[0] + "vmla.f32 q6, q4, d0[1] \n\t" //q12 = q9 * d0[1] + "vmla.f32 q7, q4, d2[0] \n\t" //q13 = q9 * d2[1] + "vmla.f32 q8, q4, d3[1] \n\t" //q14 = q9 * d4[1] + "vmla.f32 q6, q5, d1[0] \n\t" //q12 = q10 * d0[0] + "vmla.f32 q7, q5, d2[1] \n\t" //q13 = q10 * d2[0] + "vmla.f32 q8, q5, d4[0] \n\t" //q14 = q10 * d4[0] + + "vmov.f32 q0, q8 \n\t" //q14 = q10 * d4[0] + "vst1.32 {d12, d13}, [%2] \n\t" //d = q12 + "add %2, %2, #12 \n\t" //q3[0] = m0 + "vst1.32 {d14, d15}, [%2] \n\t" //d+4 = q13 + "add %2, %2, #12 \n\t" //q3[0] = m0 + "vst1.32 {d0}, [%2] \n\t" //d+8 = q14 + "add %2, %2, #8 \n\t" //q3[0] = m0 + "fsts s2, [%2] \n\t" //d = q12 + + : "+r"(m0), "+r"(m1), "+r"(d): + : "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15", "memory" + ); +#else + matmul3_c(m0, m1, d); +#endif +}; + +//matrix vector multiplication. d = m * v +void +matvec3_c(float m[9], float v[3], float d[3]) +{ + d[0] = m[0]*v[0] + m[3]*v[1] + m[6]*v[2]; + d[1] = m[1]*v[0] + m[4]*v[1] + m[7]*v[2]; + d[2] = m[2]*v[0] + m[5]*v[1] + m[8]*v[2]; +} + +void +matvec3_neon(float m[9], float v[3], float d[3]) +{ +#ifdef __MATH_NEON + int tmp; + asm volatile ( + "mov %3, #12 \n\t" //r3 = 12 + "vld1.32 {d0, d1}, [%1] \n\t" //Q0 = v + "vld1.32 {d2, d3}, [%0], %3 \n\t" //Q1 = m + "vld1.32 {d4, d5}, [%0], %3 \n\t" //Q2 = m+12 + "vld1.32 {d6, d7}, [%0], %3 \n\t" //Q3 = m+24 + + "vmul.f32 q9, q1, d0[0] \n\t" //Q9 = Q1*Q0[0] + "vmla.f32 q9, q2, d0[1] \n\t" //Q9 += Q2*Q0[1] + "vmla.f32 q9, q3, d1[0] \n\t" //Q9 += Q3*Q0[2] + "vmov.f32 q0, q9 \n\t" //Q0 = q9 + + "vst1.32 d0, [%2]! \n\t" //r2 = D24 + "fsts s2, [%2] \n\t" //r2 = D25[0] + + : "+r"(m), "+r"(v), "+r"(d), "+r"(tmp): + : "q0", "q9", "q10","q11", "q12", "q13", "memory" + ); +#else + matvec3_c(m, v, d); +#endif +} \ No newline at end of file diff --git a/jni/desmume/src/android/math-neon/math_mat4.c b/jni/desmume/src/android/math-neon/math_mat4.c new file mode 100755 index 0000000..e58aa24 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_mat4.c @@ -0,0 +1,140 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* +Matrices are specified in row major format: + +| x0 x2 | +| x1 x3 | + +therefore m[2] = x2 + +*/ + +#include "math_neon.h" + +//matrix matrix multipication. d = m0 * m1; +void +matmul4_c(float m0[16], float m1[16], float d[16]) +{ + d[0] = m0[0]*m1[0] + m0[4]*m1[1] + m0[8]*m1[2] + m0[12]*m1[3]; + d[1] = m0[1]*m1[0] + m0[5]*m1[1] + m0[9]*m1[2] + m0[13]*m1[3]; + d[2] = m0[2]*m1[0] + m0[6]*m1[1] + m0[10]*m1[2] + m0[14]*m1[3]; + d[3] = m0[3]*m1[0] + m0[7]*m1[1] + m0[11]*m1[2] + m0[15]*m1[3]; + d[4] = m0[0]*m1[4] + m0[4]*m1[5] + m0[8]*m1[6] + m0[12]*m1[7]; + d[5] = m0[1]*m1[4] + m0[5]*m1[5] + m0[9]*m1[6] + m0[13]*m1[7]; + d[6] = m0[2]*m1[4] + m0[6]*m1[5] + m0[10]*m1[6] + m0[14]*m1[7]; + d[7] = m0[3]*m1[4] + m0[7]*m1[5] + m0[11]*m1[6] + m0[15]*m1[7]; + d[8] = m0[0]*m1[8] + m0[4]*m1[9] + m0[8]*m1[10] + m0[12]*m1[11]; + d[9] = m0[1]*m1[8] + m0[5]*m1[9] + m0[9]*m1[10] + m0[13]*m1[11]; + d[10] = m0[2]*m1[8] + m0[6]*m1[9] + m0[10]*m1[10] + m0[14]*m1[11]; + d[11] = m0[3]*m1[8] + m0[7]*m1[9] + m0[11]*m1[10] + m0[15]*m1[11]; + d[12] = m0[0]*m1[12] + m0[4]*m1[13] + m0[8]*m1[14] + m0[12]*m1[15]; + d[13] = m0[1]*m1[12] + m0[5]*m1[13] + m0[9]*m1[14] + m0[13]*m1[15]; + d[14] = m0[2]*m1[12] + m0[6]*m1[13] + m0[10]*m1[14] + m0[14]*m1[15]; + d[15] = m0[3]*m1[12] + m0[7]*m1[13] + m0[11]*m1[14] + m0[15]*m1[15]; +} + +void +matmul4_neon(float m0[16], float m1[16], float d[16]) +{ +#ifdef __MATH_NEON + asm volatile ( + "vld1.32 {d0, d1}, [%1]! \n\t" //q0 = m1 + "vld1.32 {d2, d3}, [%1]! \n\t" //q1 = m1+4 + "vld1.32 {d4, d5}, [%1]! \n\t" //q2 = m1+8 + "vld1.32 {d6, d7}, [%1] \n\t" //q3 = m1+12 + "vld1.32 {d16, d17}, [%0]! \n\t" //q8 = m0 + "vld1.32 {d18, d19}, [%0]! \n\t" //q9 = m0+4 + "vld1.32 {d20, d21}, [%0]! \n\t" //q10 = m0+8 + "vld1.32 {d22, d23}, [%0] \n\t" //q11 = m0+12 + + "vmul.f32 q12, q8, d0[0] \n\t" //q12 = q8 * d0[0] + "vmul.f32 q13, q8, d2[0] \n\t" //q13 = q8 * d2[0] + "vmul.f32 q14, q8, d4[0] \n\t" //q14 = q8 * d4[0] + "vmul.f32 q15, q8, d6[0] \n\t" //q15 = q8 * d6[0] + "vmla.f32 q12, q9, d0[1] \n\t" //q12 = q9 * d0[1] + "vmla.f32 q13, q9, d2[1] \n\t" //q13 = q9 * d2[1] + "vmla.f32 q14, q9, d4[1] \n\t" //q14 = q9 * d4[1] + "vmla.f32 q15, q9, d6[1] \n\t" //q15 = q9 * d6[1] + "vmla.f32 q12, q10, d1[0] \n\t" //q12 = q10 * d0[0] + "vmla.f32 q13, q10, d3[0] \n\t" //q13 = q10 * d2[0] + "vmla.f32 q14, q10, d5[0] \n\t" //q14 = q10 * d4[0] + "vmla.f32 q15, q10, d7[0] \n\t" //q15 = q10 * d6[0] + "vmla.f32 q12, q11, d1[1] \n\t" //q12 = q11 * d0[1] + "vmla.f32 q13, q11, d3[1] \n\t" //q13 = q11 * d2[1] + "vmla.f32 q14, q11, d5[1] \n\t" //q14 = q11 * d4[1] + "vmla.f32 q15, q11, d7[1] \n\t" //q15 = q11 * d6[1] + + "vst1.32 {d24, d25}, [%2]! \n\t" //d = q12 + "vst1.32 {d26, d27}, [%2]! \n\t" //d+4 = q13 + "vst1.32 {d28, d29}, [%2]! \n\t" //d+8 = q14 + "vst1.32 {d30, d31}, [%2] \n\t" //d+12 = q15 + + : "+r"(m0), "+r"(m1), "+r"(d) : + : "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15", + "memory" + ); +#else + matmul4_c(m0, m1, d); +#endif +} + + +//matrix vector multiplication. d = m * v +void +matvec4_c(float m[16], float v[4], float d[4]) +{ + d[0] = m[0]*v[0] + m[4]*v[1] + m[8]*v[2] + m[12]*v[3]; + d[1] = m[1]*v[0] + m[5]*v[1] + m[9]*v[2] + m[13]*v[3]; + d[2] = m[2]*v[0] + m[6]*v[1] + m[10]*v[2] + m[14]*v[3]; + d[3] = m[3]*v[0] + m[7]*v[1] + m[11]*v[2] + m[15]*v[3]; +} + +void +matvec4_neon(float m[16], float v[4], float d[4]) +{ +#ifdef __MATH_NEON + asm volatile ( + "vld1.32 {d0, d1}, [%1] \n\t" //Q0 = v + "vld1.32 {d18, d19}, [%0]! \n\t" //Q1 = m + "vld1.32 {d20, d21}, [%0]! \n\t" //Q2 = m+4 + "vld1.32 {d22, d23}, [%0]! \n\t" //Q3 = m+8 + "vld1.32 {d24, d25}, [%0]! \n\t" //Q4 = m+12 + + "vmul.f32 q13, q9, d0[0] \n\t" //Q5 = Q1*Q0[0] + "vmla.f32 q13, q10, d0[1] \n\t" //Q5 += Q1*Q0[1] + "vmla.f32 q13, q11, d1[0] \n\t" //Q5 += Q2*Q0[2] + "vmla.f32 q13, q12, d1[1] \n\t" //Q5 += Q3*Q0[3] + + "vst1.32 {d26, d27}, [%2] \n\t" //Q4 = m+12 + : + : "r"(m), "r"(v), "r"(d) + : "q0", "q9", "q10","q11", "q12", "q13", "memory" + ); +#else + matvec4_c(m, v, d); +#endif +} + + + + + diff --git a/jni/desmume/src/android/math-neon/math_modf.c b/jni/desmume/src/android/math-neon/math_modf.c new file mode 100755 index 0000000..5b37a05 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_modf.c @@ -0,0 +1,67 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* +Assumes the floating point value |x| < 2,147,483,648 +*/ + +#include "math_neon.h" + +float modf_c(float x, int *i) +{ + int n; + n = (int)x; + *i = n; + x = x - (float)n; + return x; +} + + +float modf_neon_hfp(float x, int *i) +{ +#ifdef __MATH_NEON + asm volatile ( + "vcvt.s32.f32 d1, d0 \n\t" //d1 = (int) d0; + "vcvt.f32.s32 d2, d1 \n\t" //d2 = (float) d1; + "vsub.f32 d0, d0, d2 \n\t" //d0 = d0 - d2; + "vstr.i32 s2, [r0] \n\t" //[r0] = d1[0] + ::: "d0", "d1", "d2" + ); +#endif +} + + +float modf_neon_sfp(float x, int *i) +{ +#ifdef __MATH_NEON + asm volatile ( + "vdup.f32 d0, r0 \n\t" //d0 = {x, x} + "vcvt.s32.f32 d1, d0 \n\t" //d1 = (int) d0; + "vcvt.f32.s32 d2, d1 \n\t" //d2 = (float) d1; + "vsub.f32 d0, d0, d2 \n\t" //d0 = d0 - d2; + "vstr.i32 s2, [r1] \n\t" //[r0] = d1[0] + "vmov.f32 r0, s0 \n\t" //r0 = d0[0]; + ::: "d0", "d1", "d2" + ); + +#else + return modf_c(x, i); +#endif +} diff --git a/jni/desmume/src/android/math-neon/math_neon.h b/jni/desmume/src/android/math-neon/math_neon.h new file mode 100755 index 0000000..81f6f28 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_neon.h @@ -0,0 +1,433 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __MATH_NEON_H__ +#define __MATH_NEON_H__ + +#if !defined(__i386__) && defined(__arm__) +//if defined neon ASM routines are used, otherwise all calls to *_neon +//functions are rerouted to their equivalent *_c function. +#define __MATH_NEON + +//Default Floating Point value ABI: 0=softfp, 1=hardfp. Only effects *_neon routines. +//You can access the hardfp versions directly via the *_hard suffix. +//You can access the softfp versions directly via the *_soft suffix. +#define __MATH_FPABI 1 + +#endif + +#ifdef GCC +#define ALIGN(A) __attribute__ ((aligned (A)) +#else +#define ALIGN(A) +#endif + +#ifndef _MATH_H +#define M_PI 3.14159265358979323846 /* pi */ +#define M_PI_2 1.57079632679489661923 /* pi/2 */ +#define M_PI_4 0.78539816339744830962 /* pi/4 */ +#define M_E 2.7182818284590452354 /* e */ +#define M_LOG2E 1.4426950408889634074 /* log_2 e */ +#define M_LOG10E 0.43429448190325182765 /* log_10 e */ +#define M_LN2 0.69314718055994530942 /* log_e 2 */ +#define M_LN10 2.30258509299404568402 /* log_e 10 */ +#define M_1_PI 0.31830988618379067154 /* 1/pi */ +#define M_2_PI 0.63661977236758134308 /* 2/pi */ +#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ +#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ +#endif + +#if __MATH_FPABI == 1 +#define sinf_neon sinf_neon_hfp +#define cosf_neon cosf_neon_hfp +#define sincosf_neon sincosf_neon_hfp +#define tanf_neon tanf_neon_hfp +#define atanf_neon atanf_neon_hfp +#define atan2f_neon atan2f_neon_hfp +#define asinf_neon asinf_neon_hfp +#define acosf_neon acosf_neon_hfp +#define sinhf_neon sinhf_neon_hfp +#define coshf_neon coshf_neon_hfp +#define tanhf_neon tanhf_neon_hfp +#define expf_neon expf_neon_hfp +#define logf_neon logf_neon_hfp +#define log10f_neon log10f_neon_hfp +#define powf_neon powf_neon_hfp +#define floorf_neon floorf_neon_hfp +#define ceilf_neon ceilf_neon_hfp +#define fabsf_neon fabsf_neon_hfp +#define ldexpf_neon ldexpf_neon_hfp +#define frexpf_neon frexpf_neon_hfp +#define fmodf_neon fmodf_neon_hfp +#define modf_neon modf_neon_hfp +#define sqrtf_neon sqrtf_neon_hfp +#define invsqrtf_neon invsqrtf_neon_hfp +#else +#define sinf_neon sinf_neon_sfp +#define cosf_neon cosf_neon_sfp +#define sincosf_neon sincosf_neon_sfp +#define tanf_neon tanf_neon_sfp +#define atanf_neon atanf_neon_sfp +#define atan2f_neon atan2f_neon_sfp +#define asinf_neon asinf_neon_sfp +#define acosf_neon acosf_neon_sfp +#define sinhf_neon sinhf_neon_sfp +#define coshf_neon coshf_neon_sfp +#define tanhf_neon tanhf_neon_sfp +#define expf_neon expf_neon_sfp +#define logf_neon logf_neon_sfp +#define log10f_neon log10f_neon_sfp +#define powf_neon powf_neon_sfp +#define floorf_neon floorf_neon_sfp +#define ceilf_neon ceilf_neon_sfp +#define fabsf_neon fabsf_neon_sfp +#define ldexpf_neon ldexpf_neon_sfp +#define frexpf_neon frexpf_neon_sfp +#define fmodf_neon fmodf_neon_sfp +#define modf_neon modf_neon_sfp +#define sqrtf_neon sqrtf_neon_sfp +#define invsqrtf_neon invsqrtf_neon_sfp + +#define dot2_neon dot2_neon_sfp +#define dot3_neon dot3_neon_sfp +#define dot4_neon dot4_neon_sfp +#endif + +/* +function: enable_runfast + this function enables the floating point runfast mode on the + ARM Cortex A8. +*/ +void enable_runfast(); + + +float dot2_c(float v0[2], float v1[2]); +float dot2_neon(float v0[2], float v1[2]); +float dot3_c(float v0[3], float v1[3]); +float dot3_neon(float v0[3], float v1[3]); +#if 0 //funky ifdef problem... figure out later +float dot4_c(float v0[4], float v1[4]); +float dot4_neon(float v0[4], float v1[4]); +#endif + +void cross3_c(float v0[3], float v1[3], float d[3]); +void cross3_neon(float v0[3], float v1[3], float d[3]); + +void normalize2_c(float v[2], float d[2]); +void normalize2_neon(float v[2], float d[2]); +void normalize3_c(float v[3], float d[3]); +void normalize3_neon(float v[3], float d[3]); +void normalize4_c(float v[4], float d[4]); +void normalize4_neon(float v[4], float d[4]); + +/* +function: matmul2 +arguments: m0 2x2 matrix, m1 2x2 matrix +return: d 2x2 matrix +expression: d = m0 * m1 +*/ +void matmul2_c(float m0[4], float m1[4], float d[4]); +void matmul2_neon(float m0[4], float m1[4], float d[4]); + +/* +function: matmul3 +arguments: m0 3x3 matrix, m1 3x3 matrix +return: d 3x3 matrix +expression: d = m0 * m1 +*/ +void matmul3_c(float m0[9], float m1[9], float d[9]); +void matmul3_neon(float m0[9], float m1[9], float d[9]); + +/* +function: matmul4 +arguments: m0 4x4 matrix, m1 4x4 matrix +return: d 4x4 matrix +expression: d = m0 * m1 +*/ +void matmul4_c(float m0[16], float m1[16], float d[16]); +void matmul4_neon(float m0[16], float m1[16], float d[16]); +\ +/* +function: matvec2 +arguments: m 2x2 matrix, v 2 element vector +return: d 2x2 matrix +expression: d = m * v +*/ +void matvec2_c(float m[4], float v[2], float d[2]); +void matvec2_neon(float m[4], float v[2], float d[2]); + +/* +function: matvec3 +arguments: m 3x3 matrix, v 3 element vector +return: d 3x3 matrix +expression: d = m * v +*/ +void matvec3_c(float m[9], float v[3], float d[3]); +void matvec3_neon(float m[9], float v[3], float d[3]); + +/* +function: matvec4 +arguments: m 4x4 matrix, v 4 element vector +return: d 4x4 matrix +expression: d = m * v +*/ +void matvec4_c(float m[16], float v[4], float d[4]); +void matvec4_neon(float m[16], float v[4], float d[4]); + +/* +function: sinf +arguments: x radians +return: the sine function evaluated at x radians. +expression: r = sin(x) +*/ +float sinf_c(float x); +float sinf_neon_hfp(float x); +float sinf_neon_sfp(float x); + +/* +function: cosf +arguments: x radians +return: the cosine function evaluated at x radians. +expression: r = cos(x) +notes: computed using cos(x) = sin(x + pi/2) +*/ +float cosf_c(float x); +float cosf_neon_hfp(float x); +float cosf_neon_sfp(float x); + +/* +function: sincosf +arguments: x radians, r[2] result array. +return: both the sine and the cosine evaluated at x radians. +expression: r = {sin(x), cos(x)} +notes: faster than evaluating seperately. +*/ +void sincosf_c(float x, float r[2]); +void sincosf_neon_hfp(float x, float r[2]); +void sincosf_neon_sfp(float x, float r[2]); + +/* +function: sinfv +return: the sine function evaluated at x[i] radians +expression: r[i] = sin(x[i]) +notes: faster than evaluating individually. + r and x can be the same memory location. +*/ +void sinfv_c(float *x, int n, float *r); +void sinfv_neon(float *x, int n, float *r); + +/* +function: tanf +return: the tangent evaluated at x radians. +expression: r = tan(x) +notes: computed using tan(x) = sin(x) / cos(x) +*/ +float tanf_c(float x); +float tanf_neon_hfp(float x); +float tanf_neon_sfp(float x); + +/* +function: atanf +return: the arctangent evaluated at x. +expression: r = atan(x) +*/ +float atanf_c(float x); +float atanf_neon_hfp(float x); +float atanf_neon_sfp(float x); + +/* +function: atanf +return: the arctangent evaluated at x. +expression: r = atan(x) +*/ +float atan2f_c(float y, float x); +float atan2f_neon_hfp(float y, float x); +float atan2f_neon_sfp(float y, float x); + +/* +function: asinf +return: the arcsine evaluated at x. +expression: r = asin(x) +*/ +float asinf_c(float x); +float asinf_neon_hfp(float x); +float asinf_neon_sfp(float x); + +/* +function: acosf +return: the arcsine evaluated at x. +expression: r = asin(x) +*/ +float acosf_c(float x); +float acosf_neon_hfp(float x); +float acosf_neon_sfp(float x); + +/* +function: sinhf +return: the arcsine evaluated at x. +expression: r = asin(x) +*/ +float sinhf_c(float x); +float sinhf_neon_hfp(float x); +float sinhf_neon_sfp(float x); + +/* +function: coshf +return: the arcsine evaluated at x. +expression: r = asin(x) +*/ +float coshf_c(float x); +float coshf_neon_hfp(float x); +float coshf_neon_sfp(float x); + +/* +function: tanhf +return: the arcsine evaluated at x. +expression: r = asin(x) +*/ +float tanhf_c(float x); +float tanhf_neon_hfp(float x); +float tanhf_neon_sfp(float x); + +/* +function: expf +return: the natural exponential evaluated at x. +expression: r = e ** x +*/ +float expf_c(float x); +float expf_neon_hfp(float x); +float expf_neon_sfp(float x); + +/* +function: logf +return: the value of the natural logarithm of x. +expression: r = ln(x) +notes: assumes x > 0 +*/ +float logf_c(float x); +float logf_neon_hfp(float x); +float logf_neon_sfp(float x); + +/* +function: log10f +return: the value of the power 10 logarithm of x. +expression: r = log10(x) +notes: assumes x > 0 +*/ +float log10f_c(float x); +float log10f_neon_hfp(float x); +float log10f_neon_sfp(float x); + +/* +function: powf +return: x raised to the power of n, x ** n. +expression: r = x ** y +notes: computed using e ** (y * ln(x)) +*/ +float powf_c(float x, float n); +float powf_neon_sfp(float x, float n); +float powf_neon_hfp(float x, float n); + +/* +function: floorf +return: x rounded down (towards negative infinity) to its nearest + integer value. +notes: assumes |x| < 2 ** 31 +*/ +float floorf_c(float x); +float floorf_neon_sfp(float x); +float floorf_neon_hfp(float x); + +/* +function: ceilf +return: x rounded up (towards positive infinity) to its nearest + integer value. +notes: assumes |x| < 2 ** 31 +*/ +float ceilf_c(float x); +float ceilf_neon_hfp(float x); +float ceilf_neon_sfp(float x); + +/* +function: fabsf +return: absolute vvalue of x +notes: assumes |x| < 2 ** 31 +*/ +float fabsf_c(float x); +float fabsf_neon_hfp(float x); +float fabsf_neon_sfp(float x); + +/* +function: ldexpf +return: the value of m multiplied by 2 to the power of e. +expression: r = m * (2 ** e) +*/ +float ldexpf_c(float m, int e); +float ldexpf_neon_hfp(float m, int e); +float ldexpf_neon_sfp(float m, int e); + +/* +function: frexpf +return: the exponent and mantissa of x +*/ +float frexpf_c(float x, int *e); +float frexpf_neon_hfp(float x, int *e); +float frexpf_neon_sfp(float x, int *e); + +/* +function: fmodf +return: the remainder of x divided by y, x % y +expression: r = x - floor(x / y) * y; +notes: assumes that |x / y| < 2 ** 31 +*/ +float fmodf_c(float x, float y); +float fmodf_neon_hfp(float x, float y); +float fmodf_neon_sfp(float x, float y); + +/* +function: modf +return: breaks x into the integer (i) and fractional part (return) +notes: assumes that |x| < 2 ** 31 +*/ +float modf_c(float x, int *i); +float modf_neon_hfp(float x, int *i); +float modf_neon_sfp(float x, int *i); + +/* +function: sqrtf +return: (x^0.5) +notes: +*/ +float sqrtf_c(float x); +float sqrtf_neon_hfp(float x); +float sqrtf_neon_sfp(float x); + + +/* +function: invsqrtf +return: 1.0f / (x^0.5) +notes: +*/ +float invsqrtf_c(float x); +float invsqrtf_neon_hfp(float x); +float invsqrtf_neon_sfp(float x); + +#endif diff --git a/jni/desmume/src/android/math-neon/math_powf.c b/jni/desmume/src/android/math-neon/math_powf.c new file mode 100755 index 0000000..431a999 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_powf.c @@ -0,0 +1,178 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* +Based on x ^ n = exp(n * log(x)) + +Test func : powf(x, n) +Test Range: (1,1) < (x, n) < (10, 10) +Peak Error: ~0.0010% +RMS Error: ~0.0002% +*/ + +#include "math.h" +#include "math_neon.h" + +const float __powf_rng[2] = { + 1.442695041f, + 0.693147180f +}; + +const float __powf_lut[16] = { + -2.295614848256274, //p0 log + -2.470711633419806, //p4 + -5.686926051100417, //p2 + -0.165253547131978, //p6 + +5.175912446351073, //p1 + +0.844006986174912, //p5 + +4.584458825456749, //p3 + +0.014127821926000, //p7 + 0.9999999916728642, //p0 exp + 0.04165989275009526, //p4 + 0.5000006143673624, //p2 + 0.0014122663401803872, //p6 + 1.000000059694879, //p1 + 0.008336936973260111, //p5 + 0.16666570253074878, //p3 + 0.00019578093328483123 //p7 +}; + +float powf_c(float x, float n) +{ + float a, b, c, d, xx; + int m; + + union { + float f; + int i; + } r; + + //extract exponent + r.f = x; + m = (r.i >> 23); + m = m - 127; + r.i = r.i - (m << 23); + + //Taylor Polynomial (Estrins) + xx = r.f * r.f; + a = (__powf_lut[4] * r.f) + (__powf_lut[0]); + b = (__powf_lut[6] * r.f) + (__powf_lut[2]); + c = (__powf_lut[5] * r.f) + (__powf_lut[1]); + d = (__powf_lut[7] * r.f) + (__powf_lut[3]); + a = a + b * xx; + c = c + d * xx; + xx = xx * xx; + r.f = a + c * xx; + + //add exponent + r.f = r.f + ((float) m) * __powf_rng[1]; + + r.f = r.f * n; + + + //Range Reduction: + m = (int) (r.f * __powf_rng[0]); + r.f = r.f - ((float) m) * __powf_rng[1]; + + //Taylor Polynomial (Estrins) + a = (__powf_lut[12] * r.f) + (__powf_lut[8]); + b = (__powf_lut[14] * r.f) + (__powf_lut[10]); + c = (__powf_lut[13] * r.f) + (__powf_lut[9]); + d = (__powf_lut[15] * r.f) + (__powf_lut[11]); + xx = r.f * r.f; + a = a + b * xx; + c = c + d * xx; + xx = xx* xx; + r.f = a + c * xx; + + //multiply by 2 ^ m + m = m << 23; + r.i = r.i + m; + + return r.f; +} + +float powf_neon_hfp(float x, float n) +{ +#ifdef __MATH_NEON + asm volatile ( + + "vdup.f32 d16, d0[1] \n\t" //d16 = {y,y}; + "vdup.f32 d0, d0[0] \n\t" //d0 = {x,x}; + + //extract exponent + "vmov.i32 d2, #127 \n\t" //d2 = 127; + "vshr.u32 d6, d0, #23 \n\t" //d6 = d0 >> 23; + "vsub.i32 d6, d6, d2 \n\t" //d6 = d6 - d2; + "vshl.u32 d1, d6, #23 \n\t" //d1 = d6 << 23; + "vsub.i32 d0, d0, d1 \n\t" //d0 = d0 + d1; + + //polynomial: + "vmul.f32 d1, d0, d0 \n\t" //d1 = d0*d0 = {x^2, x^2} + "vld1.32 {d2, d3, d4, d5}, [%1]! \n\t" //q1 = {p0, p4, p2, p6}, q2 = {p1, p5, p3, p7} ; + "vmla.f32 q1, q2, d0[0] \n\t" //q1 = q1 + q2 * d0[0] + "vmla.f32 d2, d3, d1[0] \n\t" //d2 = d2 + d3 * d1[0] + "vmul.f32 d1, d1, d1 \n\t" //d1 = d1 * d1 = {x^4, x^4} + "vmla.f32 d2, d1, d2[1] \n\t" //d2 = d2 + d1 * d2[1] + + //add exponent + "vld1.32 d7, [%0] \n\t" //d7 = {invrange, range} + "vcvt.f32.s32 d6, d6 \n\t" //d6 = (float) d6 + "vmla.f32 d2, d6, d7[1] \n\t" //d2 = d2 + d6 * d7[1] + + "vdup.f32 d0, d2[0] \n\t" //d0 = d2[0] + "vmul.f32 d0, d0, d16 \n\t" //d0 = d0 * d16 + + //Range Reduction: + "vmul.f32 d6, d0, d7[0] \n\t" //d6 = d0 * d7[0] + "vcvt.u32.f32 d6, d6 \n\t" //d6 = (int) d6 + "vcvt.f32.u32 d1, d6 \n\t" //d1 = (float) d6 + "vmls.f32 d0, d1, d7[1] \n\t" //d0 = d0 - d1 * d7[1] + + //polynomial: + "vmul.f32 d1, d0, d0 \n\t" //d1 = d0*d0 = {x^2, x^2} + "vld1.32 {d2, d3, d4, d5}, [%1] \n\t" //q1 = {p0, p4, p2, p6}, q2 = {p1, p5, p3, p7} ; + "vmla.f32 q1, q2, d0[0] \n\t" //q1 = q1 + q2 * d0[0] + "vmla.f32 d2, d3, d1[0] \n\t" //d2 = d2 + d3 * d1[0] + "vmul.f32 d1, d1, d1 \n\t" //d1 = d1 * d1 = {x^4, x^4} + "vmla.f32 d2, d1, d2[1] \n\t" //d2 = d2 + d1 * d2[1] + + //multiply by 2 ^ m + "vshl.i32 d6, d6, #23 \n\t" //d6 = d6 << 23 + "vadd.i32 d0, d2, d6 \n\t" //d0 = d2 + d6 + + + :: "r"(__powf_rng), "r"(__powf_lut) + : "d0", "d1", "d2","d3", "d4", "d5", "d6", "d7" + ); +#endif +} + +float powf_neon_sfp(float x, float n) +{ +#ifdef __MATH_NEON + asm volatile ("vmov.f32 s0, r0 \n\t"); + asm volatile ("vmov.f32 s1, r1 \n\t"); + powf_neon_hfp(x, n); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return powf_c(x, n); +#endif +}; diff --git a/jni/desmume/src/android/math-neon/math_runfast.c b/jni/desmume/src/android/math-neon/math_runfast.c new file mode 100755 index 0000000..e17c942 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_runfast.c @@ -0,0 +1,38 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +void +enable_runfast() +{ +#ifdef __arm__ + static const unsigned int x = 0x04086060; + static const unsigned int y = 0x03000000; + int r; + asm volatile ( + "fmrx %0, fpscr \n\t" //r0 = FPSCR + "and %0, %0, %1 \n\t" //r0 = r0 & 0x04086060 + "orr %0, %0, %2 \n\t" //r0 = r0 | 0x03000000 + "fmxr fpscr, %0 \n\t" //FPSCR = r0 + : "=r"(r) + : "r"(x), "r"(y) + ); +#endif +} diff --git a/jni/desmume/src/android/math-neon/math_sincosf.c b/jni/desmume/src/android/math-neon/math_sincosf.c new file mode 100755 index 0000000..537d677 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_sincosf.c @@ -0,0 +1,157 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "math.h" +#include "math_neon.h" + +const float __sincosf_rng[2] = { + 2.0 / M_PI, + M_PI / 2.0 +}; + +const float __sincosf_lut[8] = { + -0.00018365f, //p7 + -0.00018365f, //p7 + +0.00830636f, //p5 + +0.00830636f, //p5 + -0.16664831f, //p3 + -0.16664831f, //p3 + +0.99999661f, //p1 + +0.99999661f, //p1 +}; + +void sincosf_c( float x, float r[2]) +{ + union { + float f; + int i; + } ax, bx; + + float y; + float a, b, c, d, xx, yy; + int m, n, o, p; + + y = x + __sincosf_rng[1]; + ax.f = fabsf(x); + bx.f = fabsf(y); + + //Range Reduction: + m = (int) (ax.f * __sincosf_rng[0]); + o = (int) (bx.f * __sincosf_rng[0]); + ax.f = ax.f - (((float)m) * __sincosf_rng[1]); + bx.f = bx.f - (((float)o) * __sincosf_rng[1]); + + //Test Quadrant + n = m & 1; + p = o & 1; + ax.f = ax.f - n * __sincosf_rng[1]; + bx.f = bx.f - p * __sincosf_rng[1]; + m = m >> 1; + o = o >> 1; + n = n ^ m; + p = p ^ o; + m = (x < 0.0); + o = (y < 0.0); + n = n ^ m; + p = p ^ o; + n = n << 31; + p = p << 31; + ax.i = ax.i ^ n; + bx.i = bx.i ^ p; + + //Taylor Polynomial + xx = ax.f * ax.f; + yy = bx.f * bx.f; + r[0] = __sincosf_lut[0]; + r[1] = __sincosf_lut[1]; + r[0] = r[0] * xx + __sincosf_lut[2]; + r[1] = r[1] * yy + __sincosf_lut[3]; + r[0] = r[0] * xx + __sincosf_lut[4]; + r[1] = r[1] * yy + __sincosf_lut[5]; + r[0] = r[0] * xx + __sincosf_lut[6]; + r[1] = r[1] * yy + __sincosf_lut[7]; + r[0] = r[0] * ax.f; + r[1] = r[1] * bx.f; + +} + +void sincosf_neon_hfp(float x, float r[2]) +{ + +//HACK: Assumes for softfp that r1 = x, and for hardfp that s0 = x. + +#ifdef __MATH_NEON + asm volatile ( + //{x, y} = {x, x + pi/2} + "vdup.f32 d1, d0[0] \n\t" //d1 = {x, x} + "vld1.32 d3, [%1] \n\t" //d3 = {invrange, range} + "vadd.f32 d0, d1, d3 \n\t" //d0 = d1 + d3 + "vmov.f32 s0, s2 \n\t" //d0[0] = d1[0] + "vabs.f32 d1, d0 \n\t" //d1 = {abs(x), abs(y)} + + //Range Reduction: + "vmul.f32 d2, d1, d3[0] \n\t" //d2 = d1 * d3[0] + "vcvt.u32.f32 d2, d2 \n\t" //d2 = (int) d2 + "vcvt.f32.u32 d4, d2 \n\t" //d4 = (float) d2 + "vmls.f32 d1, d4, d3[1] \n\t" //d1 = d1 - d4 * d3[1] + + //Checking Quadrant: + //ax = ax - (k&1) * M_PI_2 + "vmov.i32 d4, #1 \n\t" //d4 = 1 + "vand.i32 d4, d4, d2 \n\t" //d4 = d4 & d2 + "vcvt.f32.u32 d5, d4 \n\t" //d5 = (float) d4 + "vmls.f32 d1, d5, d3[1] \n\t" //d1 = d1 - d5 * d3[1] + + //ax = ax ^ ((k & 1) ^ (k >> 1) ^ (x < 0) << 31) + "vshr.u32 d3, d2, #1 \n\t" //d3 = d2 >> 1 + "veor.i32 d4, d4, d3 \n\t" //d4 = d4 ^ d3 + "vclt.f32 d3, d0, #0 \n\t" //d3 = (d0 < 0.0) + "veor.i32 d4, d4, d3 \n\t" //d4 = d4 ^ d3 + "vshl.i32 d4, d4, #31 \n\t" //d4 = d4 << 31 + "veor.i32 d0, d1, d4 \n\t" //d0 = d1 ^ d4 + + //polynomial: + "vldm %2!, {d2, d3} \n\t" //d2 = {p7, p7}, d3 = {p5, p5}, r3 += 4; + "vmul.f32 d1, d0, d0 \n\t" //d1 = d0 * d0 = {x^2, y^2} + "vldm %2!, {d4} \n\t" //d4 = {p3, p3}, r3 += 2; + "vmla.f32 d3, d2, d1 \n\t" //d3 = d3 + d2 * d1; + "vldm %2!, {d5} \n\t" //d5 = {p1, p1}, r3 += 2; + "vmla.f32 d4, d3, d1 \n\t" //d4 = d4 + d3 * d1; + "vmla.f32 d5, d4, d1 \n\t" //d5 = d5 + d4 * d1; + "vmul.f32 d5, d5, d0 \n\t" //d5 = d5 * d0; + + "vstm.f32 %0, {d5} \n\t" //r[0] = d5[0], r[1]=d5[1]; + + : "+r"(r) + : "r"(__sincosf_rng), "r"(__sincosf_lut) + : "d0", "d1", "d2", "d3", "d4", "d5" + ); +#else + sincosf_c(x, r); +#endif +} + +void sincosf_neon_sfp(float x, float r[2]) +{ + asm volatile ("vdup.f32 d0, r0 \n\t"); + sincosf_neon_hfp(x, r); + asm volatile ("vmov.f32 r0, s0 \n\t"); +}; + diff --git a/jni/desmume/src/android/math-neon/math_sinf.c b/jni/desmume/src/android/math-neon/math_sinf.c new file mode 100755 index 0000000..f52729a --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_sinf.c @@ -0,0 +1,124 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <math.h> +#include "math_neon.h" + +static const float __sinf_rng[2] = { + 2.0 / M_PI, + M_PI / 2.0 +} ALIGN(16); + +static const float __sinf_lut[4] = { + -0.00018365f, //p7 + -0.16664831f, //p3 + +0.00830636f, //p5 + +0.99999661f, //p1 +} ALIGN(16); + +float sinf_c(float x) +{ + union { + float f; + int i; + } ax; + + float r, a, b, xx; + int m, n; + + ax.f = fabsf(x); + + //Range Reduction: + m = (int) (ax.f * __sinf_rng[0]); + ax.f = ax.f - (((float)m) * __sinf_rng[1]); + + //Test Quadrant + n = m & 1; + ax.f = ax.f - n * __sinf_rng[1]; + m = m >> 1; + n = n ^ m; + m = (x < 0.0); + n = n ^ m; + n = n << 31; + ax.i = ax.i ^ n; + + //Taylor Polynomial (Estrins) + xx = ax.f * ax.f; + a = (__sinf_lut[0] * ax.f) * xx + (__sinf_lut[2] * ax.f); + b = (__sinf_lut[1] * ax.f) * xx + (__sinf_lut[3] * ax.f); + xx = xx * xx; + r = b + a * xx; + + return r; +} + +float sinf_neon_hfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ( + + "vld1.32 d3, [%0] \n\t" //d3 = {invrange, range} + "vdup.f32 d0, d0[0] \n\t" //d0 = {x, x} + "vabs.f32 d1, d0 \n\t" //d1 = {ax, ax} + + "vmul.f32 d2, d1, d3[0] \n\t" //d2 = d1 * d3[0] + "vcvt.u32.f32 d2, d2 \n\t" //d2 = (int) d2 + "vmov.i32 d5, #1 \n\t" //d5 = 1 + "vcvt.f32.u32 d4, d2 \n\t" //d4 = (float) d2 + "vshr.u32 d7, d2, #1 \n\t" //d7 = d2 >> 1 + "vmls.f32 d1, d4, d3[1] \n\t" //d1 = d1 - d4 * d3[1] + + "vand.i32 d5, d2, d5 \n\t" //d5 = d2 & d5 + "vclt.f32 d18, d0, #0 \n\t" //d18 = (d0 < 0.0) + "vcvt.f32.u32 d6, d5 \n\t" //d6 = (float) d5 + "vmls.f32 d1, d6, d3[1] \n\t" //d1 = d1 - d6 * d3[1] + "veor.i32 d5, d5, d7 \n\t" //d5 = d5 ^ d7 + "vmul.f32 d2, d1, d1 \n\t" //d2 = d1*d1 = {x^2, x^2} + + "vld1.32 {d16, d17}, [%1] \n\t" //q8 = {p7, p3, p5, p1} + "veor.i32 d5, d5, d18 \n\t" //d5 = d5 ^ d18 + "vshl.i32 d5, d5, #31 \n\t" //d5 = d5 << 31 + "veor.i32 d1, d1, d5 \n\t" //d1 = d1 ^ d5 + + "vmul.f32 d3, d2, d2 \n\t" //d3 = d2*d2 = {x^4, x^4} + "vmul.f32 q0, q8, d1[0] \n\t" //q0 = q8 * d1[0] = {p7x, p3x, p5x, p1x} + "vmla.f32 d1, d0, d2[0] \n\t" //d1 = d1 + d0*d2 = {p5x + p7x^3, p1x + p3x^3} + "vmla.f32 d1, d3, d1[0] \n\t" //d1 = d1 + d3*d0 = {...., p1x + p3x^3 + p5x^5 + p7x^7} + + "vmov.f32 s0, s3 \n\t" //s0 = s3 + : + : "r"(__sinf_rng), "r"(__sinf_lut) + : "q0", "q1", "q2", "q3", "q8", "q9" + ); +#endif +} + +float sinf_neon_sfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ("vdup.f32 d0, r0 \n\t"); + sinf_neon_hfp(x); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return sinf_c(x); +#endif + +}; + diff --git a/jni/desmume/src/android/math-neon/math_sinfv.c b/jni/desmume/src/android/math-neon/math_sinfv.c new file mode 100755 index 0000000..e1f8f56 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_sinfv.c @@ -0,0 +1,106 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "math.h" +#include "math_neon.h" + +const float __sinfv_rng[2] = { + 2.0 / M_PI, + M_PI / 2.0, +}; + +const float __sinfv_lut[4] = { + -0.00018365f, //p7 + -0.16664831f, //p3 + +0.00830636f, //p5 + +0.99999661f, //p1 +}; + +void sinfv_c(float *x, int n, float *r) +{ + union { + float f; + int i; + } ax, bx; + + float aa, ab, ba, bb, axx, bxx; + int am, bm, an, bn; + + if (n & 0x1) { + *r++ = sinf_c(*x++); + n--; + } + + float rng0 = __sinfv_rng[0]; + float rng1 = __sinfv_rng[1]; + + while(n > 0){ + + float x0 = *x++; + float x1 = *x++; + + ax.f = fabsf(x0); + bx.f = fabsf(x1); + + //Range Reduction: + am = (int) (ax.f * rng0); + bm = (int) (bx.f * rng0); + + ax.f = ax.f - (((float)am) * rng1); + bx.f = bx.f - (((float)bm) * rng1); + + //Test Quadrant + an = am & 1; + bn = bm & 1; + ax.f = ax.f - an * rng1; + bx.f = bx.f - bn * rng1; + am = (am & 2) >> 1; + bm = (bm & 2) >> 1; + ax.i = ax.i ^ ((an ^ am ^ (x0 < 0)) << 31); + bx.i = bx.i ^ ((bn ^ bm ^ (x1 < 0)) << 31); + + //Taylor Polynomial (Estrins) + axx = ax.f * ax.f; + bxx = bx.f * bx.f; + aa = (__sinfv_lut[0] * ax.f) * axx + (__sinfv_lut[2] * ax.f); + ba = (__sinfv_lut[0] * bx.f) * bxx + (__sinfv_lut[2] * bx.f); + ab = (__sinfv_lut[1] * ax.f) * axx + (__sinfv_lut[3] * ax.f); + bb = (__sinfv_lut[1] * bx.f) * bxx + (__sinfv_lut[3] * bx.f); + axx = axx * axx; + bxx = bxx * bxx; + *r++ = ab + aa * axx; + *r++ = bb + ba * bxx; + n -= 2; + } + + +} + +void sinfv_neon(float *x, int n, float *r) +{ +#ifdef __MATH_NEON + asm volatile ("" + : + :"r"(x), "r"(n) + ); +#else + sinfv_c(x, n, r); +#endif +} diff --git a/jni/desmume/src/android/math-neon/math_sinhf.c b/jni/desmume/src/android/math-neon/math_sinhf.c new file mode 100755 index 0000000..c8640f3 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_sinhf.c @@ -0,0 +1,116 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "math.h" +#include "math_neon.h" + +const float __sinhf_rng[2] = { + 1.442695041f, + 0.693147180f +}; + +const float __sinhf_lut[16] = { + 0.00019578093328483123, //p7 + 0.00019578093328483123, //p7 + 0.0014122663401803872, //p6 + 0.0014122663401803872, //p6 + 0.008336936973260111, //p5 + 0.008336936973260111, //p5 + 0.04165989275009526, //p4 + 0.04165989275009526, //p4 + 0.16666570253074878, //p3 + 0.16666570253074878, //p3 + 0.5000006143673624, //p2 + 0.5000006143673624, //p2 + 1.000000059694879, //p1 + 1.000000059694879, //p1 + 0.9999999916728642, //p0 + 0.9999999916728642 //p0 +}; + + +float sinhf_c(float x) +{ + float a, b, xx; + xx = -x; + a = expf_c(x); + b = expf_c(xx); + a = a - b; + a = a * 0.5f; + return a; +} + + +float sinhf_neon_hfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ( + "vdup.f32 d0, d0[0] \n\t" //d0 = {x, x} + "fnegs s1, s1 \n\t" //s1 = -s1 + + //Range Reduction: + "vld1.32 d2, [%0] \n\t" //d2 = {invrange, range} + "vld1.32 {d16, d17}, [%1]! \n\t" + "vmul.f32 d6, d0, d2[0] \n\t" //d6 = d0 * d2[0] + "vcvt.s32.f32 d6, d6 \n\t" //d6 = (int) d6 + "vld1.32 {d18}, [%1]! \n\t" + "vcvt.f32.s32 d1, d6 \n\t" //d1 = (float) d6 + "vld1.32 {d19}, [%1]! \n\t" + "vmls.f32 d0, d1, d2[1] \n\t" //d0 = d0 - d1 * d2[1] + "vld1.32 {d20}, [%1]! \n\t" + + //polynomial: + "vmla.f32 d17, d16, d0 \n\t" //d17 = d17 + d16 * d0; + "vld1.32 {d21}, [%1]! \n\t" + "vmla.f32 d18, d17, d0 \n\t" //d18 = d18 + d17 * d0; + "vld1.32 {d22}, [%1]! \n\t" + "vmla.f32 d19, d18, d0 \n\t" //d19 = d19 + d18 * d0; + "vld1.32 {d23}, [%1]! \n\t" + "vmla.f32 d20, d19, d0 \n\t" //d20 = d20 + d19 * d0; + "vmla.f32 d21, d20, d0 \n\t" //d21 = d21 + d20 * d0; + "vmla.f32 d22, d21, d0 \n\t" //d22 = d22 + d21 * d0; + "vmla.f32 d23, d22, d0 \n\t" //d23 = d23 + d22 * d0; + + //multiply by 2 ^ m + "vshl.i32 d6, d6, #23 \n\t" //d6 = d6 << 23 + "vadd.i32 d0, d23, d6 \n\t" //d0 = d22 + d6 + + "vdup.f32 d2, d0[1] \n\t" //d2 = s1 + "vmov.f32 d1, #0.5 \n\t" //d1 = 0.5 + "vsub.f32 d0, d0, d2 \n\t" //d0 = d0 - d2 + "vmul.f32 d0, d1 \n\t" //d0 = d0 * d1 + + :: "r"(__sinhf_rng), "r"(__sinhf_lut) + : "d0", "d1", "q1", "q2", "d6" + ); + +#endif +} + +float sinhf_neon_sfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ("vmov.f32 s0, r0 \n\t"); + sinhf_neon_hfp(x); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return sinhf_c(x); +#endif +}; diff --git a/jni/desmume/src/android/math-neon/math_sqrtf.c b/jni/desmume/src/android/math-neon/math_sqrtf.c new file mode 100755 index 0000000..09fea1b --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_sqrtf.c @@ -0,0 +1,100 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* +Test func : sqrtf(x) +Test Range: 0 < x < 1,000,000,000 +Peak Error: ~0.0010% +RMS Error: ~0.0005% +*/ + +#include "math.h" +#include "math_neon.h" + +float sqrtf_c(float x) +{ + + float b, c; + int m; + union { + float f; + int i; + } a; + + //fast invsqrt approx + a.f = x; + a.i = 0x5F3759DF - (a.i >> 1); //VRSQRTE + c = x * a.f; + b = (3.0f - c * a.f) * 0.5; //VRSQRTS + a.f = a.f * b; + c = x * a.f; + b = (3.0f - c * a.f) * 0.5; + a.f = a.f * b; + + //fast inverse approx + x = a.f; + m = 0x3F800000 - (a.i & 0x7F800000); + a.i = a.i + m; + a.f = 1.41176471f - 0.47058824f * a.f; + a.i = a.i + m; + b = 2.0 - a.f * x; + a.f = a.f * b; + b = 2.0 - a.f * x; + a.f = a.f * b; + + return a.f; +} + +float sqrtf_neon_hfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ( + + //fast invsqrt approx + "vmov.f32 d1, d0 \n\t" //d1 = d0 + "vrsqrte.f32 d0, d0 \n\t" //d0 = ~ 1.0 / sqrt(d0) + "vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1 + "vrsqrts.f32 d3, d2, d0 \n\t" //d3 = (3 - d0 * d2) / 2 + "vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3 + "vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1 + "vrsqrts.f32 d3, d2, d0 \n\t" //d4 = (3 - d0 * d3) / 2 + "vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3 + + //fast reciporical approximation + "vrecpe.f32 d1, d0 \n\t" //d1 = ~ 1 / d0; + "vrecps.f32 d2, d1, d0 \n\t" //d2 = 2.0 - d1 * d0; + "vmul.f32 d1, d1, d2 \n\t" //d1 = d1 * d2; + "vrecps.f32 d2, d1, d0 \n\t" //d2 = 2.0 - d1 * d0; + "vmul.f32 d0, d1, d2 \n\t" //d0 = d1 * d2; + + ::: "d0", "d1", "d2", "d3" + ); +#endif +} + +float sqrtf_neon_sfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ("vmov.f32 s0, r0 \n\t"); + sqrtf_neon_hfp(x); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return sqrtf_c(x); +#endif +}; diff --git a/jni/desmume/src/android/math-neon/math_sqrtfv.c b/jni/desmume/src/android/math-neon/math_sqrtfv.c new file mode 100755 index 0000000..bd16ca9 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_sqrtfv.c @@ -0,0 +1,143 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* +Test func : sqrtf(x) +Test Range: 0 < x < 1,000,000,000 +Peak Error: ~0.0010% +RMS Error: ~0.0005% +*/ + +#include "math.h" +#include "math_neon.h" + +void sqrtfv_c(float *x, int n, float *r) +{ + + float x0, x1; + float b0, b1, c0, c1; + int m0, m1; + union { + float f; + int i; + } a0, a1; + + + if (n & 0x1){ + *r++ = sqrtf_c(*x++); + n--; + } + + while(n > 0){ + + x0 = *x++; + x1 = *x++; + + //fast invsqrt approx + a0.f = x0; + a1.f = x1; + a0.i = 0x5F3759DF - (a0.i >> 1); //VRSQRTE + a1.i = 0x5F3759DF - (a1.i >> 1); //VRSQRTE + c0 = x0 * a0.f; + c1 = x1 * a1.f; + b0 = (3.0f - c0 * a0.f) * 0.5; //VRSQRTS + b1 = (3.0f - c1 * a1.f) * 0.5; //VRSQRTS + a0.f = a0.f * b0; + a1.f = a1.f * b1; + c0 = x0 * a0.f; + c1 = x1 * a1.f; + b0 = (3.0f - c0 * a0.f) * 0.5; //VRSQRTS + b1 = (3.0f - c1 * a1.f) * 0.5; //VRSQRTS + a0.f = a0.f * b0; + a1.f = a1.f * b1; + + //fast inverse approx + c0 = a0.f; + c0 = a1.f; + m0 = 0x3F800000 - (a0.i & 0x7F800000); + m1 = 0x3F800000 - (a1.i & 0x7F800000); + a0.i = a0.i + m0; + a1.i = a1.i + m1; + a0.f = 1.41176471f - 0.47058824f * a0.f; + a1.f = 1.41176471f - 0.47058824f * a1.f; + a0.i = a0.i + m0; + a1.i = a1.i + m1; + b0 = 2.0 - a0.f * c0; + b1 = 2.0 - a1.f * c1; + a0.f = a0.f * b0; + a1.f = a1.f * b1; + b0 = 2.0 - a0.f * c0; + b1 = 2.0 - a1.f * c1; + a0.f = a0.f * b0; + a1.f = a1.f * b1; + + *r++ = a0.f; + *r++ = a1.f; + n -= 2; + + } +} + +void sqrtfv_neon(float *x, int n, float *r) +{ +#ifdef __MATH_NEON + asm volatile ( + + "tst r1, #1 \n\t" //r1 & 1 + "beq 1f \n\t" // + + "vld1.32 d0[0], [r0]! \n\t" //s0 = *x++ + "mov ip, lr \n\t" //ip = lr + //"bl sqrtf_neon_hfp \n\t" //sqrtf_neon + "mov lr, ip \n\t" //lr = ip + "vst1.32 d0[0], [r2]! \n\t" //*r++ = r0 + "subs r1, r1, #1 \n\t" //r1 = r1 - 1; + "bxeq lr \n\t" // + + "1: \n\t" // + + "vld1.32 d0, [r0]! \n\t" //d0 = (*x[0], *x[1]), x+=2; + + //fast invsqrt approx + "vmov.f32 d1, d0 \n\t" //d1 = d0 + "vrsqrte.f32 d0, d0 \n\t" //d0 = ~ 1.0 / sqrt(d0) + "vmul.f32 d2, d0, d1 \n\t" //d3 = d0 * d2 + "vrsqrts.f32 d3, d2, d0 \n\t" //d4 = (3 - d0 * d3) / 2 + "vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d4 + "vmul.f32 d2, d0, d1 \n\t" //d3 = d0 * d2 + "vrsqrts.f32 d3, d2, d0 \n\t" //d4 = (3 - d0 * d3) / 2 + "vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d4 + + //fast reciporical approximation + "vrecpe.f32 d1, d0 \n\t" //d1 = ~ 1 / d0; + "vrecps.f32 d2, d1, d0 \n\t" //d2 = 2.0 - d1 * d0; + "vmul.f32 d1, d1, d2 \n\t" //d1 = d1 * d2; + "vrecps.f32 d2, d1, d0 \n\t" //d2 = 2.0 - d1 * d0; + "vmul.f32 d0, d1, d2 \n\t" //d0 = d1 * d2; + + "vst1.64 d0, [r2]! \n\t" //*r++ = d0; + "subs r1, r1, #2 \n\t" //n = n - 2; update flags + "bgt 1b \n\t" // + + ::: "d0", "d1", "d2", "d3" +); +#else + sqrtfv_c(x, n, r); +#endif +} diff --git a/jni/desmume/src/android/math-neon/math_tanf.c b/jni/desmume/src/android/math-neon/math_tanf.c new file mode 100755 index 0000000..6d9106b --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_tanf.c @@ -0,0 +1,152 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "math.h" +#include "math_neon.h" + +const float __tanf_rng[2] = { + 2.0 / M_PI, + M_PI / 2.0 +}; + +const float __tanf_lut[4] = { + -0.00018365f, //p7 + -0.16664831f, //p3 + +0.00830636f, //p5 + +0.99999661f, //p1 +}; + +float tanf_c(float x){ + + union { + float f; + int i; + } ax, c; + + float r, a, b, xx, cc, cx; + int m; + + ax.f = fabsf(x); + + //Range Reduction: + m = (int) (ax.f * __tanf_rng[0]); + ax.f = ax.f - (((float)m) * __tanf_rng[1]); + + //Test Quadrant + ax.f = ax.f - (m & 1) * __tanf_rng[1]; + ax.i = ax.i ^ ((*(int*)&x) & 0x80000000); + + //Taylor Polynomial (Estrins) + xx = ax.f * ax.f; + a = (__tanf_lut[0] * ax.f) * xx + (__tanf_lut[2] * ax.f); + b = (__tanf_lut[1] * ax.f) * xx + (__tanf_lut[3] * ax.f); + xx = xx * xx; + r = b + a * xx; + + //cosine + c.f = 1.0 - r * r; + + //fast invsqrt approximation (2x newton iterations) + cc = c.f; + c.i = 0x5F3759DF - (c.i >> 1); //VRSQRTE + cx = cc * c.f; + a = (3.0f - cx * c.f) / 2; //VRSQRTS + c.f = c.f * a; + cx = cc * c.f; + a = (3.0f - cx * c.f) / 2; + c.f = c.f * a; + + r = r * c.f; + + return r; +} + + +float tanf_neon_hfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ( + + "vdup.f32 d0, d0[0] \n\t" //d0 = {x, x} + "vabs.f32 d1, d0 \n\t" //d1 = {ax, ax} + + //Range Reduction: + "vld1.32 d3, [%0] \n\t" //d3 = {invrange, range} + "vmul.f32 d2, d1, d3[0] \n\t" //d2 = d1 * d3[0] + "vcvt.u32.f32 d2, d2 \n\t" //d2 = (int) d2 + "vcvt.f32.u32 d4, d2 \n\t" //d4 = (float) d2 + "vmls.f32 d1, d4, d3[1] \n\t" //d1 = d1 - d4 * d3[1] + + //Checking Quadrant: + //ax = ax - (k&1) * M_PI_2 + "vmov.i32 d4, #1 \n\t" //d4 = 1 + "vand.i32 d2, d2, d4 \n\t" //d2 = d2 & d4 + "vcvt.f32.u32 d2, d2 \n\t" //d2 = (float) d2 + "vmls.f32 d1, d2, d3[1] \n\t" //d1 = d1 - d2 * d3[1] + + //ax = ax ^ ( x.i & 0x800000000) + "vmov.i32 d4, #0x80000000 \n\t" //d4 = 0x80000000 + "vand.i32 d0, d0, d4 \n\t" //d0 = d0 & d4 + "veor.i32 d1, d1, d0 \n\t" //d1 = d1 ^ d0 + + //polynomial: + "vmul.f32 d2, d1, d1 \n\t" //d2 = d1*d1 = {x^2, x^2} + "vld1.32 {d4, d5}, [%1] \n\t" //d4 = {p7, p3}, d5 = {p5, p1} + "vmul.f32 d3, d2, d2 \n\t" //d3 = d2*d2 = {x^4, x^4} + "vmul.f32 q0, q2, d1[0] \n\t" //q0 = q2 * d1[0] = {p7x, p3x, p5x, p1x} + "vmla.f32 d1, d0, d2[0] \n\t" //d1 = d1 + d0*d2 = {p5x + p7x^3, p1x + p3x^3} + "vmla.f32 d1, d3, d1[0] \n\t" //d1 = d1 + d3*d0 = {..., p1x + p3x^3 + p5x^5 + p7x^7} + + //cosine + "vmov.f32 s1, #1.0 \n\t" //d0[1] = 1.0 + "vmls.f32 d0, d1, d1 \n\t" //d0 = {..., 1.0 - sx*sx} + + //invsqrt approx + "vmov.f32 d2, d0 \n\t" //d2 = d0 + "vrsqrte.f32 d0, d0 \n\t" //d0 = ~ 1.0 / sqrt(d0) + "vmul.f32 d3, d0, d2 \n\t" //d3 = d0 * d2 + "vrsqrts.f32 d4, d3, d0 \n\t" //d4 = (3 - d0 * d3) / 2 + "vmul.f32 d0, d0, d4 \n\t" //d0 = d0 * d4 + "vmul.f32 d3, d0, d2 \n\t" //d3 = d0 * d2 + "vrsqrts.f32 d4, d3, d0 \n\t" //d4 = (3 - d0 * d3) / 2 + "vmul.f32 d0, d0, d4 \n\t" //d0 = d0 * d4 + + "vmul.f32 d0, d0, d1 \n\t" //d0 = d0 * d1 + + "vmov.f32 s0, s1 \n\t" //s0 = s1 + + :: "r"(__tanf_rng), "r"(__tanf_lut) + : "d0", "d1", "d2", "d3", "d4", "d5" + ); +#endif +} + + +float tanf_neon_sfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ("vdup.f32 d0, r0 \n\t"); + tanf_neon_hfp(x); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return tanf_c(x); +#endif +}; + diff --git a/jni/desmume/src/android/math-neon/math_tanhf.c b/jni/desmume/src/android/math-neon/math_tanhf.c new file mode 100755 index 0000000..2e83d11 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_tanhf.c @@ -0,0 +1,91 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "math.h" +#include "math_neon.h" + +/* +TanH = (e^x - e^-x) / (e^x + e^-x) +TanH = (e^x - e^-x)(e^x) / (e^x + e^-x)(e^x) +TanH = (e^2x - 1) / (e^2x + 1) + +*/ + +float tanhf_c(float x) +{ + float a, b, c; + int m; + union{ + float f; + int i; + } xx; + + x = 2.0f * x; + a = expf_c(x); + c = a + 1.0f; + + //reciporical approx. + xx.f = c; + m = 0x3F800000 - (xx.i & 0x7F800000); + xx.i = xx.i + m; + xx.f = 1.41176471f - 0.47058824f * xx.f; + xx.i = xx.i + m; + b = 2.0 - xx.f * c; + xx.f = xx.f * b; + b = 2.0 - xx.f * c; + xx.f = xx.f * b; + c = a - 1.0; + xx.f *= c; + return xx.f; +} + + +float tanhf_neon_hfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ("vadd.f32 d0, d0, d0 \n\t"); + expf_neon_hfp(x); + asm volatile ( + "vmov.f32 d2, #1.0 \n\t" + "vsub.f32 d3, d0, d2 \n\t" + "vadd.f32 d0, d0, d2 \n\t" + + "vrecpe.f32 d1, d0 \n\t" //d1 = ~ 1 / d0; + "vrecps.f32 d2, d1, d0 \n\t" //d2 = 2.0 - d1 * d0; + "vmul.f32 d1, d1, d2 \n\t" //d1 = d1 * d2; + "vrecps.f32 d2, d1, d0 \n\t" //d2 = 2.0 - d1 * d0; + "vmul.f32 d0, d1, d2 \n\t" //d0 = d1 * d2; + "vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3; + ::: "d0", "d1", "d2", "d3" + ); +#endif +} + +float tanhf_neon_sfp(float x) +{ +#ifdef __MATH_NEON + asm volatile ("vmov.f32 s0, r0 \n\t"); + tanhf_neon_hfp(x); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return tanhf_c(x); +#endif +}; + diff --git a/jni/desmume/src/android/math-neon/math_vec2.c b/jni/desmume/src/android/math-neon/math_vec2.c new file mode 100755 index 0000000..810d562 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_vec2.c @@ -0,0 +1,114 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "math_neon.h" + +//vec2 scalar product +float +dot2_c(float v0[2], float v1[2]) +{ + float r; + r = v0[0]*v1[0]; + r += v0[1]*v1[1]; + return r; +} + +void +normalize2_c(float v[2], float d[2]) +{ + float b, c, x; + union { + float f; + int i; + } a; + + x = v[0]*v[0]; + x += v[1]*v[1]; + + //fast invsqrt approx + a.f = x; + a.i = 0x5F3759DF - (a.i >> 1); //VRSQRTE + c = x * a.f; + b = (3.0f - c * a.f) * 0.5; //VRSQRTS + a.f = a.f * b; + c = x * a.f; + b = (3.0f - c * a.f) * 0.5; + a.f = a.f * b; + + d[0] = v[0]*a.f; + d[1] = v[1]*a.f; +} + +float +dot2_neon_hfp(float v0[2], float v1[2]) +{ +#ifdef __MATH_NEON + asm volatile ( + "vld1.32 {d2}, [%0] \n\t" //d2={x0,y0} + "vld1.32 {d4}, [%1] \n\t" //d4={x1,y1} + "vmul.f32 d0, d2, d4 \n\t" //d0 = d2*d4 + "vpadd.f32 d0, d0, d0 \n\t" //d0 = d[0] + d[1] + :: "r"(v0), "r"(v1) + : + ); +#endif +} + +float +dot2_neon_sfp(float v0[2], float v1[2]) +{ +#ifdef __MATH_NEON + dot2_neon_hfp(v0, v1); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return dot2_c(v0, v1); +#endif +}; + +void +normalize2_neon(float v[2], float d[2]) +{ +#ifdef __MATH_NEON + asm volatile ( + "vld1.32 d4, [%0] \n\t" //d4 = {x0,y0} + "vmul.f32 d0, d4, d4 \n\t" //d0 = d2*d2 + "vpadd.f32 d0, d0 \n\t" //d0 = d[0] + d[1] + + "vmov.f32 d1, d0 \n\t" //d1 = d0 + "vrsqrte.f32 d0, d0 \n\t" //d0 = ~ 1.0 / sqrt(d0) + "vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1 + "vrsqrts.f32 d3, d2, d0 \n\t" //d3 = (3 - d0 * d2) / 2 + "vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3 + "vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1 + "vrsqrts.f32 d3, d2, d0 \n\t" //d3 = (3 - d0 * d2) / 2 + "vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3 + + "vmul.f32 d4, d4, d0[0] \n\t" //d4 = d4*d0[0] + "vst1.32 d4, [%1] \n\t" // + + :: "r"(v), "r"(d) + : "d0", "d1", "d2", "d3", "d4", "memory" + ); +#else + normalize2_c(v, d); +#endif +} + diff --git a/jni/desmume/src/android/math-neon/math_vec3.c b/jni/desmume/src/android/math-neon/math_vec3.c new file mode 100755 index 0000000..26f3771 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_vec3.c @@ -0,0 +1,169 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "math_neon.h" + +//vec4 scalar product +float +dot3_c(float v0[3], float v1[3]) +{ + float r; + r = v0[0]*v1[0]; + r += v0[1]*v1[1]; + r += v0[2]*v1[2]; + return r; +} + +void +cross3_c(float v0[3], float v1[3], float d[3]) +{ + d[0] = v0[1]*v1[2] - v0[2]*v1[1]; + d[1] = v0[2]*v1[0] - v0[0]*v1[2]; + d[2] = v0[0]*v1[1] - v0[1]*v1[0]; +} + +void +normalize3_c(float v[3], float d[3]) +{ + float b, c, x; + union { + float f; + int i; + } a; + + x = v[0]*v[0]; + x += v[1]*v[1]; + x += v[2]*v[2]; + + //fast invsqrt approx + a.f = x; + a.i = 0x5F3759DF - (a.i >> 1); //VRSQRTE + c = x * a.f; + b = (3.0f - c * a.f) * 0.5; //VRSQRTS + a.f = a.f * b; + c = x * a.f; + b = (3.0f - c * a.f) * 0.5; + a.f = a.f * b; + + d[0] = v[0]*a.f; + d[1] = v[1]*a.f; + d[2] = v[2]*a.f; +} + + +float +dot3_neon_hfp(float v0[3], float v1[3]) +{ +#ifdef __MATH_NEON + asm volatile ( + "vld1.32 {d2}, [%0] \n\t" //d2={x0,y0} + "flds s6, [%0, #8] \n\t" //d3[0]={z0} + "vld1.32 {d4}, [%1] \n\t" //d4={x1,y1} + "flds s10, [%1, #8] \n\t" //d5[0]={z1} + + "vmul.f32 d0, d2, d4 \n\t" //d0= d2*d4 + "vpadd.f32 d0, d0, d0 \n\t" //d0 = d[0] + d[1] + "vmla.f32 d0, d3, d5 \n\t" //d0 = d0 + d3*d5 + :: "r"(v0), "r"(v1) + : "d0","d1","d2","d3","d4","d5" + ); +#endif +} + +float +dot3_neon_sfp(float v0[3], float v1[3]) +{ +#ifdef __MATH_NEON + dot3_neon_hfp(v0, v1); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return dot3_c(v0, v1); +#endif +}; + + +void cross3_neon(float v0[3], float v1[3], float d[3]) +{ +#ifdef __MATH_NEON + asm volatile ( + "flds s3, [%0] \n\t" //d1[1]={x0} + "add %0, %0, #4 \n\t" // + "vld1.32 {d0}, [%0] \n\t" //d0={y0,z0} + "vmov.f32 s2, s1 \n\t" //d1[0]={z0} + + "flds s5, [%1] \n\t" //d2[1]={x1} + "add %1, %1, #4 \n\t" // + "vld1.32 {d3}, [%1] \n\t" //d3={y1,z1} + "vmov.f32 s4, s7 \n\t" //d2[0]=d3[1] + + "vmul.f32 d4, d0, d2 \n\t" //d4=d0*d2 + "vmls.f32 d4, d1, d3 \n\t" //d4-=d1*d3 + + "vmul.f32 d5, d3, d1[1] \n\t" //d5=d3*d1[1] + "vmls.f32 d5, d0, d2[1] \n\t" //d5-=d0*d2[1] + + "vst1.32 d4, [%2] \n\t" // + "add %2, %2, #8 \n\t" // + "fsts s10, [%2] \n\t" // + + : "+r"(v0), "+r"(v1), "+r"(d): + : "d0", "d1", "d2", "d3", "d4", "d5", "memory" + ); +#else + cross3_c(v0,v1,d); +#endif +} + +void +normalize3_neon(float v[3], float d[3]) +{ +#ifdef __MATH_NEON + asm volatile ( + "vld1.32 {d4}, [%0] \n\t" //d4={x0,y0} + "flds s10, [%0, #8] \n\t" //d5[0]={z0} + + "vmul.f32 d0, d4, d4 \n\t" //d0= d4*d4 + "vpadd.f32 d0, d0 \n\t" //d0 = d[0] + d[1] + "vmla.f32 d0, d5, d5 \n\t" //d0 = d0 + d5*d5 + + "vmov.f32 d1, d0 \n\t" //d1 = d0 + "vrsqrte.f32 d0, d0 \n\t" //d0 = ~ 1.0 / sqrt(d0) + "vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1 + "vrsqrts.f32 d3, d2, d0 \n\t" //d3 = (3 - d0 * d2) / 2 + "vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3 + "vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1 + "vrsqrts.f32 d3, d2, d0 \n\t" //d4 = (3 - d0 * d3) / 2 + "vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d4 + + "vmul.f32 q2, q2, d0[0] \n\t" //d0= d2*d4 + "vst1.32 {d4}, [%1] \n\t" // + "fsts s10, [%1, #8] \n\t" // + + :: "r"(v), "r"(d) + : "d0", "d1", "d2", "d3", "d4", "d5", "memory" + ); +#else + normalize3_c(v, d); +#endif + +} + + diff --git a/jni/desmume/src/android/math-neon/math_vec4.c b/jni/desmume/src/android/math-neon/math_vec4.c new file mode 100755 index 0000000..1fc0b86 --- /dev/null +++ b/jni/desmume/src/android/math-neon/math_vec4.c @@ -0,0 +1,144 @@ +/* +Math-NEON: Neon Optimised Math Library based on cmath +Contact: lachlan.ts@gmail.com +Copyright (C) 2009 Lachlan Tychsen - Smith aka Adventus + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "math_neon.h" + +#include "arm_neon.h" + +//vec4 scalar product +float +dot4_c(float v0[4], float v1[4]) +{ + float r; + r = v0[0]*v1[0]; + r += v0[1]*v1[1]; + r += v0[2]*v1[2]; + r += v0[3]*v1[3]; + return r; +} + +void +normalize4_c(float v[4], float d[4]) +{ + float b, c, x; + union { + float f; + int i; + } a; + + x = v[0]*v[0]; + x += v[1]*v[1]; + x += v[2]*v[2]; + x += v[3]*v[3]; + + //fast invsqrt approx + a.f = x; + a.i = 0x5F3759DF - (a.i >> 1); //VRSQRTE + c = x * a.f; + b = (3.0f - c * a.f) * 0.5; //VRSQRTS + a.f = a.f * b; + c = x * a.f; + b = (3.0f - c * a.f) * 0.5; + a.f = a.f * b; + + d[0] = v[0]*a.f; + d[1] = v[1]*a.f; + d[2] = v[2]*a.f; + d[3] = v[3]*a.f; +} + +void +normalize4_neon(float v[4], float d[4]) +{ +#ifdef __MATH_NEON + asm volatile ( + "vld1.32 {d4, d5}, [%0] \n\t" //d2={x0,y0}, d3={z0, w0} + "vmul.f32 d0, d4, d4 \n\t" //d0= d4*d4 + "vmla.f32 d0, d5, d5 \n\t" //d0 = d0 + d5*d5 + "vpadd.f32 d0, d0 \n\t" //d0 = d[0] + d[1] + + "vmov.f32 d1, d0 \n\t" //d1 = d0 + "vrsqrte.f32 d0, d0 \n\t" //d0 = ~ 1.0 / sqrt(d0) + "vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1 + "vrsqrts.f32 d3, d2, d0 \n\t" //d3 = (3 - d0 * d2) / 2 + "vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3 + "vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1 + "vrsqrts.f32 d3, d2, d0 \n\t" //d4 = (3 - d0 * d3) / 2 + "vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d4 + + "vmul.f32 q2, q2, d0[0] \n\t" //d0= d2*d4 + "vst1.32 {d4, d5}, [%1] \n\t" //d2={x0,y0}, d3={z0, w0} + + :: "r"(v), "r"(d) + : "d0", "d1", "d2", "d3", "d4", "d5", "memory" + ); +#else + normalize4_c(v, d); +#endif + +} + + +float +dot4_neon_hfp(float v0[4], float v1[4]) +{ +#ifdef __MATH_NEON + asm volatile ( + "vld1.32 {d2, d3}, [%0] \n\t" //d2={x0,y0}, d3={z0, w0} + "vld1.32 {d4, d5}, [%1] \n\t" //d4={x1,y1}, d5={z1, w1} + "vmul.f32 d0, d2, d4 \n\t" //d0= d2*d4 + "vmla.f32 d0, d3, d5 \n\t" //d0 = d0 + d3*d5 + "vpadd.f32 d0, d0 \n\t" //d0 = d[0] + d[1] + :: "r"(v0), "r"(v1) : + ); +#endif +} + +#if 0 //funky ifdef problem... figure out later + +float32_t +dot4_neon(float32x4_t v0, float32x4_t v1) +{ + float32x2_t a, b, c, d, r; + a = vget_high_f32(v0); + b = vget_low_f32(v0); + c = vget_high_f32(v1); + d = vget_low_f32(v1); + + r = vmul_f32(a, c); + r = vmla_f32(r, b, d); + r = vpadd_f32(r, r); + return vget_lane_f32(r, 0); +} + +float +dot4_neon_sfp(float v0[4], float v1[4]) +{ +#ifdef __MATH_NEON + dot4_neon_hfp(v0, v1); + asm volatile ("vmov.f32 r0, s0 \n\t"); +#else + return dot4_c(v0, v1); +#endif +}; + +#endif + diff --git a/jni/desmume/src/android/mic.cpp b/jni/desmume/src/android/mic.cpp new file mode 100755 index 0000000..4d58f21 --- /dev/null +++ b/jni/desmume/src/android/mic.cpp @@ -0,0 +1,57 @@ +/* + Copyright (C) 2012 Jeffrey Quesnelle + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* + The NDS microphone produces 8-bit sound sampled at 16khz. + The sound data must be read sample-by-sample through the + ARM7 SPI device (touchscreen controller, channel 6). + + Note : I added these notes because the microphone isn't + documented on GBATek. +*/ + +#include "../mic.h" +#include "readwrite.h" + +void Mic_DeInit() +{ +} + +BOOL Mic_Init() +{ + return FALSE; +} + +void Mic_Reset() +{ +} + +u8 Mic_ReadSample() +{ + return 0; +} + +void mic_savestate(EMUFILE* os) +{ + write32le(-1,os); +} + +bool mic_loadstate(EMUFILE* is, int size) +{ + is->fseek(size, SEEK_CUR); + return TRUE; +} \ No newline at end of file diff --git a/jni/desmume/src/android/neontest.cpp b/jni/desmume/src/android/neontest.cpp new file mode 100755 index 0000000..18c295e --- /dev/null +++ b/jni/desmume/src/android/neontest.cpp @@ -0,0 +1,226 @@ +/* + Copyright (C) 2012 Jeffrey Quesnelle + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "neontest.h" +extern "C" { +#include "math-neon/math_neon.h" +} +#include "../matrix.h" +#include "main.h" +#include <stdio.h> +#include <string.h> + +template<int WIDTH, int HEIGHT> void printmatrix(float* matrix) +{ + for(int y = 0 ; y < HEIGHT ; ++y ) + { + char line[1024], work[1024]; + strcpy(line,"|"); + for(int x = 0 ; x < WIDTH ; ++x) + { + sprintf(work, "%.2f%s", matrix[(y * WIDTH) + x], x == WIDTH - 1 ? "|" : ", "); + strcat(line, work); + } + LOGI("%s", line); + } +} + +void MatrixMultVec4x4Neon(float *matrix, float *vecPtr) +{ + matvec4_neon(matrix, vecPtr, vecPtr); +} + +void MatrixMultVec3x3Neon(float *matrix, float *vecPtr) +{ + //fails... looks like it's still packed like a 4x4 in matrix.cpp + matvec3_neon(matrix, vecPtr, vecPtr); +} + +void MatrixMultiplyNeon(float * matrix, float * rightMatrix) +{ + float ret[16]; + matmul4_neon(matrix, rightMatrix, ret); + memcpy(matrix, ret, sizeof(float)*16); +} + +void MatrixMultVec4x4_M2Neon(float *matrix, float *vecPtr) +{ + matvec4_neon(matrix+16, vecPtr, vecPtr); + matvec4_neon(matrix, vecPtr, vecPtr); +} + +void testmultvec4x4() +{ + LOGI("MatrixMultVec4x4"); + float matrix1[] = { + 1.0f, 2.0f, 3.0f, 4.0f, + 5.0f, 6.0f, 7.0f, 8.0f, + 9.0f, 10.0f, 11.0f, 12.0f, + 13.0f, 14.0f, 15.0f, 16.0f + }; + + float vector[] = { + M_PI, + M_E, + M_LN2, + M_SQRT2 + }; + + float vectorc[4], vectorneon[4]; + + memcpy(vectorc, vector, sizeof(float)* 4 ); + memcpy(vectorneon, vector, sizeof(float)* 4 ); + + printmatrix<4,4>(matrix1); + LOGI("*"); + printmatrix<4,1>(vectorc); + MatrixMultVec4x4(matrix1, vectorc); + LOGI("="); + printmatrix<4,1>(vectorc); + + printmatrix<4,4>(matrix1); + LOGI("*"); + printmatrix<4,1>(vectorneon); + MatrixMultVec4x4Neon(matrix1, vectorneon); + LOGI("="); + printmatrix<4,1>(vectorneon); +} +void testmultvec3x3() +{ + LOGI("MatrixMultVec3x3"); + float matrix1[] = { + 1.0f, 2.0f, 3.0f, + 5.0f, 6.0f, 7.0f, + 9.0f, 10.0f, 11.0f, + }; + + float vector[] = { + M_PI, + M_E, + M_LN2, + }; + + float vectorc[3], vectorneon[3]; + + memcpy(vectorc, vector, sizeof(float)* 3 ); + memcpy(vectorneon, vector, sizeof(float)* 3 ); + + printmatrix<3,3>(matrix1); + LOGI("*"); + printmatrix<3,1>(vectorc); + MatrixMultVec3x3(matrix1, vectorc); + LOGI("="); + printmatrix<3,1>(vectorc); + + printmatrix<3,3>(matrix1); + LOGI("*"); + printmatrix<3,1>(vectorneon); + MatrixMultVec3x3Neon(matrix1, vectorneon); + LOGI("="); + printmatrix<3,1>(vectorneon); +} + +void testmatrixmul() +{ + LOGI("MatrixMultiply"); + + float matrix1[] = { + 1.0f, 2.0f, 3.0f, 4.0f, + 5.0f, 6.0f, 7.0f, 8.0f, + 9.0f, 10.0f, 11.0f, 12.0f, + 13.0f, 14.0f, 15.0f, 16.0f + }; + + float matrix2[] = { + 17.0f, 18.0f, 19.0f, 20.0f, + 21.0f, 22.0f, 23.0f, 24.0f, + 25.0f, 26.0f, 27.0f, 28.0f, + 29.0f, 30.0f, 31.0f, 32.0f + }; + + float matrixc[16], matrixneon[16]; + + memcpy(matrixc, matrix1, sizeof(float)* 16 ); + memcpy(matrixneon, matrix1, sizeof(float)* 16 ); + + printmatrix<4,4>(matrixc); + LOGI("*"); + printmatrix<4,4>(matrix2); + MatrixMultiply(matrixc, matrix2); + LOGI("="); + printmatrix<4,4>(matrixc); + + printmatrix<4,4>(matrixneon); + LOGI("*"); + printmatrix<4,4>(matrix2); + MatrixMultiplyNeon(matrixneon, matrix2); + LOGI("="); + printmatrix<4,4>(matrixneon); +} + +void testmultvec4x4_m2() +{ + LOGI("MatrixMultVec4x4_M2"); + float matrix1[] = { + 1.0f, 2.0f, 3.0f, 4.0f, + 5.0f, 6.0f, 7.0f, 8.0f, + 9.0f, 10.0f, 11.0f, 12.0f, + 13.0f, 14.0f, 15.0f, 16.0f, + 17.0f, 18.0f, 19.0f, 20.0f, + 21.0f, 22.0f, 23.0f, 24.0f, + 25.0f, 26.0f, 27.0f, 28.0f, + 29.0f, 30.0f, 31.0f, 32.0f + }; + + float vector[] = { + M_PI, + M_E, + M_LN2, + M_SQRT2 + }; + + float vectorc[4], vectorneon[4]; + + memcpy(vectorc, vector, sizeof(float)* 4 ); + memcpy(vectorneon, vector, sizeof(float)* 4 ); + + printmatrix<4,4>(matrix1); + LOGI("*"); + printmatrix<4,4>(matrix1+16); + LOGI("*"); + printmatrix<4,1>(vectorc); + MatrixMultVec4x4_M2(matrix1, vectorc); + LOGI("="); + printmatrix<4,1>(vectorc); + + printmatrix<4,4>(matrix1); + LOGI("*"); + printmatrix<4,4>(matrix1+16); + LOGI("*"); + printmatrix<4,1>(vectorneon); + MatrixMultVec4x4_M2Neon(matrix1, vectorneon); + LOGI("="); + printmatrix<4,1>(vectorneon); +} + +void neontest() +{ + //testmultvec4x4(); + //testmatrixmul(); + //testmultvec4x4_m2(); + testmultvec3x3(); +} \ No newline at end of file diff --git a/jni/desmume/src/android/neontest.h b/jni/desmume/src/android/neontest.h new file mode 100755 index 0000000..dddc410 --- /dev/null +++ b/jni/desmume/src/android/neontest.h @@ -0,0 +1,6 @@ +#ifndef _NEONTEST_H +#define _NEONTEST_H + +void neontest(); + +#endif \ No newline at end of file diff --git a/jni/desmume/src/android/ogl.cpp b/jni/desmume/src/android/ogl.cpp new file mode 100755 index 0000000..7565d90 --- /dev/null +++ b/jni/desmume/src/android/ogl.cpp @@ -0,0 +1,16 @@ +/* + Copyright (C) 2012 Jeffrey Quesnelle + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ diff --git a/jni/desmume/src/android/throttle.cpp b/jni/desmume/src/android/throttle.cpp new file mode 100755 index 0000000..f990714 --- /dev/null +++ b/jni/desmume/src/android/throttle.cpp @@ -0,0 +1,291 @@ +//THIS SPEED THROTTLE WAS TAKEN FROM FCEUX. +//Copyright (C) 2002 Xodnizel +//(the code might look quite different by now, though...) + +/* + Many Modifications Copyright (C) 2009-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "../common.h" +#include "../types.h" +#include "../debug.h" +#ifndef ANDROID +#include "../console.h" +#endif +#include "throttle.h" +#include "GPU_osd.h" + +int FastForward=0; +static u64 tmethod,tfreq,afsfreq; +static const u64 core_desiredfps = 3920763; //59.8261 +static u64 desiredfps = core_desiredfps; +static float desiredspf = 65536.0f / core_desiredfps; +#ifdef ANDROID +static int desiredFpsScalerIndex = 5; +#else +static int desiredFpsScalerIndex = GetPrivateProfileInt("Video","FPS Scaler Index", 5, IniName); +#endif + +static u64 desiredFpsScalers [] = { + 1024, + 512, // 200% + 448, // 175% + 384, // 150% + 320, // 125% + 256, // 100% + 192, + 128, // 50% + 96, + 64, // 25% + 42, + 32, + 16, +}; + +#ifdef ANDROID +#include <sys/time.h> +#include <time.h> +unsigned int GetTickCount() +{ + timeval timer; + gettimeofday(&timer, NULL); + return (timer.tv_sec * 1000) + (timer.tv_usec/1000); +} + +void Sleep(int ms) +{ + usleep(ms * 1000); +} + +#endif + +void IncreaseSpeed(void) { + + if(desiredFpsScalerIndex) + desiredFpsScalerIndex--; + u64 desiredFpsScaler = desiredFpsScalers[desiredFpsScalerIndex]; + desiredfps = core_desiredfps * desiredFpsScaler / 256; + desiredspf = 65536.0f / desiredfps; + printf("Throttle fps scaling increased to: %f\n",desiredFpsScaler/256.0); + osd->addLine("Target FPS up to %2.04f",desiredFpsScaler/256.0); + #ifndef ANDROID + WritePrivateProfileInt("Video","FPS Scaler Index", desiredFpsScalerIndex, IniName); + #endif +} + +void DecreaseSpeed(void) { + + if(desiredFpsScalerIndex != sizeof(desiredFpsScalers)/sizeof(desiredFpsScalers[0]) - 1) + desiredFpsScalerIndex++; + u64 desiredFpsScaler = desiredFpsScalers[desiredFpsScalerIndex]; + desiredfps = core_desiredfps * desiredFpsScaler / 256; + desiredspf = 65536.0f / desiredfps; + printf("Throttle fps scaling decreased to: %f\n",desiredFpsScaler/256.0); + osd->addLine("Target FPS down to %2.04f",desiredFpsScaler/256.0); +#ifndef ANDROID + WritePrivateProfileInt("Video","FPS Scaler Index", desiredFpsScalerIndex, IniName); +#endif +} + +static u64 GetCurTime(void) +{ +#ifndef ANDROID + if(tmethod) + { + u64 tmp; + QueryPerformanceCounter((LARGE_INTEGER*)&tmp); + return tmp; + } + else +#endif + { + return (u64)GetTickCount(); + } +} + +void InitSpeedThrottle(void) +{ + tmethod=0; +#ifndef ANDROID + if(QueryPerformanceFrequency((LARGE_INTEGER*)&afsfreq)) + tmethod=1; + else +#endif + afsfreq=1000; + tfreq = afsfreq << 16; + + AutoFrameSkip_IgnorePreviousDelay(); +} + +static void AutoFrameSkip_BeforeThrottle(); + +static u64 ltime; + +void SpeedThrottle() +{ + AutoFrameSkip_BeforeThrottle(); + +waiter: + if(FastForward) + return; + + u64 ttime = GetCurTime(); + + if((ttime - ltime) < (tfreq / desiredfps)) + { + u64 sleepy; + sleepy = (tfreq / desiredfps) - (ttime - ltime); + sleepy *= 1000; + if(tfreq >= 65536) + sleepy /= afsfreq; + else + sleepy = 0; + if(sleepy >= 10) + Sleep((sleepy / 2)); // reduce it further beacuse Sleep usually sleeps for more than the amount we tell it to +#ifndef ANDROID + else if(sleepy > 0) // spin for <1 millisecond waits + SwitchToThread(); // limit to other threads on the same CPU core for other short waits +#endif + goto waiter; + } + if( (ttime-ltime) >= (tfreq*4/desiredfps)) + ltime=ttime; + else + ltime+=tfreq/desiredfps; +} + + +// auto frameskip + +static u64 beginticks=0, endticks=0, preThrottleEndticks=0; +static float fSkipFrames = 0; +static float fSkipFramesError = 0; +static int lastSkip = 0; +static float lastError = 0; +static float integral = 0; + +void AutoFrameSkip_IgnorePreviousDelay() +{ + beginticks = GetCurTime(); + + // this seems to be a stable way of allowing the skip frames to + // quickly adjust to a faster environment (e.g. after a loadstate) + // without causing oscillation or a sudden change in skip rate + fSkipFrames *= 0.5f; +} + +static void AutoFrameSkip_BeforeThrottle() +{ + preThrottleEndticks = GetCurTime(); +} + +void AutoFrameSkip_NextFrame() +{ + endticks = GetCurTime(); + + // calculate time since last frame + u64 diffticks = endticks - beginticks; + float diff = (float)diffticks / afsfreq; + + // calculate time since last frame not including throttle sleep time + if(!preThrottleEndticks) // if we didn't throttle, use the non-throttle time + preThrottleEndticks = endticks; + u64 diffticksUnthrottled = preThrottleEndticks - beginticks; + float diffUnthrottled = (float)diffticksUnthrottled / afsfreq; + + + float error = diffUnthrottled - desiredspf; + + + // reset way-out-of-range values + if(diff > 1) + diff = 1; + if(error > 1 || error < -1) + error = 0; + if(diffUnthrottled > 1) + diffUnthrottled = desiredspf; + + float derivative = (error - lastError) / diff; + lastError = error; + + integral = integral + (error * diff); + integral *= 0.99f; // since our integral isn't reliable, reduce it to 0 over time. + + // "PID controller" constants + // this stuff is probably being done all wrong, but these seem to work ok + static const float Kp = 40.0f; + static const float Ki = 0.55f; + static const float Kd = 0.04f; + + float errorTerm = error * Kp; + float derivativeTerm = derivative * Kd; + float integralTerm = integral * Ki; + float adjustment = errorTerm + derivativeTerm + integralTerm; + + // apply the output adjustment + fSkipFrames += adjustment; + + // if we're running too slowly, prevent the throttle from kicking in + if(adjustment > 0 && fSkipFrames > 0) + ltime-=tfreq/desiredfps; + + preThrottleEndticks = 0; + beginticks = GetCurTime(); +} + +int AutoFrameSkip_GetSkipAmount(int min, int max) +{ + int rv = (int)fSkipFrames; + fSkipFramesError += fSkipFrames - rv; + + // resolve accumulated fractional error + // where doing so doesn't push us out of range + while(fSkipFramesError >= 1.0f && rv <= lastSkip && rv < max) + { + fSkipFramesError -= 1.0f; + rv++; + } + while(fSkipFramesError <= -1.0f && rv >= lastSkip && rv > min) + { + fSkipFramesError += 1.0f; + rv--; + } + + // restrict skip amount to requested range + if(rv < min) + rv = min; + if(rv > max) + rv = max; + + // limit maximum error accumulation (it's mainly only for fractional components) + if(fSkipFramesError >= 4.0f) + fSkipFramesError = 4.0f; + if(fSkipFramesError <= -4.0f) + fSkipFramesError = -4.0f; + + // limit ongoing skipframes to requested range + 1 on each side + if(fSkipFrames < min-1) + fSkipFrames = (float)min-1; + if(fSkipFrames > max+1) + fSkipFrames = (float)max+1; + +// printf("%d", rv); + + lastSkip = rv; + return rv; +} + + diff --git a/jni/desmume/src/android/throttle.h b/jni/desmume/src/android/throttle.h new file mode 100755 index 0000000..82ab654 --- /dev/null +++ b/jni/desmume/src/android/throttle.h @@ -0,0 +1,33 @@ +/* + Copyright (C) 2008-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _THROTTLE_H_ +#define _THROTTLE_H_ + +extern int FastForward; +extern bool FrameLimit; +void IncreaseSpeed(); +void DecreaseSpeed(); + +void InitSpeedThrottle(); +void SpeedThrottle(); + +void AutoFrameSkip_NextFrame(); +void AutoFrameSkip_IgnorePreviousDelay(); +int AutoFrameSkip_GetSkipAmount(int min=0, int max=9); + +#endif diff --git a/jni/desmume/src/android/video.h b/jni/desmume/src/android/video.h new file mode 100755 index 0000000..788fe16 --- /dev/null +++ b/jni/desmume/src/android/video.h @@ -0,0 +1,251 @@ +/* + Copyright (C) 2009-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "filter/filter.h" + +class VideoInfo +{ +public: + + int width; + int height; + + int rotation; + int rotation_userset; + int screengap; + int layout; + int layout_old; + int swap; + + int currentfilter; + + u8* srcBuffer; + CACHE_ALIGN u32 buffer[16*256*192*2]; + CACHE_ALIGN u32 filteredbuffer[16*256*192*2]; + + enum { + NONE, + HQ2X, + _2XSAI, + SUPER2XSAI, + SUPEREAGLE, + SCANLINE, + BILINEAR, + NEAREST2X, + HQ2XS, + LQ2X, + LQ2XS, + EPX, + NEARESTPLUS1POINT5, + NEAREST1POINT5, + EPXPLUS, + EPX1POINT5, + EPXPLUS1POINT5, + HQ4X, + + NUM_FILTERS, + }; + + + void reset() { + width = 256; + height = 384; + } + + void setfilter(int filter) { + + if(filter < 0 || filter >= NUM_FILTERS) + filter = NONE; + + currentfilter = filter; + + switch(filter) { + + case NONE: + width = 256; + height = 384; + break; + case EPX1POINT5: + case EPXPLUS1POINT5: + case NEAREST1POINT5: + case NEARESTPLUS1POINT5: + width = 256*3/2; + height = 384*3/2; + break; + case HQ4X: + width = 256*4; + height = 384*4; + break; + default: + width = 256*2; + height = 384*2; + break; + } + } + + SSurface src; + SSurface dst; + + u16* finalBuffer() const + { + if(currentfilter == NONE) + return (u16*)buffer; + else return (u16*)filteredbuffer; + } + + void filter() { + + src.Height = 384; + src.Width = 256; + src.Pitch = 512; + src.Surface = (u8*)buffer; + + dst.Height = height; + dst.Width = width; + dst.Pitch = width*2; + dst.Surface = (u8*)filteredbuffer; + + switch(currentfilter) + { + case NONE: + break; + case LQ2X: + RenderLQ2X(src, dst); + break; + case LQ2XS: + RenderLQ2XS(src, dst); + break; + case HQ2X: + RenderHQ2X(src, dst); + break; + case HQ4X: + RenderHQ4X(src, dst); + break; + case HQ2XS: + RenderHQ2XS(src, dst); + break; + case _2XSAI: + Render2xSaI (src, dst); + break; + case SUPER2XSAI: + RenderSuper2xSaI (src, dst); + break; + case SUPEREAGLE: + RenderSuperEagle (src, dst); + break; + case SCANLINE: + RenderScanline(src, dst); + break; + case BILINEAR: + RenderBilinear(src, dst); + break; + case NEAREST2X: + RenderNearest2X(src,dst); + break; + case EPX: + RenderEPX(src,dst); + break; + case EPXPLUS: + RenderEPXPlus(src,dst); + break; + case EPX1POINT5: + RenderEPX_1Point5x(src,dst); + break; + case EPXPLUS1POINT5: + RenderEPXPlus_1Point5x(src,dst); + break; + case NEAREST1POINT5: + RenderNearest_1Point5x(src,dst); + break; + case NEARESTPLUS1POINT5: + RenderNearestPlus_1Point5x(src,dst); + break; + } + } + + int size() { + return width*height; + } + + int dividebyratio(int x) { + return x * 256 / width; + } + + int rotatedwidth() { + switch(rotation) { + case 0: + return width; + case 90: + return height; + case 180: + return width; + case 270: + return height; + default: + return 0; + } + } + + int rotatedheight() { + switch(rotation) { + case 0: + return height; + case 90: + return width; + case 180: + return height; + case 270: + return width; + default: + return 0; + } + } + + int rotatedwidthgap() { + switch(rotation) { + case 0: + return width; + case 90: + return height + ((layout == 0) ? scaledscreengap() : 0); + case 180: + return width; + case 270: + return height + ((layout == 0) ? scaledscreengap() : 0); + default: + return 0; + } + } + + int rotatedheightgap() { + switch(rotation) { + case 0: + return height + ((layout == 0) ? scaledscreengap() : 0); + case 90: + return width; + case 180: + return height + ((layout == 0) ? scaledscreengap() : 0); + case 270: + return width; + default: + return 0; + } + } + + int scaledscreengap() { + return screengap * height / 384; + } +}; diff --git a/jni/desmume/src/arm_instructions.cpp b/jni/desmume/src/arm_instructions.cpp new file mode 100755 index 0000000..4abb609 --- /dev/null +++ b/jni/desmume/src/arm_instructions.cpp @@ -0,0 +1,6388 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2006-2007 shash + Copyright (C) 2008-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +// ARM core TODO: +// - Check all the LDM/STM opcodes: quirks when Rb included in Rlist; opcodes +// operating on user registers (LDMXX2/STMXX2) +// - Force User mode memory access for LDRx/STRx opcodes with bit24=0 and bit21=1 +// (has to be done at memory side; once the PU is emulated well enough) +// - Check LDMxx2/STMxx2 (those opcodes that act on User mode registers instead +// of current ones) + +//#define UNTESTEDOPCODEDEBUG +#include "cp15.h" +#include "debug.h" +#include "MMU.h" +#include "armcpu.h" +#include "NDSSystem.h" +#include "arm_instructions.h" +#include "MMU_timing.h" + +#define cpu (&ARMPROC) +#define TEMPLATE template<int PROCNUM> + +//----------------------------------------------------------------------------- +// Shifting macros +//----------------------------------------------------------------------------- + +#define LSL_IMM \ + u32 shift_op = cpu->R[REG_POS(i,0)]<<((i>>7)&0x1F); + +#define S_LSL_IMM \ + u32 shift_op = ((i>>7)&0x1F); \ + u32 c = cpu->CPSR.bits.C; \ + if(shift_op==0) \ + shift_op=cpu->R[REG_POS(i,0)]; \ + else \ + { \ + c = BIT_N(cpu->R[REG_POS(i,0)], 32-shift_op); \ + shift_op = cpu->R[REG_POS(i,0)]<<shift_op; \ + } + +#define LSL_REG \ + u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF; \ + if(shift_op>=32) \ + shift_op=0; \ + else \ + shift_op=cpu->R[REG_POS(i,0)]<<shift_op; + +#define S_LSL_REG \ + u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF; \ + u32 c = cpu->CPSR.bits.C; \ + if(shift_op==0) \ + shift_op=cpu->R[REG_POS(i,0)]; \ + else \ + if(shift_op<32) \ + { \ + c = BIT_N(cpu->R[REG_POS(i,0)], 32-shift_op); \ + shift_op = cpu->R[REG_POS(i,0)]<<shift_op; \ + } \ + else \ + if(shift_op==32) \ + { \ + shift_op = 0; \ + c = BIT0(cpu->R[REG_POS(i,0)]); \ + } \ + else \ + { \ + shift_op = 0; \ + c = 0; \ + } + +#define LSR_IMM \ + u32 shift_op = ((i>>7)&0x1F); \ + if(shift_op!=0) \ + shift_op = cpu->R[REG_POS(i,0)]>>shift_op; + +#define S_LSR_IMM \ + u32 shift_op = ((i>>7)&0x1F); \ + u32 c = cpu->CPSR.bits.C; \ + if(shift_op==0) \ + { \ + c = BIT31(cpu->R[REG_POS(i,0)]); \ + } \ + else \ + { \ + c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1); \ + shift_op = cpu->R[REG_POS(i,0)]>>shift_op; \ + } + +#define LSR_REG \ + u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF; \ + if(shift_op>=32) \ + shift_op = 0; \ + else \ + shift_op = cpu->R[REG_POS(i,0)]>>shift_op; + +#define S_LSR_REG \ + u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF; \ + u32 c = cpu->CPSR.bits.C; \ + if(shift_op==0) \ + { \ + shift_op = cpu->R[REG_POS(i,0)]; \ + } \ + else \ + if(shift_op<32) \ + { \ + c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1); \ + shift_op = cpu->R[REG_POS(i,0)]>>shift_op; \ + } \ + else \ + if(shift_op==32) \ + { \ + c = BIT31(cpu->R[REG_POS(i,0)]); \ + shift_op = 0; \ + } \ + else \ + { \ + c = 0; \ + shift_op = 0; \ + } + +#define ASR_IMM \ + u32 shift_op = ((i>>7)&0x1F); \ + if(shift_op==0) \ + shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF; \ + else \ + shift_op = (u32)((s32)cpu->R[REG_POS(i,0)]>>shift_op); + +#define S_ASR_IMM \ + u32 shift_op = ((i>>7)&0x1F); \ + u32 c = cpu->CPSR.bits.C; \ + if(shift_op==0) \ + { \ + shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF; \ + c = BIT31(cpu->R[REG_POS(i,0)]); \ + } \ + else \ + { \ + c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1); \ + shift_op = (u32)((s32)cpu->R[REG_POS(i,0)]>>shift_op); \ + } + +#define ASR_REG \ + u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF; \ + if(shift_op==0) \ + shift_op=cpu->R[REG_POS(i,0)]; \ + else \ + if(shift_op<32) \ + shift_op = (u32)((s32)cpu->R[REG_POS(i,0)]>>shift_op); \ + else \ + shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF; + +#define S_ASR_REG \ + u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF; \ + u32 c = cpu->CPSR.bits.C; \ + if(shift_op==0) \ + shift_op=cpu->R[REG_POS(i,0)]; \ + else \ + if(shift_op<32) \ + { \ + c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1); \ + shift_op = (u32)((s32)cpu->R[REG_POS(i,0)]>>shift_op); \ + } \ + else \ + { \ + c = BIT31(cpu->R[REG_POS(i,0)]); \ + shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF; \ + } + +#define ROR_IMM \ + u32 shift_op = ((i>>7)&0x1F); \ + if(shift_op==0) \ + { \ + shift_op = ((u32)cpu->CPSR.bits.C<<31)|(cpu->R[REG_POS(i,0)]>>1); \ + } \ + else \ + shift_op = ROR(cpu->R[REG_POS(i,0)],shift_op); + +#define S_ROR_IMM \ + u32 shift_op = ((i>>7)&0x1F); \ + u32 c = cpu->CPSR.bits.C; \ + if(shift_op==0) \ + { \ + shift_op = ((u32)cpu->CPSR.bits.C<<31)|(cpu->R[REG_POS(i,0)]>>1); \ + c = BIT0(cpu->R[REG_POS(i,0)]); \ + } \ + else \ + { \ + c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1); \ + shift_op = ROR(cpu->R[REG_POS(i,0)],shift_op); \ + } + +#define ROR_REG \ + u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF; \ + if((shift_op==0)||((shift_op&0x1F)==0)) \ + shift_op=cpu->R[REG_POS(i,0)]; \ + else \ + shift_op = ROR(cpu->R[REG_POS(i,0)],(shift_op&0x1F)); + +#define S_ROR_REG \ + u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF; \ + u32 c = cpu->CPSR.bits.C; \ + if(shift_op==0) \ + shift_op=cpu->R[REG_POS(i,0)]; \ + else \ + { \ + shift_op&=0x1F; \ + if(shift_op==0) \ + { \ + shift_op=cpu->R[REG_POS(i,0)]; \ + c = BIT31(cpu->R[REG_POS(i,0)]); \ + } \ + else \ + { \ + c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1); \ + shift_op = ROR(cpu->R[REG_POS(i,0)],shift_op); \ + } \ + } + +#define IMM_VALUE \ + u32 shift_op = ROR((i&0xFF), (i>>7)&0x1E); + +#define S_IMM_VALUE \ + u32 shift_op = ROR((i&0xFF), (i>>7)&0x1E); \ + u32 c = cpu->CPSR.bits.C; \ + if((i>>8)&0xF) \ + c = BIT31(shift_op); + +#define IMM_OFF (((i>>4)&0xF0)+(i&0xF)) + +#define IMM_OFF_12 ((i)&0xFFF) + +//----------------------------------------------------------------------------- +// Undefined instruction +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_UND(const u32 i) +{ + TRAPUNDEF(cpu); + return 1; +} + +//----------------------------------------------------------------------------- +// AND / ANDS +// Timing: OK +//----------------------------------------------------------------------------- + +#define OP_AND(a, b) \ + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] & shift_op; \ + if(REG_POS(i,12)==15) \ + { \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + return a; + +#define OP_ANDS(a, b) \ + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] & shift_op; \ + if(REG_POS(i,12)==15) \ + { \ + Status_Reg SPSR = cpu->SPSR; \ + armcpu_switchMode(cpu, SPSR.bits.mode); \ + cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ + cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.bits.T)<<1)); \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + cpu->CPSR.bits.C = c; \ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); \ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); \ + return a; + +TEMPLATE static u32 FASTCALL OP_AND_LSL_IMM(const u32 i) +{ + LSL_IMM; + OP_AND(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_AND_LSL_REG(const u32 i) +{ + LSL_REG; + OP_AND(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_AND_LSR_IMM(const u32 i) +{ + LSR_IMM; + OP_AND(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_AND_LSR_REG(const u32 i) +{ + LSR_REG; + OP_AND(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_AND_ASR_IMM(const u32 i) +{ + ASR_IMM; + OP_AND(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_AND_ASR_REG(const u32 i) +{ + ASR_REG; + OP_AND(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_AND_ROR_IMM(const u32 i) +{ + ROR_IMM; + OP_AND(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_AND_ROR_REG(const u32 i) +{ + ROR_REG; + OP_AND(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_AND_IMM_VAL(const u32 i) +{ + IMM_VALUE; + OP_AND(1, 3); +} + + +TEMPLATE static u32 FASTCALL OP_AND_S_LSL_IMM(const u32 i) +{ + S_LSL_IMM; + OP_ANDS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_AND_S_LSL_REG(const u32 i) +{ + S_LSL_REG; + OP_ANDS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_AND_S_LSR_IMM(const u32 i) +{ + S_LSR_IMM; + OP_ANDS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_AND_S_LSR_REG(const u32 i) +{ + S_LSR_REG; + OP_ANDS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_AND_S_ASR_IMM(const u32 i) +{ + S_ASR_IMM; + OP_ANDS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_AND_S_ASR_REG(const u32 i) +{ + S_ASR_REG; + OP_ANDS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_AND_S_ROR_IMM(const u32 i) +{ + S_ROR_IMM; + OP_ANDS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_AND_S_ROR_REG(const u32 i) +{ + S_ROR_REG; + OP_ANDS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_AND_S_IMM_VAL(const u32 i) +{ + S_IMM_VALUE; + OP_ANDS(1, 3); +} + +//----------------------------------------------------------------------------- +// EOR / EORS +//----------------------------------------------------------------------------- + +#define OP_EOR(a, b) \ + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] ^ shift_op; \ + if(REG_POS(i,12)==15) \ + { \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + return a; + +#define OP_EORS(a, b) \ + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] ^ shift_op; \ + if(REG_POS(i,12)==15) \ + { \ + Status_Reg SPSR = cpu->SPSR; \ + armcpu_switchMode(cpu, SPSR.bits.mode); \ + cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ + cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.bits.T)<<1)); \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + cpu->CPSR.bits.C = c; \ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); \ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); \ + return a; + +TEMPLATE static u32 FASTCALL OP_EOR_LSL_IMM(const u32 i) +{ + LSL_IMM; + OP_EOR(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_EOR_LSL_REG(const u32 i) +{ + LSL_REG; + OP_EOR(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_EOR_LSR_IMM(const u32 i) +{ + LSR_IMM; + OP_EOR(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_EOR_LSR_REG(const u32 i) +{ + LSR_REG; + OP_EOR(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_EOR_ASR_IMM(const u32 i) +{ + ASR_IMM; + OP_EOR(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_EOR_ASR_REG(const u32 i) +{ + ASR_REG; + OP_EOR(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_EOR_ROR_IMM(const u32 i) +{ + ROR_IMM; + OP_EOR(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_EOR_ROR_REG(const u32 i) +{ + ROR_REG; + OP_EOR(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_EOR_IMM_VAL(const u32 i) +{ + IMM_VALUE; + OP_EOR(1, 3); +} + + +TEMPLATE static u32 FASTCALL OP_EOR_S_LSL_IMM(const u32 i) +{ + S_LSL_IMM; + OP_EORS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_EOR_S_LSL_REG(const u32 i) +{ + S_LSL_REG; + OP_EORS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_EOR_S_LSR_IMM(const u32 i) +{ + S_LSR_IMM; + OP_EORS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_EOR_S_LSR_REG(const u32 i) +{ + S_LSR_REG; + OP_EORS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_EOR_S_ASR_IMM(const u32 i) +{ + S_ASR_IMM; + OP_EORS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_EOR_S_ASR_REG(const u32 i) +{ + S_ASR_REG; + OP_EORS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_EOR_S_ROR_IMM(const u32 i) +{ + S_ROR_IMM; + OP_EORS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_EOR_S_ROR_REG(const u32 i) +{ + S_ROR_REG; + OP_EORS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_EOR_S_IMM_VAL(const u32 i) +{ + S_IMM_VALUE; + OP_EORS(1, 3); +} + +//----------------------------------------------------------------------------- +// SUB / SUBS +//----------------------------------------------------------------------------- + +#define OP_SUB(a, b) \ + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] - shift_op; \ + if(REG_POS(i,12)==15) \ + { \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + return a; + +#define OP_SUBS(a, b) \ + cpu->R[REG_POS(i,12)] = v - shift_op; \ + if(REG_POS(i,12)==15) \ + { \ + Status_Reg SPSR = cpu->SPSR; \ + armcpu_switchMode(cpu, SPSR.bits.mode); \ + cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ + cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.bits.T)<<1)); \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); \ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); \ + cpu->CPSR.bits.C = !BorrowFrom(v, shift_op); \ + cpu->CPSR.bits.V = OverflowFromSUB(cpu->R[REG_POS(i,12)], v, shift_op); \ + return a; + +TEMPLATE static u32 FASTCALL OP_SUB_LSL_IMM(const u32 i) +{ + LSL_IMM; + OP_SUB(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_SUB_LSL_REG(const u32 i) +{ + LSL_REG; + OP_SUB(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_SUB_LSR_IMM(const u32 i) +{ + LSR_IMM; + OP_SUB(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_SUB_LSR_REG(const u32 i) +{ + LSR_REG; + OP_SUB(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_SUB_ASR_IMM(const u32 i) +{ + ASR_IMM; + OP_SUB(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_SUB_ASR_REG(const u32 i) +{ + ASR_REG; + OP_SUB(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_SUB_ROR_IMM(const u32 i) +{ + ROR_IMM; + OP_SUB(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_SUB_ROR_REG(const u32 i) +{ + ROR_REG; + OP_SUB(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_SUB_IMM_VAL(const u32 i) +{ + IMM_VALUE; + OP_SUB(1, 3); +} + + +TEMPLATE static u32 FASTCALL OP_SUB_S_LSL_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSL_IMM; + OP_SUBS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_SUB_S_LSL_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSL_REG; + OP_SUBS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_SUB_S_LSR_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSR_IMM; + OP_SUBS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_SUB_S_LSR_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSR_REG; + OP_SUBS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_SUB_S_ASR_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ASR_IMM; + OP_SUBS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_SUB_S_ASR_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ASR_REG; + OP_SUBS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_SUB_S_ROR_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ROR_IMM; + OP_SUBS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_SUB_S_ROR_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ROR_REG; + OP_SUBS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_SUB_S_IMM_VAL(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + IMM_VALUE; + OP_SUBS(1, 3); +} + +//----------------------------------------------------------------------------- +// RSB / RSBS +//----------------------------------------------------------------------------- + +#define OP_RSB(a, b) \ + cpu->R[REG_POS(i,12)] = shift_op - cpu->R[REG_POS(i,16)]; \ + if(REG_POS(i,12)==15) \ + { \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + return a; + +#define OP_RSBS(a, b) \ + cpu->R[REG_POS(i,12)] = shift_op - v; \ + if(REG_POS(i,12)==15) \ + { \ + Status_Reg SPSR = cpu->SPSR; \ + armcpu_switchMode(cpu, SPSR.bits.mode); \ + cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ + cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.bits.T)<<1)); \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); \ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); \ + cpu->CPSR.bits.C = !BorrowFrom(shift_op, v); \ + cpu->CPSR.bits.V = OverflowFromSUB(cpu->R[REG_POS(i,12)], shift_op, v); \ + return a; + +TEMPLATE static u32 FASTCALL OP_RSB_LSL_IMM(const u32 i) +{ + LSL_IMM; + OP_RSB(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_RSB_LSL_REG(const u32 i) +{ + LSL_REG; + OP_RSB(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_RSB_LSR_IMM(const u32 i) +{ + LSR_IMM; + OP_RSB(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_RSB_LSR_REG(const u32 i) +{ + LSR_REG; + OP_RSB(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_RSB_ASR_IMM(const u32 i) +{ + ASR_IMM; + OP_RSB(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_RSB_ASR_REG(const u32 i) +{ + ASR_REG; + OP_RSB(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_RSB_ROR_IMM(const u32 i) +{ + ROR_IMM; + OP_RSB(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_RSB_ROR_REG(const u32 i) +{ + ROR_REG; + OP_RSB(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_RSB_IMM_VAL(const u32 i) +{ + IMM_VALUE; + OP_RSB(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_RSB_S_LSL_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSL_IMM; + OP_RSBS(1, 3); +} + + +TEMPLATE static u32 FASTCALL OP_RSB_S_LSL_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSL_REG; + OP_RSBS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_RSB_S_LSR_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSR_IMM; + OP_RSBS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_RSB_S_LSR_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSR_REG; + OP_RSBS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_RSB_S_ASR_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ASR_IMM; + OP_RSBS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_RSB_S_ASR_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ASR_REG; + OP_RSBS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_RSB_S_ROR_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ROR_IMM; + OP_RSBS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_RSB_S_ROR_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ROR_REG; + OP_RSBS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_RSB_S_IMM_VAL(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + IMM_VALUE; + OP_RSBS(1, 3); +} + +//----------------------------------------------------------------------------- +// ADD / ADDS +//----------------------------------------------------------------------------- + +#define OP_ADD(a, b) \ + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] + shift_op; \ + if(REG_POS(i,12)==15) \ + { \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + return a; + +#define OP_ADDS(a, b) \ + cpu->R[REG_POS(i,12)] = v + shift_op; \ + if(REG_POS(i,12)==15) \ + { \ + Status_Reg SPSR = cpu->SPSR; \ + armcpu_switchMode(cpu, SPSR.bits.mode); \ + cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ + cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.bits.T)<<1)); \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); \ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); \ + cpu->CPSR.bits.C = CarryFrom(v, shift_op); \ + cpu->CPSR.bits.V = OverflowFromADD(cpu->R[REG_POS(i,12)], v, shift_op); \ + return a; + +TEMPLATE static u32 FASTCALL OP_ADD_LSL_IMM(const u32 i) +{ + LSL_IMM; + OP_ADD(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_ADD_LSL_REG(const u32 i) +{ + LSL_REG; + OP_ADD(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_ADD_LSR_IMM(const u32 i) +{ + LSR_IMM; + OP_ADD(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_ADD_LSR_REG(const u32 i) +{ + LSR_REG; + OP_ADD(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_ADD_ASR_IMM(const u32 i) +{ + ASR_IMM; + OP_ADD(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_ADD_ASR_REG(const u32 i) +{ + ASR_REG; + OP_ADD(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_ADD_ROR_IMM(const u32 i) +{ + ROR_IMM; + OP_ADD(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_ADD_ROR_REG(const u32 i) +{ + ROR_REG; + OP_ADD(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_ADD_IMM_VAL(const u32 i) +{ + IMM_VALUE; + OP_ADD(1, 3); +} + + +TEMPLATE static u32 FASTCALL OP_ADD_S_LSL_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSL_IMM; + OP_ADDS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_ADD_S_LSL_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSL_REG; + OP_ADDS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_ADD_S_LSR_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSR_IMM; + OP_ADDS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_ADD_S_LSR_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSR_REG; + OP_ADDS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_ADD_S_ASR_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ASR_IMM; + OP_ADDS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_ADD_S_ASR_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ASR_REG; + OP_ADDS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_ADD_S_ROR_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ROR_IMM; + OP_ADDS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_ADD_S_ROR_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ROR_REG; + OP_ADDS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_ADD_S_IMM_VAL(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + IMM_VALUE; + OP_ADDS(1, 3); +} + +//----------------------------------------------------------------------------- +// ADC / ADCS +//----------------------------------------------------------------------------- +#define OP_ADC(a, b) \ + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] + shift_op + cpu->CPSR.bits.C; \ + if(REG_POS(i,12)==15) \ + { \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + return a; + +#define OP_ADCS(a, b) \ + { \ + if(REG_POS(i,12)==15) \ + { \ + cpu->R[REG_POS(i,12)] = v + shift_op + cpu->CPSR.bits.C; \ + Status_Reg SPSR = cpu->SPSR; \ + armcpu_switchMode(cpu, SPSR.bits.mode); \ + cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ + cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.bits.T)<<1)); \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + if (!cpu->CPSR.bits.C) \ + { \ + cpu->R[REG_POS(i,12)] = v + shift_op; \ + cpu->CPSR.bits.C = cpu->R[REG_POS(i,12)] < v; \ + } \ + else \ + { \ + cpu->R[REG_POS(i,12)] = v + shift_op + 1; \ + cpu->CPSR.bits.C = cpu->R[REG_POS(i,12)] <= v; \ + } \ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); \ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); \ + cpu->CPSR.bits.V = BIT31((v ^ shift_op ^ -1) & (v ^ cpu->R[REG_POS(i, 12)]));\ + return a; \ + } + +TEMPLATE static u32 FASTCALL OP_ADC_LSL_IMM(const u32 i) +{ + LSL_IMM; + OP_ADC(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_ADC_LSL_REG(const u32 i) +{ + LSL_REG; + OP_ADC(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_ADC_LSR_IMM(const u32 i) +{ + LSR_IMM; + OP_ADC(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_ADC_LSR_REG(const u32 i) +{ + LSR_REG; + OP_ADC(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_ADC_ASR_IMM(const u32 i) +{ + ASR_IMM; + OP_ADC(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_ADC_ASR_REG(const u32 i) +{ + ASR_REG; + OP_ADC(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_ADC_ROR_IMM(const u32 i) +{ + ROR_IMM; + OP_ADC(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_ADC_ROR_REG(const u32 i) +{ + ROR_REG; + OP_ADC(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_ADC_IMM_VAL(const u32 i) +{ + IMM_VALUE; + OP_ADC(1, 3); +} + + +TEMPLATE static u32 FASTCALL OP_ADC_S_LSL_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSL_IMM; + OP_ADCS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_ADC_S_LSL_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSL_REG; + OP_ADCS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_ADC_S_LSR_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSR_IMM; + OP_ADCS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_ADC_S_LSR_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSR_REG; + OP_ADCS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_ADC_S_ASR_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ASR_IMM; + OP_ADCS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_ADC_S_ASR_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ASR_REG; + OP_ADCS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_ADC_S_ROR_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ROR_IMM; + OP_ADCS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_ADC_S_ROR_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ROR_REG; + OP_ADCS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_ADC_S_IMM_VAL(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + IMM_VALUE; + OP_ADCS(1, 3); +} + +//----------------------------------------------------------------------------- +// SBC / SBCS +//----------------------------------------------------------------------------- + +#define OP_SBC(a, b) \ + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] - shift_op - !cpu->CPSR.bits.C; \ + if(REG_POS(i,12)==15) \ + { \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + return a; + +#define OP_SBCS(a, b) \ + { \ + if(REG_POS(i,12)==15) \ + { \ + cpu->R[REG_POS(i,12)] = v - shift_op - !cpu->CPSR.bits.C; \ + Status_Reg SPSR = cpu->SPSR; \ + armcpu_switchMode(cpu, SPSR.bits.mode); \ + cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ + cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.bits.T)<<1)); \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + if (!cpu->CPSR.bits.C) \ + { \ + cpu->R[REG_POS(i,12)] = v - shift_op - 1; \ + cpu->CPSR.bits.C = v > shift_op; \ + } \ + else \ + { \ + cpu->R[REG_POS(i,12)] = v - shift_op; \ + cpu->CPSR.bits.C = v >= shift_op; \ + } \ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); \ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); \ + cpu->CPSR.bits.V = BIT31((v ^ shift_op) & (v ^ cpu->R[REG_POS(i, 12)])); \ + return a; \ + } + +TEMPLATE static u32 FASTCALL OP_SBC_LSL_IMM(const u32 i) +{ + LSL_IMM; + OP_SBC(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_SBC_LSL_REG(const u32 i) +{ + LSL_REG; + OP_SBC(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_SBC_LSR_IMM(const u32 i) +{ + LSR_IMM; + OP_SBC(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_SBC_LSR_REG(const u32 i) +{ + LSR_REG; + OP_SBC(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_SBC_ASR_IMM(const u32 i) +{ + ASR_IMM; + OP_SBC(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_SBC_ASR_REG(const u32 i) +{ + ASR_REG; + OP_SBC(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_SBC_ROR_IMM(const u32 i) +{ + ROR_IMM; + OP_SBC(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_SBC_ROR_REG(const u32 i) +{ + ROR_REG; + OP_SBC(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_SBC_IMM_VAL(const u32 i) +{ + IMM_VALUE; + OP_SBC(1, 3); +} + + +TEMPLATE static u32 FASTCALL OP_SBC_S_LSL_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSL_IMM; + OP_SBCS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_SBC_S_LSL_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSL_REG; + OP_SBCS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_SBC_S_LSR_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSR_IMM; + OP_SBCS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_SBC_S_LSR_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSR_REG; + OP_SBCS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_SBC_S_ASR_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ASR_IMM; + OP_SBCS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_SBC_S_ASR_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ASR_REG; + OP_SBCS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_SBC_S_ROR_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ROR_IMM; + OP_SBCS(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_SBC_S_ROR_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ROR_REG; + OP_SBCS(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_SBC_S_IMM_VAL(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + IMM_VALUE; + OP_SBCS(1, 3); +} + +//----------------------------------------------------------------------------- +// RSC / RSCS +//----------------------------------------------------------------------------- + +#define OP_RSC(a, b) \ + cpu->R[REG_POS(i,12)] = shift_op - cpu->R[REG_POS(i,16)] + cpu->CPSR.bits.C - 1; \ + if(REG_POS(i,12)==15) \ + { \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + return a; + +#define OP_RSCS(a, b) \ + { \ + if(REG_POS(i,12)==15) \ + { \ + cpu->R[REG_POS(i,12)] = shift_op - v - !cpu->CPSR.bits.C; \ + Status_Reg SPSR = cpu->SPSR; \ + armcpu_switchMode(cpu, SPSR.bits.mode); \ + cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ + cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.bits.T)<<1)); \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + if (!cpu->CPSR.bits.C) \ + { \ + cpu->R[REG_POS(i,12)] = shift_op - v - 1; \ + cpu->CPSR.bits.C = shift_op > v; \ + } \ + else \ + { \ + cpu->R[REG_POS(i,12)] = shift_op - v; \ + cpu->CPSR.bits.C = shift_op >= v; \ + } \ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); \ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); \ + cpu->CPSR.bits.V = BIT31((shift_op ^ v) & (shift_op ^ cpu->R[REG_POS(i, 12)])); \ + return a; \ + } + +TEMPLATE static u32 FASTCALL OP_RSC_LSL_IMM(const u32 i) +{ + LSL_IMM; + OP_RSC(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_RSC_LSL_REG(const u32 i) +{ + LSL_REG; + OP_RSC(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_RSC_LSR_IMM(const u32 i) +{ + LSR_IMM; + OP_RSC(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_RSC_LSR_REG(const u32 i) +{ + LSR_REG; + OP_RSC(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_RSC_ASR_IMM(const u32 i) +{ + ASR_IMM; + OP_RSC(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_RSC_ASR_REG(const u32 i) +{ + ASR_REG; + OP_RSC(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_RSC_ROR_IMM(const u32 i) +{ + ROR_IMM; + OP_RSC(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_RSC_ROR_REG(const u32 i) +{ + ROR_REG; + OP_RSC(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_RSC_IMM_VAL(const u32 i) +{ + IMM_VALUE; + OP_RSC(1, 3); +} + + +TEMPLATE static u32 FASTCALL OP_RSC_S_LSL_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSL_IMM; + OP_RSCS(1,3); +} + +TEMPLATE static u32 FASTCALL OP_RSC_S_LSL_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSL_REG; + OP_RSCS(2,4); +} + +TEMPLATE static u32 FASTCALL OP_RSC_S_LSR_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSR_IMM; + OP_RSCS(1,3); +} + +TEMPLATE static u32 FASTCALL OP_RSC_S_LSR_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + LSR_REG; + OP_RSCS(2,4); +} + +TEMPLATE static u32 FASTCALL OP_RSC_S_ASR_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ASR_IMM; + OP_RSCS(1,3); +} + +TEMPLATE static u32 FASTCALL OP_RSC_S_ASR_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ASR_REG; + OP_RSCS(2,4); +} + +TEMPLATE static u32 FASTCALL OP_RSC_S_ROR_IMM(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ROR_IMM; + OP_RSCS(1,3); +} + +TEMPLATE static u32 FASTCALL OP_RSC_S_ROR_REG(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + ROR_REG; + OP_RSCS(2,4); +} + +TEMPLATE static u32 FASTCALL OP_RSC_S_IMM_VAL(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,16)]; + IMM_VALUE; + OP_RSCS(1,3); +} + +//----------------------------------------------------------------------------- +// TST +//----------------------------------------------------------------------------- + +#define OP_TST(a) \ + { \ + u32 tmp = cpu->R[REG_POS(i,16)] & shift_op; \ + cpu->CPSR.bits.C = c; \ + cpu->CPSR.bits.N = BIT31(tmp); \ + cpu->CPSR.bits.Z = (tmp==0); \ + return a; \ + } + +TEMPLATE static u32 FASTCALL OP_TST_LSL_IMM(const u32 i) +{ + S_LSL_IMM; + OP_TST(1); +} + +TEMPLATE static u32 FASTCALL OP_TST_LSL_REG(const u32 i) +{ + S_LSL_REG; + OP_TST(2); +} + +TEMPLATE static u32 FASTCALL OP_TST_LSR_IMM(const u32 i) +{ + S_LSR_IMM; + OP_TST(1); +} + +TEMPLATE static u32 FASTCALL OP_TST_LSR_REG(const u32 i) +{ + S_LSR_REG; + OP_TST(2); +} + +TEMPLATE static u32 FASTCALL OP_TST_ASR_IMM(const u32 i) +{ + S_ASR_IMM; + OP_TST(1); +} + +TEMPLATE static u32 FASTCALL OP_TST_ASR_REG(const u32 i) +{ + S_ASR_REG; + OP_TST(2); +} + +TEMPLATE static u32 FASTCALL OP_TST_ROR_IMM(const u32 i) +{ + S_ROR_IMM; + OP_TST(1); +} + +TEMPLATE static u32 FASTCALL OP_TST_ROR_REG(const u32 i) +{ + S_ROR_REG; + OP_TST(2); +} + +TEMPLATE static u32 FASTCALL OP_TST_IMM_VAL(const u32 i) +{ + S_IMM_VALUE; + OP_TST(1); +} + +//----------------------------------------------------------------------------- +// TEQ +//----------------------------------------------------------------------------- + +#define OP_TEQ(a) \ + { \ + unsigned tmp = cpu->R[REG_POS(i,16)] ^ shift_op; \ + cpu->CPSR.bits.C = c; \ + cpu->CPSR.bits.N = BIT31(tmp); \ + cpu->CPSR.bits.Z = (tmp==0); \ + return a; \ + } + +TEMPLATE static u32 FASTCALL OP_TEQ_LSL_IMM(const u32 i) +{ + S_LSL_IMM; + OP_TEQ(1); +} + +TEMPLATE static u32 FASTCALL OP_TEQ_LSL_REG(const u32 i) +{ + S_LSL_REG; + OP_TEQ(2); +} + +TEMPLATE static u32 FASTCALL OP_TEQ_LSR_IMM(const u32 i) +{ + S_LSR_IMM; + OP_TEQ(1); +} + +TEMPLATE static u32 FASTCALL OP_TEQ_LSR_REG(const u32 i) +{ + S_LSR_REG; + OP_TEQ(2); +} + +TEMPLATE static u32 FASTCALL OP_TEQ_ASR_IMM(const u32 i) +{ + S_ASR_IMM; + OP_TEQ(1); +} + +TEMPLATE static u32 FASTCALL OP_TEQ_ASR_REG(const u32 i) +{ + S_ASR_REG; + OP_TEQ(2); +} + +TEMPLATE static u32 FASTCALL OP_TEQ_ROR_IMM(const u32 i) +{ + S_ROR_IMM; + OP_TEQ(1); +} + +TEMPLATE static u32 FASTCALL OP_TEQ_ROR_REG(const u32 i) +{ + S_ROR_REG; + OP_TEQ(2); +} + +TEMPLATE static u32 FASTCALL OP_TEQ_IMM_VAL(const u32 i) +{ + S_IMM_VALUE; + OP_TEQ(1); +} + +//----------------------------------------------------------------------------- +// CMP +//----------------------------------------------------------------------------- + +#define OP_CMP(a) \ + { \ + u32 tmp = cpu->R[REG_POS(i,16)] - shift_op; \ + cpu->CPSR.bits.N = BIT31(tmp); \ + cpu->CPSR.bits.Z = (tmp==0); \ + cpu->CPSR.bits.C = !BorrowFrom(cpu->R[REG_POS(i,16)], shift_op); \ + cpu->CPSR.bits.V = OverflowFromSUB(tmp, cpu->R[REG_POS(i,16)], shift_op); \ + return a; \ + } + +TEMPLATE static u32 FASTCALL OP_CMP_LSL_IMM(const u32 i) +{ + LSL_IMM; + OP_CMP(1); +} + +TEMPLATE static u32 FASTCALL OP_CMP_LSL_REG(const u32 i) +{ + LSL_REG; + OP_CMP(2); +} + +TEMPLATE static u32 FASTCALL OP_CMP_LSR_IMM(const u32 i) +{ + LSR_IMM; + OP_CMP(1); +} + +TEMPLATE static u32 FASTCALL OP_CMP_LSR_REG(const u32 i) +{ + LSR_REG; + OP_CMP(2); +} + +TEMPLATE static u32 FASTCALL OP_CMP_ASR_IMM(const u32 i) +{ + ASR_IMM; + OP_CMP(1); +} + +TEMPLATE static u32 FASTCALL OP_CMP_ASR_REG(const u32 i) +{ + ASR_REG; + OP_CMP(2); +} + +TEMPLATE static u32 FASTCALL OP_CMP_ROR_IMM(const u32 i) +{ + ROR_IMM; + OP_CMP(1); +} + +TEMPLATE static u32 FASTCALL OP_CMP_ROR_REG(const u32 i) +{ + ROR_REG; + OP_CMP(2); +} + +TEMPLATE static u32 FASTCALL OP_CMP_IMM_VAL(const u32 i) +{ + IMM_VALUE; + OP_CMP(1); +} + +//----------------------------------------------------------------------------- +// CMN +//----------------------------------------------------------------------------- + +#define OP_CMN(a) \ + { \ + u32 tmp = cpu->R[REG_POS(i,16)] + shift_op; \ + cpu->CPSR.bits.N = BIT31(tmp); \ + cpu->CPSR.bits.Z = (tmp==0); \ + cpu->CPSR.bits.C = CarryFrom(cpu->R[REG_POS(i,16)], shift_op); \ + cpu->CPSR.bits.V = OverflowFromADD(tmp, cpu->R[REG_POS(i,16)], shift_op); \ + return a; \ + } + +TEMPLATE static u32 FASTCALL OP_CMN_LSL_IMM(const u32 i) +{ + LSL_IMM; + OP_CMN(1); +} + +TEMPLATE static u32 FASTCALL OP_CMN_LSL_REG(const u32 i) +{ + LSL_REG; + OP_CMN(2); +} + +TEMPLATE static u32 FASTCALL OP_CMN_LSR_IMM(const u32 i) +{ + LSR_IMM; + OP_CMN(1); +} + +TEMPLATE static u32 FASTCALL OP_CMN_LSR_REG(const u32 i) +{ + LSR_REG; + OP_CMN(2); +} + +TEMPLATE static u32 FASTCALL OP_CMN_ASR_IMM(const u32 i) +{ + ASR_IMM; + OP_CMN(1); +} + +TEMPLATE static u32 FASTCALL OP_CMN_ASR_REG(const u32 i) +{ + ASR_REG; + OP_CMN(2); +} + +TEMPLATE static u32 FASTCALL OP_CMN_ROR_IMM(const u32 i) +{ + ROR_IMM; + OP_CMN(1); +} + +TEMPLATE static u32 FASTCALL OP_CMN_ROR_REG(const u32 i) +{ + ROR_REG; + OP_CMN(2); +} + +TEMPLATE static u32 FASTCALL OP_CMN_IMM_VAL(const u32 i) +{ + IMM_VALUE; + OP_CMN(1); +} + +//----------------------------------------------------------------------------- +// ORR / ORRS +//----------------------------------------------------------------------------- + +#define OP_ORR(a, b) \ + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op; \ + if(REG_POS(i,12)==15) \ + { \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + return a; + +#define OP_ORRS(a,b) \ + { \ + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op; \ + if(REG_POS(i,12)==15) \ + { \ + Status_Reg SPSR = cpu->SPSR; \ + armcpu_switchMode(cpu, SPSR.bits.mode); \ + cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ + cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.bits.T)<<1)); \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + cpu->CPSR.bits.C = c; \ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); \ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); \ + return a; \ + } + +TEMPLATE static u32 FASTCALL OP_ORR_LSL_IMM(const u32 i) +{ + LSL_IMM; + OP_ORR(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_ORR_LSL_REG(const u32 i) +{ + LSL_REG; + OP_ORR(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_ORR_LSR_IMM(const u32 i) +{ + LSR_IMM; + OP_ORR(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_ORR_LSR_REG(const u32 i) +{ + LSR_REG; + OP_ORR(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_ORR_ASR_IMM(const u32 i) +{ + ASR_IMM; + OP_ORR(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_ORR_ASR_REG(const u32 i) +{ + ASR_REG; + OP_ORR(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_ORR_ROR_IMM(const u32 i) +{ + ROR_IMM; + OP_ORR(1, 3); +} + +TEMPLATE static u32 FASTCALL OP_ORR_ROR_REG(const u32 i) +{ + ROR_REG; + OP_ORR(2, 4); +} + +TEMPLATE static u32 FASTCALL OP_ORR_IMM_VAL(const u32 i) +{ + IMM_VALUE; + OP_ORR(1, 3); +} + + +TEMPLATE static u32 FASTCALL OP_ORR_S_LSL_IMM(const u32 i) +{ + S_LSL_IMM; + OP_ORRS(1,3); +} + +TEMPLATE static u32 FASTCALL OP_ORR_S_LSL_REG(const u32 i) +{ + S_LSL_REG; + OP_ORRS(2,4); +} + +TEMPLATE static u32 FASTCALL OP_ORR_S_LSR_IMM(const u32 i) +{ + S_LSR_IMM; + OP_ORRS(1,3); +} + +TEMPLATE static u32 FASTCALL OP_ORR_S_LSR_REG(const u32 i) +{ + S_LSR_REG; + OP_ORRS(2,4); +} + +TEMPLATE static u32 FASTCALL OP_ORR_S_ASR_IMM(const u32 i) +{ + S_ASR_IMM; + OP_ORRS(1,3); +} + +TEMPLATE static u32 FASTCALL OP_ORR_S_ASR_REG(const u32 i) +{ + S_ASR_REG; + OP_ORRS(2,4); +} + +TEMPLATE static u32 FASTCALL OP_ORR_S_ROR_IMM(const u32 i) +{ + S_ROR_IMM; + OP_ORRS(1,3); +} + +TEMPLATE static u32 FASTCALL OP_ORR_S_ROR_REG(const u32 i) +{ + S_ROR_REG; + OP_ORRS(2,4); +} + +TEMPLATE static u32 FASTCALL OP_ORR_S_IMM_VAL(const u32 i) +{ + S_IMM_VALUE; + OP_ORRS(1,3); +} + +//----------------------------------------------------------------------------- +// MOV / MOVS +//----------------------------------------------------------------------------- + +#define OP_MOV(a, b) \ + cpu->R[REG_POS(i,12)] = shift_op; \ + if(REG_POS(i,12)==15) \ + { \ + cpu->next_instruction = shift_op; \ + return b; \ + } \ + return a; + +#define OP_MOVS(a, b) \ + cpu->R[REG_POS(i,12)] = shift_op; \ + if(REG_POS(i,12)==15) \ + { \ + Status_Reg SPSR = cpu->SPSR; \ + armcpu_switchMode(cpu, SPSR.bits.mode); \ + cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ + cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.bits.T)<<1)); \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + cpu->CPSR.bits.C = c; \ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); \ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); \ + return a; \ + +TEMPLATE static u32 FASTCALL OP_MOV_LSL_IMM(const u32 i) +{ + LSL_IMM; + OP_MOV(1,3); +} + +TEMPLATE static u32 FASTCALL OP_MOV_LSL_REG(const u32 i) +{ + LSL_REG; + if (REG_POS(i,0) == 15) shift_op += 4; + OP_MOV(2,4); +} + +TEMPLATE static u32 FASTCALL OP_MOV_LSR_IMM(const u32 i) +{ + LSR_IMM; + OP_MOV(1,3); +} + +TEMPLATE static u32 FASTCALL OP_MOV_LSR_REG(const u32 i) +{ + LSR_REG; + if (REG_POS(i,0) == 15) shift_op += 4; + OP_MOV(2,4); +} + +TEMPLATE static u32 FASTCALL OP_MOV_ASR_IMM(const u32 i) +{ + ASR_IMM; + OP_MOV(1,3); +} + +TEMPLATE static u32 FASTCALL OP_MOV_ASR_REG(const u32 i) +{ + ASR_REG; + OP_MOV(2,4); +} + +TEMPLATE static u32 FASTCALL OP_MOV_ROR_IMM(const u32 i) +{ + ROR_IMM; + OP_MOV(1,3); +} + +TEMPLATE static u32 FASTCALL OP_MOV_ROR_REG(const u32 i) +{ + ROR_REG; + OP_MOV(2,4); +} + +TEMPLATE static u32 FASTCALL OP_MOV_IMM_VAL(const u32 i) +{ + IMM_VALUE; + OP_MOV(1,3); +} + + +TEMPLATE static u32 FASTCALL OP_MOV_S_LSL_IMM(const u32 i) +{ + S_LSL_IMM; + OP_MOVS(1,3); +} + +TEMPLATE static u32 FASTCALL OP_MOV_S_LSL_REG(const u32 i) +{ + S_LSL_REG; + if (REG_POS(i,0) == 15) shift_op += 4; + OP_MOVS(2,4); +} + +TEMPLATE static u32 FASTCALL OP_MOV_S_LSR_IMM(const u32 i) +{ + S_LSR_IMM; + OP_MOVS(1,3); +} + +TEMPLATE static u32 FASTCALL OP_MOV_S_LSR_REG(const u32 i) +{ + S_LSR_REG; + if (REG_POS(i,0) == 15) shift_op += 4; + OP_MOVS(2,4); +} + +TEMPLATE static u32 FASTCALL OP_MOV_S_ASR_IMM(const u32 i) +{ + S_ASR_IMM; + OP_MOVS(1,3); +} + +TEMPLATE static u32 FASTCALL OP_MOV_S_ASR_REG(const u32 i) +{ + S_ASR_REG; + OP_MOVS(2,4); +} + +TEMPLATE static u32 FASTCALL OP_MOV_S_ROR_IMM(const u32 i) +{ + S_ROR_IMM; + OP_MOVS(1,3); +} + +TEMPLATE static u32 FASTCALL OP_MOV_S_ROR_REG(const u32 i) +{ + S_ROR_REG; + OP_MOVS(2,4); +} + +TEMPLATE static u32 FASTCALL OP_MOV_S_IMM_VAL(const u32 i) +{ + S_IMM_VALUE; + OP_MOVS(1,3); +} + +//----------------------------------------------------------------------------- +// BIC / BICS +//----------------------------------------------------------------------------- + +#define OP_BIC(a, b) \ + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] & (~shift_op); \ + if(REG_POS(i,12)==15) \ + { \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + return a; + +#define OP_BICS(a, b) \ + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] & (~shift_op); \ + if(REG_POS(i,12)==15) \ + { \ + Status_Reg SPSR = cpu->SPSR; \ + armcpu_switchMode(cpu, SPSR.bits.mode); \ + cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ + cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.bits.T)<<1)); \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + cpu->CPSR.bits.C = c; \ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); \ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); \ + return a; + +TEMPLATE static u32 FASTCALL OP_BIC_LSL_IMM(const u32 i) +{ + LSL_IMM; + OP_BIC(1,3); +} + +TEMPLATE static u32 FASTCALL OP_BIC_LSL_REG(const u32 i) +{ + LSL_REG; + OP_BIC(2,4); +} + +TEMPLATE static u32 FASTCALL OP_BIC_LSR_IMM(const u32 i) +{ + LSR_IMM; + OP_BIC(1,3); +} + +TEMPLATE static u32 FASTCALL OP_BIC_LSR_REG(const u32 i) +{ + LSR_REG; + OP_BIC(2,4); +} + +TEMPLATE static u32 FASTCALL OP_BIC_ASR_IMM(const u32 i) +{ + ASR_IMM; + OP_BIC(1,3); +} + +TEMPLATE static u32 FASTCALL OP_BIC_ASR_REG(const u32 i) +{ + ASR_REG; + OP_BIC(2,4); +} + +TEMPLATE static u32 FASTCALL OP_BIC_ROR_IMM(const u32 i) +{ + ROR_IMM; + OP_BIC(1,3); +} + +TEMPLATE static u32 FASTCALL OP_BIC_ROR_REG(const u32 i) +{ + ROR_REG; + OP_BIC(2,4); +} + +TEMPLATE static u32 FASTCALL OP_BIC_IMM_VAL(const u32 i) +{ + IMM_VALUE; + OP_BIC(1,3); +} + + +TEMPLATE static u32 FASTCALL OP_BIC_S_LSL_IMM(const u32 i) +{ + S_LSL_IMM; + OP_BICS(1,3); +} + +TEMPLATE static u32 FASTCALL OP_BIC_S_LSL_REG(const u32 i) +{ + S_LSL_REG; + OP_BICS(2,4); +} + +TEMPLATE static u32 FASTCALL OP_BIC_S_LSR_IMM(const u32 i) +{ + S_LSR_IMM; + OP_BICS(1,3); +} + +TEMPLATE static u32 FASTCALL OP_BIC_S_LSR_REG(const u32 i) +{ + S_LSR_REG; + OP_BICS(2,4); +} + +TEMPLATE static u32 FASTCALL OP_BIC_S_ASR_IMM(const u32 i) +{ + S_ASR_IMM; + OP_BICS(1,3); +} + +TEMPLATE static u32 FASTCALL OP_BIC_S_ASR_REG(const u32 i) +{ + S_ASR_REG; + OP_BICS(2,4); +} + +TEMPLATE static u32 FASTCALL OP_BIC_S_ROR_IMM(const u32 i) +{ + S_ROR_IMM; + OP_BICS(1,3); +} + +TEMPLATE static u32 FASTCALL OP_BIC_S_ROR_REG(const u32 i) +{ + S_ROR_REG; + OP_BICS(2,4); +} + +TEMPLATE static u32 FASTCALL OP_BIC_S_IMM_VAL(const u32 i) +{ + S_IMM_VALUE; + OP_BICS(1,3); +} + +//----------------------------------------------------------------------------- +// MVN / MVNS +//----------------------------------------------------------------------------- + +#define OP_MVN(a, b) \ + cpu->R[REG_POS(i,12)] = ~shift_op; \ + if(REG_POS(i,12)==15) \ + { \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + return a; + +#define OP_MVNS(a, b) \ + cpu->R[REG_POS(i,12)] = ~shift_op; \ + if(REG_POS(i,12)==15) \ + { \ + Status_Reg SPSR = cpu->SPSR; \ + armcpu_switchMode(cpu, SPSR.bits.mode); \ + cpu->CPSR=SPSR; \ + cpu->changeCPSR(); \ + cpu->R[15] &= (0xFFFFFFFC|(((u32)cpu->CPSR.bits.T)<<1)); \ + cpu->next_instruction = cpu->R[15]; \ + return b; \ + } \ + cpu->CPSR.bits.C = c; \ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); \ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); \ + return a; + +TEMPLATE static u32 FASTCALL OP_MVN_LSL_IMM(const u32 i) +{ + LSL_IMM; + OP_MVN(1,3); +} + +TEMPLATE static u32 FASTCALL OP_MVN_LSL_REG(const u32 i) +{ + LSL_REG; + OP_MVN(2,4); +} + +TEMPLATE static u32 FASTCALL OP_MVN_LSR_IMM(const u32 i) +{ + LSR_IMM; + OP_MVN(1,3); +} + +TEMPLATE static u32 FASTCALL OP_MVN_LSR_REG(const u32 i) +{ + LSR_REG; + OP_MVN(2,4); +} + +TEMPLATE static u32 FASTCALL OP_MVN_ASR_IMM(const u32 i) +{ + ASR_IMM; + OP_MVN(1,3); +} + +TEMPLATE static u32 FASTCALL OP_MVN_ASR_REG(const u32 i) +{ + ASR_REG; + OP_MVN(2,4); +} + +TEMPLATE static u32 FASTCALL OP_MVN_ROR_IMM(const u32 i) +{ + ROR_IMM; + OP_MVN(1,3); +} + +TEMPLATE static u32 FASTCALL OP_MVN_ROR_REG(const u32 i) +{ + ROR_REG; + OP_MVN(2,4); +} + +TEMPLATE static u32 FASTCALL OP_MVN_IMM_VAL(const u32 i) +{ + IMM_VALUE; + OP_MVN(1,3); +} + +TEMPLATE static u32 FASTCALL OP_MVN_S_LSL_IMM(const u32 i) +{ + S_LSL_IMM; + OP_MVNS(1,3); +} + +TEMPLATE static u32 FASTCALL OP_MVN_S_LSL_REG(const u32 i) +{ + S_LSL_REG; + OP_MVNS(2,4); +} + +TEMPLATE static u32 FASTCALL OP_MVN_S_LSR_IMM(const u32 i) +{ + S_LSR_IMM; + OP_MVNS(1,3); +} + +TEMPLATE static u32 FASTCALL OP_MVN_S_LSR_REG(const u32 i) +{ + S_LSR_REG; + OP_MVNS(2,4); +} + +TEMPLATE static u32 FASTCALL OP_MVN_S_ASR_IMM(const u32 i) +{ + S_ASR_IMM; + OP_MVNS(1,3); +} + +TEMPLATE static u32 FASTCALL OP_MVN_S_ASR_REG(const u32 i) +{ + S_ASR_REG; + OP_MVNS(2,4); +} + +TEMPLATE static u32 FASTCALL OP_MVN_S_ROR_IMM(const u32 i) +{ + S_ROR_IMM; + OP_MVNS(1,3); +} + +TEMPLATE static u32 FASTCALL OP_MVN_S_ROR_REG(const u32 i) +{ + S_ROR_REG; + OP_MVNS(2,4); +} + +TEMPLATE static u32 FASTCALL OP_MVN_S_IMM_VAL(const u32 i) +{ + S_IMM_VALUE; + OP_MVNS(1,3); +} + +//----------------------------------------------------------------------------- +// MUL / MULS / MLA / MLAS +//----------------------------------------------------------------------------- + +#define MUL_Mxx_END(c) \ + v >>= 8; \ + if((v==0)||(v==0xFFFFFF)) \ + return c+1; \ + v >>= 8; \ + if((v==0)||(v==0xFFFF)) \ + return c+2; \ + v >>= 8; \ + if((v==0)||(v==0xFF)) \ + return c+3; \ + return c+4; \ + + +TEMPLATE static u32 FASTCALL OP_MUL(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,8)]; + cpu->R[REG_POS(i,16)] = cpu->R[REG_POS(i,0)] * v; + + MUL_Mxx_END(1); +} + +TEMPLATE static u32 FASTCALL OP_MLA(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,8)]; + cpu->R[REG_POS(i,16)] = cpu->R[REG_POS(i,0)] * v + cpu->R[REG_POS(i,12)]; + + MUL_Mxx_END(2); +} + +TEMPLATE static u32 FASTCALL OP_MUL_S(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,8)]; + cpu->R[REG_POS(i,16)] = cpu->R[REG_POS(i,0)] * v; + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0); + + MUL_Mxx_END(1); +} + +TEMPLATE static u32 FASTCALL OP_MLA_S(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,8)]; + cpu->R[REG_POS(i,16)] = cpu->R[REG_POS(i,0)] * v + cpu->R[REG_POS(i,12)]; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0); + + MUL_Mxx_END(2); +} + +//----------------------------------------------------------------------------- +// UMULL / UMULLS / UMLAL / UMLALS +//----------------------------------------------------------------------------- + +#define MUL_UMxxL_END(c) \ + v >>= 8; \ + if(v==0) \ + return c+1; \ + v >>= 8; \ + if(v==0) \ + return c+2; \ + v >>= 8; \ + if(v==0) \ + return c+3; \ + return c+4; \ + + +TEMPLATE static u32 FASTCALL OP_UMULL(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,8)]; + u64 res = (u64)cpu->R[REG_POS(i,0)] * (u64)v; + + cpu->R[REG_POS(i,12)] = (u32)res; + cpu->R[REG_POS(i,16)] = (u32)(res>>32); + + MUL_UMxxL_END(2); +} + +TEMPLATE static u32 FASTCALL OP_UMLAL(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,8)]; + u64 res = (u64)cpu->R[REG_POS(i,0)] * (u64)v; + + // RdLo = (Rm * Rs)[31:0] + RdLo /* Unsigned multiplication */ + // RdHi = (Rm * Rs)[63:32] + RdHi + CarryFrom((Rm * Rs)[31:0] + RdLo) + u32 tmp = (u32)res; // low + cpu->R[REG_POS(i,16)] = (u32)(res>>32) + cpu->R[REG_POS(i,16)] + CarryFrom(tmp, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,12)] += tmp; + + MUL_UMxxL_END(3); +} + +TEMPLATE static u32 FASTCALL OP_UMULL_S(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,8)]; + u64 res = ((u64)cpu->R[REG_POS(i,0)] * (u64)v); + + cpu->R[REG_POS(i,12)] = (u32)res; + cpu->R[REG_POS(i,16)] = (u32)(res>>32); + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) && (cpu->R[REG_POS(i,12)]==0); + + MUL_UMxxL_END(2); +} + +TEMPLATE static u32 FASTCALL OP_UMLAL_S(const u32 i) +{ + u32 v = cpu->R[REG_POS(i,8)]; + u64 res = (u64)cpu->R[REG_POS(i,0)] * (u64)v; + + // RdLo = (Rm * Rs)[31:0] + RdLo /* Unsigned multiplication */ + // RdHi = (Rm * Rs)[63:32] + RdHi + CarryFrom((Rm * Rs)[31:0] + RdLo) + u32 tmp = (u32)res; // low + cpu->R[REG_POS(i,16)] = (u32)(res>>32) + cpu->R[REG_POS(i,16)] + CarryFrom(tmp, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,12)] += tmp; + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0); + + MUL_UMxxL_END(3); +} + +//----------------------------------------------------------------------------- +// SMULL / SMULLS / SMLAL / SMLALS +//----------------------------------------------------------------------------- + +#define MUL_SMxxL_END(c) \ + v &= 0xFFFFFFFF; \ + v >>= 8; \ + if((v==0)||(v==0xFFFFFF)) \ + return c+1; \ + v >>= 8; \ + if((v==0)||(v==0xFFFF)) \ + return c+2; \ + v >>= 8; \ + if((v==0)||(v==0xFF)) \ + return c+3; \ + return c+4; \ + + +TEMPLATE static u32 FASTCALL OP_SMULL(const u32 i) +{ + s64 v = (s32)cpu->R[REG_POS(i,8)]; + s64 res = v * (s64)(s32)cpu->R[REG_POS(i,0)]; + + cpu->R[REG_POS(i,12)] = (u32)res; + cpu->R[REG_POS(i,16)] = (u32)(res>>32); + + MUL_SMxxL_END(2); +} + +TEMPLATE static u32 FASTCALL OP_SMLAL(const u32 i) +{ + + s64 v = (s32)cpu->R[REG_POS(i,8)]; + s64 res = v * (s64)(s32)cpu->R[REG_POS(i,0)]; + + //LOG("%08X * %08X + %08X%08X\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], cpu->R[REG_POS(i,16)], cpu->R[REG_POS(i,12)]); + + u32 tmp = (u32)res; + cpu->R[REG_POS(i,16)] = (u32)(res>>32) + cpu->R[REG_POS(i,16)] + CarryFrom(tmp, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,12)] += tmp; + + //LOG("= %08X%08X %08X%08X\n", cpu->R[REG_POS(i,16)], cpu->R[REG_POS(i,12)], res); + + MUL_SMxxL_END(3); +} + +TEMPLATE static u32 FASTCALL OP_SMULL_S(const u32 i) +{ + s64 v = (s32)cpu->R[REG_POS(i,8)]; + s64 res = v * (s64)(s32)cpu->R[REG_POS(i,0)]; + + cpu->R[REG_POS(i,12)] = (u32)res; + cpu->R[REG_POS(i,16)] = (u32)(res>>32); + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0); + + MUL_SMxxL_END(2); +} + +TEMPLATE static u32 FASTCALL OP_SMLAL_S(const u32 i) +{ + s64 v = (s32)cpu->R[REG_POS(i,8)]; + s64 res = v * (s64)(s32)cpu->R[REG_POS(i,0)]; + + u32 tmp = (u32)res; + cpu->R[REG_POS(i,16)] = (u32)(res>>32) + cpu->R[REG_POS(i,16)] + CarryFrom(tmp, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,12)] += tmp; + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0); + + MUL_SMxxL_END(3); +} + +//----------------------------------------------------------------------------- +// SWP / SWPB +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_SWP(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + u32 tmp = ROR(READ32(cpu->mem_if->data, adr), (adr & 3)<<3); + + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,0)]); + cpu->R[REG_POS(i,12)] = tmp; + + u32 c = MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(adr); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(adr); + return MMU_aluMemCycles<PROCNUM>(4, c); +} + +TEMPLATE static u32 FASTCALL OP_SWPB(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + u8 tmp = READ8(cpu->mem_if->data, adr); + WRITE8(cpu->mem_if->data, adr, (u8)(cpu->R[REG_POS(i,0)]&0xFF)); + cpu->R[REG_POS(i,12)] = tmp; + + u32 c = MMU_memAccessCycles<PROCNUM,8,MMU_AD_READ>(adr); + c += MMU_memAccessCycles<PROCNUM,8,MMU_AD_WRITE>(adr); + return MMU_aluMemCycles<PROCNUM>(4, c); +} + +//----------------------------------------------------------------------------- +// LDRH +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_LDRH_P_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRH_M_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRH_P_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRH_M_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRH_PRE_INDE_P_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRH_PRE_INDE_M_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRH_PRE_INDE_P_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] =(u32)READ16(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRH_PRE_INDE_M_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRH_POS_INDE_P_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] += IMM_OFF; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRH_POS_INDE_M_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] -= IMM_OFF; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRH_POS_INDE_P_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] += cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRH_POS_INDE_M_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] -= cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +//----------------------------------------------------------------------------- +// STRH +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_STRH_P_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRH_M_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRH_P_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRH_M_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRH_PRE_INDE_P_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,16)] = adr; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRH_PRE_INDE_M_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + cpu->R[REG_POS(i,16)] = adr; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRH_PRE_INDE_P_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,16)] = adr; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRH_PRE_INDE_M_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,16)] = adr; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRH_POS_INDE_P_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] += IMM_OFF; + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRH_POS_INDE_M_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] -= IMM_OFF; + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRH_POS_INDE_P_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] += cpu->R[REG_POS(i,0)]; + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRH_POS_INDE_M_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] -= cpu->R[REG_POS(i,0)]; + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_WRITE>(2,adr); +} + +//----------------------------------------------------------------------------- +// LDRSH +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_LDRSH_P_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSH_M_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSH_P_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSH_M_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSH_PRE_INDE_P_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSH_PRE_INDE_M_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSH_PRE_INDE_P_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSH_PRE_INDE_M_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSH_POS_INDE_P_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] += IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSH_POS_INDE_M_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] -= IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSH_POS_INDE_P_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] += cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSH_POS_INDE_M_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] -= cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3,adr); +} + +//----------------------------------------------------------------------------- +// LDRSB +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_LDRSB_P_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSB_M_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSB_P_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSB_M_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSB_PRE_INDE_P_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSB_PRE_INDE_M_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSB_PRE_INDE_P_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSB_PRE_INDE_M_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSB_POS_INDE_P_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] += IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSB_POS_INDE_M_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] -= IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSB_POS_INDE_P_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] += cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRSB_POS_INDE_M_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] -= cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +//----------------------------------------------------------------------------- +// MRS / MSR +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_MRS_CPSR(const u32 i) +{ + cpu->R[REG_POS(i,12)] = cpu->CPSR.val; + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_MRS_SPSR(const u32 i) +{ + cpu->R[REG_POS(i,12)] = cpu->SPSR.val; + + return 1; +} +#define v4_UNALLOC_MASK 0x0FFFFF00 +#define v4_USER_MASK 0xF0000000 +#define v4_PRIV_MASK 0x0000000F +#define v4_STATE_MASK 0x00000020 + +#define v5_UNALLOC_MASK 0x07FFFF00 +#define v5_USER_MASK 0xF8000000 +#define v5_PRIV_MASK 0x0000000F +#define v5_STATE_MASK 0x00000020 + +TEMPLATE static u32 FASTCALL OP_MSR_CPSR(const u32 i) +{ + u32 operand = cpu->R[REG_POS(i,0)]; + +#if 0 + // TODO + u32 mask = 0; + u32 byte_mask = (BIT16(i)?0x000000FF:0x00000000) | + (BIT17(i)?0x0000FF00:0x00000000) | + (BIT18(i)?0x00FF0000:0x00000000) | + (BIT19(i)?0xFF000000:0x00000000); + + if (PROCNUM == 0) + { + if ((operand & v5_UNALLOC_MASK) != 0) printf("ARM9: MSR_CPSR_REG UNPREDICTABLE UNALLOC (operand %08X)\n", operand); + if (cpu->CPSR.bits.mode != USR) // Privileged mode + { + if ((operand & v5_STATE_MASK) != 0) printf("ARM9: MSR_CPSR_REG UNPREDICTABLE STATE (operand %08X)\n", operand); + mask = byte_mask & (v5_USER_MASK | v5_PRIV_MASK); + } + else + mask = byte_mask & v5_USER_MASK; + } + else + { + if ((operand & v4_UNALLOC_MASK) != 0) printf("ARM7: MSR_CPSR_REG UNPREDICTABLE UNALLOC (operand %08X)\n", operand); + if(cpu->CPSR.bits.mode != USR) // Privileged mode + { + if ((operand & v4_STATE_MASK) != 0) printf("ARM7: MSR_CPSR_REG UNPREDICTABLE STATE (operand %08X)\n", operand); + mask = byte_mask & (v4_USER_MASK | v4_PRIV_MASK); + } + else + mask = byte_mask & v4_USER_MASK; + } + cpu->CPSR.val = ((cpu->CPSR.val & (~mask)) | (operand & mask)); + if (BIT16(i)) armcpu_switchMode(cpu, cpu->CPSR.bits.mode); + cpu->changeCPSR(); +#else + if(cpu->CPSR.bits.mode!=USR) + { + if(BIT16(i)) + { + armcpu_switchMode(cpu, operand & 0x1F); + cpu->CPSR.val = (cpu->CPSR.val & 0xFFFFFF00) | (operand & 0xFF); + } + if(BIT17(i)) + cpu->CPSR.val = (cpu->CPSR.val & 0xFFFF00FF) | (operand & 0xFF00); + if(BIT18(i)) + cpu->CPSR.val = (cpu->CPSR.val & 0xFF00FFFF) | (operand & 0xFF0000); + } + if(BIT19(i)) + cpu->CPSR.val = (cpu->CPSR.val & 0x00FFFFFF) | (operand & 0xFF000000); + + cpu->changeCPSR(); +#endif + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_MSR_SPSR(const u32 i) +{ + u32 operand = cpu->R[REG_POS(i,0)]; + +#if 0 + // TODO + u32 mask = 0; + u32 byte_mask = (BIT16(i)?0x000000FF:0x00000000) | + (BIT17(i)?0x0000FF00:0x00000000) | + (BIT18(i)?0x00FF0000:0x00000000) | + (BIT19(i)?0xFF000000:0x00000000); + + if (PROCNUM == 0) + { + if ((operand & v5_UNALLOC_MASK) != 0) printf("ARM9: MSR_SPSR_REG UNPREDICTABLE UNALLOC (operand %08X)\n", operand); + // if CurrentModeHasSPSR + mask = byte_mask & (v5_USER_MASK | v5_PRIV_MASK | v5_STATE_MASK); + } + else + { + if ((operand & v4_UNALLOC_MASK) != 0) printf("ARM7: MSR_SPSR_REG UNPREDICTABLE UNALLOC (operand %08X)\n", operand); + // if CurrentModeHasSPSR + mask = byte_mask & (v4_USER_MASK | v4_PRIV_MASK | v4_STATE_MASK); + } + cpu->SPSR.val = ((cpu->SPSR.val & (~mask)) | (operand & mask)); + cpu->changeCPSR(); +#else + if(cpu->CPSR.bits.mode!=USR) + { + if(BIT16(i)) + { + cpu->SPSR.val = (cpu->SPSR.val & 0xFFFFFF00) | (operand & 0xFF); + } + if(BIT17(i)) + cpu->SPSR.val = (cpu->SPSR.val & 0xFFFF00FF) | (operand & 0xFF00); + if(BIT18(i)) + cpu->SPSR.val = (cpu->SPSR.val & 0xFF00FFFF) | (operand & 0xFF0000); + } + if(BIT19(i)) + cpu->SPSR.val = (cpu->SPSR.val & 0x00FFFFFF) | (operand & 0xFF000000); + cpu->changeCPSR(); +#endif + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_MSR_CPSR_IMM_VAL(const u32 i) +{ + IMM_VALUE; + +#if 0 + // TODO + u32 operand = shift_op; + u32 mask = 0; + u32 byte_mask = (BIT16(i)?0x000000FF:0x00000000) | + (BIT17(i)?0x0000FF00:0x00000000) | + (BIT18(i)?0x00FF0000:0x00000000) | + (BIT19(i)?0xFF000000:0x00000000); + + if (PROCNUM == 0) + { + if ((operand & v5_UNALLOC_MASK) != 0) printf("ARM9: MSR_CPSR_IMM UNPREDICTABLE UNALLOC (operand %08X)\n", operand); + if (cpu->CPSR.bits.mode != USR) // Privileged mode + { + if ((operand & v5_STATE_MASK) != 0) printf("ARM9: MSR_CPSR_IMM UNPREDICTABLE STATE (operand %08X)\n", operand); + mask = byte_mask & (v5_USER_MASK | v5_PRIV_MASK); + } + else + mask = byte_mask & v5_USER_MASK; + } + else + { + if ((operand & v4_UNALLOC_MASK) != 0) printf("ARM7: MSR_CPSR_IMM UNPREDICTABLE UNALLOC (operand %08X)\n", operand); + if(cpu->CPSR.bits.mode != USR) // Privileged mode + { + if ((operand & v4_STATE_MASK) != 0) printf("ARM7: MSR_CPSR_IMM UNPREDICTABLE STATE (operand %08X)\n", operand); + mask = byte_mask & (v4_USER_MASK | v4_PRIV_MASK); + } + else + mask = byte_mask & v4_USER_MASK; + } + cpu->CPSR.val = ((cpu->CPSR.val & (~mask)) | (operand & mask)); + if (BIT16(i)) armcpu_switchMode(cpu, cpu->CPSR.bits.mode); + cpu->changeCPSR(); +#else + if(cpu->CPSR.bits.mode!=USR) + { + if(BIT16(i)) + { + armcpu_switchMode(cpu, shift_op & 0x1F); + cpu->CPSR.val = (cpu->CPSR.val & 0xFFFFFF00) | (shift_op & 0xFF); + } + if(BIT17(i)) + cpu->CPSR.val = (cpu->CPSR.val & 0xFFFF00FF) | (shift_op & 0xFF00); + if(BIT18(i)) + cpu->CPSR.val = (cpu->CPSR.val & 0xFF00FFFF) | (shift_op & 0xFF0000); + } + if(BIT19(i)) + { + //cpu->CPSR.val = (cpu->CPSR.val & 0xFF000000) | (shift_op & 0xFF000000); + cpu->CPSR.val = (cpu->CPSR.val & 0x00FFFFFF) | (shift_op & 0xFF000000); + } + cpu->changeCPSR(); +#endif + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_MSR_SPSR_IMM_VAL(const u32 i) +{ + IMM_VALUE; + +#if 0 + // TODO + u32 operand = shift_op; + u32 mask = 0; + u32 byte_mask = (BIT16(i)?0x000000FF:0x00000000) | + (BIT17(i)?0x0000FF00:0x00000000) | + (BIT18(i)?0x00FF0000:0x00000000) | + (BIT19(i)?0xFF000000:0x00000000); + + if (PROCNUM == 0) + { + if ((operand & v5_UNALLOC_MASK) != 0) printf("ARM9: MSR_SPSR_IMM UNPREDICTABLE UNALLOC (operand %08X)\n", operand); + // if CurrentModeHasSPSR + mask = byte_mask & (v5_USER_MASK | v5_PRIV_MASK | v5_STATE_MASK); + } + else + { + if ((operand & v4_UNALLOC_MASK) != 0) printf("ARM7: MSR_SPSR_IMM UNPREDICTABLE UNALLOC (operand %08X)\n", operand); + // if CurrentModeHasSPSR + mask = byte_mask & (v4_USER_MASK | v4_PRIV_MASK | v4_STATE_MASK); + } + cpu->SPSR.val = ((cpu->SPSR.val & (~mask)) | (operand & mask)); +#else + if(cpu->CPSR.bits.mode!=USR) + { + if(BIT16(i)) + { + cpu->SPSR.val = (cpu->SPSR.val & 0xFFFFFF00) | (shift_op & 0xFF); + } + if(BIT17(i)) + cpu->SPSR.val = (cpu->SPSR.val & 0xFFFF00FF) | (shift_op & 0xFF00); + if(BIT18(i)) + cpu->SPSR.val = (cpu->SPSR.val & 0xFF00FFFF) | (shift_op & 0xFF0000); + } + if(BIT19(i)) + { + cpu->SPSR.val = (cpu->SPSR.val & 0xFF000000) | (shift_op & 0xFF000000); + } + + cpu->changeCPSR(); +#endif + + return 1; +} + +//----------------------------------------------------------------------------- +// Branch +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_BX(const u32 i) +{ + u32 tmp = cpu->R[REG_POS(i, 0)]; + + if (REG_POS(i, 0) == 15) + { + //printf("ARM%c: BX using PC as operand\n", PROCNUM?'7':'9'); + //emu_halt(); + } + cpu->CPSR.bits.T = BIT0(tmp); + cpu->R[15] = tmp & (0xFFFFFFFC|(cpu->CPSR.bits.T<<1)); + cpu->next_instruction = cpu->R[15]; + return 3; +} + +TEMPLATE static u32 FASTCALL OP_BLX_REG(const u32 i) +{ + u32 tmp = cpu->R[REG_POS(i, 0)]; + + cpu->R[14] = cpu->next_instruction; + cpu->CPSR.bits.T = BIT0(tmp); + cpu->R[15] = tmp & (0xFFFFFFFC|(cpu->CPSR.bits.T<<1)); + cpu->next_instruction = cpu->R[15]; + return 3; +} + +#define SIGNEXTEND_24(i) (((s32)i<<8)>>8) + +TEMPLATE static u32 FASTCALL OP_B(const u32 i) +{ + static const u32 mov_r12_r12 = 0xE1A0C00C; + const u32 last = _MMU_read32<PROCNUM,MMU_AT_DEBUG>(cpu->instruct_adr-4); + if(last == mov_r12_r12) + { + const u32 next = _MMU_read16<PROCNUM,MMU_AT_DEBUG>(cpu->instruct_adr+4); + if(next == 0x6464) + NocashMessage(cpu, 8); + } + + u32 off = SIGNEXTEND_24(i); + if(CONDITION(i)==0xF) + { + cpu->R[14] = cpu->next_instruction; + cpu->CPSR.bits.T = 1; + } + cpu->R[15] += (off<<2); + cpu->R[15] &= (0xFFFFFFFC|(cpu->CPSR.bits.T<<1)); + cpu->next_instruction = cpu->R[15]; + + return 3; +} + +TEMPLATE static u32 FASTCALL OP_BL(const u32 i) +{ + u32 off = SIGNEXTEND_24(i); + if(CONDITION(i)==0xF) + { + cpu->CPSR.bits.T = 1; + cpu->R[15] += 2; + } + cpu->R[14] = cpu->next_instruction; + cpu->R[15] += (off<<2); + cpu->R[15] &= (0xFFFFFFFC|(cpu->CPSR.bits.T<<1)); + cpu->next_instruction = cpu->R[15]; + + return 3; +} + +//----------------------------------------------------------------------------- +// CLZ +//----------------------------------------------------------------------------- + +const u8 CLZ_TAB[16]= +{ + 0, // 0000 + 1, // 0001 + 2, 2, // 001X + 3, 3, 3, 3, // 01XX + 4, 4, 4, 4, 4, 4, 4, 4 // 1XXX +}; + +TEMPLATE static u32 FASTCALL OP_CLZ(const u32 i) +{ + u32 Rm = cpu->R[REG_POS(i,0)]; + u32 pos; + + if(Rm==0) + { + cpu->R[REG_POS(i,12)]=32; + return 2; + } + + Rm |= (Rm >>1); + Rm |= (Rm >>2); + Rm |= (Rm >>4); + Rm |= (Rm >>8); + Rm |= (Rm >>16); + + pos = + CLZ_TAB[Rm&0xF] + + CLZ_TAB[(Rm>>4)&0xF] + + CLZ_TAB[(Rm>>8)&0xF] + + CLZ_TAB[(Rm>>12)&0xF] + + CLZ_TAB[(Rm>>16)&0xF] + + CLZ_TAB[(Rm>>20)&0xF] + + CLZ_TAB[(Rm>>24)&0xF] + + CLZ_TAB[(Rm>>28)&0xF]; + + cpu->R[REG_POS(i,12)]=32 - pos; + + return 2; +} + +//----------------------------------------------------------------------------- +// QADD / QDADD / QSUB / QDSUB +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_QADD(const u32 i) +{ + u32 res = cpu->R[REG_POS(i,16)]+cpu->R[REG_POS(i,0)]; + + //LOG("spe add\n"); + if(SIGNED_OVERFLOW(cpu->R[REG_POS(i,16)],cpu->R[REG_POS(i,0)], res)) + { + cpu->CPSR.bits.Q=1; + cpu->R[REG_POS(i,12)]=0x80000000-BIT31(res); + return 2; + } + cpu->R[REG_POS(i,12)]=res; + if(REG_POS(i,12)==15) + { + cpu->R[15] &= 0xFFFFFFFC; + cpu->next_instruction = cpu->R[15]; + return 3; + } + return 2; +} + +TEMPLATE static u32 FASTCALL OP_QSUB(const u32 i) +{ + u32 res = cpu->R[REG_POS(i,0)]-cpu->R[REG_POS(i,16)]; + + //LOG("spe add\n"); + if(SIGNED_UNDERFLOW(cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,16)], res)) + { + cpu->CPSR.bits.Q=1; + cpu->R[REG_POS(i,12)]=0x80000000-BIT31(res); + return 2; + } + cpu->R[REG_POS(i,12)]=res; + if(REG_POS(i,12)==15) + { + cpu->R[15] &= 0xFFFFFFFC; + cpu->next_instruction = cpu->R[15]; + return 3; + } + return 2; +} + +TEMPLATE static u32 FASTCALL OP_QDADD(const u32 i) +{ + u32 mul = cpu->R[REG_POS(i,16)]<<1; + u32 res; + + + //LOG("spe add\n"); + if(BIT31(cpu->R[REG_POS(i,16)])!=BIT31(mul)) + { + cpu->CPSR.bits.Q=1; + mul = 0x80000000-BIT31(mul); + } + + res = mul + cpu->R[REG_POS(i,0)]; + if(SIGNED_OVERFLOW(cpu->R[REG_POS(i,0)],mul, res)) + { + cpu->CPSR.bits.Q=1; + cpu->R[REG_POS(i,12)]=0x80000000-BIT31(res); + return 2; + } + cpu->R[REG_POS(i,12)]=res; + if(REG_POS(i,12)==15) + { + cpu->R[15] &= 0xFFFFFFFC; + cpu->next_instruction = cpu->R[15]; + return 3; + } + return 2; +} + +TEMPLATE static u32 FASTCALL OP_QDSUB(const u32 i) +{ + u32 mul = cpu->R[REG_POS(i,16)]<<1; + u32 res; + + + //LOG("spe add\n"); + if(BIT31(cpu->R[REG_POS(i,16)])!=BIT31(mul)) + { + cpu->CPSR.bits.Q=1; + mul = 0x80000000-BIT31(mul); + } + + res = cpu->R[REG_POS(i,0)] - mul; + if(SIGNED_UNDERFLOW(cpu->R[REG_POS(i,0)], mul, res)) + { + cpu->CPSR.bits.Q=1; + cpu->R[REG_POS(i,12)]=0x80000000-BIT31(res); + return 2; + } + cpu->R[REG_POS(i,12)]=res; + if(REG_POS(i,12)==15) + { + cpu->R[15] &= 0xFFFFFFFC; + cpu->next_instruction = cpu->R[15]; + return 3; + } + return 2; +} + +//----------------------------------------------------------------------------- +// SMUL +//----------------------------------------------------------------------------- + +#define HWORD(i) ((s32)(((s32)(i))>>16)) +#define LWORD(i) (s32)(((s32)((i)<<16))>>16) + +TEMPLATE static u32 FASTCALL OP_SMUL_B_B(const u32 i) +{ + // checked + //INFO("SMUL_B_B\n"); + cpu->R[REG_POS(i,16)] = (u32)(LWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)])); + + return 2; +} + +TEMPLATE static u32 FASTCALL OP_SMUL_B_T(const u32 i) +{ + //INFO("SMUL_B_T\n"); + cpu->R[REG_POS(i,16)] = (u32)(LWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); + + return 2; +} + +TEMPLATE static u32 FASTCALL OP_SMUL_T_B(const u32 i) +{ + //INFO("SMUL_T_B\n"); + cpu->R[REG_POS(i,16)] = (u32)(HWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)])); + + return 2; +} + +TEMPLATE static u32 FASTCALL OP_SMUL_T_T(const u32 i) +{ + //INFO("SMUL_T_T\n"); + cpu->R[REG_POS(i,16)] = (u32)(HWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); + + return 2; +} + +//----------------------------------------------------------------------------- +// SMLA +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_SMLA_B_B(const u32 i) +{ + u32 tmp = (u32)((s16)cpu->R[REG_POS(i,0)]* (s16)cpu->R[REG_POS(i,8)]); + + cpu->R[REG_POS(i,16)] = tmp + cpu->R[REG_POS(i,12)]; + + if (OverflowFromADD(cpu->R[REG_POS(i,16)], tmp, cpu->R[REG_POS(i,12)])) + cpu->CPSR.bits.Q = 1; + //INFO("SMLABB %08X * %08X + %08X = %08X\n", (s16)cpu->R[REG_POS(i,0)], (s16)cpu->R[REG_POS(i,8)], cpu->R[REG_POS(i,12)], (s32)cpu->R[REG_POS(i,16)]); + + return 2; +} + +TEMPLATE static u32 FASTCALL OP_SMLA_B_T(const u32 i) +{ + u32 tmp = (u32)(LWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); + u32 a = cpu->R[REG_POS(i,12)]; + + //INFO("SMLABT %08X * %08X + %08X = %08X\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a); + cpu->R[REG_POS(i,16)] = tmp + a; + + if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)])) + cpu->CPSR.bits.Q = 1; + + return 2; +} + +TEMPLATE static u32 FASTCALL OP_SMLA_T_B(const u32 i) +{ + u32 tmp = (u32)(HWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)])); + u32 a = cpu->R[REG_POS(i,12)]; + + //INFO("SMLATB %08X * %08X + %08X = %08X\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a); + cpu->R[REG_POS(i,16)] = tmp + a; + + if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)])) + cpu->CPSR.bits.Q = 1; + + return 2; +} + +TEMPLATE static u32 FASTCALL OP_SMLA_T_T(const u32 i) +{ + u32 tmp = (u32)(HWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); + u32 a = cpu->R[REG_POS(i,12)]; + + //INFO("SMLATT %08X * %08X + %08X = %08X\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a); + cpu->R[REG_POS(i,16)] = tmp + a; + + if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)])) + cpu->CPSR.bits.Q = 1; + + return 2; +} + +//----------------------------------------------------------------------------- +// SMLAL +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_SMLAL_B_B(const u32 i) +{ + s64 tmp = (s64)(LWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)])); + u64 res = (u64)tmp + cpu->R[REG_POS(i,12)]; + + //INFO("SMLALBB %08X * %08X + %08X%08X = %08X%08X\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + (res + ((tmp<0)*0xFFFFFFFF))), (int)(u32) res); + + cpu->R[REG_POS(i,12)] = (u32) res; + cpu->R[REG_POS(i,16)] += (res + ((tmp<0)*0xFFFFFFFF)); + + return 2; +} + +TEMPLATE static u32 FASTCALL OP_SMLAL_B_T(const u32 i) +{ + s64 tmp = (s64)(LWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); + u64 res = (u64)tmp + cpu->R[REG_POS(i,12)]; + + //INFO("SMLALBT %08X * %08X + %08X%08X = %08X%08X\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + res + ((tmp<0)*0xFFFFFFFF)), (int)(u32) res); + + cpu->R[REG_POS(i,12)] = (u32) res; + cpu->R[REG_POS(i,16)] += res + ((tmp<0)*0xFFFFFFFF); + + return 2; +} + +TEMPLATE static u32 FASTCALL OP_SMLAL_T_B(const u32 i) +{ + s64 tmp = (s64)(HWORD(cpu->R[REG_POS(i,0)])* (s64)LWORD(cpu->R[REG_POS(i,8)])); + u64 res = (u64)tmp + cpu->R[REG_POS(i,12)]; + + //INFO("SMLALTB %08X * %08X + %08X%08X = %08X%08X\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + res + ((tmp<0)*0xFFFFFFFF)), (int)(u32) res); + + cpu->R[REG_POS(i,12)] = (u32) res; + cpu->R[REG_POS(i,16)] += res + ((tmp<0)*0xFFFFFFFF); + + return 2; +} + +TEMPLATE static u32 FASTCALL OP_SMLAL_T_T(const u32 i) +{ + s64 tmp = (s64)(HWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); + u64 res = (u64)tmp + cpu->R[REG_POS(i,12)]; + + //INFO("SMLALTT %08X * %08X + %08X%08X = %08X%08X\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + res + ((tmp<0)*0xFFFFFFFF)), (int)(u32) res); + + cpu->R[REG_POS(i,12)] = (u32) res; + cpu->R[REG_POS(i,16)] += res + ((tmp<0)*0xFFFFFFFF); + + return 2; +} + +//----------------------------------------------------------------------------- +// SMULW +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_SMULW_B(const u32 i) +{ + s64 tmp = (s64)LWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]); + + //INFO("SMULWB %08X * %08X = %08X\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], ((tmp>>16)&0xFFFFFFFF)); + + cpu->R[REG_POS(i,16)] = ((tmp>>16)&0xFFFFFFFF); + + return 2; +} + +TEMPLATE static u32 FASTCALL OP_SMULW_T(const u32 i) +{ + s64 tmp = (s64)HWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]); + + //INFO("SMULWT %08X * %08X = %08X\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], ((tmp>>16)&0xFFFFFFFF)); + + cpu->R[REG_POS(i,16)] = ((tmp>>16)&0xFFFFFFFF); + + return 2; +} + +//----------------------------------------------------------------------------- +// SMLAW +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_SMLAW_B(const u32 i) +{ + s64 tmp = (s64)LWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]); + u32 a = cpu->R[REG_POS(i,12)]; + + //INFO("SMLAWB %08X * %08X + %08X = %08X\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, (tmp>>16) + a); + + tmp = (tmp>>16); + + cpu->R[REG_POS(i,16)] = tmp + a; + + if(SIGNED_OVERFLOW((u32)tmp, a, cpu->R[REG_POS(i,16)])) + cpu->CPSR.bits.Q = 1; + + return 2; +} + +TEMPLATE static u32 FASTCALL OP_SMLAW_T(const u32 i) +{ + s64 tmp = (s64)HWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]); + u32 a = cpu->R[REG_POS(i,12)]; + + //INFO("SMLAWT %08X * %08X + %08X = %08X\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, ((tmp>>16)&0xFFFFFFFF) + a); + + tmp = ((tmp>>16)&0xFFFFFFFF); + cpu->R[REG_POS(i,16)] = tmp + a; + + if(SIGNED_OVERFLOW((u32)tmp, a, cpu->R[REG_POS(i,16)])) + cpu->CPSR.bits.Q = 1; + + return 2; +} + +//----------------------------------------------------------------------------- +// LDR +//----------------------------------------------------------------------------- +#define OP_LDR(a, b) \ + cpu->R[REG_POS(i,12)] = ROR(READ32(cpu->mem_if->data, adr), 8*(adr&3)); \ + \ + if(REG_POS(i,12)==15) \ + { \ + if (cpu->LDTBit) \ + { \ + cpu->CPSR.bits.T = BIT0(cpu->R[15]); \ + cpu->R[15] &= 0xFFFFFFFE; \ + } \ + else \ + { \ + cpu->R[15] &= 0xFFFFFFFC; \ + } \ + cpu->next_instruction = cpu->R[15]; \ + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_READ>(b,adr); \ + } \ + \ + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_READ>(a,adr); + +// PRE +#define OP_LDR_W(a, b) \ + cpu->R[REG_POS(i,16)] = adr;\ + cpu->R[REG_POS(i,12)] = ROR(READ32(cpu->mem_if->data, adr), 8*(adr&3)); \ + \ + if(REG_POS(i,12)==15) \ + { \ + if (cpu->LDTBit) \ + { \ + cpu->CPSR.bits.T = BIT0(cpu->R[15]); \ + cpu->R[15] &= 0xFFFFFFFE; \ + } \ + else \ + { \ + cpu->R[15] &= 0xFFFFFFFC; \ + } \ + cpu->next_instruction = cpu->R[15]; \ + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_READ>(b,adr); \ + } \ + \ + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_READ>(a,adr); + +// POST +#define OP_LDR_W2(a, b, c) \ + u32 adr = cpu->R[REG_POS(i,16)]; \ + cpu->R[REG_POS(i,16)] = adr + c;\ + cpu->R[REG_POS(i,12)] = ROR(READ32(cpu->mem_if->data, adr), 8*(adr&3)); \ + \ + if(REG_POS(i,12)==15) \ + { \ + if (cpu->LDTBit) \ + { \ + cpu->CPSR.bits.T = BIT0(cpu->R[15]); \ + cpu->R[15] &= 0xFFFFFFFE; \ + } \ + else \ + { \ + cpu->R[15] &= 0xFFFFFFFC; \ + } \ + cpu->next_instruction = cpu->R[15]; \ + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_READ>(b,adr); \ + } \ + \ + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_READ>(a,adr); + + +TEMPLATE static u32 FASTCALL OP_LDR_P_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + OP_LDR(3, 5); +} + +TEMPLATE static u32 FASTCALL OP_LDR_M_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + OP_LDR(3, 5); +} + +TEMPLATE static u32 FASTCALL OP_LDREX(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = ROR(READ32(cpu->mem_if->data, adr), 8*(adr&3)); + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDR_P_LSL_IMM_OFF(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + OP_LDR(3, 5); +} + +TEMPLATE static u32 FASTCALL OP_LDR_M_LSL_IMM_OFF(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + OP_LDR(3, 5); +} + +TEMPLATE static u32 FASTCALL OP_LDR_P_LSR_IMM_OFF(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + OP_LDR(3, 5); +} + +TEMPLATE static u32 FASTCALL OP_LDR_M_LSR_IMM_OFF(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + OP_LDR(3, 5); +} + +TEMPLATE static u32 FASTCALL OP_LDR_P_ASR_IMM_OFF(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + OP_LDR(3, 5); +} + +TEMPLATE static u32 FASTCALL OP_LDR_M_ASR_IMM_OFF(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + OP_LDR(3, 5); +} + +TEMPLATE static u32 FASTCALL OP_LDR_P_ROR_IMM_OFF(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + OP_LDR(3, 5); +} + +TEMPLATE static u32 FASTCALL OP_LDR_M_ROR_IMM_OFF(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + OP_LDR(3, 5); +} + +TEMPLATE static u32 FASTCALL OP_LDR_P_IMM_OFF_PREIND(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + OP_LDR_W(3, 5); +} + +TEMPLATE static u32 FASTCALL OP_LDR_M_IMM_OFF_PREIND(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + OP_LDR_W(3, 5); +} + +TEMPLATE static u32 FASTCALL OP_LDR_P_LSL_IMM_OFF_PREIND(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + OP_LDR_W(3, 5); +} + +TEMPLATE static u32 FASTCALL OP_LDR_M_LSL_IMM_OFF_PREIND(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + OP_LDR_W(3, 5); +} + +TEMPLATE static u32 FASTCALL OP_LDR_P_LSR_IMM_OFF_PREIND(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + OP_LDR_W(3, 5); +} + +TEMPLATE static u32 FASTCALL OP_LDR_M_LSR_IMM_OFF_PREIND(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + OP_LDR_W(3, 5); +} + +TEMPLATE static u32 FASTCALL OP_LDR_P_ASR_IMM_OFF_PREIND(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + OP_LDR_W(3, 5); +} + +TEMPLATE static u32 FASTCALL OP_LDR_M_ASR_IMM_OFF_PREIND(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + OP_LDR_W(3, 5); +} + +TEMPLATE static u32 FASTCALL OP_LDR_P_ROR_IMM_OFF_PREIND(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + OP_LDR_W(3, 5); +} + +TEMPLATE static u32 FASTCALL OP_LDR_M_ROR_IMM_OFF_PREIND(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + OP_LDR_W(3, 5); +} + +TEMPLATE static u32 FASTCALL OP_LDR_P_IMM_OFF_POSTIND(const u32 i) +{ + OP_LDR_W2(3, 5, IMM_OFF_12); +} + +TEMPLATE static u32 FASTCALL OP_LDR_M_IMM_OFF_POSTIND(const u32 i) +{ + OP_LDR_W2(3, 5, -IMM_OFF_12); +} + +TEMPLATE static u32 FASTCALL OP_LDR_P_LSL_IMM_OFF_POSTIND(const u32 i) +{ + LSL_IMM; + OP_LDR_W2(3, 5, shift_op); +} + +TEMPLATE static u32 FASTCALL OP_LDR_M_LSL_IMM_OFF_POSTIND(const u32 i) +{ + LSL_IMM; + OP_LDR_W2(3, 5, -shift_op); +} + +TEMPLATE static u32 FASTCALL OP_LDR_P_LSR_IMM_OFF_POSTIND(const u32 i) +{ + LSR_IMM; + OP_LDR_W2(3, 5, shift_op); +} + +TEMPLATE static u32 FASTCALL OP_LDR_M_LSR_IMM_OFF_POSTIND(const u32 i) +{ + LSR_IMM; + OP_LDR_W2(3, 5, -shift_op); +} + +TEMPLATE static u32 FASTCALL OP_LDR_P_ASR_IMM_OFF_POSTIND(const u32 i) +{ + ASR_IMM; + OP_LDR_W2(3, 5, shift_op); +} + +TEMPLATE static u32 FASTCALL OP_LDR_M_ASR_IMM_OFF_POSTIND(const u32 i) +{ + ASR_IMM; + OP_LDR_W2(3, 5, -shift_op); +} + +TEMPLATE static u32 FASTCALL OP_LDR_P_ROR_IMM_OFF_POSTIND(const u32 i) +{ + ROR_IMM; + OP_LDR_W2(3, 5, shift_op); +} + +TEMPLATE static u32 FASTCALL OP_LDR_M_ROR_IMM_OFF_POSTIND(const u32 i) +{ + ROR_IMM; + OP_LDR_W2(3, 5, -shift_op); +} + +//----------------------------------------------------------------------------- +// LDRB +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_LDRB_P_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_M_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_P_LSL_IMM_OFF(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_M_LSL_IMM_OFF(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr);; + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_P_LSR_IMM_OFF(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + cpu->R[REG_POS(i,12)] = READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_M_LSR_IMM_OFF(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_P_ASR_IMM_OFF(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_M_ASR_IMM_OFF(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_P_ROR_IMM_OFF(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_M_ROR_IMM_OFF(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_P_IMM_OFF_PREIND(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_M_IMM_OFF_PREIND(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr);; + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_P_LSL_IMM_OFF_PREIND(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_M_LSL_IMM_OFF_PREIND(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_P_LSR_IMM_OFF_PREIND(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_M_LSR_IMM_OFF_PREIND(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_P_ASR_IMM_OFF_PREIND(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_M_ASR_IMM_OFF_PREIND(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_P_ROR_IMM_OFF_PREIND(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_M_ROR_IMM_OFF_PREIND(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_P_IMM_OFF_POSTIND(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_M_IMM_OFF_POSTIND(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_P_LSL_IMM_OFF_POSTIND(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_M_LSL_IMM_OFF_POSTIND(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] = adr - shift_op; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_P_LSR_IMM_OFF_POSTIND(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_M_LSR_IMM_OFF_POSTIND(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] = adr - shift_op; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_P_ASR_IMM_OFF_POSTIND(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_M_ASR_IMM_OFF_POSTIND(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] = adr - shift_op; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_P_ROR_IMM_OFF_POSTIND(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_M_ROR_IMM_OFF_POSTIND(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,16)] = adr - shift_op; + cpu->R[REG_POS(i,12)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3,adr); +} + +//----------------------------------------------------------------------------- +// STR +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_STR_P_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_M_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STREX(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,0)]); + cpu->R[REG_POS(i,12)] = 0; + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_P_LSL_IMM_OFF(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_M_LSL_IMM_OFF(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_P_LSR_IMM_OFF(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_M_LSR_IMM_OFF(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_P_ASR_IMM_OFF(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_M_ASR_IMM_OFF(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_P_ROR_IMM_OFF(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_M_ROR_IMM_OFF(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_P_IMM_OFF_PREIND(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + cpu->R[REG_POS(i,16)] = adr; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_M_IMM_OFF_PREIND(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + cpu->R[REG_POS(i,16)] = adr; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_P_LSL_IMM_OFF_PREIND(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + cpu->R[REG_POS(i,16)] = adr; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_M_LSL_IMM_OFF_PREIND(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + cpu->R[REG_POS(i,16)] = adr; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_P_LSR_IMM_OFF_PREIND(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + cpu->R[REG_POS(i,16)] = adr; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_M_LSR_IMM_OFF_PREIND(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + cpu->R[REG_POS(i,16)] = adr; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_P_ASR_IMM_OFF_PREIND(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + cpu->R[REG_POS(i,16)] = adr; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_M_ASR_IMM_OFF_PREIND(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + cpu->R[REG_POS(i,16)] = adr; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_P_ROR_IMM_OFF_PREIND(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + cpu->R[REG_POS(i,16)] = adr; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_M_ROR_IMM_OFF_PREIND(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + cpu->R[REG_POS(i,16)] = adr; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_P_IMM_OFF_POSTIND(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_M_IMM_OFF_POSTIND(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_P_LSL_IMM_OFF_POSTIND(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_M_LSL_IMM_OFF_POSTIND(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_P_LSR_IMM_OFF_POSTIND(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_M_LSR_IMM_OFF_POSTIND(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_P_ASR_IMM_OFF_POSTIND(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_M_ASR_IMM_OFF_POSTIND(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_P_ROR_IMM_OFF_POSTIND(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_M_ROR_IMM_OFF_POSTIND(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2,adr); +} + +//----------------------------------------------------------------------------- +// STRB +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_STRB_P_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_M_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_P_LSL_IMM_OFF(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_M_LSL_IMM_OFF(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_P_LSR_IMM_OFF(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_M_LSR_IMM_OFF(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_P_ASR_IMM_OFF(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_M_ASR_IMM_OFF(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_P_ROR_IMM_OFF(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_M_ROR_IMM_OFF(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_P_IMM_OFF_PREIND(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + cpu->R[REG_POS(i,16)] = adr; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_M_IMM_OFF_PREIND(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + cpu->R[REG_POS(i,16)] = adr; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_P_LSL_IMM_OFF_PREIND(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + cpu->R[REG_POS(i,16)] = adr; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_M_LSL_IMM_OFF_PREIND(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + cpu->R[REG_POS(i,16)] = adr; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_P_LSR_IMM_OFF_PREIND(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + cpu->R[REG_POS(i,16)] = adr; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_M_LSR_IMM_OFF_PREIND(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + cpu->R[REG_POS(i,16)] = adr; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_P_ASR_IMM_OFF_PREIND(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + cpu->R[REG_POS(i,16)] = adr; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_M_ASR_IMM_OFF_PREIND(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + cpu->R[REG_POS(i,16)] = adr; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_P_ROR_IMM_OFF_PREIND(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] + shift_op; + cpu->R[REG_POS(i,16)] = adr; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_M_ROR_IMM_OFF_PREIND(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)] - shift_op; + cpu->R[REG_POS(i,16)] = adr; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_P_IMM_OFF_POSTIND(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_M_IMM_OFF_POSTIND(const u32 i) +{ + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_P_LSL_IMM_OFF_POSTIND(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_M_LSL_IMM_OFF_POSTIND(const u32 i) +{ + LSL_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_P_LSR_IMM_OFF_POSTIND(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_M_LSR_IMM_OFF_POSTIND(const u32 i) +{ + LSR_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_P_ASR_IMM_OFF_POSTIND(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_M_ASR_IMM_OFF_POSTIND(const u32 i) +{ + ASR_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_P_ROR_IMM_OFF_POSTIND(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +TEMPLATE static u32 FASTCALL OP_STRB_M_ROR_IMM_OFF_POSTIND(const u32 i) +{ + ROR_IMM; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2,adr); +} + +//----------------------------------------------------------------------------- +// LDMIA / LDMIB / LDMDA / LDMDB +//----------------------------------------------------------------------------- + +#define OP_L_IA(reg, adr) if(BIT##reg(i)) \ + { \ + registres[reg] = READ32(cpu->mem_if->data, start); \ + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start); \ + adr += 4; \ + } + +#define OP_L_IB(reg, adr) if(BIT##reg(i)) \ + { \ + adr += 4; \ + registres[reg] = READ32(cpu->mem_if->data, start); \ + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start); \ + } + +#define OP_L_DA(reg, adr) if(BIT##reg(i)) \ + { \ + registres[reg] = READ32(cpu->mem_if->data, start); \ + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start); \ + adr -= 4; \ + } + +#define OP_L_DB(reg, adr) if(BIT##reg(i)) \ + { \ + adr -= 4; \ + registres[reg] = READ32(cpu->mem_if->data, start); \ + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start); \ + } + +TEMPLATE static u32 FASTCALL OP_LDMIA(const u32 i) +{ + u32 c = 0; + u32 start = cpu->R[REG_POS(i,16)]; + + u32 * registres = cpu->R; + + OP_L_IA(0, start); + OP_L_IA(1, start); + OP_L_IA(2, start); + OP_L_IA(3, start); + OP_L_IA(4, start); + OP_L_IA(5, start); + OP_L_IA(6, start); + OP_L_IA(7, start); + OP_L_IA(8, start); + OP_L_IA(9, start); + OP_L_IA(10, start); + OP_L_IA(11, start); + OP_L_IA(12, start); + OP_L_IA(13, start); + OP_L_IA(14, start); + + if(BIT15(i)) + { + u32 tmp = READ32(cpu->mem_if->data, start); + // TODO + // The general-purpose registers loaded can include the PC. If they do, the word loaded for the PC is treated + // as an address and a branch occurs to that address. In ARMv5 and above, bit[0] of the loaded value + // determines whether execution continues after this branch in ARM state or in Thumb state, as though a BX + // (loaded_value) instruction had been executed (but see also The T and J bits on page A2-15 for operation on + // non-T variants of ARMv5). In earlier versions of the architecture, bits[1:0] of the loaded value are ignored + // and execution continues in ARM state, as though the instruction MOV PC,(loaded_value) had been executed. + // + //value = Memory[address,4] + //if (architecture version 5 or above) then + // pc = value AND 0xFFFFFFFE + // T Bit = value[0] + //else + // pc = value AND 0xFFFFFFFC + if (cpu->LDTBit) + { + cpu->CPSR.bits.T = BIT0(tmp); + registres[15] = tmp & 0xFFFFFFFE; + } + else + registres[15] = tmp & 0xFFFFFFFC; + + //start += 4; + cpu->next_instruction = registres[15]; + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start); + } + + return MMU_aluMemCycles<PROCNUM>(2, c); +} + +TEMPLATE static u32 FASTCALL OP_LDMIB(const u32 i) +{ + u32 c = 0; + u32 start = cpu->R[REG_POS(i,16)]; + + u32 * registres = cpu->R; + + OP_L_IB(0, start); + OP_L_IB(1, start); + OP_L_IB(2, start); + OP_L_IB(3, start); + OP_L_IB(4, start); + OP_L_IB(5, start); + OP_L_IB(6, start); + OP_L_IB(7, start); + OP_L_IB(8, start); + OP_L_IB(9, start); + OP_L_IB(10, start); + OP_L_IB(11, start); + OP_L_IB(12, start); + OP_L_IB(13, start); + OP_L_IB(14, start); + + if(BIT15(i)) + { + start += 4; + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start); + u32 tmp = READ32(cpu->mem_if->data, start); + if (cpu->LDTBit) + { + cpu->CPSR.bits.T = BIT0(tmp); + registres[15] = tmp & 0xFFFFFFFE; + } + else + registres[15] = tmp & 0xFFFFFFFC; + cpu->next_instruction = registres[15]; + return MMU_aluMemCycles<PROCNUM>(4, c); + } + + return MMU_aluMemCycles<PROCNUM>(2, c); +} + +TEMPLATE static u32 FASTCALL OP_LDMDA(const u32 i) +{ + u32 c = 0; + u32 start = cpu->R[REG_POS(i,16)]; + + u32 * registres = cpu->R; + + if(BIT15(i)) + { + u32 tmp = READ32(cpu->mem_if->data, start); + if (cpu->LDTBit) + { + cpu->CPSR.bits.T = BIT0(tmp); + registres[15] = tmp & 0xFFFFFFFE; + } + else + registres[15] = tmp & 0xFFFFFFFC; + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start); + start -= 4; + cpu->next_instruction = registres[15]; + } + + OP_L_DA(14, start); + OP_L_DA(13, start); + OP_L_DA(12, start); + OP_L_DA(11, start); + OP_L_DA(10, start); + OP_L_DA(9, start); + OP_L_DA(8, start); + OP_L_DA(7, start); + OP_L_DA(6, start); + OP_L_DA(5, start); + OP_L_DA(4, start); + OP_L_DA(3, start); + OP_L_DA(2, start); + OP_L_DA(1, start); + OP_L_DA(0, start); + + return MMU_aluMemCycles<PROCNUM>(2, c); +} + +TEMPLATE static u32 FASTCALL OP_LDMDB(const u32 i) +{ + u32 c = 0; + u32 start = cpu->R[REG_POS(i,16)]; + + u32 * registres = cpu->R; + + if(BIT15(i)) + { + start -= 4; + u32 tmp = READ32(cpu->mem_if->data, start); + if (cpu->LDTBit) + { + cpu->CPSR.bits.T = BIT0(tmp); + registres[15] = tmp & 0xFFFFFFFE; + } + else + registres[15] = tmp & 0xFFFFFFFC; + cpu->next_instruction = registres[15]; + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start); + } + + OP_L_DB(14, start); + OP_L_DB(13, start); + OP_L_DB(12, start); + OP_L_DB(11, start); + OP_L_DB(10, start); + OP_L_DB(9, start); + OP_L_DB(8, start); + OP_L_DB(7, start); + OP_L_DB(6, start); + OP_L_DB(5, start); + OP_L_DB(4, start); + OP_L_DB(3, start); + OP_L_DB(2, start); + OP_L_DB(1, start); + OP_L_DB(0, start); + + return MMU_aluMemCycles<PROCNUM>(2, c); +} + +TEMPLATE static u32 FASTCALL OP_LDMIA_W(const u32 i) +{ + u32 c = 0; + u32 start = cpu->R[REG_POS(i,16)]; + u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; + + u32 * registres = cpu->R; + + OP_L_IA(0, start); + OP_L_IA(1, start); + OP_L_IA(2, start); + OP_L_IA(3, start); + OP_L_IA(4, start); + OP_L_IA(5, start); + OP_L_IA(6, start); + OP_L_IA(7, start); + OP_L_IA(8, start); + OP_L_IA(9, start); + OP_L_IA(10, start); + OP_L_IA(11, start); + OP_L_IA(12, start); + OP_L_IA(13, start); + OP_L_IA(14, start); + + if(BIT15(i)) + { + u32 tmp = READ32(cpu->mem_if->data, start); + if (cpu->LDTBit) + { + cpu->CPSR.bits.T = BIT0(tmp); + registres[15] = tmp & 0xFFFFFFFE; + } + else + registres[15] = tmp & 0xFFFFFFFC; + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start); + start += 4; + cpu->next_instruction = registres[15]; + } + + if(i & (1 << REG_POS(i,16))) { + if(i & bitList) + cpu->R[REG_POS(i,16)] = start; + } + else + cpu->R[REG_POS(i,16)] = start; + + return MMU_aluMemCycles<PROCNUM>(2, c); +} + +TEMPLATE static u32 FASTCALL OP_LDMIB_W(const u32 i) +{ + u32 c = 0; + u32 start = cpu->R[REG_POS(i,16)]; + u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; + + u32 * registres = cpu->R; + + OP_L_IB(0, start); + OP_L_IB(1, start); + OP_L_IB(2, start); + OP_L_IB(3, start); + OP_L_IB(4, start); + OP_L_IB(5, start); + OP_L_IB(6, start); + OP_L_IB(7, start); + OP_L_IB(8, start); + OP_L_IB(9, start); + OP_L_IB(10, start); + OP_L_IB(11, start); + OP_L_IB(12, start); + OP_L_IB(13, start); + OP_L_IB(14, start); + + if(BIT15(i)) + { + u32 tmp; + start += 4; + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start); + tmp = READ32(cpu->mem_if->data, start); + if (cpu->LDTBit) + { + cpu->CPSR.bits.T = BIT0(tmp); + registres[15] = tmp & 0xFFFFFFFE; + } + else + registres[15] = tmp & 0xFFFFFFFC; + cpu->next_instruction = registres[15]; + } + + if(i & (1 << REG_POS(i,16))) { + if(i & bitList) + cpu->R[REG_POS(i,16)] = start; + } + else + cpu->R[REG_POS(i,16)] = start; + + if(BIT15(i)) + return MMU_aluMemCycles<PROCNUM>(4, c); + else + return MMU_aluMemCycles<PROCNUM>(2, c); +} + +TEMPLATE static u32 FASTCALL OP_LDMDA_W(const u32 i) +{ + u32 c = 0; + u32 start = cpu->R[REG_POS(i,16)]; + u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; + + u32 * registres = cpu->R; + + if(BIT15(i)) + { + u32 tmp = READ32(cpu->mem_if->data, start); + if (cpu->LDTBit) + { + cpu->CPSR.bits.T = BIT0(tmp); + registres[15] = tmp & 0xFFFFFFFE; + } + else + registres[15] = tmp & 0xFFFFFFFC; + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start); + start -= 4; + cpu->next_instruction = registres[15]; + } + + OP_L_DA(14, start); + OP_L_DA(13, start); + OP_L_DA(12, start); + OP_L_DA(11, start); + OP_L_DA(10, start); + OP_L_DA(9, start); + OP_L_DA(8, start); + OP_L_DA(7, start); + OP_L_DA(6, start); + OP_L_DA(5, start); + OP_L_DA(4, start); + OP_L_DA(3, start); + OP_L_DA(2, start); + OP_L_DA(1, start); + OP_L_DA(0, start); + + if(i & (1 << REG_POS(i,16))) { + if(i & bitList) + cpu->R[REG_POS(i,16)] = start; + } + else + cpu->R[REG_POS(i,16)] = start; + + return MMU_aluMemCycles<PROCNUM>(2, c); +} + +TEMPLATE static u32 FASTCALL OP_LDMDB_W(const u32 i) +{ + u32 c = 0; + u32 start = cpu->R[REG_POS(i,16)]; + u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; + u32 * registres = cpu->R; + + if(BIT15(i)) + { + u32 tmp; + start -= 4; + tmp = READ32(cpu->mem_if->data, start); + if (cpu->LDTBit) + { + cpu->CPSR.bits.T = BIT0(tmp); + registres[15] = tmp & 0xFFFFFFFE; } + else + registres[15] = tmp & 0xFFFFFFFC; + cpu->next_instruction = registres[15]; + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start); + } + + OP_L_DB(14, start); + OP_L_DB(13, start); + OP_L_DB(12, start); + OP_L_DB(11, start); + OP_L_DB(10, start); + OP_L_DB(9, start); + OP_L_DB(8, start); + OP_L_DB(7, start); + OP_L_DB(6, start); + OP_L_DB(5, start); + OP_L_DB(4, start); + OP_L_DB(3, start); + OP_L_DB(2, start); + OP_L_DB(1, start); + OP_L_DB(0, start); + + if(i & (1 << REG_POS(i,16))) { + if(i & bitList) + cpu->R[REG_POS(i,16)] = start; + } + else + cpu->R[REG_POS(i,16)] = start; + + return MMU_aluMemCycles<PROCNUM>(2, c); +} + +TEMPLATE static u32 FASTCALL OP_LDMIA2(const u32 i) +{ + u32 oldmode = 0; + + u32 c = 0; + + u32 start = cpu->R[REG_POS(i,16)]; + u32 * registres; + + if(BIT15(i)==0) + { + if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + + OP_L_IA(0, start); + OP_L_IA(1, start); + OP_L_IA(2, start); + OP_L_IA(3, start); + OP_L_IA(4, start); + OP_L_IA(5, start); + OP_L_IA(6, start); + OP_L_IA(7, start); + OP_L_IA(8, start); + OP_L_IA(9, start); + OP_L_IA(10, start); + OP_L_IA(11, start); + OP_L_IA(12, start); + OP_L_IA(13, start); + OP_L_IA(14, start); + + if(BIT15(i) == 0) + { + armcpu_switchMode(cpu, oldmode); + } + else + { + + u32 tmp = READ32(cpu->mem_if->data, start); + Status_Reg SPSR; + cpu->R[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->changeCPSR(); + //start += 4; + cpu->next_instruction = cpu->R[15]; + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start); + } + return MMU_aluMemCycles<PROCNUM>(2, c); +} + +TEMPLATE static u32 FASTCALL OP_LDMIB2(const u32 i) +{ + u32 oldmode = 0; + u32 c = 0; + + u32 start = cpu->R[REG_POS(i,16)]; + u32 * registres; + + UNTESTEDOPCODELOG("Untested opcode: OP_LDMIB2 \n"); + + if(BIT15(i)==0) + { + if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + + OP_L_IB(0, start); + OP_L_IB(1, start); + OP_L_IB(2, start); + OP_L_IB(3, start); + OP_L_IB(4, start); + OP_L_IB(5, start); + OP_L_IB(6, start); + OP_L_IB(7, start); + OP_L_IB(8, start); + OP_L_IB(9, start); + OP_L_IB(10, start); + OP_L_IB(11, start); + OP_L_IB(12, start); + OP_L_IB(13, start); + OP_L_IB(14, start); + + if(BIT15(i) == 0) + { + armcpu_switchMode(cpu, oldmode); + } + else + { + u32 tmp; + Status_Reg SPSR; + start += 4; + tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->changeCPSR(); + cpu->next_instruction = registres[15]; + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start); + } + return MMU_aluMemCycles<PROCNUM>(2, c); +} + +TEMPLATE static u32 FASTCALL OP_LDMDA2(const u32 i) +{ + + u32 oldmode = 0; + u32 c = 0; + u32 * registres; + + u32 start = cpu->R[REG_POS(i,16)]; + + UNTESTEDOPCODELOG("Untested opcode: OP_LDMDA2 \n"); + + if(BIT15(i)==0) + { + if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + + if(BIT15(i)) + { + u32 tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR = cpu->SPSR; + cpu->changeCPSR(); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start); + start -= 4; + cpu->next_instruction = registres[15]; + } + + OP_L_DA(14, start); + OP_L_DA(13, start); + OP_L_DA(12, start); + OP_L_DA(11, start); + OP_L_DA(10, start); + OP_L_DA(9, start); + OP_L_DA(8, start); + OP_L_DA(7, start); + OP_L_DA(6, start); + OP_L_DA(5, start); + OP_L_DA(4, start); + OP_L_DA(3, start); + OP_L_DA(2, start); + OP_L_DA(1, start); + OP_L_DA(0, start); + + if(BIT15(i)==0) + { + armcpu_switchMode(cpu, oldmode); + } + else + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->changeCPSR(); + } + + return MMU_aluMemCycles<PROCNUM>(2, c); +} + +TEMPLATE static u32 FASTCALL OP_LDMDB2(const u32 i) +{ + u32 oldmode = 0; + u32 c = 0; + u32 * registres; + + u32 start = cpu->R[REG_POS(i,16)]; + if(BIT15(i)==0) + { + if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + + if(BIT15(i)) + { + u32 tmp; + start -= 4; + tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR = cpu->SPSR; + cpu->changeCPSR(); + cpu->next_instruction = registres[15]; + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start); + } + + OP_L_DB(14, start); + OP_L_DB(13, start); + OP_L_DB(12, start); + OP_L_DB(11, start); + OP_L_DB(10, start); + OP_L_DB(9, start); + OP_L_DB(8, start); + OP_L_DB(7, start); + OP_L_DB(6, start); + OP_L_DB(5, start); + OP_L_DB(4, start); + OP_L_DB(3, start); + OP_L_DB(2, start); + OP_L_DB(1, start); + OP_L_DB(0, start); + + if(BIT15(i)==0) + { + armcpu_switchMode(cpu, oldmode); + } + else + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->changeCPSR(); + } + + return MMU_aluMemCycles<PROCNUM>(2, c); +} + +TEMPLATE static u32 FASTCALL OP_LDMIA2_W(const u32 i) +{ + u32 c = 0; + + u32 oldmode = 0; + u32 start = cpu->R[REG_POS(i,16)]; + u32 * registres; + u32 tmp; + Status_Reg SPSR; +// emu_halt(); + if(BIT15(i)==0) + { + if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + + OP_L_IA(0, start); + OP_L_IA(1, start); + OP_L_IA(2, start); + OP_L_IA(3, start); + OP_L_IA(4, start); + OP_L_IA(5, start); + OP_L_IA(6, start); + OP_L_IA(7, start); + OP_L_IA(8, start); + OP_L_IA(9, start); + OP_L_IA(10, start); + OP_L_IA(11, start); + OP_L_IA(12, start); + OP_L_IA(13, start); + OP_L_IA(14, start); + + if(BIT15(i)==0) + { + if (!BIT_N(i, REG_POS(i,16))) + registres[REG_POS(i,16)] = start; + armcpu_switchMode(cpu, oldmode); + return MMU_aluMemCycles<PROCNUM>(2, c); + } + + if (!BIT_N(i, REG_POS(i,16))) + registres[REG_POS(i,16)] = start + 4; + tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->changeCPSR(); + cpu->next_instruction = registres[15]; + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start); + + return MMU_aluMemCycles<PROCNUM>(2, c); +} + +TEMPLATE static u32 FASTCALL OP_LDMIB2_W(const u32 i) +{ + u32 c = 0; + + u32 oldmode = 0; + u32 start = cpu->R[REG_POS(i,16)]; + u32 * registres; + u32 tmp; + Status_Reg SPSR; + + if(BIT15(i)==0) + { + if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + + OP_L_IB(0, start); + OP_L_IB(1, start); + OP_L_IB(2, start); + OP_L_IB(3, start); + OP_L_IB(4, start); + OP_L_IB(5, start); + OP_L_IB(6, start); + OP_L_IB(7, start); + OP_L_IB(8, start); + OP_L_IB(9, start); + OP_L_IB(10, start); + OP_L_IB(11, start); + OP_L_IB(12, start); + OP_L_IB(13, start); + OP_L_IB(14, start); + + if(BIT15(i)==0) + { + if (!BIT_N(i, REG_POS(i,16))) + registres[REG_POS(i,16)] = start; + armcpu_switchMode(cpu, oldmode); + + return MMU_aluMemCycles<PROCNUM>(2, c); + } + + if (!BIT_N(i, REG_POS(i,16))) + registres[REG_POS(i,16)] = start + 4; + tmp = READ32(cpu->mem_if->data, start + 4); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR = cpu->SPSR; + cpu->changeCPSR(); + cpu->next_instruction = registres[15]; + SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->changeCPSR(); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start); + + return MMU_aluMemCycles<PROCNUM>(2, c); +} + +TEMPLATE static u32 FASTCALL OP_LDMDA2_W(const u32 i) +{ + u32 c = 0; + + u32 oldmode = 0; + u32 start = cpu->R[REG_POS(i,16)]; + u32 * registres; + Status_Reg SPSR; +// emu_halt(); + if(BIT15(i)==0) + { + if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + + if(BIT15(i)) + { + if (BIT_N(i, REG_POS(i,16))) printf("error1_1\n"); + u32 tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start); + start -= 4; + cpu->next_instruction = registres[15]; + } + + OP_L_DA(14, start); + OP_L_DA(13, start); + OP_L_DA(12, start); + OP_L_DA(11, start); + OP_L_DA(10, start); + OP_L_DA(9, start); + OP_L_DA(8, start); + OP_L_DA(7, start); + OP_L_DA(6, start); + OP_L_DA(5, start); + OP_L_DA(4, start); + OP_L_DA(3, start); + OP_L_DA(2, start); + OP_L_DA(1, start); + OP_L_DA(0, start); + + if (!BIT_N(i, REG_POS(i,16))) + registres[REG_POS(i,16)] = start; + + if(BIT15(i)==0) + { + armcpu_switchMode(cpu, oldmode); + return MMU_aluMemCycles<PROCNUM>(2, c); + } + + SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->changeCPSR(); + return MMU_aluMemCycles<PROCNUM>(2, c); +} + +TEMPLATE static u32 FASTCALL OP_LDMDB2_W(const u32 i) +{ + u32 c = 0; + + u32 oldmode = 0; + u32 start = cpu->R[REG_POS(i,16)]; + u32 * registres; + Status_Reg SPSR; +// emu_halt(); + if(BIT15(i)==0) + { + if((cpu->CPSR.bits.mode==USR)||(cpu->CPSR.bits.mode==SYS)) { printf("ERROR1\n"); return 1; } + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + + if(BIT15(i)) + { + if (BIT_N(i, REG_POS(i,16))) printf("error1_2\n"); + u32 tmp; + start -= 4; + tmp = READ32(cpu->mem_if->data, start); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR = cpu->SPSR; + cpu->changeCPSR(); + cpu->next_instruction = registres[15]; + } + + OP_L_DB(14, start); + OP_L_DB(13, start); + OP_L_DB(12, start); + OP_L_DB(11, start); + OP_L_DB(10, start); + OP_L_DB(9, start); + OP_L_DB(8, start); + OP_L_DB(7, start); + OP_L_DB(6, start); + OP_L_DB(5, start); + OP_L_DB(4, start); + OP_L_DB(3, start); + OP_L_DB(2, start); + OP_L_DB(1, start); + OP_L_DB(0, start); + + if (!BIT_N(i, REG_POS(i,16))) + registres[REG_POS(i,16)] = start; + + if(BIT15(i)==0) + { + armcpu_switchMode(cpu, oldmode); + return MMU_aluMemCycles<PROCNUM>(2, c); + } + + SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->changeCPSR(); + return MMU_aluMemCycles<PROCNUM>(2, c); +} + +//----------------------------------------------------------------------------- +// STMIA / STMIB / STMDA / STMDB +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_STMIA(const u32 i) +{ + u32 c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; b++) + { + if(BIT_N(i, b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(start); + start += 4; + } + } + return MMU_aluMemCycles<PROCNUM>(1, c); +} + +TEMPLATE static u32 FASTCALL OP_STMIB(const u32 i) +{ + u32 c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; b++) + { + if(BIT_N(i, b)) + { + start += 4; + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(start); + } + } + return MMU_aluMemCycles<PROCNUM>(1, c); +} + +TEMPLATE static u32 FASTCALL OP_STMDA(const u32 i) +{ + u32 c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; b++) + { + if(BIT_N(i, 15-b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(start); + start -= 4; + } + } + return MMU_aluMemCycles<PROCNUM>(1, c); +} + +TEMPLATE static u32 FASTCALL OP_STMDB(const u32 i) +{ + u32 c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; b++) + { + if(BIT_N(i, 15-b)) + { + start -= 4; + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(start); + } + } + return MMU_aluMemCycles<PROCNUM>(1, c); +} + +TEMPLATE static u32 FASTCALL OP_STMIA_W(const u32 i) +{ + u32 c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; b++) + { + if(BIT_N(i, b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(start); + start += 4; + } + } + + cpu->R[REG_POS(i,16)] = start; + return MMU_aluMemCycles<PROCNUM>(1, c); +} + +TEMPLATE static u32 FASTCALL OP_STMIB_W(const u32 i) +{ + u32 c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; b++) + { + if(BIT_N(i, b)) + { + start += 4; + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(start); + } + } + cpu->R[REG_POS(i,16)] = start; + return MMU_aluMemCycles<PROCNUM>(1, c); +} + +TEMPLATE static u32 FASTCALL OP_STMDA_W(const u32 i) +{ + u32 c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; b++) + { + if(BIT_N(i, 15-b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(start); + start -= 4; + } + } + + cpu->R[REG_POS(i,16)] = start; + return MMU_aluMemCycles<PROCNUM>(1, c); +} + +TEMPLATE static u32 FASTCALL OP_STMDB_W(const u32 i) +{ + u32 c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; b++) + { + if(BIT_N(i, 15-b)) + { + start -= 4; + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(start); + } + } + + cpu->R[REG_POS(i,16)] = start; + return MMU_aluMemCycles<PROCNUM>(1, c); +} + +TEMPLATE static u32 FASTCALL OP_STMIA2(const u32 i) +{ + u32 c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + c = 0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + UNTESTEDOPCODELOG("Untested opcode: OP_STMIA2 \n"); + + for(b=0; b<16; b++) + { + if(BIT_N(i, b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(start); + start += 4; + } + } + + armcpu_switchMode(cpu, oldmode); + return MMU_aluMemCycles<PROCNUM>(1, c); +} + +TEMPLATE static u32 FASTCALL OP_STMIB2(const u32 i) +{ + u32 c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + c = 0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + UNTESTEDOPCODELOG("Untested opcode: OP_STMIB2 \n"); + + for(b=0; b<16; b++) + { + if(BIT_N(i, b)) + { + start += 4; + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(start); + } + } + + armcpu_switchMode(cpu, oldmode); + return MMU_aluMemCycles<PROCNUM>(1, c); +} + +TEMPLATE static u32 FASTCALL OP_STMDA2(const u32 i) +{ + u32 c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + c = 0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + UNTESTEDOPCODELOG("Untested opcode: OP_STMDA2 \n"); + + for(b=0; b<16; b++) + { + if(BIT_N(i, 15-b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(start); + start -= 4; + } + } + + armcpu_switchMode(cpu, oldmode); + return MMU_aluMemCycles<PROCNUM>(1, c); +} + +TEMPLATE static u32 FASTCALL OP_STMDB2(const u32 i) +{ + u32 c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + c=0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + for(b=0; b<16; b++) + { + if(BIT_N(i, 15-b)) + { + start -= 4; + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(start); + } + } + + armcpu_switchMode(cpu, oldmode); + return MMU_aluMemCycles<PROCNUM>(1, c); +} + +TEMPLATE static u32 FASTCALL OP_STMIA2_W(const u32 i) +{ + u32 c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + c=0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + UNTESTEDOPCODELOG("Untested opcode: OP_STMIA2_W \n"); + + for(b=0; b<16; b++) + { + if(BIT_N(i, b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(start); + start += 4; + } + } + + cpu->R[REG_POS(i,16)] = start; + + armcpu_switchMode(cpu, oldmode); + return MMU_aluMemCycles<PROCNUM>(1, c); +} + +TEMPLATE static u32 FASTCALL OP_STMIB2_W(const u32 i) +{ + u32 c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + c=0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + for(b=0; b<16; b++) + { + if(BIT_N(i, b)) + { + start += 4; + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(start); + } + } + armcpu_switchMode(cpu, oldmode); + cpu->R[REG_POS(i,16)] = start; + + return MMU_aluMemCycles<PROCNUM>(1, c); +} + +TEMPLATE static u32 FASTCALL OP_STMDA2_W(const u32 i) +{ + u32 c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + c = 0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + UNTESTEDOPCODELOG("Untested opcode: OP_STMDA2_W \n"); + + for(b=0; b<16; b++) + { + if(BIT_N(i, 15-b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(start); + start -= 4; + } + } + + cpu->R[REG_POS(i,16)] = start; + + armcpu_switchMode(cpu, oldmode); + return MMU_aluMemCycles<PROCNUM>(1, c); +} + +TEMPLATE static u32 FASTCALL OP_STMDB2_W(const u32 i) +{ + u32 c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + c = 0; + + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + UNTESTEDOPCODELOG("Untested opcode: OP_STMDB2_W \n"); + + for(b=0; b<16; b++) + { + if(BIT_N(i, 15-b)) + { + start -= 4; + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(start); + } + } + + cpu->R[REG_POS(i,16)] = start; + + armcpu_switchMode(cpu, oldmode); + return MMU_aluMemCycles<PROCNUM>(1, c); +} + +//----------------------------------------------------------------------------- +// LDRD / STRD +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_LDRD_STRD_POST_INDEX(const u32 i) +{ + u32 Rd_num = REG_POS( i, 12); + u32 addr = cpu->R[REG_POS(i,16)]; + u32 index; + //printf("%s POST\n", BIT5(i)?"STRD":"LDRD"); + /* I bit - immediate or register */ + if ( BIT22(i)) + index = IMM_OFF; + else + index = cpu->R[REG_POS(i,0)]; + + // U bit - add or subtract + if ( BIT23(i)) + cpu->R[REG_POS(i,16)] += index; + else + cpu->R[REG_POS(i,16)] -= index; + + u32 c = 0; + if ( !(Rd_num & 0x1)) + { + // Store/Load + if ( BIT5(i)) + { + WRITE32(cpu->mem_if->data, addr, cpu->R[Rd_num]); + WRITE32(cpu->mem_if->data, addr + 4, cpu->R[Rd_num + 1]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(addr); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(addr + 4); + } + else + { + cpu->R[Rd_num] = READ32(cpu->mem_if->data, addr); + cpu->R[Rd_num + 1] = READ32(cpu->mem_if->data, addr + 4); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(addr); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(addr + 4); + } + } + + return MMU_aluMemCycles<PROCNUM>(3, c); +} + +TEMPLATE static u32 FASTCALL OP_LDRD_STRD_OFFSET_PRE_INDEX(const u32 i) +{ + u32 Rd_num = REG_POS( i, 12); + u32 addr = cpu->R[REG_POS(i,16)]; + u32 index; + + //printf("%s PRE\n", BIT5(i)?"STRD":"LDRD"); + // I bit - immediate or register + if ( BIT22(i)) + index = IMM_OFF; + else + index = cpu->R[REG_POS(i,0)]; + + // U bit - add or subtract + if ( BIT23(i)) + addr += index; + else + addr -= index; + + u32 c = 0; + if ( !(Rd_num & 0x1)) + { + // Store/Load + if ( BIT5(i)) + { + WRITE32(cpu->mem_if->data, addr, cpu->R[Rd_num]); + WRITE32(cpu->mem_if->data, addr + 4, cpu->R[Rd_num + 1]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(addr); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(addr + 4); + // W bit - writeback + if ( BIT21(i)) + cpu->R[REG_POS(i,16)] = addr; + } + else + { + // W bit - writeback + if ( BIT21(i)) + cpu->R[REG_POS(i,16)] = addr; + cpu->R[Rd_num] = READ32(cpu->mem_if->data, addr); + cpu->R[Rd_num + 1] = READ32(cpu->mem_if->data, addr + 4); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(addr); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(addr + 4); + } + } + + return MMU_aluMemCycles<PROCNUM>(3, c); +} + +//----------------------------------------------------------------------------- +// STC +// the NDS has no coproc that responses to a STC, no feedback is given to the arm +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_STC_P_IMM_OFF(const u32 i) +{ + //INFO("OP_STC_P_IMM_OFF\n"); + return TRAPUNDEF(cpu); +} + +TEMPLATE static u32 FASTCALL OP_STC_M_IMM_OFF(const u32 i) +{ + //INFO("OP_STC_M_IMM_OFF\n"); + return TRAPUNDEF(cpu); +} + +TEMPLATE static u32 FASTCALL OP_STC_P_PREIND(const u32 i) +{ + //INFO("OP_STC_P_PREIND\n"); + return TRAPUNDEF(cpu); +} + +TEMPLATE static u32 FASTCALL OP_STC_M_PREIND(const u32 i) +{ + //INFO("OP_STC_M_PREIND\n"); + return TRAPUNDEF(cpu); +} + +TEMPLATE static u32 FASTCALL OP_STC_P_POSTIND(const u32 i) +{ + //INFO("OP_STC_P_POSTIND: cp_num %i\n", (i>>8)&0x0F); + return TRAPUNDEF(cpu); + + +} + +TEMPLATE static u32 FASTCALL OP_STC_M_POSTIND(const u32 i) +{ + //INFO("OP_STC_M_POSTIND\n"); + return TRAPUNDEF(cpu); +} + +TEMPLATE static u32 FASTCALL OP_STC_OPTION(const u32 i) +{ + //INFO("OP_STC_OPTION\n"); + return TRAPUNDEF(cpu); +} + +//----------------------------------------------------------------------------- +// LDC +// the NDS has no coproc that responses to a LDC, no feedback is given to the arm +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_LDC_P_IMM_OFF(const u32 i) +{ + //INFO("OP_LDC_P_IMM_OFF\n"); + return TRAPUNDEF(cpu); +} + +TEMPLATE static u32 FASTCALL OP_LDC_M_IMM_OFF(const u32 i) +{ + //INFO("OP_LDC_M_IMM_OFF\n"); + return TRAPUNDEF(cpu); +} + +TEMPLATE static u32 FASTCALL OP_LDC_P_PREIND(const u32 i) +{ + //INFO("OP_LDC_P_PREIND\n"); + return TRAPUNDEF(cpu); +} + +TEMPLATE static u32 FASTCALL OP_LDC_M_PREIND(const u32 i) +{ + //INFO("OP_LDC_M_PREIND\n"); + return TRAPUNDEF(cpu); +} + +TEMPLATE static u32 FASTCALL OP_LDC_P_POSTIND(const u32 i) +{ + //INFO("OP_LDC_P_POSTIND\n"); + return TRAPUNDEF(cpu); +} + +TEMPLATE static u32 FASTCALL OP_LDC_M_POSTIND(const u32 i) +{ + //INFO("OP_LDC_M_POSTIND\n"); + return TRAPUNDEF(cpu); +} + +TEMPLATE static u32 FASTCALL OP_LDC_OPTION(const u32 i) +{ + //INFO("OP_LDC_OPTION\n"); + return TRAPUNDEF(cpu); +} + +//----------------------------------------------------------------------------- +// MCR / MRC +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_MCR(const u32 i) +{ + u32 cpnum = REG_POS(i, 8); + + if(!cpu->coproc[cpnum]) + { + //emu_halt(); + //INFO("Stopped (OP_MCR) \n"); + INFO("ARM%c: MCR P%i, 0, R%i, C%i, C%i, %i, %i (don't allocated coprocessor)\n", + PROCNUM?'7':'9', cpnum, REG_POS(i, 12), REG_POS(i, 16), REG_POS(i, 0), (i>>21)&0x7, (i>>5)&0x7); + return 2; + } + + armcp15_moveARM2CP((armcp15_t*)cpu->coproc[cpnum], cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&0x7, (i>>5)&0x7); + //cpu->coproc[cpnum]->moveARM2CP(cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7); + return 2; +} + +TEMPLATE static u32 FASTCALL OP_MRC(const u32 i) +{ + //if (PROCNUM != 0) return 1; + + u32 cpnum = REG_POS(i, 8); + + if(!cpu->coproc[cpnum]) + { + //emu_halt(); + //INFO("Stopped (OP_MRC) \n"); + INFO("ARM%c: MRC P%i, 0, R%i, C%i, C%i, %i, %i (don't allocated coprocessor)\n", + PROCNUM?'7':'9', cpnum, REG_POS(i, 12), REG_POS(i, 16), REG_POS(i, 0), (i>>21)&0x7, (i>>5)&0x7); + return 2; + } + + // ARM REF: + //data = value from Coprocessor[cp_num] + //if Rd is R15 then + // N flag = data[31] + // Z flag = data[30] + // C flag = data[29] + // V flag = data[28] + //else /* Rd is not R15 */ + // Rd = data + + u32 data = 0; + armcp15_moveCP2ARM((armcp15_t*)cpu->coproc[cpnum], &data, REG_POS(i, 16), REG_POS(i, 0), (i>>21)&0x7, (i>>5)&0x7); + if (REG_POS(i, 12) == 15) + { + cpu->CPSR.bits.N = BIT31(data); + cpu->CPSR.bits.Z = BIT30(data); + cpu->CPSR.bits.C = BIT29(data); + cpu->CPSR.bits.V = BIT28(data); + } + else + cpu->R[REG_POS(i, 12)] = data; + //cpu->coproc[cpnum]->moveCP2ARM(&cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7); + return 4; +} + +//----------------------------------------------------------------------------- +// SWI +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_SWI(const u32 i) +{ + u32 swinum = (i>>16)&0xFF; + + //ideas-style debug prints (execute this SWI with the null terminated string address in R0) + if(swinum==0xFC) + { + IdeasLog(cpu); + return 0; + } + + //if the user has changed the intVector to point away from the nds bioses, + //then it doesn't really make any sense to use the builtin SWI's since + //the bios ones aren't getting called anyway + bool bypassBuiltinSWI = + (cpu->intVector == 0x00000000 && PROCNUM==0) + || (cpu->intVector == 0xFFFF0000 && PROCNUM==1); + + if(cpu->swi_tab && !bypassBuiltinSWI) + { + swinum &= 0x1F; + //printf("%d ARM SWI %d \n",PROCNUM,swinum); + return cpu->swi_tab[swinum]() + 3; + } + else + { + /* TODO (#1#): translocated SWI vectors */ + /* we use an irq thats not in the irq tab, as + it was replaced duie to a changed intVector */ + Status_Reg tmp = cpu->CPSR; + armcpu_switchMode(cpu, SVC); /* enter svc mode */ + cpu->R[14] = cpu->next_instruction; + cpu->SPSR = tmp; /* save old CPSR as new SPSR */ + cpu->CPSR.bits.T = 0; /* handle as ARM32 code */ + cpu->CPSR.bits.I = 1; + cpu->changeCPSR(); + cpu->R[15] = cpu->intVector + 0x08; + cpu->next_instruction = cpu->R[15]; + return 4; + } +} + +//----------------------------------------------------------------------------- +// BKPT +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_BKPT(const u32 i) +{ + static u32 last_bkpt = 0xFFFFFFFF; + if(i != last_bkpt) + printf("ARM OP_BKPT triggered\n"); + last_bkpt = i; + + //this is not 100% correctly emulated, but it does the job + cpu->next_instruction = cpu->instruct_adr; + return 4; +} + +//----------------------------------------------------------------------------- +// CDP +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_CDP(const u32 i) +{ + //INFO("Stopped (OP_CDP) \n"); + return TRAPUNDEF(cpu); +} + +//----------------------------------------------------------------------------- +// The End +//----------------------------------------------------------------------------- + +#define TABDECL(x) x<0> +const ArmOpFunc arm_instructions_set_0[4096] = { +#include "instruction_tabdef.inc" +}; +#undef TABDECL + +#define TABDECL(x) x<1> +const ArmOpFunc arm_instructions_set_1[4096] = { +#include "instruction_tabdef.inc" +}; +#undef TABDECL + +#define TABDECL(x) #x +const char* arm_instruction_names[4096] = { +#include "instruction_tabdef.inc" +}; +#undef TABDECL diff --git a/jni/desmume/src/arm_instructions.h b/jni/desmume/src/arm_instructions.h new file mode 100755 index 0000000..8782f9c --- /dev/null +++ b/jni/desmume/src/arm_instructions.h @@ -0,0 +1,32 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2006-2009 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef ARMINSTRUCTION_H +#define ARMINSTRUCTION_H + +#include "armcpu.h" + +typedef u32 (FASTCALL* ArmOpFunc)(const u32 i); + +extern const ArmOpFunc arm_instructions_set_0[4096]; +extern const ArmOpFunc arm_instructions_set_1[4096]; + +extern const char* arm_instruction_names[4096]; + +#endif + diff --git a/jni/desmume/src/armcpu.cpp b/jni/desmume/src/armcpu.cpp new file mode 100755 index 0000000..764a43a --- /dev/null +++ b/jni/desmume/src/armcpu.cpp @@ -0,0 +1,725 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2009-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include <algorithm> +#include "types.h" +#include "arm_instructions.h" +#include "thumb_instructions.h" +#include "cp15.h" +#include "bios.h" +#include "debug.h" +#include "Disassembler.h" +#include "NDSSystem.h" +#include "MMU_timing.h" +#ifdef HAVE_LUA +#include "lua-engine.h" +#endif + +template<u32> static u32 armcpu_prefetch(); + +FORCEINLINE u32 armcpu_prefetch(armcpu_t *armcpu) { + if(armcpu->proc_ID==0) return armcpu_prefetch<0>(); + else return armcpu_prefetch<1>(); +} + +const unsigned char arm_cond_table[16*16] = { + /* N=0, Z=0, C=0, V=0 */ + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF, + 0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20, + /* N=0, Z=0, C=0, V=1 */ + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x00, + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=0, Z=0, C=1, V=0 */ + 0x00,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF, + 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20, + /* N=0, Z=0, C=1, V=1 */ + 0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00, + 0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=0, Z=1, C=0, V=0 */ + 0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF, + 0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20, + /* N=0, Z=1, C=0, V=1 */ + 0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x00, + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=0, Z=1, C=1, V=0 */ + 0xFF,0x00,0xFF,0x00,0x00,0xFF,0x00,0xFF, + 0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20, + /* N=0, Z=1, C=1, V=1 */ + 0xFF,0x00,0xFF,0x00,0x00,0xFF,0xFF,0x00, + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=1, Z=0, C=0, V=0 */ + 0x00,0xFF,0x00,0xFF,0xFF,0x00,0x00,0xFF, + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=1, Z=0, C=0, V=1 */ + 0x00,0xFF,0x00,0xFF,0xFF,0x00,0xFF,0x00, + 0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20, + /* N=1, Z=0, C=1, V=0 */ + 0x00,0xFF,0xFF,0x00,0xFF,0x00,0x00,0xFF, + 0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=1, Z=0, C=1, V=1 */ + 0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x00, + 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20, + /* N=1, Z=1, C=0, V=0 */ + 0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF, + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=1, Z=1, C=0, V=1 */ + 0xFF,0x00,0x00,0xFF,0xFF,0x00,0xFF,0x00, + 0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20, + /* N=1, Z=1, C=1, V=0 */ + 0xFF,0x00,0xFF,0x00,0xFF,0x00,0x00,0xFF, + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=1, Z=1, C=1, V=1 */ + 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00, + 0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20, +}; + +armcpu_t NDS_ARM7; +armcpu_t NDS_ARM9; + +#define SWAP(a, b, c) do \ + { \ + c=a; \ + a=b; \ + b=c; \ + } \ + while(0) + +#ifdef GDB_STUB + +#define STALLED_CYCLE_COUNT 10 + +static void +stall_cpu( void *instance) { + armcpu_t *armcpu = (armcpu_t *)instance; + printf("UNSTALL\n"); + armcpu->stalled = 1; +} + +static void +unstall_cpu( void *instance) { + armcpu_t *armcpu = (armcpu_t *)instance; + printf("UNSTALL\n"); + armcpu->stalled = 0; +} + +static void +install_post_exec_fn( void *instance, + void (*ex_fn)( void *, u32 adr, int thumb), + void *fn_data) { + armcpu_t *armcpu = (armcpu_t *)instance; + + armcpu->post_ex_fn = ex_fn; + armcpu->post_ex_fn_data = fn_data; +} + +static void +remove_post_exec_fn( void *instance) { + armcpu_t *armcpu = (armcpu_t *)instance; + + armcpu->post_ex_fn = NULL; +} +#endif + +#ifdef GDB_STUB +static u32 read_cpu_reg( void *instance, u32 reg_num) +{ + armcpu_t *armcpu = (armcpu_t *)instance; + + if ( reg_num <= 14) { + return armcpu->R[reg_num]; + } + else if ( reg_num == 15) { + return armcpu->instruct_adr; + } + else if ( reg_num == 16) { + //CPSR + return armcpu->CPSR.val; + } +} + +static void +set_cpu_reg( void *instance, u32 reg_num, u32 value) { + armcpu_t *armcpu = (armcpu_t *)instance; + + if ( reg_num <= 14) { + armcpu->R[reg_num] = value; + } + else if ( reg_num == 15) { + armcpu->next_instruction = value; + } + else if ( reg_num == 16) { + /* FIXME: setting the CPSR */ + } +} +#endif + +#ifdef GDB_STUB +int armcpu_new( armcpu_t *armcpu, u32 id, + struct armcpu_memory_iface *mem_if, + struct armcpu_ctrl_iface **ctrl_iface_ret) +#else +int armcpu_new( armcpu_t *armcpu, u32 id) +#endif +{ + armcpu->proc_ID = id; + +#ifdef GDB_STUB + armcpu->mem_if = mem_if; + + /* populate the control interface */ + armcpu->ctrl_iface.stall = stall_cpu; + armcpu->ctrl_iface.unstall = unstall_cpu; + armcpu->ctrl_iface.read_reg = read_cpu_reg; + armcpu->ctrl_iface.set_reg = set_cpu_reg; + armcpu->ctrl_iface.install_post_ex_fn = install_post_exec_fn; + armcpu->ctrl_iface.remove_post_ex_fn = remove_post_exec_fn; + armcpu->ctrl_iface.data = armcpu; + + *ctrl_iface_ret = &armcpu->ctrl_iface; + + armcpu->post_ex_fn = NULL; +#endif + + armcpu->stalled = 0; + + armcpu_init(armcpu, 0); + + return 0; +} + +//call this whenever CPSR is changed (other than CNVZQ or T flags); interrupts may need to be unleashed +void armcpu_t::changeCPSR() +{ + //but all it does is give them a chance to unleash by forcing an immediate reschedule + //TODO - we could actually set CPSR through here and look for a change in the I bit + //that would be a little optimization as well as a safety measure if we prevented setting CPSR directly + NDS_Reschedule(); +} + +void armcpu_init(armcpu_t *armcpu, u32 adr) +{ + armcpu->LDTBit = (armcpu->proc_ID==0); //arm9 is ARMv5 style. this should be renamed, or more likely, all references to this should poll a function to return an architecture level enum + armcpu->intVector = 0xFFFF0000 * (armcpu->proc_ID==0); + armcpu->waitIRQ = FALSE; + armcpu->halt_IE_and_IF = FALSE; + armcpu->intrWaitARM_state = 0; + +//#ifdef GDB_STUB +// armcpu->irq_flag = 0; +//#endif + + for(int i = 0; i < 16; ++i) + { + armcpu->R[i] = 0; + if(armcpu->coproc[i]) free(armcpu->coproc[i]); + armcpu->coproc[i] = NULL; + } + + armcpu->CPSR.val = armcpu->SPSR.val = SYS; + + armcpu->R13_usr = armcpu->R14_usr = 0; + armcpu->R13_svc = armcpu->R14_svc = 0; + armcpu->R13_abt = armcpu->R14_abt = 0; + armcpu->R13_und = armcpu->R14_und = 0; + armcpu->R13_irq = armcpu->R14_irq = 0; + armcpu->R8_fiq = armcpu->R9_fiq = armcpu->R10_fiq = armcpu->R11_fiq = armcpu->R12_fiq = armcpu->R13_fiq = armcpu->R14_fiq = 0; + + armcpu->SPSR_svc.val = armcpu->SPSR_abt.val = armcpu->SPSR_und.val = armcpu->SPSR_irq.val = armcpu->SPSR_fiq.val = 0; + +//#ifdef GDB_STUB +// armcpu->instruct_adr = adr; +// armcpu->R[15] = adr + 8; +//#else + //armcpu->R[15] = adr; +//#endif + + armcpu->next_instruction = adr; + + // only ARM9 have co-processor + if (armcpu->proc_ID==0) + armcpu->coproc[15] = (armcp_t*)armcp15_new(armcpu); + +//#ifndef GDB_STUB + armcpu_prefetch(armcpu); +//#endif +} + +u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode) +{ + u32 oldmode = armcpu->CPSR.bits.mode; + + switch(oldmode) + { + case USR : + case SYS : + armcpu->R13_usr = armcpu->R[13]; + armcpu->R14_usr = armcpu->R[14]; + break; + + case FIQ : + { + u32 tmp; + SWAP(armcpu->R[8], armcpu->R8_fiq, tmp); + SWAP(armcpu->R[9], armcpu->R9_fiq, tmp); + SWAP(armcpu->R[10], armcpu->R10_fiq, tmp); + SWAP(armcpu->R[11], armcpu->R11_fiq, tmp); + SWAP(armcpu->R[12], armcpu->R12_fiq, tmp); + armcpu->R13_fiq = armcpu->R[13]; + armcpu->R14_fiq = armcpu->R[14]; + armcpu->SPSR_fiq = armcpu->SPSR; + break; + } + case IRQ : + armcpu->R13_irq = armcpu->R[13]; + armcpu->R14_irq = armcpu->R[14]; + armcpu->SPSR_irq = armcpu->SPSR; + break; + + case SVC : + armcpu->R13_svc = armcpu->R[13]; + armcpu->R14_svc = armcpu->R[14]; + armcpu->SPSR_svc = armcpu->SPSR; + break; + + case ABT : + armcpu->R13_abt = armcpu->R[13]; + armcpu->R14_abt = armcpu->R[14]; + armcpu->SPSR_abt = armcpu->SPSR; + break; + + case UND : + armcpu->R13_und = armcpu->R[13]; + armcpu->R14_und = armcpu->R[14]; + armcpu->SPSR_und = armcpu->SPSR; + break; + default : + break; + } + + switch(mode) + { + case USR : + case SYS : + armcpu->R[13] = armcpu->R13_usr; + armcpu->R[14] = armcpu->R14_usr; + //SPSR = CPSR; + break; + + case FIQ : + { + u32 tmp; + SWAP(armcpu->R[8], armcpu->R8_fiq, tmp); + SWAP(armcpu->R[9], armcpu->R9_fiq, tmp); + SWAP(armcpu->R[10], armcpu->R10_fiq, tmp); + SWAP(armcpu->R[11], armcpu->R11_fiq, tmp); + SWAP(armcpu->R[12], armcpu->R12_fiq, tmp); + armcpu->R[13] = armcpu->R13_fiq; + armcpu->R[14] = armcpu->R14_fiq; + armcpu->SPSR = armcpu->SPSR_fiq; + break; + } + + case IRQ : + armcpu->R[13] = armcpu->R13_irq; + armcpu->R[14] = armcpu->R14_irq; + armcpu->SPSR = armcpu->SPSR_irq; + break; + + case SVC : + armcpu->R[13] = armcpu->R13_svc; + armcpu->R[14] = armcpu->R14_svc; + armcpu->SPSR = armcpu->SPSR_svc; + break; + + case ABT : + armcpu->R[13] = armcpu->R13_abt; + armcpu->R[14] = armcpu->R14_abt; + armcpu->SPSR = armcpu->SPSR_abt; + break; + + case UND : + armcpu->R[13] = armcpu->R13_und; + armcpu->R[14] = armcpu->R14_und; + armcpu->SPSR = armcpu->SPSR_und; + break; + + default : + break; + } + + armcpu->CPSR.bits.mode = mode & 0x1F; + armcpu->changeCPSR(); + return oldmode; +} + +u32 armcpu_Wait4IRQ(armcpu_t *cpu) +{ + cpu->waitIRQ = TRUE; + cpu->halt_IE_and_IF = TRUE; + return 1; +} + +template<u32 PROCNUM> +FORCEINLINE static u32 armcpu_prefetch() +{ + armcpu_t* const armcpu = &ARMPROC; +//#ifdef GDB_STUB +// u32 temp_instruction; +//#endif + u32 curInstruction = armcpu->next_instruction; + + if(armcpu->CPSR.bits.T == 0) + { +//#ifdef GDB_STUB +// temp_instruction = +// armcpu->mem_if->prefetch32( armcpu->mem_if->data, +// armcpu->next_instruction); +// +// if ( !armcpu->stalled) { +// armcpu->instruction = temp_instruction; +// armcpu->instruct_adr = armcpu->next_instruction; +// armcpu->next_instruction += 4; +// armcpu->R[15] = armcpu->next_instruction + 4; +// } +//#else + curInstruction &= 0xFFFFFFFC; //please don't change this to 0x0FFFFFFC -- the NDS will happily run on 0xF******* addresses all day long + //please note that we must setup R[15] before reading the instruction since there is a protection + //which prevents PC > 0x3FFF from reading the bios region + armcpu->instruct_adr = curInstruction; + armcpu->next_instruction = curInstruction + 4; + armcpu->R[15] = curInstruction + 8; + armcpu->instruction = _MMU_read32<PROCNUM, MMU_AT_CODE>(curInstruction); +//#endif + + return MMU_codeFetchCycles<PROCNUM,32>(curInstruction); + } + +//#ifdef GDB_STUB +// temp_instruction = +// armcpu->mem_if->prefetch16( armcpu->mem_if->data, +// armcpu->next_instruction); +// +// if ( !armcpu->stalled) { +// armcpu->instruction = temp_instruction; +// armcpu->instruct_adr = armcpu->next_instruction; +// armcpu->next_instruction = armcpu->next_instruction + 2; +// armcpu->R[15] = armcpu->next_instruction + 2; +// } +//#else + curInstruction &= 0xFFFFFFFE; //please don't change this to 0x0FFFFFFE -- the NDS will happily run on 0xF******* addresses all day long + //please note that we must setup R[15] before reading the instruction since there is a protection + //which prevents PC > 0x3FFF from reading the bios region + armcpu->instruct_adr = curInstruction; + armcpu->next_instruction = curInstruction + 2; + armcpu->R[15] = curInstruction + 4; + armcpu->instruction = _MMU_read16<PROCNUM, MMU_AT_CODE>(curInstruction); +//#endif + + if(PROCNUM==0) + { + // arm9 fetches 2 instructions at a time in thumb mode + if(!(curInstruction == armcpu->instruct_adr + 2 && (curInstruction & 2))) + return MMU_codeFetchCycles<PROCNUM,32>(curInstruction); + else + return 0; + } + + return MMU_codeFetchCycles<PROCNUM,16>(curInstruction); +} + +#if 0 /* not used */ +static BOOL FASTCALL test_EQ(Status_Reg CPSR) { return ( CPSR.bits.Z); } +static BOOL FASTCALL test_NE(Status_Reg CPSR) { return (!CPSR.bits.Z); } +static BOOL FASTCALL test_CS(Status_Reg CPSR) { return ( CPSR.bits.C); } +static BOOL FASTCALL test_CC(Status_Reg CPSR) { return (!CPSR.bits.C); } +static BOOL FASTCALL test_MI(Status_Reg CPSR) { return ( CPSR.bits.N); } +static BOOL FASTCALL test_PL(Status_Reg CPSR) { return (!CPSR.bits.N); } +static BOOL FASTCALL test_VS(Status_Reg CPSR) { return ( CPSR.bits.V); } +static BOOL FASTCALL test_VC(Status_Reg CPSR) { return (!CPSR.bits.V); } +static BOOL FASTCALL test_HI(Status_Reg CPSR) { return (CPSR.bits.C) && (!CPSR.bits.Z); } +static BOOL FASTCALL test_LS(Status_Reg CPSR) { return (CPSR.bits.Z) || (!CPSR.bits.C); } +static BOOL FASTCALL test_GE(Status_Reg CPSR) { return (CPSR.bits.N==CPSR.bits.V); } +static BOOL FASTCALL test_LT(Status_Reg CPSR) { return (CPSR.bits.N!=CPSR.bits.V); } +static BOOL FASTCALL test_GT(Status_Reg CPSR) { return (!CPSR.bits.Z) && (CPSR.bits.N==CPSR.bits.V); } +static BOOL FASTCALL test_LE(Status_Reg CPSR) { return ( CPSR.bits.Z) || (CPSR.bits.N!=CPSR.bits.V); } +static BOOL FASTCALL test_AL(Status_Reg CPSR) { return 1; } + +static BOOL (FASTCALL* test_conditions[])(Status_Reg CPSR)= { + test_EQ , test_NE , + test_CS , test_CC , + test_MI , test_PL , + test_VS , test_VC , + test_HI , test_LS , + test_GE , test_LT , + test_GT , test_LE , + test_AL +}; +#define TEST_COND2(cond, CPSR) \ + (cond<15&&test_conditions[cond](CPSR)) +#endif + +//TODO - merge with armcpu_irqException? +//http://www.ethernut.de/en/documents/arm-exceptions.html +//http://docs.google.com/viewer?a=v&q=cache:V4ht1YkxprMJ:www.cs.nctu.edu.tw/~wjtsai/EmbeddedSystemDesign/Ch3-1.pdf+arm+exception+handling&hl=en&gl=us&pid=bl&srcid=ADGEEShx9VTHbUhWdDOrTVRzLkcCsVfJiijncNDkkgkrlJkLa7D0LCpO8fQ_hhU3DTcgZh9rcZWWQq4TYhhCovJ625h41M0ZUX3WGasyzWQFxYzDCB-VS6bsUmpoJnRxAc-bdkD0qmsu&sig=AHIEtbR9VHvDOCRmZFQDUVwy53iJDjoSPQ +void armcpu_exception(armcpu_t *cpu, u32 number) +{ + Mode cpumode = USR; + switch(number) + { + case EXCEPTION_RESET: cpumode = SVC; break; + case EXCEPTION_UNDEFINED_INSTRUCTION: cpumode = UND; break; + case EXCEPTION_SWI: cpumode = SVC; break; + case EXCEPTION_PREFETCH_ABORT: cpumode = ABT; break; + case EXCEPTION_DATA_ABORT: cpumode = ABT; break; + case EXCEPTION_RESERVED_0x14: emu_halt(); break; + case EXCEPTION_IRQ: cpumode = IRQ; break; + case EXCEPTION_FAST_IRQ: cpumode = FIQ; break; + } + + Status_Reg tmp = cpu->CPSR; + armcpu_switchMode(cpu, cpumode); //enter new mode + cpu->R[14] = cpu->next_instruction; + cpu->SPSR = tmp; //save old CPSR as new SPSR + cpu->CPSR.bits.T = 0; //handle as ARM32 code + cpu->CPSR.bits.I = 1; + cpu->changeCPSR(); + cpu->R[15] = cpu->intVector + number; + cpu->next_instruction = cpu->R[15]; + printf("armcpu_exception!\n"); + //extern bool dolog; + //dolog=true; + + //HOW DOES THIS WORTK WITHOUT A PREFETCH, LIKE IRQ BELOW? + //I REALLY WISH WE DIDNT PREFETCH BEFORE EXECUTING +} + +BOOL armcpu_irqException(armcpu_t *armcpu) +{ + Status_Reg tmp; + + //TODO - remove GDB specific code +//#ifdef GDB_STUB +// armcpu->irq_flag = 0; +//#endif + + tmp = armcpu->CPSR; + armcpu_switchMode(armcpu, IRQ); + + //TODO - remove GDB specific code +//#ifdef GDB_STUB +// armcpu->R[14] = armcpu->next_instruction + 4; +//#else + armcpu->R[14] = armcpu->instruct_adr + 4; +//#endif + armcpu->SPSR = tmp; + armcpu->CPSR.bits.T = 0; + armcpu->CPSR.bits.I = 1; + armcpu->next_instruction = armcpu->intVector + 0x18; + armcpu->waitIRQ = 0; + + //must retain invariant of having next instruction to be executed prefetched + //(yucky) + armcpu_prefetch(armcpu); + + return TRUE; +} + +//TODO - remove GDB specific code +//BOOL +//armcpu_flagIrq( armcpu_t *armcpu) { +// if(armcpu->CPSR.bits.I) return FALSE; +// +// armcpu->waitIRQ = 0; +// +//#ifdef GDB_STUB +// armcpu->irq_flag = 1; +//#endif +// +// return TRUE; +//} + +u32 TRAPUNDEF(armcpu_t* cpu) +{ + INFO("ARM%c: Undefined instruction: 0x%08X (%s) PC=0x%08X\n", cpu->proc_ID?'7':'9', cpu->instruction, decodeIntruction(false, cpu->instruction), cpu->instruct_adr); + + if (((cpu->intVector != 0) ^ (cpu->proc_ID == ARMCPU_ARM9))) + { + armcpu_exception(&NDS_ARM9,EXCEPTION_UNDEFINED_INSTRUCTION); + return 4; + } + else + { + emu_halt(); + return 4; + } +} + +//BOOL +//armcpu_flagIrq( armcpu_t *armcpu) { +// if(armcpu->CPSR.bits.I) return FALSE; +// +// armcpu->waitIRQ = 0; +// +//#ifdef GDB_STUB +// armcpu->irq_flag = 1; +//#endif +// +// return TRUE; +//} + +template<int PROCNUM> +u32 armcpu_exec() +{ + // Usually, fetching and executing are processed parallelly. + // So this function stores the cycles of each process to + // the variables below, and returns appropriate cycle count. + u32 cFetch = 0; + u32 cExecute = 0; + + //this assert is annoying. but sometimes it is handy. + //assert(ARMPROC.instruct_adr!=0x00000000); +//#ifdef DEVELOPER +#if 0 + if ((((ARMPROC.instruct_adr & 0x0F000000) == 0x0F000000) && (PROCNUM == 0)) || + (((ARMPROC.instruct_adr & 0x0F000000) == 0x00000000) && (PROCNUM == 1))) + { + switch (ARMPROC.instruct_adr & 0xFFFF) + { + case 0x00000000: + printf("BIOS%c: Reset!!!\n", PROCNUM?'7':'9'); + emu_halt(); + break; + case 0x00000004: + printf("BIOS%c: Undefined instruction\n", PROCNUM?'7':'9'); + //emu_halt(); + break; + case 0x00000008: + //printf("BIOS%c: SWI\n", PROCNUM?'7':'9'); + break; + case 0x0000000C: + printf("BIOS%c: Prefetch Abort!!!\n", PROCNUM?'7':'9'); + //emu_halt(); + break; + case 0x00000010: + //printf("BIOS%c: Data Abort!!!\n", PROCNUM?'7':'9'); + //emu_halt(); + break; + case 0x00000014: + printf("BIOS%c: Reserved!!!\n", PROCNUM?'7':'9'); + break; + case 0x00000018: + //printf("BIOS%c: IRQ\n", PROCNUM?'7':'9'); + break; + case 0x0000001C: + printf("BIOS%c: Fast IRQ\n", PROCNUM?'7':'9'); + break; + } + } +#endif + +#if 0 //#ifdef GDB_STUB + if (ARMPROC.stalled) { + return STALLED_CYCLE_COUNT; + } + + /* check for interrupts */ + if (ARMPROC.irq_flag) { + armcpu_irqException(&ARMPROC); + } + + cFetch = armcpu_prefetch(&ARMPROC); + + if (ARMPROC.stalled) { + return MMU_fetchExecuteCycles<PROCNUM>(cExecute, cFetch); + } +#endif + + //cFetch = armcpu_prefetch(&ARMPROC); + + //printf("%d: %08X\n",PROCNUM,ARMPROC.instruct_adr); + + if(ARMPROC.CPSR.bits.T == 0) + { + if( + CONDITION(ARMPROC.instruction) == 0x0E //fast path for unconditional instructions + || (TEST_COND(CONDITION(ARMPROC.instruction), CODE(ARMPROC.instruction), ARMPROC.CPSR)) //handles any condition + ) + { +#ifdef HAVE_LUA + CallRegisteredLuaMemHook(ARMPROC.instruct_adr, 4, ARMPROC.instruction, LUAMEMHOOK_EXEC); // should report even if condition=false? +#endif + if(PROCNUM==0) { + #ifdef DEVELOPER + DEBUG_statistics.instructionHits[0].arm[INSTRUCTION_INDEX(ARMPROC.instruction)]++; + #endif + cExecute = arm_instructions_set_0[INSTRUCTION_INDEX(ARMPROC.instruction)](ARMPROC.instruction); + } + else { + #ifdef DEVELOPER + DEBUG_statistics.instructionHits[1].arm[INSTRUCTION_INDEX(ARMPROC.instruction)]++; + #endif + cExecute = arm_instructions_set_1[INSTRUCTION_INDEX(ARMPROC.instruction)](ARMPROC.instruction); + } + } + else + cExecute = 1; // If condition=false: 1S cycle +#ifdef GDB_STUB + if ( ARMPROC.post_ex_fn != NULL) { + /* call the external post execute function */ + ARMPROC.post_ex_fn(ARMPROC.post_ex_fn_data, ARMPROC.instruct_adr, 0); + } + ARMPROC.mem_if->prefetch32( ARMPROC.mem_if->data, ARMPROC.next_instruction); +#endif + cFetch = armcpu_prefetch<PROCNUM>(); + return MMU_fetchExecuteCycles<PROCNUM>(cExecute, cFetch); + } + +#ifdef HAVE_LUA + CallRegisteredLuaMemHook(ARMPROC.instruct_adr, 2, ARMPROC.instruction, LUAMEMHOOK_EXEC); +#endif + if(PROCNUM==0) + { + #ifdef DEVELOPER + DEBUG_statistics.instructionHits[0].thumb[ARMPROC.instruction>>6]++; + #endif + cExecute = thumb_instructions_set_0[ARMPROC.instruction>>6](ARMPROC.instruction); + } + else { + #ifdef DEVELOPER + DEBUG_statistics.instructionHits[1].thumb[ARMPROC.instruction>>6]++; + #endif + cExecute = thumb_instructions_set_1[ARMPROC.instruction>>6](ARMPROC.instruction); + } + +#ifdef GDB_STUB + if ( ARMPROC.post_ex_fn != NULL) { + /* call the external post execute function */ + ARMPROC.post_ex_fn( ARMPROC.post_ex_fn_data, ARMPROC.instruct_adr, 1); + } + ARMPROC.mem_if->prefetch32( ARMPROC.mem_if->data, ARMPROC.next_instruction); +#endif + cFetch = armcpu_prefetch<PROCNUM>(); + return MMU_fetchExecuteCycles<PROCNUM>(cExecute, cFetch); +} + +//these templates needed to be instantiated manually +template u32 armcpu_exec<0>(); +template u32 armcpu_exec<1>(); diff --git a/jni/desmume/src/armcpu.h b/jni/desmume/src/armcpu.h new file mode 100755 index 0000000..2745886 --- /dev/null +++ b/jni/desmume/src/armcpu.h @@ -0,0 +1,294 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2006-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef ARM_CPU +#define ARM_CPU + +#include "types.h" +#include "bits.h" +#include "MMU.h" +#include "common.h" + +#define CODE(i) (((i)>>25)&0x7) +#define OPCODE(i) (((i)>>21)&0xF) +#define SIGNEBIT(i) BIT_N(i,20) + +#define EXCEPTION_RESET 0x00 +#define EXCEPTION_UNDEFINED_INSTRUCTION 0x04 +#define EXCEPTION_SWI 0x08 +#define EXCEPTION_PREFETCH_ABORT 0x0C +#define EXCEPTION_DATA_ABORT 0x10 +#define EXCEPTION_RESERVED_0x14 0x14 +#define EXCEPTION_IRQ 0x18 +#define EXCEPTION_FAST_IRQ 0x1C + +#define INSTRUCTION_INDEX(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF)) + +inline u32 ROR(u32 i, u32 j) { return ((((u32)(i))>>(j)) | (((u32)(i))<<(32-(j)))); } + +template<typename T> +inline T UNSIGNED_OVERFLOW(T a,T b,T c) { return BIT31(((a)&(b)) | (((a)|(b))&(~c))); } + +template<typename T> +inline T UNSIGNED_UNDERFLOW(T a,T b,T c) { return BIT31(((~a)&(b)) | (((~a)|(b))&(c))); } + +template<typename T> +inline T SIGNED_OVERFLOW(T a,T b,T c) { return BIT31(((a)&(b)&(~c)) | ((~a)&(~(b))&(c))); } + +template<typename T> +inline T SIGNED_UNDERFLOW(T a,T b,T c) { return BIT31(((a)&(~(b))&(~c)) | ((~a)&(b)&(c))); } + +// ============================= CPRS flags funcs +inline bool CarryFrom(s32 left, s32 right) +{ + u32 res = (0xFFFFFFFFU - (u32)left); + + return ((u32)right > res); +} + +inline bool BorrowFrom(s32 left, s32 right) +{ + return ((u32)right > (u32)left); +} + +inline bool OverflowFromADD(s32 alu_out, s32 left, s32 right) +{ + return ((left >= 0 && right >= 0) || (left < 0 && right < 0)) + && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); +} + +inline bool OverflowFromSUB(s32 alu_out, s32 left, s32 right) +{ + return ((left < 0 && right >= 0) || (left >= 0 && right < 0)) + && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); +} + +//zero 15-feb-2009 - these werent getting used and they were getting in my way +//#define EQ 0x0 +//#define NE 0x1 +//#define CS 0x2 +//#define CC 0x3 +//#define MI 0x4 +//#define PL 0x5 +//#define VS 0x6 +//#define VC 0x7 +//#define HI 0x8 +//#define LS 0x9 +//#define GE 0xA +//#define LT 0xB +//#define GT 0xC +//#define LE 0xD +//#define AL 0xE + +extern const unsigned char arm_cond_table[16*16]; + +#define TEST_COND(cond, inst, CPSR) ((arm_cond_table[((CPSR.val >> 24) & 0xf0)|(cond)]) & (1 << (inst))) + + +enum Mode +{ + USR = 0x10, + FIQ = 0x11, + IRQ = 0x12, + SVC = 0x13, + ABT = 0x17, + UND = 0x1B, + SYS = 0x1F +}; + +#ifdef WORDS_BIGENDIAN +typedef union +{ + struct + { + u32 N : 1, + Z : 1, + C : 1, + V : 1, + Q : 1, + RAZ : 19, + I : 1, + F : 1, + T : 1, + mode : 5; + } bits; + u32 val; +} Status_Reg; +#else +typedef union +{ + struct + { + u32 mode : 5, + T : 1, + F : 1, + I : 1, + RAZ : 19, + Q : 1, + V : 1, + C : 1, + Z : 1, + N : 1; + } bits; + u32 val; +} Status_Reg; +#endif + +/** + * The control interface to a CPU + */ +struct armcpu_ctrl_iface { + /** stall the processor */ + void (*stall)( void *instance); + + /** unstall the processor */ + void (*unstall)( void *instance); + + /** read a register value */ + u32 (*read_reg)( void *instance, u32 reg_num); + + /** set a register value */ + void (*set_reg)( void *instance, u32 reg_num, u32 value); + + /** install the post execute function */ + void (*install_post_ex_fn)( void *instance, + void (*fn)( void *, u32 adr, int thumb), + void *fn_data); + + /** remove the post execute function */ + void (*remove_post_ex_fn)( void *instance); + + /** the private data passed to all interface functions */ + void *data; +}; + + +typedef void* armcp_t; + +struct armcpu_t +{ + u32 proc_ID; + u32 instruction; //4 + u32 instruct_adr; //8 + u32 next_instruction; //12 + + u32 R[16]; //16 + Status_Reg CPSR; //80 + Status_Reg SPSR; + + void changeCPSR(); + + u32 R13_usr, R14_usr; + u32 R13_svc, R14_svc; + u32 R13_abt, R14_abt; + u32 R13_und, R14_und; + u32 R13_irq, R14_irq; + u32 R8_fiq, R9_fiq, R10_fiq, R11_fiq, R12_fiq, R13_fiq, R14_fiq; + Status_Reg SPSR_svc, SPSR_abt, SPSR_und, SPSR_irq, SPSR_fiq; + + armcp_t *coproc[16]; + + u32 intVector; + u8 LDTBit; //1 : ARMv5 style 0 : non ARMv5 (earlier) + BOOL waitIRQ; + BOOL halt_IE_and_IF; //the cpu is halted, waiting for IE&IF to signal something + u8 intrWaitARM_state; + + BOOL BIOS_loaded; + + u32 (* *swi_tab)(); + + // flag indicating if the processor is stalled (for debugging) + int stalled; + +#ifdef GDB_STUB + /** there is a pending irq for the cpu */ + int irq_flag; + + /** the post executed function (if installed) */ + void (*post_ex_fn)( void *, u32 adr, int thumb); + + /** data for the post executed function */ + void *post_ex_fn_data; + + + + /** the memory interface */ + struct armcpu_memory_iface *mem_if; + + /** the ctrl interface */ + struct armcpu_ctrl_iface ctrl_iface; +#endif +}; + +#ifdef GDB_STUB +int armcpu_new( armcpu_t *armcpu, u32 id, struct armcpu_memory_iface *mem_if, + struct armcpu_ctrl_iface **ctrl_iface_ret); +#else +int armcpu_new( armcpu_t *armcpu, u32 id); +#endif +void armcpu_init(armcpu_t *armcpu, u32 adr); +u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode); + + +template<int PROCNUM> u32 armcpu_exec(); + +BOOL armcpu_irqException(armcpu_t *armcpu); +BOOL armcpu_flagIrq( armcpu_t *armcpu); +void armcpu_exception(armcpu_t *cpu, u32 number); +u32 TRAPUNDEF(armcpu_t* cpu); +u32 armcpu_Wait4IRQ(armcpu_t *cpu); + +extern armcpu_t NDS_ARM7; +extern armcpu_t NDS_ARM9; + + +static INLINE void setIF(int PROCNUM, u32 flag) +{ + //don't set generated bits!!! + assert(!(flag&0x00200000)); + + MMU.reg_IF_bits[PROCNUM] |= flag; + + extern void NDS_Reschedule(); + NDS_Reschedule(); +} + +static INLINE void NDS_makeIrq(int PROCNUM, u32 num) +{ + setIF(PROCNUM,1<<num); +} + +static INLINE char *decodeIntruction(bool thumb_mode, u32 instr) +{ + char txt[20] = {0}; + u32 tmp = 0; + if (thumb_mode == true) + { + tmp = (instr >> 6); + strcpy(txt, intToBin((u16)tmp)+6); + } + else + { + tmp = ((instr >> 16) & 0x0FF0) | ((instr >> 4) & 0x0F); + strcpy(txt, intToBin((u32)tmp)+20); + } + return strdup(txt); +} + +#endif diff --git a/jni/desmume/src/bios.cpp b/jni/desmume/src/bios.cpp new file mode 100755 index 0000000..e2fd09e --- /dev/null +++ b/jni/desmume/src/bios.cpp @@ -0,0 +1,1179 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2008-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "cp15.h" +#include <math.h> +#include "MMU.h" +#include "debug.h" +#include "NDSSystem.h" + +#define cpu (&ARMPROC) +#define TEMPLATE template<int PROCNUM> + +static const u16 getsinetbl[] = { +0x0000, 0x0324, 0x0648, 0x096A, 0x0C8C, 0x0FAB, 0x12C8, 0x15E2, +0x18F9, 0x1C0B, 0x1F1A, 0x2223, 0x2528, 0x2826, 0x2B1F, 0x2E11, +0x30FB, 0x33DF, 0x36BA, 0x398C, 0x3C56, 0x3F17, 0x41CE, 0x447A, +0x471C, 0x49B4, 0x4C3F, 0x4EBF, 0x5133, 0x539B, 0x55F5, 0x5842, +0x5A82, 0x5CB3, 0x5ED7, 0x60EB, 0x62F1, 0x64E8, 0x66CF, 0x68A6, +0x6A6D, 0x6C23, 0x6DC9, 0x6F5E, 0x70E2, 0x7254, 0x73B5, 0x7504, +0x7641, 0x776B, 0x7884, 0x7989, 0x7A7C, 0x7B5C, 0x7C29, 0x7CE3, +0x7D89, 0x7E1D, 0x7E9C, 0x7F09, 0x7F61, 0x7FA6, 0x7FD8, 0x7FF5 +}; + +static const u16 getpitchtbl[] = { +0x0000, 0x003B, 0x0076, 0x00B2, 0x00ED, 0x0128, 0x0164, 0x019F, +0x01DB, 0x0217, 0x0252, 0x028E, 0x02CA, 0x0305, 0x0341, 0x037D, +0x03B9, 0x03F5, 0x0431, 0x046E, 0x04AA, 0x04E6, 0x0522, 0x055F, +0x059B, 0x05D8, 0x0614, 0x0651, 0x068D, 0x06CA, 0x0707, 0x0743, +0x0780, 0x07BD, 0x07FA, 0x0837, 0x0874, 0x08B1, 0x08EF, 0x092C, +0x0969, 0x09A7, 0x09E4, 0x0A21, 0x0A5F, 0x0A9C, 0x0ADA, 0x0B18, +0x0B56, 0x0B93, 0x0BD1, 0x0C0F, 0x0C4D, 0x0C8B, 0x0CC9, 0x0D07, +0x0D45, 0x0D84, 0x0DC2, 0x0E00, 0x0E3F, 0x0E7D, 0x0EBC, 0x0EFA, +0x0F39, 0x0F78, 0x0FB6, 0x0FF5, 0x1034, 0x1073, 0x10B2, 0x10F1, +0x1130, 0x116F, 0x11AE, 0x11EE, 0x122D, 0x126C, 0x12AC, 0x12EB, +0x132B, 0x136B, 0x13AA, 0x13EA, 0x142A, 0x146A, 0x14A9, 0x14E9, +0x1529, 0x1569, 0x15AA, 0x15EA, 0x162A, 0x166A, 0x16AB, 0x16EB, +0x172C, 0x176C, 0x17AD, 0x17ED, 0x182E, 0x186F, 0x18B0, 0x18F0, +0x1931, 0x1972, 0x19B3, 0x19F5, 0x1A36, 0x1A77, 0x1AB8, 0x1AFA, +0x1B3B, 0x1B7D, 0x1BBE, 0x1C00, 0x1C41, 0x1C83, 0x1CC5, 0x1D07, +0x1D48, 0x1D8A, 0x1DCC, 0x1E0E, 0x1E51, 0x1E93, 0x1ED5, 0x1F17, +0x1F5A, 0x1F9C, 0x1FDF, 0x2021, 0x2064, 0x20A6, 0x20E9, 0x212C, +0x216F, 0x21B2, 0x21F5, 0x2238, 0x227B, 0x22BE, 0x2301, 0x2344, +0x2388, 0x23CB, 0x240E, 0x2452, 0x2496, 0x24D9, 0x251D, 0x2561, +0x25A4, 0x25E8, 0x262C, 0x2670, 0x26B4, 0x26F8, 0x273D, 0x2781, +0x27C5, 0x280A, 0x284E, 0x2892, 0x28D7, 0x291C, 0x2960, 0x29A5, +0x29EA, 0x2A2F, 0x2A74, 0x2AB9, 0x2AFE, 0x2B43, 0x2B88, 0x2BCD, +0x2C13, 0x2C58, 0x2C9D, 0x2CE3, 0x2D28, 0x2D6E, 0x2DB4, 0x2DF9, +0x2E3F, 0x2E85, 0x2ECB, 0x2F11, 0x2F57, 0x2F9D, 0x2FE3, 0x302A, +0x3070, 0x30B6, 0x30FD, 0x3143, 0x318A, 0x31D0, 0x3217, 0x325E, +0x32A5, 0x32EC, 0x3332, 0x3379, 0x33C1, 0x3408, 0x344F, 0x3496, +0x34DD, 0x3525, 0x356C, 0x35B4, 0x35FB, 0x3643, 0x368B, 0x36D3, +0x371A, 0x3762, 0x37AA, 0x37F2, 0x383A, 0x3883, 0x38CB, 0x3913, +0x395C, 0x39A4, 0x39ED, 0x3A35, 0x3A7E, 0x3AC6, 0x3B0F, 0x3B58, +0x3BA1, 0x3BEA, 0x3C33, 0x3C7C, 0x3CC5, 0x3D0E, 0x3D58, 0x3DA1, +0x3DEA, 0x3E34, 0x3E7D, 0x3EC7, 0x3F11, 0x3F5A, 0x3FA4, 0x3FEE, +0x4038, 0x4082, 0x40CC, 0x4116, 0x4161, 0x41AB, 0x41F5, 0x4240, +0x428A, 0x42D5, 0x431F, 0x436A, 0x43B5, 0x4400, 0x444B, 0x4495, +0x44E1, 0x452C, 0x4577, 0x45C2, 0x460D, 0x4659, 0x46A4, 0x46F0, +0x473B, 0x4787, 0x47D3, 0x481E, 0x486A, 0x48B6, 0x4902, 0x494E, +0x499A, 0x49E6, 0x4A33, 0x4A7F, 0x4ACB, 0x4B18, 0x4B64, 0x4BB1, +0x4BFE, 0x4C4A, 0x4C97, 0x4CE4, 0x4D31, 0x4D7E, 0x4DCB, 0x4E18, +0x4E66, 0x4EB3, 0x4F00, 0x4F4E, 0x4F9B, 0x4FE9, 0x5036, 0x5084, +0x50D2, 0x5120, 0x516E, 0x51BC, 0x520A, 0x5258, 0x52A6, 0x52F4, +0x5343, 0x5391, 0x53E0, 0x542E, 0x547D, 0x54CC, 0x551A, 0x5569, +0x55B8, 0x5607, 0x5656, 0x56A5, 0x56F4, 0x5744, 0x5793, 0x57E2, +0x5832, 0x5882, 0x58D1, 0x5921, 0x5971, 0x59C1, 0x5A10, 0x5A60, +0x5AB0, 0x5B01, 0x5B51, 0x5BA1, 0x5BF1, 0x5C42, 0x5C92, 0x5CE3, +0x5D34, 0x5D84, 0x5DD5, 0x5E26, 0x5E77, 0x5EC8, 0x5F19, 0x5F6A, +0x5FBB, 0x600D, 0x605E, 0x60B0, 0x6101, 0x6153, 0x61A4, 0x61F6, +0x6248, 0x629A, 0x62EC, 0x633E, 0x6390, 0x63E2, 0x6434, 0x6487, +0x64D9, 0x652C, 0x657E, 0x65D1, 0x6624, 0x6676, 0x66C9, 0x671C, +0x676F, 0x67C2, 0x6815, 0x6869, 0x68BC, 0x690F, 0x6963, 0x69B6, +0x6A0A, 0x6A5E, 0x6AB1, 0x6B05, 0x6B59, 0x6BAD, 0x6C01, 0x6C55, +0x6CAA, 0x6CFE, 0x6D52, 0x6DA7, 0x6DFB, 0x6E50, 0x6EA4, 0x6EF9, +0x6F4E, 0x6FA3, 0x6FF8, 0x704D, 0x70A2, 0x70F7, 0x714D, 0x71A2, +0x71F7, 0x724D, 0x72A2, 0x72F8, 0x734E, 0x73A4, 0x73FA, 0x7450, +0x74A6, 0x74FC, 0x7552, 0x75A8, 0x75FF, 0x7655, 0x76AC, 0x7702, +0x7759, 0x77B0, 0x7807, 0x785E, 0x78B4, 0x790C, 0x7963, 0x79BA, +0x7A11, 0x7A69, 0x7AC0, 0x7B18, 0x7B6F, 0x7BC7, 0x7C1F, 0x7C77, +0x7CCF, 0x7D27, 0x7D7F, 0x7DD7, 0x7E2F, 0x7E88, 0x7EE0, 0x7F38, +0x7F91, 0x7FEA, 0x8042, 0x809B, 0x80F4, 0x814D, 0x81A6, 0x81FF, +0x8259, 0x82B2, 0x830B, 0x8365, 0x83BE, 0x8418, 0x8472, 0x84CB, +0x8525, 0x857F, 0x85D9, 0x8633, 0x868E, 0x86E8, 0x8742, 0x879D, +0x87F7, 0x8852, 0x88AC, 0x8907, 0x8962, 0x89BD, 0x8A18, 0x8A73, +0x8ACE, 0x8B2A, 0x8B85, 0x8BE0, 0x8C3C, 0x8C97, 0x8CF3, 0x8D4F, +0x8DAB, 0x8E07, 0x8E63, 0x8EBF, 0x8F1B, 0x8F77, 0x8FD4, 0x9030, +0x908C, 0x90E9, 0x9146, 0x91A2, 0x91FF, 0x925C, 0x92B9, 0x9316, +0x9373, 0x93D1, 0x942E, 0x948C, 0x94E9, 0x9547, 0x95A4, 0x9602, +0x9660, 0x96BE, 0x971C, 0x977A, 0x97D8, 0x9836, 0x9895, 0x98F3, +0x9952, 0x99B0, 0x9A0F, 0x9A6E, 0x9ACD, 0x9B2C, 0x9B8B, 0x9BEA, +0x9C49, 0x9CA8, 0x9D08, 0x9D67, 0x9DC7, 0x9E26, 0x9E86, 0x9EE6, +0x9F46, 0x9FA6, 0xA006, 0xA066, 0xA0C6, 0xA127, 0xA187, 0xA1E8, +0xA248, 0xA2A9, 0xA30A, 0xA36B, 0xA3CC, 0xA42D, 0xA48E, 0xA4EF, +0xA550, 0xA5B2, 0xA613, 0xA675, 0xA6D6, 0xA738, 0xA79A, 0xA7FC, +0xA85E, 0xA8C0, 0xA922, 0xA984, 0xA9E7, 0xAA49, 0xAAAC, 0xAB0E, +0xAB71, 0xABD4, 0xAC37, 0xAC9A, 0xACFD, 0xAD60, 0xADC3, 0xAE27, +0xAE8A, 0xAEED, 0xAF51, 0xAFB5, 0xB019, 0xB07C, 0xB0E0, 0xB145, +0xB1A9, 0xB20D, 0xB271, 0xB2D6, 0xB33A, 0xB39F, 0xB403, 0xB468, +0xB4CD, 0xB532, 0xB597, 0xB5FC, 0xB662, 0xB6C7, 0xB72C, 0xB792, +0xB7F7, 0xB85D, 0xB8C3, 0xB929, 0xB98F, 0xB9F5, 0xBA5B, 0xBAC1, +0xBB28, 0xBB8E, 0xBBF5, 0xBC5B, 0xBCC2, 0xBD29, 0xBD90, 0xBDF7, +0xBE5E, 0xBEC5, 0xBF2C, 0xBF94, 0xBFFB, 0xC063, 0xC0CA, 0xC132, +0xC19A, 0xC202, 0xC26A, 0xC2D2, 0xC33A, 0xC3A2, 0xC40B, 0xC473, +0xC4DC, 0xC544, 0xC5AD, 0xC616, 0xC67F, 0xC6E8, 0xC751, 0xC7BB, +0xC824, 0xC88D, 0xC8F7, 0xC960, 0xC9CA, 0xCA34, 0xCA9E, 0xCB08, +0xCB72, 0xCBDC, 0xCC47, 0xCCB1, 0xCD1B, 0xCD86, 0xCDF1, 0xCE5B, +0xCEC6, 0xCF31, 0xCF9C, 0xD008, 0xD073, 0xD0DE, 0xD14A, 0xD1B5, +0xD221, 0xD28D, 0xD2F8, 0xD364, 0xD3D0, 0xD43D, 0xD4A9, 0xD515, +0xD582, 0xD5EE, 0xD65B, 0xD6C7, 0xD734, 0xD7A1, 0xD80E, 0xD87B, +0xD8E9, 0xD956, 0xD9C3, 0xDA31, 0xDA9E, 0xDB0C, 0xDB7A, 0xDBE8, +0xDC56, 0xDCC4, 0xDD32, 0xDDA0, 0xDE0F, 0xDE7D, 0xDEEC, 0xDF5B, +0xDFC9, 0xE038, 0xE0A7, 0xE116, 0xE186, 0xE1F5, 0xE264, 0xE2D4, +0xE343, 0xE3B3, 0xE423, 0xE493, 0xE503, 0xE573, 0xE5E3, 0xE654, +0xE6C4, 0xE735, 0xE7A5, 0xE816, 0xE887, 0xE8F8, 0xE969, 0xE9DA, +0xEA4B, 0xEABC, 0xEB2E, 0xEB9F, 0xEC11, 0xEC83, 0xECF5, 0xED66, +0xEDD9, 0xEE4B, 0xEEBD, 0xEF2F, 0xEFA2, 0xF014, 0xF087, 0xF0FA, +0xF16D, 0xF1E0, 0xF253, 0xF2C6, 0xF339, 0xF3AD, 0xF420, 0xF494, +0xF507, 0xF57B, 0xF5EF, 0xF663, 0xF6D7, 0xF74C, 0xF7C0, 0xF834, +0xF8A9, 0xF91E, 0xF992, 0xFA07, 0xFA7C, 0xFAF1, 0xFB66, 0xFBDC, +0xFC51, 0xFCC7, 0xFD3C, 0xFDB2, 0xFE28, 0xFE9E, 0xFF14, 0xFF8A +}; + +static const u8 getvoltbl[] = { +0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, +0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, +0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, +0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, +0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, +0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, +0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, +0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, +0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, +0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, +0x09, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, +0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0E, +0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, +0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, +0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x18, +0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x1A, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1C, 0x1C, 0x1C, +0x1D, 0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, +0x22, 0x23, 0x23, 0x24, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x27, 0x28, 0x28, 0x29, +0x29, 0x2A, 0x2A, 0x2B, 0x2B, 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30, 0x31, 0x31, +0x32, 0x32, 0x33, 0x33, 0x34, 0x35, 0x35, 0x36, 0x36, 0x37, 0x38, 0x38, 0x39, 0x3A, 0x3A, 0x3B, +0x3C, 0x3C, 0x3D, 0x3E, 0x3F, 0x3F, 0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x45, 0x45, 0x46, 0x47, +0x48, 0x49, 0x4A, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x52, 0x53, 0x54, 0x55, +0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67, +0x68, 0x69, 0x6A, 0x6B, 0x6D, 0x6E, 0x6F, 0x71, 0x72, 0x73, 0x75, 0x76, 0x77, 0x79, 0x7A, 0x7B, +0x7D, 0x7E, 0x7F, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, +0x26, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B, 0x2C, 0x2C, 0x2D, +0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30, 0x30, 0x31, 0x31, 0x32, 0x33, 0x33, 0x34, 0x34, 0x35, 0x36, +0x36, 0x37, 0x37, 0x38, 0x39, 0x39, 0x3A, 0x3B, 0x3B, 0x3C, 0x3D, 0x3E, 0x3E, 0x3F, 0x40, 0x40, +0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x47, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4D, +0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, +0x5E, 0x5F, 0x60, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6F, 0x70, +0x71, 0x73, 0x74, 0x75, 0x77, 0x78, 0x79, 0x7B, 0x7C, 0x7E, 0x7E, 0x40, 0x41, 0x42, 0x43, 0x43, +0x44, 0x45, 0x46, 0x47, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, +0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, +0x62, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6B, 0x6C, 0x6D, 0x6E, 0x70, 0x71, 0x72, 0x74, 0x75, +0x76, 0x78, 0x79, 0x7B, 0x7C, 0x7D, 0x7E, 0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x45, 0x46, 0x46, +0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, +0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x65, 0x66, +0x67, 0x68, 0x69, 0x6A, 0x6C, 0x6D, 0x6E, 0x6F, 0x71, 0x72, 0x73, 0x75, 0x76, 0x77, 0x79, 0x7A, +0x7C, 0x7D, 0x7E, 0x7F +}; + +TEMPLATE static u32 bios_nop() +{ + LOG("SWI: ARM%c Unimplemented BIOS function %02X was used. R0:%08X, R1:%08X, R2:%08X\n", PROCNUM?'7':'9', + (cpu->instruction)&0x1F, cpu->R[0], cpu->R[1], cpu->R[2]); + return 3; +} + +TEMPLATE static u32 WaitByLoop() +{ + u32 elapsed; + + //printf("%lld waitbyloop\n",nds_timer); + //INFO("ARM%c: SWI 0x03 (WaitByLoop)\n", PROCNUM?'7':'9'); + if (PROCNUM == ARMCPU_ARM9) + { + armcp15_t *cp = (armcp15_t*)(cpu->coproc[15]); + + if (cp->ctrl & ((1<<16)|(1<<18))) // DTCM or ITCM is on (cache) + elapsed = cpu->R[0] * 2; + else + elapsed = cpu->R[0] * 8; + } + else + elapsed = cpu->R[0] * 4; + cpu->R[0] = 0; + return elapsed; +} + +TEMPLATE static u32 wait4IRQ() +{ + cpu->waitIRQ = TRUE; + cpu->halt_IE_and_IF = TRUE; + return 1; +} + +TEMPLATE u32 intrWaitARM() +{ + //TODO - account for differences between arm7 and arm9 (according to gbatek, the "bug doesn't work") + + const u32 intrFlagAdr = (PROCNUM == ARMCPU_ARM7) + ? 0x380FFF8 + : (((armcp15_t *)(cpu->coproc[15]))->DTCMRegion&0xFFFFF000)+0x3FF8; + + //set IME=1 + //without this, no irq handlers can happen (even though IF&IE waits can happily happen) + //and so no bits in the OS irq flag variable can get set by the handlers + _MMU_write32<PROCNUM>(0x04000208, 1); + + //analyze the OS irq flag variable + u32 intr = _MMU_read32<PROCNUM>(intrFlagAdr); + u32 intrFlag = (cpu->R[1] & intr); + + //if the user requested us to discard flags, then clear the flag(s) we're going to be waiting on. + //(be sure to only do this only on the first run through. use a little state machine to control that) + if(cpu->intrWaitARM_state==0 && cpu->R[0]==1) + { + intr ^= intrFlag; + _MMU_write32<PROCNUM>(intrFlagAdr, intr); + + //we want to make sure we wait at least once below + intrFlag = 0; + } + + cpu->intrWaitARM_state = 1; + + //now, if the condition is satisfied (and it won't be the first time through, no matter what, due to cares taken above) + if(intrFlag) + { + //write back the OS irq flags with the ones we were waiting for cleared + intr ^= intrFlag; + _MMU_write32<PROCNUM>(intrFlagAdr, intr); + + cpu->intrWaitARM_state = 0; + return 1; + } + + //the condition wasn't satisfied. this means that we need to halt, wait for some enabled interrupt, + //and then ensure that we return to this opcode again to check the condition again + cpu->waitIRQ = TRUE; + cpu->halt_IE_and_IF = TRUE; + + //(rewire PC to jump back to this opcode) + u32 instructAddr = cpu->instruct_adr; + cpu->R[15] = instructAddr; + cpu->next_instruction = instructAddr; + return 1; +} + +TEMPLATE static u32 waitVBlankARM() +{ + cpu->R[0] = 1; + cpu->R[1] = 1; + return intrWaitARM<PROCNUM>(); +} + +TEMPLATE static u32 sleep() +{ + _MMU_write08<PROCNUM>(0x04000301, 0xC0); + return 1; +} + +TEMPLATE static u32 divide() +{ + s32 num = (s32)cpu->R[0]; + s32 dnum = (s32)cpu->R[1]; + + if(dnum==0) return 0; + + s32 res = num / dnum; + cpu->R[0] = (u32)res; + cpu->R[1] = (u32)(num % dnum); + cpu->R[3] = (u32)abs(res); + + //INFO("ARM%c: SWI 0x09 (divide): in num %i, dnum %i, out R0:%i, R1:%i, R3:%i\n", PROCNUM?'7':'9', num, dnum, cpu->R[0], cpu->R[1], cpu->R[3]); + + return 6; +} + +TEMPLATE static u32 copy() +{ + u32 src = cpu->R[0]; + u32 dst = cpu->R[1]; + u32 cnt = cpu->R[2]; + + //INFO("swi copy from %08X to %08X, cnt=%08X\n", src, dst, cnt); + + switch(BIT26(cnt)) + { + case 0: + src &= 0xFFFFFFFE; + dst &= 0xFFFFFFFE; + switch(BIT24(cnt)) + { + case 0: + cnt &= 0x1FFFFF; + while(cnt) + { + _MMU_write16<PROCNUM>(dst, _MMU_read16<PROCNUM>(src)); + cnt--; + dst+=2; + src+=2; + } + break; + case 1: + { + u32 val = _MMU_read16<PROCNUM>(src); + cnt &= 0x1FFFFF; + while(cnt) + { + _MMU_write16<PROCNUM>(dst, val); + cnt--; + dst+=2; + } + } + break; + } + break; + case 1: + src &= 0xFFFFFFFC; + dst &= 0xFFFFFFFC; + switch(BIT24(cnt)) + { + case 0: + cnt &= 0x1FFFFF; + while(cnt) + { + _MMU_write32<PROCNUM>(dst, _MMU_read32<PROCNUM>(src)); + cnt--; + dst+=4; + src+=4; + } + break; + case 1: + { + u32 val = _MMU_read32<PROCNUM>(src); + cnt &= 0x1FFFFF; + while(cnt) + { + _MMU_write32<PROCNUM>(dst, val); + cnt--; + dst+=4; + } + } + break; + } + break; + } + return 1; +} + +TEMPLATE static u32 fastCopy() +{ + u32 src = cpu->R[0] & 0xFFFFFFFC; + u32 dst = cpu->R[1] & 0xFFFFFFFC; + u32 cnt = cpu->R[2]; + + //INFO("swi fastcopy from %08X to %08X, cnt=%08X\n", src, dst, cnt); + + switch(BIT24(cnt)) + { + case 0: + cnt &= 0x1FFFFF; + while(cnt) + { + _MMU_write32<PROCNUM>(dst, _MMU_read32<PROCNUM>(src)); + cnt--; + dst+=4; + src+=4; + } + break; + case 1: + { + u32 val = _MMU_read32<PROCNUM>(src); + cnt &= 0x1FFFFF; + while(cnt) + { + _MMU_write32<PROCNUM>(dst, val); + cnt--; + dst+=4; + } + } + break; + } + return 1; +} + +TEMPLATE static u32 LZ77UnCompVram() +{ + int i1, i2; + int byteCount; + int byteShift; + u32 writeValue; + int len; + u32 source = cpu->R[0]; + u32 dest = cpu->R[1]; + u32 header = _MMU_read32<PROCNUM>(source); + source += 4; + + //INFO("swi lz77uncompvram\n"); + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return 0; + + byteCount = 0; + byteShift = 0; + writeValue = 0; + + len = header >> 8; + + while(len > 0) { + u8 d = _MMU_read08<PROCNUM>(source++); + + if(d) { + for(i1 = 0; i1 < 8; i1++) { + if(d & 0x80) { + int length; + int offset; + u32 windowOffset; + u16 data = _MMU_read08<PROCNUM>(source++) << 8; + data |= _MMU_read08<PROCNUM>(source++); + length = (data >> 12) + 3; + offset = (data & 0x0FFF); + windowOffset = dest + byteCount - offset - 1; + for(i2 = 0; i2 < length; i2++) { + writeValue |= (_MMU_read08<PROCNUM>(windowOffset++) << byteShift); + byteShift += 8; + byteCount++; + + if(byteCount == 2) { + _MMU_write16<PROCNUM>(dest, writeValue); + dest += 2; + byteCount = 0; + byteShift = 0; + writeValue = 0; + } + len--; + if(len == 0) + return 0; + } + } else { + writeValue |= (_MMU_read08<PROCNUM>(source++) << byteShift); + byteShift += 8; + byteCount++; + if(byteCount == 2) { + _MMU_write16<PROCNUM>(dest, writeValue); + dest += 2; + byteCount = 0; + byteShift = 0; + writeValue = 0; + } + len--; + if(len == 0) + return 0; + } + d <<= 1; + } + } else { + for(i1 = 0; i1 < 8; i1++) { + writeValue |= (_MMU_read08<PROCNUM>(source++) << byteShift); + byteShift += 8; + byteCount++; + if(byteCount == 2) { + _MMU_write16<PROCNUM>(dest, writeValue); + dest += 2; + byteShift = 0; + byteCount = 0; + writeValue = 0; + } + len--; + if(len == 0) + return 0; + } + } + } + return 1; +} + +TEMPLATE static u32 LZ77UnCompWram() +{ + int i1, i2; + int len; + u32 source = cpu->R[0]; + u32 dest = cpu->R[1]; + + u32 header = _MMU_read32<PROCNUM>(source); + source += 4; + + //INFO("swi lz77uncompwram\n"); + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return 0; + + len = header >> 8; + + while(len > 0) { + u8 d = _MMU_read08<PROCNUM>(source++); + + if(d) { + for(i1 = 0; i1 < 8; i1++) { + if(d & 0x80) { + int length; + int offset; + u32 windowOffset; + u16 data = _MMU_read08<PROCNUM>(source++) << 8; + data |= _MMU_read08<PROCNUM>(source++); + length = (data >> 12) + 3; + offset = (data & 0x0FFF); + windowOffset = dest - offset - 1; + for(i2 = 0; i2 < length; i2++) { + _MMU_write08<PROCNUM>(dest++, _MMU_read08<PROCNUM>(windowOffset++)); + len--; + if(len == 0) + return 0; + } + } else { + _MMU_write08<PROCNUM>(dest++, _MMU_read08<PROCNUM>(source++)); + len--; + if(len == 0) + return 0; + } + d <<= 1; + } + } else { + for(i1 = 0; i1 < 8; i1++) { + _MMU_write08<PROCNUM>(dest++, _MMU_read08<PROCNUM>(source++)); + len--; + if(len == 0) + return 0; + } + } + } + return 1; +} + +TEMPLATE static u32 RLUnCompVram() +{ + int i; + int len; + int byteCount; + int byteShift; + u32 writeValue; + u32 source = cpu->R[0]; + u32 dest = cpu->R[1]; + + u32 header = _MMU_read32<PROCNUM>(source); + source += 4; + + //INFO("swi rluncompvram\n"); + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return 0; + + len = header >> 8; + byteCount = 0; + byteShift = 0; + writeValue = 0; + + while(len > 0) { + u8 d = _MMU_read08<PROCNUM>(source++); + int l = d & 0x7F; + if(d & 0x80) { + u8 data = _MMU_read08<PROCNUM>(source++); + l += 3; + for(i = 0;i < l; i++) { + writeValue |= (data << byteShift); + byteShift += 8; + byteCount++; + + if(byteCount == 2) { + _MMU_write16<PROCNUM>(dest, writeValue); + dest += 2; + byteCount = 0; + byteShift = 0; + writeValue = 0; + } + len--; + if(len == 0) + return 0; + } + } else { + l++; + for(i = 0; i < l; i++) { + writeValue |= (_MMU_read08<PROCNUM>(source++) << byteShift); + byteShift += 8; + byteCount++; + if(byteCount == 2) { + _MMU_write16<PROCNUM>(dest, writeValue); + dest += 2; + byteCount = 0; + byteShift = 0; + writeValue = 0; + } + len--; + if(len == 0) + return 0; + } + } + } + return 1; +} + +TEMPLATE static u32 RLUnCompWram() +{ + int i; + int len; + u32 source = cpu->R[0]; + u32 dest = cpu->R[1]; + + u32 header = _MMU_read32<PROCNUM>(source); + source += 4; + + //INFO("swi rluncompwram\n"); + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return 0; + + len = header >> 8; + + while(len > 0) { + u8 d = _MMU_read08<PROCNUM>(source++); + int l = d & 0x7F; + if(d & 0x80) { + u8 data = _MMU_read08<PROCNUM>(source++); + l += 3; + for(i = 0;i < l; i++) { + _MMU_write08<PROCNUM>(dest++, data); + len--; + if(len == 0) + return 0; + } + } else { + l++; + for(i = 0; i < l; i++) { + _MMU_write08<PROCNUM>(dest++, _MMU_read08<PROCNUM>(source++)); + len--; + if(len == 0) + return 0; + } + } + } + return 1; +} + +TEMPLATE static u32 UnCompHuffman() +{ + u32 source, dest, writeValue, header, treeStart, mask; + u32 data; + u8 treeSize, currentNode, rootNode; + int byteCount, byteShift, len, pos; + int writeData; + + source = cpu->R[0]; + dest = cpu->R[1]; + + header = _MMU_read08<PROCNUM>(source); + source += 4; + + //INFO("swi uncomphuffman\n"); + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return 0; + + treeSize = _MMU_read08<PROCNUM>(source++); + + treeStart = source; + + source += ((treeSize+1)<<1)-1; // minus because we already skipped one byte + + len = header >> 8; + + mask = 0x80000000; + data = _MMU_read08<PROCNUM>(source); + source += 4; + + pos = 0; + rootNode = _MMU_read08<PROCNUM>(treeStart); + currentNode = rootNode; + writeData = 0; + byteShift = 0; + byteCount = 0; + writeValue = 0; + + if((header & 0x0F) == 8) { + while(len > 0) { + // take left + if(pos == 0) + pos++; + else + pos += (((currentNode & 0x3F)+1)<<1); + + if(data & mask) { + // right + if(currentNode & 0x40) + writeData = 1; + currentNode = _MMU_read08<PROCNUM>(treeStart+pos+1); + } else { + // left + if(currentNode & 0x80) + writeData = 1; + currentNode = _MMU_read08<PROCNUM>(treeStart+pos); + } + + if(writeData) { + writeValue |= (currentNode << byteShift); + byteCount++; + byteShift += 8; + + pos = 0; + currentNode = rootNode; + writeData = 0; + + if(byteCount == 4) { + byteCount = 0; + byteShift = 0; + _MMU_write08<PROCNUM>(dest, writeValue); + writeValue = 0; + dest += 4; + len -= 4; + } + } + mask >>= 1; + if(mask == 0) { + mask = 0x80000000; + data = _MMU_read08<PROCNUM>(source); + source += 4; + } + } + } else { + int halfLen = 0; + int value = 0; + while(len > 0) { + // take left + if(pos == 0) + pos++; + else + pos += (((currentNode & 0x3F)+1)<<1); + + if((data & mask)) { + // right + if(currentNode & 0x40) + writeData = 1; + currentNode = _MMU_read08<PROCNUM>(treeStart+pos+1); + } else { + // left + if(currentNode & 0x80) + writeData = 1; + currentNode = _MMU_read08<PROCNUM>(treeStart+pos); + } + + if(writeData) { + if(halfLen == 0) + value |= currentNode; + else + value |= (currentNode<<4); + + halfLen += 4; + if(halfLen == 8) { + writeValue |= (value << byteShift); + byteCount++; + byteShift += 8; + + halfLen = 0; + value = 0; + + if(byteCount == 4) { + byteCount = 0; + byteShift = 0; + _MMU_write08<PROCNUM>(dest, writeValue); + dest += 4; + writeValue = 0; + len -= 4; + } + } + pos = 0; + currentNode = rootNode; + writeData = 0; + } + mask >>= 1; + if(mask == 0) { + mask = 0x80000000; + data = _MMU_read08<PROCNUM>(source); + source += 4; + } + } + } + return 1; +} + +TEMPLATE static u32 BitUnPack() +{ + u32 source,dest,header,base,d,temp; + int len,bits,revbits,dataSize,data,bitwritecount,mask,bitcount,addBase; + u8 b; + + source = cpu->R[0]; + dest = cpu->R[1]; + header = cpu->R[2]; + + len = _MMU_read16<PROCNUM>(header); + bits = _MMU_read08<PROCNUM>(header+2); + switch (bits) + { + case 1: + case 2: + case 4: + case 8: + break; + default: return (0); // error + } + dataSize = _MMU_read08<PROCNUM>(header+3); + switch (dataSize) + { + case 1: + case 2: + case 4: + case 8: + case 16: + case 32: + break; + default: return (0); // error + } + + revbits = 8 - bits; + // u32 value = 0; + base = _MMU_read08<PROCNUM>(header+4); + addBase = (base & 0x80000000) ? 1 : 0; + base &= 0x7fffffff; + + //INFO("SWI10: bitunpack src 0x%08X dst 0x%08X hdr 0x%08X (src len %05i src bits %02i dst bits %02i)\n\n", source, dest, header, len, bits, dataSize); + + data = 0; + bitwritecount = 0; + while(1) { + len -= 1; + if(len < 0) + break; + mask = 0xff >> revbits; + b = _MMU_read08<PROCNUM>(source); + source++; + bitcount = 0; + while(1) { + if(bitcount >= 8) + break; + d = b & mask; + temp = d >> bitcount; + if(!temp && addBase) { + temp += base; + } + data |= temp << bitwritecount; + bitwritecount += dataSize; + if(bitwritecount >= 32) { + _MMU_write08<PROCNUM>(dest, data); + dest += 4; + data = 0; + bitwritecount = 0; + } + mask <<= bits; + bitcount += bits; + } + } + return 1; +} + +TEMPLATE static u32 Diff8bitUnFilterWram() +{ + u32 source,dest,header; + u8 data,diff; + int len; + + source = cpu->R[0]; + dest = cpu->R[1]; + + header = _MMU_read08<PROCNUM>(source); + source += 4; + + //INFO("swi diff8bitunfilterwram\n"); + + if(((source & 0xe000000) == 0) || + (( (source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)) + return 0; + + len = header >> 8; + + data = _MMU_read08<PROCNUM>(source++); + _MMU_write08<PROCNUM>(dest++, data); + len--; + + while(len > 0) { + diff = _MMU_read08<PROCNUM>(source++); + data += diff; + _MMU_write08<PROCNUM>(dest++, data); + len--; + } + return 1; +} + +TEMPLATE static u32 Diff16bitUnFilter() +{ + u32 source,dest,header; + u16 data; + int len; + + source = cpu->R[0]; + dest = cpu->R[1]; + + //INFO("swi diff16bitunfilter\n"); + + header = _MMU_read08<PROCNUM>(source); + source += 4; + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return 0; + + len = header >> 8; + + data = _MMU_read16<PROCNUM>(source); + source += 2; + _MMU_write16<PROCNUM>(dest, data); + dest += 2; + len -= 2; + + while(len >= 2) { + u16 diff = _MMU_read16<PROCNUM>(source); + source += 2; + data += diff; + _MMU_write16<PROCNUM>(dest, data); + dest += 2; + len -= 2; + } + return 1; +} + +TEMPLATE static u32 bios_sqrt() +{ + cpu->R[0] = (u32)sqrt((double)(cpu->R[0])); + return 1; +} + +TEMPLATE static u32 setHaltCR() +{ + _MMU_write08<PROCNUM>(0x4000300+cpu->proc_ID, cpu->R[0]); + return 1; +} + +TEMPLATE static u32 getSineTab() +{ + //ds returns garbage according to gbatek, but we must protect ourselves + if(cpu->R[0] >= ARRAY_SIZE(getsinetbl)) + { + printf("Invalid SWI getSineTab: %08X\n",cpu->R[0]); + return 1; + } + + + cpu->R[0] = getsinetbl[cpu->R[0]]; + return 1; +} + +TEMPLATE static u32 getPitchTab() +{ + //ds returns garbage according to gbatek, but we must protect ourselves + if(cpu->R[0] >= ARRAY_SIZE(getpitchtbl)) + { + printf("Invalid SWI getPitchTab: %08X\n",cpu->R[0]); + return 1; + } + + cpu->R[0] = getpitchtbl[cpu->R[0]]; + return 1; +} + +TEMPLATE static u32 getVolumeTab() +{ + //ds returns garbage according to gbatek, but we must protect ourselves + if(cpu->R[0] >= ARRAY_SIZE(getvoltbl)) + { + printf("Invalid SWI getVolumeTab: %08X\n",cpu->R[0]); + return 1; + } + + + cpu->R[0] = getvoltbl[cpu->R[0]]; + return 1; +} + + +//TEMPLATE static u32 getCRC16_old(u32 crc, u32 datap, u32 size) +//{ +// unsigned int i,j; +// +// const u16 val[] = { 0xC0C1,0xC181,0xC301,0xC601,0xCC01,0xD801,0xF001,0xA001 }; +// for(i = 0; i < size; i++) +// { +// crc = crc ^ _MMU_read08<PROCNUM>(datap + i); +// +// for(j = 0; j < 8; j++) { +// int do_bit = 0; +// +// if ( crc & 0x1) +// do_bit = 1; +// +// crc = crc >> 1; +// +// if ( do_bit) { +// crc = crc ^ (val[j] << (7-j)); +// } +// } +// } +// return crc; +//} + +TEMPLATE static u32 getCRC16() +{ + //gbatek is wrong. + + //dawn of sorrow uses this to checksum its save data; + //if this implementation is wrong, then it won't match what the real bios returns, + //and savefiles created with a bios will be invalid when loaded with non-bios (and vice-versa) + + //u32 old = getCRC16_old<PROCNUM>(cpu->R[0],cpu->R[1],cpu->R[2]); + + u16 crc = (u16)cpu->R[0]; + u32 datap = cpu->R[1]; + u32 size = cpu->R[2]>>1; + u16 currVal = 0; + + const u16 val[] = { 0x0000,0xCC01,0xD801,0x1400,0xF001,0x3C00,0x2800,0xE401,0xA001,0x6C00,0x7800,0xB401,0x5000,0x9C01,0x8801,0x4400}; + + for(u32 i = 0; i < size; i++) + { + currVal = _MMU_read16<PROCNUM>(datap + i*2); + + for(int j=0;j<4;j++) + { + u16 tabVal = val[crc&0xF]; + crc >>= 4; + crc ^= tabVal; + + u16 tempVal = currVal >> (4*j); + tabVal = val[tempVal&0xF]; + crc ^= tabVal; + } + } + + cpu->R[0] = crc; + // R3 contains the last processed halfword + cpu->R[3] = currVal; + return 1; +} + +TEMPLATE static u32 isDebugger() +{ + //gbatek has additional specifications which are not emulated here + if(nds.Is_DebugConsole()) + cpu->R[0] = 1; + else + cpu->R[0] = 0; + return 1; +} + +TEMPLATE static u32 SoundBias() +{ + u32 curBias = _MMU_read32<ARMCPU_ARM7>(0x04000504); + u32 newBias = (curBias == 0) ? 0x000:0x200; + u32 delay = (newBias > curBias) ? (newBias-curBias) : (curBias-newBias); + + _MMU_write32<ARMCPU_ARM7>(0x04000504, newBias); + return cpu->R[1] * delay; +} + +TEMPLATE static u32 getBootProcs() +{ + cpu->R[0] = 0x00000A2E; + cpu->R[1] = 0x00002C3C; + cpu->R[3] = 0x000005FF; + return 1; +} + +u32 (* ARM9_swi_tab[32])()={ + bios_nop<ARMCPU_ARM9>, // 0x00 + bios_nop<ARMCPU_ARM9>, // 0x01 + bios_nop<ARMCPU_ARM9>, // 0x02 + WaitByLoop<ARMCPU_ARM9>, // 0x03 + intrWaitARM<ARMCPU_ARM9>, // 0x04 + waitVBlankARM<ARMCPU_ARM9>, // 0x05 + wait4IRQ<ARMCPU_ARM9>, // 0x06 + bios_nop<ARMCPU_ARM9>, // 0x07 + bios_nop<ARMCPU_ARM9>, // 0x08 + divide<ARMCPU_ARM9>, // 0x09 + bios_nop<ARMCPU_ARM9>, // 0x0A + copy<ARMCPU_ARM9>, // 0x0B + fastCopy<ARMCPU_ARM9>, // 0x0C + bios_sqrt<ARMCPU_ARM9>, // 0x0D + getCRC16<ARMCPU_ARM9>, // 0x0E + isDebugger<ARMCPU_ARM9>, // 0x0F + BitUnPack<ARMCPU_ARM9>, // 0x10 + LZ77UnCompWram<ARMCPU_ARM9>, // 0x11 + LZ77UnCompVram<ARMCPU_ARM9>, // 0x12 + UnCompHuffman<ARMCPU_ARM9>, // 0x13 + RLUnCompWram<ARMCPU_ARM9>, // 0x14 + RLUnCompVram<ARMCPU_ARM9>, // 0x15 + Diff8bitUnFilterWram<ARMCPU_ARM9>, // 0x16 + bios_nop<ARMCPU_ARM9>, // 0x17 + Diff16bitUnFilter<ARMCPU_ARM9>, // 0x18 + bios_nop<ARMCPU_ARM9>, // 0x19 + bios_nop<ARMCPU_ARM9>, // 0x1A + bios_nop<ARMCPU_ARM9>, // 0x1B + bios_nop<ARMCPU_ARM9>, // 0x1C + bios_nop<ARMCPU_ARM9>, // 0x1D + bios_nop<ARMCPU_ARM9>, // 0x1E + setHaltCR<ARMCPU_ARM9>, // 0x1F +}; + +u32 (* ARM7_swi_tab[32])()={ + bios_nop<ARMCPU_ARM7>, // 0x00 + bios_nop<ARMCPU_ARM7>, // 0x01 + bios_nop<ARMCPU_ARM7>, // 0x02 + WaitByLoop<ARMCPU_ARM7>, // 0x03 + intrWaitARM<ARMCPU_ARM7>, // 0x04 + waitVBlankARM<ARMCPU_ARM7>, // 0x05 + wait4IRQ<ARMCPU_ARM7>, // 0x06 + sleep<ARMCPU_ARM7>, // 0x07 + SoundBias<ARMCPU_ARM7>, // 0x08 + divide<ARMCPU_ARM7>, // 0x09 + bios_nop<ARMCPU_ARM7>, // 0x0A + copy<ARMCPU_ARM7>, // 0x0B + fastCopy<ARMCPU_ARM7>, // 0x0C + bios_sqrt<ARMCPU_ARM7>, // 0x0D + getCRC16<ARMCPU_ARM7>, // 0x0E + isDebugger<ARMCPU_ARM7>, // 0x0F + BitUnPack<ARMCPU_ARM7>, // 0x10 + LZ77UnCompWram<ARMCPU_ARM7>, // 0x11 + LZ77UnCompVram<ARMCPU_ARM7>, // 0x12 + UnCompHuffman<ARMCPU_ARM7>, // 0x13 + RLUnCompWram<ARMCPU_ARM7>, // 0x14 + RLUnCompVram<ARMCPU_ARM7>, // 0x15 + Diff8bitUnFilterWram<ARMCPU_ARM7>, // 0x16 + bios_nop<ARMCPU_ARM7>, // 0x17 + bios_nop<ARMCPU_ARM7>, // 0x18 + bios_nop<ARMCPU_ARM7>, // 0x19 + getSineTab<ARMCPU_ARM7>, // 0x1A + getPitchTab<ARMCPU_ARM7>, // 0x1B + getVolumeTab<ARMCPU_ARM7>, // 0x1C + getBootProcs<ARMCPU_ARM7>, // 0x1D + bios_nop<ARMCPU_ARM7>, // 0x1E + setHaltCR<ARMCPU_ARM7>, // 0x1F +}; diff --git a/jni/desmume/src/bios.h b/jni/desmume/src/bios.h new file mode 100755 index 0000000..0936cc1 --- /dev/null +++ b/jni/desmume/src/bios.h @@ -0,0 +1,28 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2006-2009 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef BIOS_H +#define BIOS_H + +#include "armcpu.h" + +extern u32 (* ARM9_swi_tab[32])(); +extern u32 (* ARM7_swi_tab[32])(); + +#endif + diff --git a/jni/desmume/src/bits.h b/jni/desmume/src/bits.h new file mode 100755 index 0000000..be64f65 --- /dev/null +++ b/jni/desmume/src/bits.h @@ -0,0 +1,44 @@ +#ifndef BITS_H +#define BITS_H + +#define BIT(n) (1<<(n)) + +#define BIT_N(i,n) (((i)>>(n))&1) +#define BIT0(i) ((i)&1) +#define BIT1(i) BIT_N(i,1) +#define BIT2(i) BIT_N(i,2) +#define BIT3(i) BIT_N(i,3) +#define BIT4(i) BIT_N(i,4) +#define BIT5(i) BIT_N(i,5) +#define BIT6(i) BIT_N(i,6) +#define BIT7(i) BIT_N(i,7) +#define BIT8(i) BIT_N(i,8) +#define BIT9(i) BIT_N(i,9) +#define BIT10(i) BIT_N(i,10) +#define BIT11(i) BIT_N(i,11) +#define BIT12(i) BIT_N(i,12) +#define BIT13(i) BIT_N(i,13) +#define BIT14(i) BIT_N(i,14) +#define BIT15(i) BIT_N(i,15) +#define BIT16(i) BIT_N(i,16) +#define BIT17(i) BIT_N(i,17) +#define BIT18(i) BIT_N(i,18) +#define BIT19(i) BIT_N(i,19) +#define BIT20(i) BIT_N(i,20) +#define BIT21(i) BIT_N(i,21) +#define BIT22(i) BIT_N(i,22) +#define BIT23(i) BIT_N(i,23) +#define BIT24(i) BIT_N(i,24) +#define BIT25(i) BIT_N(i,25) +#define BIT26(i) BIT_N(i,26) +#define BIT27(i) BIT_N(i,27) +#define BIT28(i) BIT_N(i,28) +#define BIT29(i) BIT_N(i,29) +#define BIT30(i) BIT_N(i,30) +#define BIT31(i) ((i)>>31) + +#define CONDITION(i) (i)>>28 + +#define REG_POS(i,n) (((i)>>n)&0xF) + +#endif diff --git a/jni/desmume/src/build.bat b/jni/desmume/src/build.bat new file mode 100755 index 0000000..8bb85bd --- /dev/null +++ b/jni/desmume/src/build.bat @@ -0,0 +1,4 @@ +configure +make clean +make +pause \ No newline at end of file diff --git a/jni/desmume/src/cheatSystem.cpp b/jni/desmume/src/cheatSystem.cpp new file mode 100755 index 0000000..b654c27 --- /dev/null +++ b/jni/desmume/src/cheatSystem.cpp @@ -0,0 +1,1426 @@ +/* + Copyright (C) 2009-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <string.h> +#include "cheatSystem.h" +#include "NDSSystem.h" +#include "mem.h" +#include "MMU.h" +#include "debug.h" +#include "utils/xstring.h" + +#ifndef _MSC_VER +#include <stdint.h> +#endif + +CHEATS *cheats = NULL; +CHEATSEARCH *cheatSearch = NULL; + +void CHEATS::clear() +{ + list.resize(0); + currentGet = 0; +} + +void CHEATS::init(char *path) +{ + clear(); + strcpy((char *)filename, path); + + load(); +} + +BOOL CHEATS::add(u8 size, u32 address, u32 val, char *description, BOOL enabled) +{ + size_t num = list.size(); + list.push_back(CHEATS_LIST()); + list[num].code[0][0] = address & 0x00FFFFFF; + list[num].code[0][1] = val; + list[num].num = 1; + list[num].type = 0; + list[num].size = size; + this->setDescription(description, num); + list[num].enabled = enabled; + return TRUE; +} + +BOOL CHEATS::update(u8 size, u32 address, u32 val, char *description, BOOL enabled, u32 pos) +{ + if (pos >= list.size()) return FALSE; + list[pos].code[0][0] = address & 0x00FFFFFF; + list[pos].code[0][1] = val; + list[pos].num = 1; + list[pos].type = 0; + list[pos].size = size; + this->setDescription(description, pos); + list[pos].enabled = enabled; + return TRUE; +} + +void CHEATS::ARparser(CHEATS_LIST& list) +{ + u8 type = 0; + u8 subtype = 0; + u32 hi = 0; + u32 lo = 0; + u32 addr = 0; + u32 val = 0; + // AR temporary vars & flags + u32 offset = 0; + u32 datareg = 0; + u32 loopcount = 0; + u32 counter = 0; + u32 if_flag = 0; + s32 loopbackline = 0; + u32 loop_flag = 0; + + for (int i=0; i < list.num; i++) + { + type = list.code[i][0] >> 28; + subtype = (list.code[i][0] >> 24) & 0x0F; + + hi = list.code[i][0] & 0x0FFFFFFF; + lo = list.code[i][1]; + + if (if_flag > 0) + { + if ( (type == 0x0D) && (subtype == 0)) if_flag--; // ENDIF + if ( (type == 0x0D) && (subtype == 2)) // NEXT & Flush + { + if (loop_flag) + i = (loopbackline-1); + else + { + offset = 0; + datareg = 0; + loopcount = 0; + counter = 0; + if_flag = 0; + loop_flag = 0; + } + } + continue; + } + + switch (type) + { + case 0x00: + { + if (hi==0) + { + //manual hook + } + else + if ((hi==0x0000AA99) && (lo==0)) // 0000AA99 00000000 parameter bytes 9..10 for above code (padded with 00s) + { + //parameter bytes 9..10 for above code (padded with 00s) + } + else // 0XXXXXXX YYYYYYYY word[XXXXXXX+offset] = YYYYYYYY + { + addr = hi + offset; + _MMU_write32<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, lo); + } + } + break; + + case 0x01: // 1XXXXXXX 0000YYYY half[XXXXXXX+offset] = YYYY + addr = hi + offset; + _MMU_write16<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, lo); + break; + + case 0x02: // 2XXXXXXX 000000YY byte[XXXXXXX+offset] = YY + addr = hi + offset; + _MMU_write08<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, lo); + break; + + case 0x03: // 3XXXXXXX YYYYYYYY IF YYYYYYYY > word[XXXXXXX] ;unsigned + if (hi == 0) hi = offset; // V1.54+ + val = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(hi); + if ( lo > val ) + { + if (if_flag > 0) if_flag--; + } + else + { + if_flag++; + } + break; + + case 0x04: // 4XXXXXXX YYYYYYYY IF YYYYYYYY < word[XXXXXXX] ;unsigned + if ((hi == 0x04332211) && (lo == 88776655)) //44332211 88776655 parameter bytes 1..8 for above code (example) + { + break; + } + if (hi == 0) hi = offset; // V1.54+ + val = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(hi); + if ( lo < val ) + { + if (if_flag > 0) if_flag--; + } + else + { + if_flag++; + } + break; + + case 0x05: // 5XXXXXXX YYYYYYYY IF YYYYYYYY = word[XXXXXXX] + if (hi == 0) hi = offset; // V1.54+ + val = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(hi); + if ( lo == val ) + { + if (if_flag > 0) if_flag--; + } + else + { + if_flag++; + } + break; + + case 0x06: // 6XXXXXXX YYYYYYYY IF YYYYYYYY <> word[XXXXXXX] + if (hi == 0) hi = offset; // V1.54+ + val = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(hi); + if ( lo != val ) + { + if (if_flag > 0) if_flag--; + } + else + { + if_flag++; + } + break; + + case 0x07: // 7XXXXXXX ZZZZYYYY IF YYYY > ((not ZZZZ) AND half[XXXXXXX]) + if (hi == 0) hi = offset; // V1.54+ + val = _MMU_read16<ARMCPU_ARM9,MMU_AT_DEBUG>(hi); + if ( (lo & 0xFFFF) > ( (~(lo >> 16)) & val) ) + { + if (if_flag > 0) if_flag--; + } + else + { + if_flag++; + } + break; + + case 0x08: // 8XXXXXXX ZZZZYYYY IF YYYY < ((not ZZZZ) AND half[XXXXXXX]) + if (hi == 0) hi = offset; // V1.54+ + val = _MMU_read16<ARMCPU_ARM9,MMU_AT_DEBUG>(hi); + if ( (lo & 0xFFFF) < ( (~(lo >> 16)) & val) ) + { + if (if_flag > 0) if_flag--; + } + else + { + if_flag++; + } + break; + + case 0x09: // 9XXXXXXX ZZZZYYYY IF YYYY = ((not ZZZZ) AND half[XXXXXXX]) + if (hi == 0) hi = offset; // V1.54+ + val = _MMU_read16<ARMCPU_ARM9,MMU_AT_DEBUG>(hi); + if ( (lo & 0xFFFF) == ( (~(lo >> 16)) & val) ) + { + if (if_flag > 0) if_flag--; + } + else + { + if_flag++; + } + break; + + case 0x0A: // AXXXXXXX ZZZZYYYY IF YYYY <> ((not ZZZZ) AND half[XXXXXXX]) + if (hi == 0) hi = offset; // V1.54+ + val = _MMU_read16<ARMCPU_ARM9,MMU_AT_DEBUG>(hi); + if ( (lo & 0xFFFF) != ( (~(lo >> 16)) & val) ) + { + if (if_flag > 0) if_flag--; + } + else + { + if_flag++; + } + break; + + case 0x0B: // BXXXXXXX 00000000 offset = word[XXXXXXX+offset] + addr = hi + offset; + offset = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(addr);; + break; + + case 0x0C: + switch (subtype) + { + case 0x0: // C0000000 YYYYYYYY FOR loopcount=0 to YYYYYYYY ;execute Y+1 times + if (loopcount < (lo+1)) + loop_flag = 1; + else + loop_flag = 0; + loopcount++; + loopbackline = i; + break; + + case 0x4: // C4000000 00000000 offset = address of the C4000000 code ; V1.54 + printf("AR: untested code C4\n"); + break; + + case 0x5: // C5000000 XXXXYYYY counter=counter+1, IF (counter AND YYYY) = XXXX ; V1.54 + counter++; + if ( (counter & (lo & 0xFFFF)) == ((lo >> 8) & 0xFFFF) ) + { + if (if_flag > 0) if_flag--; + } + else + { + if_flag++; + } + break; + + case 0x6: // C6000000 XXXXXXXX [XXXXXXXX]=offset ; V1.54 + _MMU_write32<ARMCPU_ARM9,MMU_AT_DEBUG>(lo, offset); + break; + } + break; + + case 0x0D: + { + switch (subtype) + { + case 0x0: // D0000000 00000000 ENDIF + break; + + case 0x1: // D1000000 00000000 NEXT loopcount + if (loop_flag) + i = (loopbackline-1); + break; + + case 0x2: // D2000000 00000000 NEXT loopcount, and then FLUSH everything + if (loop_flag) + i = (loopbackline-1); + else + { + offset = 0; + datareg = 0; + loopcount = 0; + counter = 0; + if_flag = 0; + loop_flag = 0; + } + break; + + case 0x3: // D3000000 XXXXXXXX offset = XXXXXXXX + offset = lo; + break; + + case 0x4: // D4000000 XXXXXXXX datareg = datareg + XXXXXXXX + datareg += lo; + break; + + case 0x5: // D5000000 XXXXXXXX datareg = XXXXXXXX + datareg = lo; + break; + + case 0x6: // D6000000 XXXXXXXX word[XXXXXXXX+offset]=datareg, offset=offset+4 + addr = lo + offset; + _MMU_write32<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, datareg); + offset += 4; + break; + + case 0x7: // D7000000 XXXXXXXX half[XXXXXXXX+offset]=datareg, offset=offset+2 + addr = lo + offset; + _MMU_write16<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, datareg); + offset += 2; + break; + + case 0x8: // D8000000 XXXXXXXX byte[XXXXXXXX+offset]=datareg, offset=offset+1 + addr = lo + offset; + _MMU_write08<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, datareg); + offset += 1; + break; + + case 0x9: // D9000000 XXXXXXXX datareg = word[XXXXXXXX+offset] + addr = lo + offset; + datareg = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(addr); + break; + + case 0xA: // DA000000 XXXXXXXX datareg = half[XXXXXXXX+offset] + addr = lo + offset; + datareg = _MMU_read16<ARMCPU_ARM9,MMU_AT_DEBUG>(addr); + break; + + case 0xB: // DB000000 XXXXXXXX datareg = byte[XXXXXXXX+offset] ;bugged on pre-v1.54 + addr = lo + offset; + datareg = _MMU_read08<ARMCPU_ARM9,MMU_AT_DEBUG>(addr); + break; + + case 0xC: // DC000000 XXXXXXXX offset = offset + XXXXXXXX + offset += lo; + break; + } + } + break; + + case 0xE: // EXXXXXXX YYYYYYYY Copy YYYYYYYY parameter bytes to [XXXXXXXX+offset...] + { + u8 *tmp_code = (u8*)(list.code[i+1]); + u32 addr = hi+offset; + u32 maxByteReadLocation = ((2 * 4) * (MAX_XX_CODE - i - 1)) - 1; // 2 = 2 array dimensions, 4 = 4 bytes per array element + + if (lo <= maxByteReadLocation) + { + for (u32 t = 0; t < lo; t++) + { + u8 tmp = tmp_code[t]; + _MMU_write08<ARMCPU_ARM9,MMU_AT_DEBUG>(addr, tmp); + addr++; + } + } + + i += (lo / 8); + } + break; + + case 0xF: // FXXXXXXX YYYYYYYY Copy YYYYYYYY bytes from [offset..] to [XXXXXXX...] + for (u32 t = 0; t < lo; t++) + { + u8 tmp = _MMU_read08<ARMCPU_ARM9,MMU_AT_DEBUG>(offset+t); + _MMU_write08<ARMCPU_ARM9,MMU_AT_DEBUG>(hi+t, tmp); + } + break; + default: PROGINFO("AR: ERROR uknown command 0x%2X at %08X:%08X\n", type, hi, lo); break; + } + } +} + +BOOL CHEATS::add_AR_Direct(CHEATS_LIST cheat) +{ + size_t num = list.size(); + list.push_back(cheat); + list[num].type = 1; + return TRUE; +} + +BOOL CHEATS::add_AR(char *code, char *description, BOOL enabled) +{ + //if (num == MAX_CHEAT_LIST) return FALSE; + size_t num = list.size(); + + CHEATS_LIST temp; + if (!CHEATS::XXCodeFromString(&temp, code)) return FALSE; + + list.push_back(temp); + + list[num].type = 1; + + this->setDescription(description, num); + list[num].enabled = enabled; + return TRUE; +} + +BOOL CHEATS::update_AR(char *code, char *description, BOOL enabled, u32 pos) +{ + if (pos >= list.size()) return FALSE; + + if (code != NULL) + { + if (!CHEATS::XXCodeFromString(this->getItemByIndex(pos), code)) return FALSE; + this->setDescription(description, pos); + list[pos].type = 1; + } + + list[pos].enabled = enabled; + return TRUE; +} + +BOOL CHEATS::add_CB(char *code, char *description, BOOL enabled) +{ + //if (num == MAX_CHEAT_LIST) return FALSE; + size_t num = list.size(); + + if (!CHEATS::XXCodeFromString(this->getItemByIndex(num), code)) return FALSE; + + list[num].type = 2; + + this->setDescription(description, num); + list[num].enabled = enabled; + return TRUE; +} + +BOOL CHEATS::update_CB(char *code, char *description, BOOL enabled, u32 pos) +{ + if (pos >= list.size()) return FALSE; + + if (code != NULL) + { + if (!CHEATS::XXCodeFromString(this->getItemByIndex(pos), code)) return FALSE; + list[pos].type = 2; + this->setDescription(description, pos); + } + list[pos].enabled = enabled; + return TRUE; +} + +BOOL CHEATS::remove(u32 pos) +{ + if (pos >= list.size()) return FALSE; + if (list.size() == 0) return FALSE; + + list.erase(list.begin()+pos); + + return TRUE; +} + +void CHEATS::getListReset() +{ + currentGet = 0; + return; +} + +BOOL CHEATS::getList(CHEATS_LIST *cheat) +{ + BOOL result = FALSE; + + if (currentGet >= this->list.size()) + { + this->getListReset(); + return result; + } + + result = this->get(cheat, currentGet++); + + return result; +} + +CHEATS_LIST* CHEATS::getListPtr() +{ + return &this->list[0]; +} + +BOOL CHEATS::get(CHEATS_LIST *cheat, u32 pos) +{ + CHEATS_LIST *item = this->getItemByIndex(pos); + if (item == NULL) + { + return FALSE; + } + + *cheat = *item; + + return TRUE; +} + +CHEATS_LIST* CHEATS::getItemByIndex(const u32 pos) +{ + if (pos >= this->getSize()) + { + return NULL; + } + + return &this->list[pos]; +} + +u32 CHEATS::getSize() +{ + return list.size(); +} + +void CHEATS::setDescription(const char *description, u32 pos) +{ + strncpy(list[pos].description, description, sizeof(list[pos].description)); + list[pos].description[sizeof(list[pos].description) - 1] = '\0'; +} + +BOOL CHEATS::save() +{ + const char *types[] = {"DS", "AR", "CB"}; + std::string cheatLineStr = ""; + FILE *flist = fopen((char *)filename, "w"); + + if (flist) + { + fprintf(flist, "; DeSmuME cheats file. VERSION %i.%03i\n", CHEAT_VERSION_MAJOR, CHEAT_VERSION_MINOR); + fprintf(flist, "Name=%s\n", gameInfo.ROMname); + fprintf(flist, "Serial=%s\n", gameInfo.ROMserial); + fputs("\n; cheats list\n", flist); + for (size_t i = 0; i < list.size(); i++) + { + if (list[i].num == 0) continue; + + char buf1[8] = {0}; + sprintf(buf1, "%s %c ", types[list[i].type], list[i].enabled?'1':'0'); + cheatLineStr = buf1; + + for (int t = 0; t < list[i].num; t++) + { + char buf2[10] = { 0 }; + + u32 adr = list[i].code[t][0]; + if (list[i].type == 0) + { + //size of the cheat is written out as adr highest nybble + adr &= 0x0FFFFFFF; + adr |= (list[i].size << 28); + } + sprintf(buf2, "%08X", adr); + cheatLineStr += buf2; + + sprintf(buf2, "%08X", list[i].code[t][1]); + cheatLineStr += buf2; + if (t < (list[i].num - 1)) + cheatLineStr += ","; + } + + cheatLineStr += " ;"; + cheatLineStr += trim(list[i].description); + fprintf(flist, "%s\n", cheatLineStr.c_str()); + } + fputs("\n", flist); + fclose(flist); + return TRUE; + } + + return FALSE; +} + +char *CHEATS::clearCode(char *s) +{ + char *buf = s; + if (!s) return NULL; + if (!*s) return s; + + for (u32 i = 0; i < strlen(s); i++) + { + if (s[i] == ';') break; + if (strchr(hexValid, s[i])) + { + *buf = s[i]; + buf++; + } + } + *buf = 0; + return s; +} + +BOOL CHEATS::load() +{ + FILE *flist = fopen((char *)filename, "r"); + if (flist == NULL) + { + return FALSE; + } + + size_t readSize = (MAX_XX_CODE * 17) + sizeof(list[0].description) + 7; + if (readSize < CHEAT_FILE_MIN_FGETS_BUFFER) + { + readSize = CHEAT_FILE_MIN_FGETS_BUFFER; + } + + char *buf = (char *)malloc(readSize); + if (buf == NULL) + { + fclose(flist); + return FALSE; + } + + readSize *= sizeof(*buf); + + std::string codeStr = ""; + u32 last = 0; + u32 line = 0; + + INFO("Load cheats: %s\n", filename); + clear(); + last = 0; line = 0; + while (!feof(flist)) + { + CHEATS_LIST tmp_cht; + line++; // only for debug + memset(buf, 0, readSize); + if (fgets(buf, readSize, flist) == NULL) { + //INFO("Cheats: Failed to read from flist at line %i\n", line); + continue; + } + trim(buf); + if ((strlen(buf) == 0) || (buf[0] == ';')) continue; + if(!strncasecmp(buf,"name=",5)) continue; + if(!strncasecmp(buf,"serial=",7)) continue; + + memset(&tmp_cht, 0, sizeof(tmp_cht)); + if ((buf[0] == 'D') && (buf[1] == 'S')) // internal + tmp_cht.type = 0; + else + if ((buf[0] == 'A') && (buf[1] == 'R')) // Action Replay + tmp_cht.type = 1; + else + if ((buf[0] == 'B') && (buf[1] == 'S')) // Codebreaker + tmp_cht.type = 2; + else + continue; + // TODO: CB not supported + if (tmp_cht.type == 3) + { + INFO("Cheats: Codebreaker code no supported at line %i\n", line); + continue; + } + + codeStr = (char *)(buf + 5); + codeStr = clearCode((char *)codeStr.c_str()); + + if (codeStr.empty() || (codeStr.length() % 16 != 0)) + { + INFO("Cheats: Syntax error at line %i\n", line); + continue; + } + + tmp_cht.enabled = (buf[3] == '0')?FALSE:TRUE; + u32 descr_pos = (u32)(std::max<s32>(strchr((char*)buf, ';') - buf, 0)); + if (descr_pos != 0) + { + strncpy(tmp_cht.description, (buf + descr_pos + 1), sizeof(tmp_cht.description)); + tmp_cht.description[sizeof(tmp_cht.description) - 1] = '\0'; + } + + tmp_cht.num = codeStr.length() / 16; + if ((tmp_cht.type == 0) && (tmp_cht.num > 1)) + { + INFO("Cheats: Too many values for internal cheat\n", line); + continue; + } + for (int i = 0; i < tmp_cht.num; i++) + { + char tmp_buf[9] = {0}; + + strncpy(tmp_buf, &codeStr[i * 16], 8); + sscanf_s(tmp_buf, "%x", &tmp_cht.code[i][0]); + + if (tmp_cht.type == 0) + { + tmp_cht.size = std::min<u32>(3, ((tmp_cht.code[i][0] & 0xF0000000) >> 28)); + tmp_cht.code[i][0] &= 0x00FFFFFF; + } + + strncpy(tmp_buf, &codeStr[(i * 16) + 8], 8); + sscanf_s(tmp_buf, "%x", &tmp_cht.code[i][1]); + } + + list.push_back(tmp_cht); + last++; + } + + free(buf); + buf = NULL; + + fclose(flist); + INFO("Added %i cheat codes\n", list.size()); + + return TRUE; +} + +void CHEATS::process() +{ + if (CommonSettings.cheatsDisable) return; + if (list.size() == 0) return; + size_t num = list.size(); + for (size_t i = 0; i < num; i++) + { + if (!list[i].enabled) continue; + + switch (list[i].type) + { + case 0: // internal cheat system + { + //INFO("list at 0x02|%06X value %i (size %i)\n",list[i].code[0], list[i].lo[0], list[i].size); + u32 addr = list[i].code[0][0] | 0x02000000; + u32 val = list[i].code[0][1]; + switch (list[i].size) + { + case 0: + _MMU_write08<ARMCPU_ARM9,MMU_AT_DEBUG>(addr,val); + break; + case 1: + _MMU_write16<ARMCPU_ARM9,MMU_AT_DEBUG>(addr,val); + break; + case 2: + { + u32 tmp = _MMU_read32<ARMCPU_ARM9,MMU_AT_DEBUG>(addr); + tmp &= 0xFF000000; + tmp |= (val & 0x00FFFFFF); + _MMU_write32<ARMCPU_ARM9,MMU_AT_DEBUG>(addr,tmp); + break; + } + case 3: + _MMU_write32<ARMCPU_ARM9,MMU_AT_DEBUG>(addr,val); + break; + } + break; + } //end case 0 internal cheat system + + case 1: // Action Replay + ARparser(list[i]); + break; + case 2: // Codebreaker + break; + default: continue; + } + } +} + +void CHEATS::getXXcodeString(CHEATS_LIST list, char *res_buf) +{ + char buf[50] = { 0 }; + + for (int i=0; i < list.num; i++) + { + sprintf(buf, "%08X %08X\n", list.code[i][0], list.code[i][1]); + strcat(res_buf, buf); + } +} + +BOOL CHEATS::XXCodeFromString(CHEATS_LIST *cheatItem, const std::string codeString) +{ + return CHEATS::XXCodeFromString(cheatItem, codeString.c_str()); +} + +BOOL CHEATS::XXCodeFromString(CHEATS_LIST *cheatItem, const char *codeString) +{ + BOOL result = FALSE; + + if (cheatItem == NULL || codeString == NULL) + { + return result; + } + + int count = 0; + u16 t = 0; + char tmp_buf[sizeof(cheatItem->code) * 2 + 1]; + memset(tmp_buf, 0, sizeof(tmp_buf)); + + size_t code_len = strlen(codeString); + // remove wrong chars + for (size_t i=0; i < code_len; i++) + { + char c = codeString[i]; + //apparently 100% of pokemon codes were typed with the letter O in place of zero in some places + //so let's try to adjust for that here + static const char *AR_Valid = "Oo0123456789ABCDEFabcdef"; + if (strchr(AR_Valid, c)) + { + if(c=='o' || c=='O') c='0'; + tmp_buf[t++] = c; + } + } + + size_t len = strlen(tmp_buf); + if ((len % 16) != 0) return result; // error + + // TODO: syntax check + count = (len / 16); + for (int i=0; i < count; i++) + { + char buf[9] = {0}; + memcpy(buf, tmp_buf+(i*16), 8); + sscanf(buf, "%x", &cheatItem->code[i][0]); + memcpy(buf, tmp_buf+(i*16) + 8, 8); + sscanf(buf, "%x", &cheatItem->code[i][1]); + } + + cheatItem->num = count; + cheatItem->size = 0; + + result = TRUE; + + return result; +} + +// ========================================== search +BOOL CHEATSEARCH::start(u8 type, u8 size, u8 sign) +{ + if (statMem) return FALSE; + if (mem) return FALSE; + + statMem = new u8 [ ( 4 * 1024 * 1024 ) / 8 ]; + memset(statMem, 0xFF, ( 4 * 1024 * 1024 ) / 8); + + // comparative search type (need 8Mb RAM !!! (4+4)) + mem = new u8 [ ( 4 * 1024 * 1024 ) ]; + memcpy(mem, MMU.MMU_MEM[0][0x20], ( 4 * 1024 * 1024 ) ); + + _type = type; + _size = size; + _sign = sign; + amount = 0; + lastRecord = 0; + + //INFO("Cheat search system is inited (type %s)\n", type?"comparative":"exact"); + return TRUE; +} + +BOOL CHEATSEARCH::close() +{ + if (statMem) + { + delete [] statMem; + statMem = NULL; + } + + if (mem) + { + delete [] mem; + mem = NULL; + } + amount = 0; + lastRecord = 0; + //INFO("Cheat search system is closed\n"); + return FALSE; +} + +u32 CHEATSEARCH::search(u32 val) +{ + amount = 0; + + switch (_size) + { + case 0: // 1 byte + for (u32 i = 0; i < (4 * 1024 * 1024); i++) + { + u32 addr = (i >> 3); + u32 offs = (i % 8); + if (statMem[addr] & (1<<offs)) + { + if ( T1ReadByte(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) == val ) + { + statMem[addr] |= (1<<offs); + amount++; + continue; + } + statMem[addr] &= ~(1<<offs); + } + } + break; + + case 1: // 2 bytes + for (u32 i = 0; i < (4 * 1024 * 1024); i+=2) + { + u32 addr = (i >> 3); + u32 offs = (i % 8); + if (statMem[addr] & (3<<offs)) + { + if ( T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) == val ) + { + statMem[addr] |= (3<<offs); + amount++; + continue; + } + statMem[addr] &= ~(3<<offs); + } + } + break; + + case 2: // 3 bytes + for (u32 i = 0; i < (4 * 1024 * 1024); i+=3) + { + u32 addr = (i >> 3); + u32 offs = (i % 8); + if (statMem[addr] & (0x7<<offs)) + { + if ( (T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) & 0x00FFFFFF) == val ) + { + statMem[addr] |= (0x7<<offs); + amount++; + continue; + } + statMem[addr] &= ~(0x7<<offs); + } + } + break; + + case 3: // 4 bytes + for (u32 i = 0; i < (4 * 1024 * 1024); i+=4) + { + u32 addr = (i >> 3); + u32 offs = (i % 8); + if (statMem[addr] & (0xF<<offs)) + { + if ( T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) == val ) + { + statMem[addr] |= (0xF<<offs); + amount++; + continue; + } + statMem[addr] &= ~(0xF<<offs); + } + } + break; + } + + return (amount); +} + +u32 CHEATSEARCH::search(u8 comp) +{ + BOOL res = FALSE; + + amount = 0; + + switch (_size) + { + case 0: // 1 byte + for (u32 i = 0; i < (4 * 1024 * 1024); i++) + { + u32 addr = (i >> 3); + u32 offs = (i % 8); + if (statMem[addr] & (1<<offs)) + { + switch (comp) + { + case 0: res=(T1ReadByte(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) > T1ReadByte(mem, i)); break; + case 1: res=(T1ReadByte(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) < T1ReadByte(mem, i)); break; + case 2: res=(T1ReadByte(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) == T1ReadByte(mem, i)); break; + case 3: res=(T1ReadByte(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) != T1ReadByte(mem, i)); break; + default: res = FALSE; break; + } + if ( res ) + { + statMem[addr] |= (1<<offs); + amount++; + continue; + } + statMem[addr] &= ~(1<<offs); + } + } + break; + + case 1: // 2 bytes + for (u32 i = 0; i < (4 * 1024 * 1024); i+=2) + { + u32 addr = (i >> 3); + u32 offs = (i % 8); + if (statMem[addr] & (3<<offs)) + { + switch (comp) + { + case 0: res=(T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) > T1ReadWord(mem, i)); break; + case 1: res=(T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) < T1ReadWord(mem, i)); break; + case 2: res=(T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) == T1ReadWord(mem, i)); break; + case 3: res=(T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) != T1ReadWord(mem, i)); break; + default: res = FALSE; break; + } + if ( res ) + { + statMem[addr] |= (3<<offs); + amount++; + continue; + } + statMem[addr] &= ~(3<<offs); + } + } + break; + + case 2: // 3 bytes + for (u32 i = 0; i < (4 * 1024 * 1024); i+=3) + { + u32 addr = (i >> 3); + u32 offs = (i % 8); + if (statMem[addr] & (7<<offs)) + { + switch (comp) + { + case 0: res=((T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) & 0x00FFFFFF) > (T1ReadLong(mem, i) & 0x00FFFFFF) ); break; + case 1: res=((T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) & 0x00FFFFFF) < (T1ReadLong(mem, i) & 0x00FFFFFF) ); break; + case 2: res=((T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) & 0x00FFFFFF) == (T1ReadLong(mem, i) & 0x00FFFFFF) ); break; + case 3: res=((T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) & 0x00FFFFFF) != (T1ReadLong(mem, i) & 0x00FFFFFF) ); break; + default: res = FALSE; break; + } + if ( res ) + { + statMem[addr] |= (7<<offs); + amount++; + continue; + } + statMem[addr] &= ~(7<<offs); + } + } + break; + + case 3: // 4 bytes + for (u32 i = 0; i < (4 * 1024 * 1024); i+=4) + { + u32 addr = (i >> 3); + u32 offs = (i % 8); + if (statMem[addr] & (0xF<<offs)) + { + switch (comp) + { + case 0: res=(T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) > T1ReadLong(mem, i)); break; + case 1: res=(T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) < T1ReadLong(mem, i)); break; + case 2: res=(T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) == T1ReadLong(mem, i)); break; + case 3: res=(T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) != T1ReadLong(mem, i)); break; + default: res = FALSE; break; + } + if ( res ) + { + statMem[addr] |= (0xF<<offs); + amount++; + continue; + } + statMem[addr] &= ~(0xF<<offs); + } + } + break; + } + + memcpy(mem, MMU.MMU_MEM[0][0x20], ( 4 * 1024 * 1024 ) ); + + return (amount); +} + +u32 CHEATSEARCH::getAmount() +{ + return (amount); +} + +BOOL CHEATSEARCH::getList(u32 *address, u32 *curVal) +{ + u8 step = (_size+1); + u8 stepMem = 1; + switch (_size) + { + case 1: stepMem = 0x3; break; + case 2: stepMem = 0x7; break; + case 3: stepMem = 0xF; break; + } + + for (u32 i = lastRecord; i < (4 * 1024 * 1024); i+=step) + { + u32 addr = (i >> 3); + u32 offs = (i % 8); + if (statMem[addr] & (stepMem<<offs)) + { + *address = i; + lastRecord = i+step; + + switch (_size) + { + case 0: *curVal=(u32)T1ReadByte(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i); return TRUE; + case 1: *curVal=(u32)T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i); return TRUE; + case 2: *curVal=(u32)T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i) & 0x00FFFFFF; return TRUE; + case 3: *curVal=(u32)T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x20], i); return TRUE; + default: return TRUE; + } + } + } + lastRecord = 0; + return FALSE; +} + +void CHEATSEARCH::getListReset() +{ + lastRecord = 0; +} + +// ========================================================================= Export +void CHEATSEXPORT::R4decrypt(u8 *buf, u32 len, u32 n) +{ + size_t r = 0; + while (r < len) + { + size_t i ; + u16 key = n ^ 0x484A; + for (i = 0 ; i < 512 && i < len - r ; i ++) + { + u8 _xor = 0; + if (key & 0x4000) _xor |= 0x80; + if (key & 0x1000) _xor |= 0x40; + if (key & 0x0800) _xor |= 0x20; + if (key & 0x0200) _xor |= 0x10; + if (key & 0x0080) _xor |= 0x08; + if (key & 0x0040) _xor |= 0x04; + if (key & 0x0002) _xor |= 0x02; + if (key & 0x0001) _xor |= 0x01; + + u32 k = ((buf[i] << 8) ^ key) << 16; + u32 x = k; + for (u8 j = 1; j < 32; j ++) + x ^= k >> j; + key = 0x0000; + if (BIT_N(x, 23)) key |= 0x8000; + if (BIT_N(k, 22)) key |= 0x4000; + if (BIT_N(k, 21)) key |= 0x2000; + if (BIT_N(k, 20)) key |= 0x1000; + if (BIT_N(k, 19)) key |= 0x0800; + if (BIT_N(k, 18)) key |= 0x0400; + if (BIT_N(k, 17) != BIT_N(x, 31)) key |= 0x0200; + if (BIT_N(k, 16) != BIT_N(x, 30)) key |= 0x0100; + if (BIT_N(k, 30) != BIT_N(k, 29)) key |= 0x0080; + if (BIT_N(k, 29) != BIT_N(k, 28)) key |= 0x0040; + if (BIT_N(k, 28) != BIT_N(k, 27)) key |= 0x0020; + if (BIT_N(k, 27) != BIT_N(k, 26)) key |= 0x0010; + if (BIT_N(k, 26) != BIT_N(k, 25)) key |= 0x0008; + if (BIT_N(k, 25) != BIT_N(k, 24)) key |= 0x0004; + if (BIT_N(k, 25) != BIT_N(x, 26)) key |= 0x0002; + if (BIT_N(k, 24) != BIT_N(x, 25)) key |= 0x0001; + buf[i] ^= _xor; + } + + buf+= 512; + r += 512; + n += 1; + } +} + +bool CHEATSEXPORT::load(char *path) +{ + error = 0; + + fp = fopen(path, "rb"); + if (!fp) + { + printf("Error open database\n"); + error = 1; + return false; + } + + const char *headerID = "R4 CheatCode"; + char buf[255] = {0}; + fread(buf, 1, strlen(headerID), fp); + if (strncmp(buf, headerID, strlen(headerID)) != 0) + { + // check encrypted + R4decrypt((u8 *)buf, strlen(headerID), 0); + if (strcmp(buf, headerID) != 0) + { + error = 2; + return false; + } + encrypted = true; + } + + fseek(fp, 0, SEEK_END); + fsize = ftell(fp); + fseek(fp, 0, SEEK_SET); + + if (!search()) + { + printf("ERROR: cheat in database not found\n"); + error = 3; + return false; + } + + if (!getCodes()) + { + printf("ERROR: export cheats failed\n"); + error = 4; + return false; + } + + return true; +} +void CHEATSEXPORT::close() +{ + if (fp) + fclose(fp); + if (cheats) + { + delete [] cheats; + cheats = NULL; + } +} + +bool CHEATSEXPORT::search() +{ + if (!fp) return false; + + u32 pos = 0x0100; + FAT_R4 fat_tmp = {0}; + u8 buf[512] = {0}; + + CRC = 0; + encOffset = 0; + u32 t = 0; + memset(date, 0, sizeof(date)); + if (encrypted) + { + fseek(fp, 0, SEEK_SET); + fread(&buf[0], 1, 512, fp); + R4decrypt((u8 *)&buf[0], 512, 0); + memcpy(&date[0], &buf[0x10], 16); + } + else + { + fseek(fp, 0x10, SEEK_SET); + fread(&date, 16, 1, fp); + fseek(fp, pos, SEEK_SET); + fread(&fat_tmp, sizeof(fat), 1, fp); + } + + while (1) + { + if (encrypted) + { + memcpy(&fat, &buf[pos % 512], sizeof(fat)); + pos += sizeof(fat); + if ((pos>>9) > t) + { + t++; + fread(&buf[0], 1, 512, fp); + R4decrypt((u8 *)&buf[0], 512, t); + } + memcpy(&fat_tmp, &buf[pos % 512], sizeof(fat_tmp)); // next + } + else + { + memcpy(&fat, &fat_tmp, sizeof(fat)); + fread(&fat_tmp, sizeof(fat_tmp), 1, fp); + + } + //printf("serial: %s, offset %08X\n", fat.serial, fat.addr); + if (memcmp(gameInfo.header.gameCode, &fat.serial[0], 4) == 0) + { + dataSize = fat_tmp.addr?(fat_tmp.addr - fat.addr):0; + if (encrypted) + { + encOffset = fat.addr % 512; + dataSize += encOffset; + } + if (!dataSize) return false; + CRC = fat.CRC; + char buf[5] = {0}; + memcpy(&buf, &fat.serial[0], 4); + printf("Cheats: found %s CRC %08X at 0x%08llX, size %i byte(s)\n", buf, fat.CRC, fat.addr, dataSize - encOffset); + return true; + } + + if (fat.addr == 0) break; + } + + memset(&fat, 0, sizeof(FAT_R4)); + return false; +} + +bool CHEATSEXPORT::getCodes() +{ + if (!fp) return false; + + u32 pos = 0; + u32 pos_cht = 0; + + u8 *data = new u8 [dataSize+8]; + if (!data) return false; + memset(data, 0, dataSize+8); + + fseek(fp, fat.addr - encOffset, SEEK_SET); + + if (fread(data, 1, dataSize, fp) != dataSize) + { + delete [] data; + data = NULL; + return false; + } + + if (encrypted) + R4decrypt(data, dataSize, fat.addr >> 9); + + intptr_t ptrMask = (~0 << 2); + u8 *gameTitlePtr = (u8 *)data + encOffset; + + memset(gametitle, 0, CHEAT_DB_GAME_TITLE_SIZE); + memcpy(gametitle, gameTitlePtr, strlen((const char *)gameTitlePtr)); + + u32 *cmd = (u32 *)(((intptr_t)gameTitlePtr + strlen((const char *)gameTitlePtr) + 4) & ptrMask); + numCheats = cmd[0] & 0x0FFFFFFF; + cmd += 9; + cheats = new CHEATS_LIST[numCheats]; + memset(cheats, 0, sizeof(CHEATS_LIST) * numCheats); + + while (pos < numCheats) + { + u32 folderNum = 1; + u8 *folderName = NULL; + u8 *folderNote = NULL; + if ((*cmd & 0xF0000000) == 0x10000000) // Folder + { + folderNum = (*cmd & 0x00FFFFFF); + folderName = (u8*)((intptr_t)cmd + 4); + folderNote = (u8*)((intptr_t)folderName + strlen((char*)folderName) + 1); + pos++; + cmd = (u32 *)(((intptr_t)folderName + strlen((char*)folderName) + 1 + strlen((char*)folderNote) + 1 + 3) & ptrMask); + } + + for (u32 i = 0; i < folderNum; i++) // in folder + { + u8 *cheatName = (u8 *)((intptr_t)cmd + 4); + u8 *cheatNote = (u8 *)((intptr_t)cheatName + strlen((char*)cheatName) + 1); + u32 *cheatData = (u32 *)(((intptr_t)cheatNote + strlen((char*)cheatNote) + 1 + 3) & ptrMask); + u32 cheatDataLen = *cheatData++; + u32 numberCodes = cheatDataLen / 2; + + if (numberCodes <= MAX_XX_CODE) + { + std::string descriptionStr = ""; + + if ( folderName && *folderName ) + { + descriptionStr += (char *)folderName; + descriptionStr += ": "; + } + + descriptionStr += (char *)cheatName; + + if ( cheatNote && *cheatNote ) + { + descriptionStr += " | "; + descriptionStr += (char *)cheatNote; + } + + strncpy(cheats[pos_cht].description, descriptionStr.c_str(), sizeof(cheats[pos_cht].description)); + cheats[pos_cht].description[sizeof(cheats[pos_cht].description) - 1] = '\0'; + + cheats[pos_cht].num = numberCodes; + cheats[pos_cht].type = 1; + + for(u32 j = 0, t = 0; j < numberCodes; j++, t+=2 ) + { + cheats[pos_cht].code[j][0] = (u32)*(cheatData+t); + //printf("%i: %08X ", j, cheats[pos_cht].code[j][0]); + cheats[pos_cht].code[j][1] = (u32)*(cheatData+t+1); + //printf("%08X\n", cheats[pos_cht].code[j][1]); + + } + pos_cht++; + } + + pos++; + cmd = (u32 *)((intptr_t)cmd + ((*cmd + 1)*4)); + } + + }; + + delete [] data; + + numCheats = pos_cht; + //for (int i = 0; i < numCheats; i++) + // printf("%i: %s\n", i, cheats[i].description); + + return true; +} + +CHEATS_LIST *CHEATSEXPORT::getCheats() +{ + return cheats; +} +u32 CHEATSEXPORT::getCheatsNum() +{ + return numCheats; +} diff --git a/jni/desmume/src/cheatSystem.h b/jni/desmume/src/cheatSystem.h new file mode 100755 index 0000000..a37a90b --- /dev/null +++ b/jni/desmume/src/cheatSystem.h @@ -0,0 +1,195 @@ +/* + Copyright (C) 2009-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include <string.h> +#include "common.h" +#include <vector> + +#define CHEAT_VERSION_MAJOR 2 +#define CHEAT_VERSION_MINOR 0 +#define MAX_CHEAT_LIST 100 +#define MAX_XX_CODE 1024 +#define CHEAT_FILE_MIN_FGETS_BUFFER 32768 +#define CHEAT_DB_GAME_TITLE_SIZE 256 + +struct CHEATS_LIST +{ + CHEATS_LIST() + { + memset(this,0,sizeof(*this)); + type = 0xFF; + } + u8 type; // 0 - internal cheat system + // 1 - Action Replay + // 2 - Codebreakers + BOOL enabled; + // TODO + u8 freezeType; // 0 - normal freeze + // 1 - can decrease + // 2 - can increase + u32 code[MAX_XX_CODE][2]; + char description[1024]; + int num; + u8 size; +}; + +class CHEATS +{ +private: + std::vector<CHEATS_LIST> list; + u8 filename[MAX_PATH]; + u32 currentGet; + + void clear(); + void ARparser(CHEATS_LIST& cheat); + char *clearCode(char *s); + +public: + CHEATS() + : currentGet(0) + { + memset(filename, 0, sizeof(filename)); + } + ~CHEATS() {} + + void init(char *path); + BOOL add(u8 size, u32 address, u32 val, char *description, BOOL enabled); + BOOL update(u8 size, u32 address, u32 val, char *description, BOOL enabled, u32 pos); + BOOL add_AR(char *code, char *description, BOOL enabled); + BOOL update_AR(char *code, char *description, BOOL enabled, u32 pos); + BOOL add_AR_Direct(CHEATS_LIST cheat); + BOOL add_CB(char *code, char *description, BOOL enabled); + BOOL update_CB(char *code, char *description, BOOL enabled, u32 pos); + BOOL remove(u32 pos); + void getListReset(); + BOOL getList(CHEATS_LIST *cheat); + CHEATS_LIST* getListPtr(); + BOOL get(CHEATS_LIST *cheat, u32 pos); + CHEATS_LIST* getItemByIndex(const u32 pos); + u32 getSize(); + void setDescription(const char *description, u32 pos); + BOOL save(); + BOOL load(); + void process(); + void getXXcodeString(CHEATS_LIST cheat, char *res_buf); + + static BOOL XXCodeFromString(CHEATS_LIST *cheatItem, const std::string codeString); + static BOOL XXCodeFromString(CHEATS_LIST *cheatItem, const char *codeString); +}; + +class CHEATSEARCH +{ +private: + u8 *statMem; + u8 *mem; + u32 amount; + u32 lastRecord; + + u32 _type; + u32 _size; + u32 _sign; + +public: + CHEATSEARCH() + : statMem(0), mem(0), amount(0), lastRecord(0), _type(0), _size(0), _sign(0) + {} + ~CHEATSEARCH() { close(); } + BOOL start(u8 type, u8 size, u8 sign); + BOOL close(); + u32 search(u32 val); + u32 search(u8 comp); + u32 getAmount(); + BOOL getList(u32 *address, u32 *curVal); + void getListReset(); +}; + +enum CHEATS_DB_TYPE +{ + CHEATS_DB_R4 = 0 +}; + +#pragma pack(push) +#pragma pack(1) +typedef struct FAT_R4 +{ + u8 serial[4]; + u32 CRC; + u64 addr; +} FAT_R4; +#pragma pack(pop) + +class CHEATSEXPORT +{ +private: + CHEATS_DB_TYPE type; + bool encrypted; + FILE *fp; + u32 fsize; + u32 dataSize; + u32 encOffset; + FAT_R4 fat; + bool search(); + bool getCodes(); + void R4decrypt(u8 *buf, u32 len, u32 n); + + u32 numCheats; + CHEATS_LIST *cheats; + + u8 error; // 0 - no errors + // 1 - open failed/file not found + // 2 - file format is wrong (no valid header ID) + // 3 - cheat not found in database + // 4 - export error from database + +public: + CHEATSEXPORT() : + fp(NULL), + fsize(0), + dataSize(0), + encOffset(0), + type(CHEATS_DB_R4), + encrypted(false), + numCheats(0), + cheats(0), + CRC(0), + error(0) + { + memset(date, 0, sizeof(date)); + gametitle = (u8 *)malloc(CHEAT_DB_GAME_TITLE_SIZE); + memset(gametitle, 0, CHEAT_DB_GAME_TITLE_SIZE); + } + ~CHEATSEXPORT() + { + free(gametitle); + gametitle = NULL; + } + + u8 *gametitle; + u8 date[17]; + u32 CRC; + bool load(char *path); + void close(); + CHEATS_LIST *getCheats(); + u32 getCheatsNum(); + u8 getErrorCode() { return error; } +}; + +extern CHEATS *cheats; +extern CHEATSEARCH *cheatSearch; + + diff --git a/jni/desmume/src/commandline.cpp b/jni/desmume/src/commandline.cpp new file mode 100755 index 0000000..7390a70 --- /dev/null +++ b/jni/desmume/src/commandline.cpp @@ -0,0 +1,272 @@ +/* + Copyright (C) 2009-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +//windows note: make sure this file gets compiled with _cdecl + +#include <glib.h> +#include <algorithm> +#include <stdio.h> +#include "commandline.h" +#include "types.h" +#include "movie.h" +#include "addons.h" +#include "slot1.h" +#include "NDSSystem.h" +#include "utils/xstring.h" + +int scanline_filter_a = 2, scanline_filter_b = 4; +int _commandline_linux_nojoy = 0; + +CommandLine::CommandLine() +: is_cflash_configured(false) +, error(NULL) +, ctx(g_option_context_new ("")) +, _play_movie_file(0) +, _record_movie_file(0) +, _cflash_image(0) +, _cflash_path(0) +, _gbaslot_rom(0) +, _bios_arm9(NULL) +, _bios_arm7(NULL) +, _bios_swi(0) +, _spu_advanced(0) +, _num_cores(-1) +, _rigorous_timing(0) +, _advanced_timing(-1) +, _slot1(NULL) +, _slot1_fat_dir(NULL) +, _console_type(NULL) +, depth_threshold(-1) +, load_slot(-1) +, arm9_gdb_port(0) +, arm7_gdb_port(0) +, start_paused(FALSE) +, autodetect_method(-1) +{ +#ifndef _MSC_VER + disable_sound = 0; + disable_limiter = 0; +#endif +} + +CommandLine::~CommandLine() +{ + if(error) g_error_free (error); + g_option_context_free (ctx); +} + +void CommandLine::loadCommonOptions() +{ + //these options should be available in every port. + //my advice is, do not be afraid of using #ifdef here if it makes sense. + //but also see the gtk port for an example of how to combine this with other options + //(you may need to use ifdefs to cause options to be entered in the desired order) + static const GOptionEntry options[] = { + { "load-slot", 0, 0, G_OPTION_ARG_INT, &load_slot, "Loads savegame from slot NUM", "NUM"}, + { "play-movie", 0, 0, G_OPTION_ARG_FILENAME, &_play_movie_file, "Specifies a dsm format movie to play", "PATH_TO_PLAY_MOVIE"}, + { "record-movie", 0, 0, G_OPTION_ARG_FILENAME, &_record_movie_file, "Specifies a path to a new dsm format movie", "PATH_TO_RECORD_MOVIE"}, + { "start-paused", 0, 0, G_OPTION_ARG_NONE, &start_paused, "Indicates that emulation should start paused", "START_PAUSED"}, + { "cflash-image", 0, 0, G_OPTION_ARG_FILENAME, &_cflash_image, "Requests cflash in gbaslot with fat image at this path", "CFLASH_IMAGE"}, + { "cflash-path", 0, 0, G_OPTION_ARG_FILENAME, &_cflash_path, "Requests cflash in gbaslot with filesystem rooted at this path", "CFLASH_PATH"}, + { "gbaslot-rom", 0, 0, G_OPTION_ARG_FILENAME, &_gbaslot_rom, "Requests this GBA rom in gbaslot", "GBASLOT_ROM"}, + { "bios-arm9", 0, 0, G_OPTION_ARG_FILENAME, &_bios_arm9, "Uses the arm9 bios provided at the specified path", "BIOS_ARM9_PATH"}, + { "bios-arm7", 0, 0, G_OPTION_ARG_FILENAME, &_bios_arm7, "Uses the arm7 bios provided at the specified path", "BIOS_ARM7_PATH"}, + { "bios-swi", 0, 0, G_OPTION_ARG_INT, &_bios_swi, "Uses SWI from the provided bios files", "BIOS_SWI"}, + { "spu-advanced", 0, 0, G_OPTION_ARG_INT, &_spu_advanced, "Uses advanced SPU capture functions", "SPU_ADVANCED"}, + { "num-cores", 0, 0, G_OPTION_ARG_INT, &_num_cores, "Override numcores detection and use this many", "NUM_CORES"}, + { "scanline-filter-a", 0, 0, G_OPTION_ARG_INT, &scanline_filter_a, "Intensity of fadeout for scanlines filter (edge) (default 2)", "SCANLINE_FILTER_A"}, + { "scanline-filter-b", 0, 0, G_OPTION_ARG_INT, &scanline_filter_b, "Intensity of fadeout for scanlines filter (corner) (default 4)", "SCANLINE_FILTER_B"}, + { "rigorous-timing", 0, 0, G_OPTION_ARG_INT, &_rigorous_timing, "Use some rigorous timings instead of unrealistically generous (default 0)", "RIGOROUS_TIMING"}, + { "advanced-timing", 0, 0, G_OPTION_ARG_INT, &_advanced_timing, "Use advanced BUS-level timing (default 1)", "ADVANCED_TIMING"}, + { "slot1", 0, 0, G_OPTION_ARG_STRING, &_slot1, "Device to load in slot 1 (default retail)", "SLOT1"}, + { "slot1-fat-dir", 0, 0, G_OPTION_ARG_STRING, &_slot1_fat_dir, "Directory to scan for slot 1", "SLOT1_DIR"}, + { "depth-threshold", 0, 0, G_OPTION_ARG_INT, &depth_threshold, "Depth comparison threshold (default 0)", "DEPTHTHRESHOLD"}, + { "console-type", 0, 0, G_OPTION_ARG_STRING, &_console_type, "Select console type: {fat,lite,ique,debug,dsi}", "CONSOLETYPE" }, +#ifndef _MSC_VER + { "disable-sound", 0, 0, G_OPTION_ARG_NONE, &disable_sound, "Disables the sound emulation", NULL}, + { "disable-limiter", 0, 0, G_OPTION_ARG_NONE, &disable_limiter, "Disables the 60fps limiter", NULL}, + { "nojoy", 0, 0, G_OPTION_ARG_INT, &_commandline_linux_nojoy, "Disables joystick support", "NOJOY"}, +#endif +#ifdef GDB_STUB + { "arm9gdb", 0, 0, G_OPTION_ARG_INT, &arm9_gdb_port, "Enable the ARM9 GDB stub on the given port", "PORT_NUM"}, + { "arm7gdb", 0, 0, G_OPTION_ARG_INT, &arm7_gdb_port, "Enable the ARM7 GDB stub on the given port", "PORT_NUM"}, +#endif + { "autodetect_method", 0, 0, G_OPTION_ARG_INT, &autodetect_method, "Autodetect backup method (0 - internal, 1 - from database)", "AUTODETECT_METHOD"}, + { NULL } + }; + + g_option_context_add_main_entries (ctx, options, "options"); +} + +static char mytoupper(char c) { return ::toupper(c); } + +bool CommandLine::parse(int argc,char **argv) +{ + g_option_context_parse (ctx, &argc, &argv, &error); + if (error) + { + g_printerr("Error parsing command line arguments: %s\n", error->message); + return false; + } + + if(_slot1_fat_dir) slot1_fat_dir = _slot1_fat_dir; + if(_slot1) slot1 = _slot1; + if(_console_type) console_type = _console_type; + if(slot1.size() != 0) str_lcase((char*)&slot1[0]); + if(_play_movie_file) play_movie_file = _play_movie_file; + if(_record_movie_file) record_movie_file = _record_movie_file; + if(_cflash_image) cflash_image = _cflash_image; + if(_cflash_path) cflash_path = _cflash_path; + if(_gbaslot_rom) gbaslot_rom = _gbaslot_rom; + + if(_num_cores != -1) CommonSettings.num_cores = _num_cores; + if(_rigorous_timing) CommonSettings.rigorous_timing = true; + if(_advanced_timing != -1) CommonSettings.advanced_timing = _advanced_timing==1; + if(depth_threshold != -1) + CommonSettings.GFX3D_Zelda_Shadow_Depth_Hack = depth_threshold; + + + //process console type + CommonSettings.DebugConsole = false; + CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_FAT; + std::transform(console_type.begin(), console_type.end(), console_type.begin(), ::mytoupper); + if(console_type == "") {} + else if(console_type == "FAT") CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_FAT; + else if(console_type == "LITE") CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_LITE; + else if(console_type == "IQUE") CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_IQUE; + else if(console_type == "DSI") CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_DSI; + else if(console_type == "DEBUG") + { + CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_FAT; + CommonSettings.DebugConsole = true; + } + + if (autodetect_method != -1) + CommonSettings.autodetectBackupMethod = autodetect_method; + + //TODO NOT MAX PRIORITY! change ARM9BIOS etc to be a std::string + if(_bios_arm9) { CommonSettings.UseExtBIOS = true; strcpy(CommonSettings.ARM9BIOS,_bios_arm9); } + if(_bios_arm7) { CommonSettings.UseExtBIOS = true; strcpy(CommonSettings.ARM7BIOS,_bios_arm7); } + if(_bios_swi) CommonSettings.SWIFromBIOS = true; + if(_spu_advanced) CommonSettings.spu_advanced = true; + + if (argc == 2) + nds_file = argv[1]; + if (argc > 2) + return false; + + return true; +} + +bool CommandLine::validate() +{ + + + if(slot1 != "") + { + if(slot1 != "r4" && slot1 != "retail" && slot1 != "none") { + g_printerr("Invalid slot1 device specified.\n"); + return false; + } + } + + if (load_slot < -1 || load_slot > 10) { + g_printerr("I only know how to load from slots 0-10; -1 means 'do not load savegame' and is default\n"); + return false; + } + + if(play_movie_file != "" && record_movie_file != "") { + g_printerr("Cannot both play and record a movie.\n"); + return false; + } + + if(record_movie_file != "" && load_slot != -1) { + g_printerr("Cannot both record a movie and load a savestate.\n"); + return false; + } + + if(cflash_path != "" && cflash_image != "") { + g_printerr("Cannot specify both cflash-image and cflash-path.\n"); + return false; + } + + if((_bios_arm9 && !_bios_arm7) || (_bios_arm7 && !_bios_arm9)) { + g_printerr("If either bios-arm7 or bios-arm9 are specified, both must be.\n"); + return false; + } + + if(_bios_swi && (!_bios_arm7 || !_bios_arm9)) { + g_printerr("If either bios-swi is used, bios-arm9 and bios-arm7 must be specified.\n"); + } + + if((_cflash_image && _gbaslot_rom) || (_cflash_path && _gbaslot_rom)) { + g_printerr("Cannot specify both cflash and gbaslot rom (both occupy SLOT-2)\n"); + } + + if (autodetect_method < -1 || autodetect_method > 1) { + g_printerr("Invalid autodetect save method (0 - internal, 1 - from database)\n"); + } + + + return true; +} + +void CommandLine::errorHelp(const char* binName) +{ + //TODO - strip this down to just the filename + g_printerr("USAGE: %s [options] [nds-file]\n", binName); + g_printerr("USAGE: %s --help - for help\n", binName); +} + +void CommandLine::process_movieCommands() +{ + if(play_movie_file != "") + { + FCEUI_LoadMovie(play_movie_file.c_str(),true,false,-1); + } + else if(record_movie_file != "") + { + FCEUI_SaveMovie(record_movie_file.c_str(), L"", 0, NULL, FCEUI_MovieGetRTCDefault()); + } +} + +void CommandLine::process_addonCommands() +{ + if (cflash_image != "") + { + CFlash_Mode = ADDON_CFLASH_MODE_File; + CFlash_Path = cflash_image; + is_cflash_configured = true; + } + if (cflash_path != "") + { + CFlash_Mode = ADDON_CFLASH_MODE_Path; + CFlash_Path = cflash_path; + is_cflash_configured = true; + } + + if(slot1_fat_dir != "") + slot1SetFatDir(slot1_fat_dir); + + if(slot1 == "retail") + slot1Change(NDS_SLOT1_RETAIL); + else if(slot1 == "r4") + slot1Change(NDS_SLOT1_R4); + else if(slot1 == "retailNAND") + slot1Change(NDS_SLOT1_RETAIL_NAND); +} + diff --git a/jni/desmume/src/commandline.h b/jni/desmume/src/commandline.h new file mode 100755 index 0000000..0707790 --- /dev/null +++ b/jni/desmume/src/commandline.h @@ -0,0 +1,97 @@ +/* + Copyright (C) 2009-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _COMMANDLINE_H_ +#define _COMMANDLINE_H_ + +#include <string> + +//I hate C. we have to forward declare these with more detail than I like +typedef struct _GOptionContext GOptionContext; +typedef struct _GError GError; + +//hacky commandline options that i didnt want to route through commonoptions +extern int _commandline_linux_nojoy; + +//this class will also eventually try to take over the responsibility of using the args that it handles +//for example: preparing the emulator run by loading the rom, savestate, and/or movie in the correct pattern. +//it should also populate CommonSettings with its initial values + +class CommandLine +{ +public: + //actual options: these may move to another sturct + int load_slot; + int depth_threshold; + int autodetect_method; + std::string nds_file; + std::string play_movie_file; + std::string record_movie_file; + int arm9_gdb_port, arm7_gdb_port; + int start_paused; + std::string cflash_image; + std::string cflash_path; + std::string gbaslot_rom; + std::string slot1; + std::string console_type; + std::string slot1_fat_dir; +#ifndef _MSC_VER + int disable_sound; + int disable_limiter; +#endif + + //load up the common commandline options + void loadCommonOptions(); + + bool parse(int argc,char **argv); + + //validate the common commandline options + bool validate(); + + //process movie play/record commands + void process_movieCommands(); + //etc. + void process_addonCommands(); + bool is_cflash_configured; + + //print a little help message for cases when erroneous commandlines are entered + void errorHelp(const char* binName); + + CommandLine(); + ~CommandLine(); + + GError *error; + GOptionContext *ctx; + +private: + char* _play_movie_file; + char* _record_movie_file; + char* _cflash_image; + char* _cflash_path; + char* _gbaslot_rom; + char* _bios_arm9, *_bios_arm7; + int _bios_swi; + int _spu_advanced; + int _num_cores; + int _rigorous_timing; + int _advanced_timing; + char* _slot1; + char *_slot1_fat_dir; + char* _console_type; +}; + +#endif diff --git a/jni/desmume/src/common.cpp b/jni/desmume/src/common.cpp new file mode 100755 index 0000000..7963a4d --- /dev/null +++ b/jni/desmume/src/common.cpp @@ -0,0 +1,66 @@ +/* + Copyright (C) 2008-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +//TODO - move this into ndssystem where it belongs probably + +#include <string.h> +#include <string> +#include "common.h" + +const u8 logo_data[156] = { + 0x24,0xFF,0xAE,0x51,0x69,0x9A,0xA2,0x21,0x3D,0x84,0x82,0x0A,0x84,0xE4,0x09,0xAD, + 0x11,0x24,0x8B,0x98,0xC0,0x81,0x7F,0x21,0xA3,0x52,0xBE,0x19,0x93,0x09,0xCE,0x20, + 0x10,0x46,0x4A,0x4A,0xF8,0x27,0x31,0xEC,0x58,0xC7,0xE8,0x33,0x82,0xE3,0xCE,0xBF, + 0x85,0xF4,0xDF,0x94,0xCE,0x4B,0x09,0xC1,0x94,0x56,0x8A,0xC0,0x13,0x72,0xA7,0xFC, + 0x9F,0x84,0x4D,0x73,0xA3,0xCA,0x9A,0x61,0x58,0x97,0xA3,0x27,0xFC,0x03,0x98,0x76, + 0x23,0x1D,0xC7,0x61,0x03,0x04,0xAE,0x56,0xBF,0x38,0x84,0x00,0x40,0xA7,0x0E,0xFD, + 0xFF,0x52,0xFE,0x03,0x6F,0x95,0x30,0xF1,0x97,0xFB,0xC0,0x85,0x60,0xD6,0x80,0x25, + 0xA9,0x63,0xBE,0x03,0x01,0x4E,0x38,0xE2,0xF9,0xA2,0x34,0xFF,0xBB,0x3E,0x03,0x44, + 0x78,0x00,0x90,0xCB,0x88,0x11,0x3A,0x94,0x65,0xC0,0x7C,0x63,0x87,0xF0,0x3C,0xAF, + 0xD6,0x25,0xE4,0x8B,0x38,0x0A,0xAC,0x72,0x21,0xD4,0xF8,0x07}; + +char *trim(char *s, int len) +{ + char *ptr = NULL; + if (!s) return NULL; + if (!*s) return s; + + if(len==-1) + ptr = s + strlen(s) - 1; + else ptr = s+len - 1; + for (; (ptr >= s) && (!*ptr || isspace((u8)*ptr)) ; ptr--); + ptr[1] = '\0'; + return s; +} + +char *removeSpecialChars(char *s) +{ + char *buf = s; + if (!s) return NULL; + if (!*s) return s; + + for (u32 i = 0; i < strlen(s); i++) + { + if (isspace((u8)s[i]) && (s[i] != 0x20)) + *buf = 0x20; + else + *buf = s[i]; + buf++; + } + *buf = 0; + return s; +} diff --git a/jni/desmume/src/common.h b/jni/desmume/src/common.h new file mode 100755 index 0000000..66c56f8 --- /dev/null +++ b/jni/desmume/src/common.h @@ -0,0 +1,85 @@ +/* + Copyright (C) 2008-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +//TODO - dismantle this file + +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#include <stdio.h> +#include <string.h> +#include "types.h" +#include <string> + +extern const u8 logo_data[156]; + +#if defined(WIN32) + + #include <winsock2.h> + #include <windows.h> + + + #define CLASSNAME "DeSmuME" + + extern HINSTANCE hAppInst; + + extern bool romloaded; + + extern char IniName[MAX_PATH]; + extern void GetINIPath(); + extern void WritePrivateProfileInt(char* appname, char* keyname, int val, char* file); + + bool GetPrivateProfileBool(const char* appname, const char* keyname, bool defval, const char* filename); + void WritePrivateProfileBool(char* appname, char* keyname, bool val, char* file); + +#else // non Windows + +#define sscanf_s sscanf + +#endif + +template<typename T> +T reverseBits(T x) +{ + T h = 0; + T i = 0; + + for (i = 0; i < sizeof(T)*8; i++) + { + h = (h << 1) + (x & 1); + x >>= 1; + } + + return h; +} + +template<typename T> +char *intToBin(T val) +{ + char buf[256] = {0}; + for (int i = sizeof(T)*8, t = 0; i > 0; --i, t++) + { + buf[i-1] = (val & (1<<t))?'1':'0'; + } + return strdup(buf); +} + +extern char *trim(char *s, int len=-1); +extern char *removeSpecialChars(char *s); + +#endif + diff --git a/jni/desmume/src/cp15.cpp b/jni/desmume/src/cp15.cpp new file mode 100755 index 0000000..1dfa6fe --- /dev/null +++ b/jni/desmume/src/cp15.cpp @@ -0,0 +1,572 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2006-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> + +#include "cp15.h" +#include "debug.h" +#include "MMU.h" + +armcp15_t *armcp15_new(armcpu_t * c) +{ + int i; + armcp15_t *armcp15 = (armcp15_t*)malloc(sizeof(armcp15_t)); + if(!armcp15) return NULL; + + + armcp15->cpu = c; + armcp15->IDCode = 0x41059461; + armcp15->cacheType = 0x0F0D2112; + armcp15->TCMSize = 0x00140180; + armcp15->ctrl = 0x00012078; + armcp15->DCConfig = 0x0; + armcp15->ICConfig = 0x0; + armcp15->writeBuffCtrl = 0x0; + armcp15->und = 0x0; + armcp15->DaccessPerm = 0x22222222; + armcp15->IaccessPerm = 0x22222222; + armcp15->protectBaseSize0 = 0x0; + armcp15->protectBaseSize1 = 0x0; + armcp15->protectBaseSize2 = 0x0; + armcp15->protectBaseSize3 = 0x0; + armcp15->protectBaseSize4 = 0x0; + armcp15->protectBaseSize5 = 0x0; + armcp15->protectBaseSize6 = 0x0; + armcp15->protectBaseSize7 = 0x0; + armcp15->cacheOp = 0x0; + armcp15->DcacheLock = 0x0; + armcp15->IcacheLock = 0x0; + armcp15->ITCMRegion = 0x0C; + armcp15->DTCMRegion = 0x0080000A; + armcp15->processID = 0; + + MMU.ARM9_RW_MODE = BIT7(armcp15->ctrl); + armcp15->cpu->intVector = 0xFFFF0000 * (BIT13(armcp15->ctrl)); + armcp15->cpu->LDTBit = !BIT15(armcp15->ctrl); //TBit + + /* preset calculated regionmasks */ + for (i=0;i<8;i++) { + armcp15->regionWriteMask_USR[i] = 0 ; + armcp15->regionWriteMask_SYS[i] = 0 ; + armcp15->regionReadMask_USR[i] = 0 ; + armcp15->regionReadMask_SYS[i] = 0 ; + armcp15->regionExecuteMask_USR[i] = 0 ; + armcp15->regionExecuteMask_SYS[i] = 0 ; + armcp15->regionWriteSet_USR[i] = 0 ; + armcp15->regionWriteSet_SYS[i] = 0 ; + armcp15->regionReadSet_USR[i] = 0 ; + armcp15->regionReadSet_SYS[i] = 0 ; + armcp15->regionExecuteSet_USR[i] = 0 ; + armcp15->regionExecuteSet_SYS[i] = 0 ; + } ; + + return armcp15; +} + +#define ACCESSTYPE(val,n) (((val) >> (4*n)) & 0x0F) +#define SIZEIDENTIFIER(val) ((((val) >> 1) & 0x1F)) +#define SIZEBINARY(val) (1 << (SIZEIDENTIFIER(val)+1)) +#define MASKFROMREG(val) (~((SIZEBINARY(val)-1) | 0x3F)) +#define SETFROMREG(val) ((val) & MASKFROMREG(val)) +/* sets the precalculated regions to mask,set for the affected accesstypes */ +static void armcp15_setSingleRegionAccess(armcp15_t *armcp15,u32 dAccess,u32 iAccess,unsigned char num, u32 mask,u32 set) { + + switch (ACCESSTYPE(dAccess,num)) { + case 4: /* UNP */ + case 7: /* UNP */ + case 8: /* UNP */ + case 9: /* UNP */ + case 10: /* UNP */ + case 11: /* UNP */ + case 12: /* UNP */ + case 13: /* UNP */ + case 14: /* UNP */ + case 15: /* UNP */ + case 0: /* no access at all */ + armcp15->regionWriteMask_USR[num] = 0 ; + armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_USR[num] = 0 ; + armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionWriteMask_SYS[num] = 0 ; + armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_SYS[num] = 0 ; + armcp15->regionReadSet_SYS[num] = 0xFFFFFFFF ; + break ; + case 1: /* no access at USR, all to sys */ + armcp15->regionWriteMask_USR[num] = 0 ; + armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_USR[num] = 0 ; + armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionWriteMask_SYS[num] = mask ; + armcp15->regionWriteSet_SYS[num] = set ; + armcp15->regionReadMask_SYS[num] = mask ; + armcp15->regionReadSet_SYS[num] = set ; + break ; + case 2: /* read at USR, all to sys */ + armcp15->regionWriteMask_USR[num] = 0 ; + armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_USR[num] = mask ; + armcp15->regionReadSet_USR[num] = set ; + armcp15->regionWriteMask_SYS[num] = mask ; + armcp15->regionWriteSet_SYS[num] = set ; + armcp15->regionReadMask_SYS[num] = mask ; + armcp15->regionReadSet_SYS[num] = set ; + break ; + case 3: /* all to USR, all to sys */ + armcp15->regionWriteMask_USR[num] = mask ; + armcp15->regionWriteSet_USR[num] = set ; + armcp15->regionReadMask_USR[num] = mask ; + armcp15->regionReadSet_USR[num] = set ; + armcp15->regionWriteMask_SYS[num] = mask ; + armcp15->regionWriteSet_SYS[num] = set ; + armcp15->regionReadMask_SYS[num] = mask ; + armcp15->regionReadSet_SYS[num] = set ; + break ; + case 5: /* no access at USR, read to sys */ + armcp15->regionWriteMask_USR[num] = 0 ; + armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_USR[num] = 0 ; + armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionWriteMask_SYS[num] = 0 ; + armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_SYS[num] = mask ; + armcp15->regionReadSet_SYS[num] = set ; + break ; + case 6: /* read at USR, read to sys */ + armcp15->regionWriteMask_USR[num] = 0 ; + armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_USR[num] = mask ; + armcp15->regionReadSet_USR[num] = set ; + armcp15->regionWriteMask_SYS[num] = 0 ; + armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_SYS[num] = mask ; + armcp15->regionReadSet_SYS[num] = set ; + break ; + } + switch (ACCESSTYPE(iAccess,num)) { + case 4: /* UNP */ + case 7: /* UNP */ + case 8: /* UNP */ + case 9: /* UNP */ + case 10: /* UNP */ + case 11: /* UNP */ + case 12: /* UNP */ + case 13: /* UNP */ + case 14: /* UNP */ + case 15: /* UNP */ + case 0: /* no access at all */ + armcp15->regionExecuteMask_USR[num] = 0 ; + armcp15->regionExecuteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionExecuteMask_SYS[num] = 0 ; + armcp15->regionExecuteSet_SYS[num] = 0xFFFFFFFF ; + break ; + case 1: + armcp15->regionExecuteMask_USR[num] = 0 ; + armcp15->regionExecuteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionExecuteMask_SYS[num] = mask ; + armcp15->regionExecuteSet_SYS[num] = set ; + break ; + case 2: + case 3: + case 6: + armcp15->regionExecuteMask_USR[num] = mask ; + armcp15->regionExecuteSet_USR[num] = set ; + armcp15->regionExecuteMask_SYS[num] = mask ; + armcp15->regionExecuteSet_SYS[num] = set ; + break ; + } +} ; + +/* precalculate region masks/sets from cp15 register */ +static void armcp15_maskPrecalc(armcp15_t *armcp15) +{ +#define precalc(num) { \ + u32 mask = 0, set = 0xFFFFFFFF ; /* (x & 0) == 0xFF..FF is allways false (disabled) */ \ + if (BIT_N(armcp15->protectBaseSize##num,0)) /* if region is enabled */ \ + { /* reason for this define: naming includes var */ \ + mask = MASKFROMREG(armcp15->protectBaseSize##num) ; \ + set = SETFROMREG(armcp15->protectBaseSize##num) ; \ + if (SIZEIDENTIFIER(armcp15->protectBaseSize##num)==0x1F) \ + { /* for the 4GB region, u32 suffers wraparound */ \ + mask = 0 ; set = 0 ; /* (x & 0) == 0 is allways true (enabled) */ \ +} \ +} \ + armcp15_setSingleRegionAccess(armcp15,armcp15->DaccessPerm,armcp15->IaccessPerm,num,mask,set) ; \ +} + precalc(0) ; + precalc(1) ; + precalc(2) ; + precalc(3) ; + precalc(4) ; + precalc(5) ; + precalc(6) ; + precalc(7) ; +} + +BOOL armcp15_isAccessAllowed(armcp15_t *armcp15,u32 address,u32 access) +{ + int i ; + if (!(armcp15->ctrl & 1)) return TRUE ; /* protection checking is not enabled */ + for (i=0;i<8;i++) { + switch (access) { + case CP15_ACCESS_WRITEUSR: + if ((address & armcp15->regionWriteMask_USR[i]) == armcp15->regionWriteSet_USR[i]) return TRUE ; + break ; + case CP15_ACCESS_WRITESYS: + if ((address & armcp15->regionWriteMask_SYS[i]) == armcp15->regionWriteSet_SYS[i]) return TRUE ; + break ; + case CP15_ACCESS_READUSR: + if ((address & armcp15->regionReadMask_USR[i]) == armcp15->regionReadSet_USR[i]) return TRUE ; + break ; + case CP15_ACCESS_READSYS: + if ((address & armcp15->regionReadMask_SYS[i]) == armcp15->regionReadSet_SYS[i]) return TRUE ; + break ; + case CP15_ACCESS_EXECUSR: + if ((address & armcp15->regionExecuteMask_USR[i]) == armcp15->regionExecuteSet_USR[i]) return TRUE ; + break ; + case CP15_ACCESS_EXECSYS: + if ((address & armcp15->regionExecuteMask_SYS[i]) == armcp15->regionExecuteSet_SYS[i]) return TRUE ; + break ; + } + } + /* when protections are enabled, but no region allows access, deny access */ + return FALSE ; +} + +BOOL armcp15_dataProcess(armcp15_t *armcp15, u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2) +{ + LOG("Unsupported CP15 operation : DataProcess\n"); + return FALSE; +} + +BOOL armcp15_load(armcp15_t *armcp15, u8 CRd, u8 adr) +{ + LOG("Unsupported CP15 operation : Load\n"); + return FALSE; +} + +BOOL armcp15_store(armcp15_t *armcp15, u8 CRd, u8 adr) +{ + LOG("Unsupported CP15 operation : Store\n"); + return FALSE; +} + +BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2) +{ + if(armcp15->cpu->CPSR.bits.mode == USR) return FALSE; + + switch(CRn) + { + case 0: + if((opcode1 == 0)&&(CRm==0)) + { + switch(opcode2) + { + case 1: + *R = armcp15->cacheType; + return TRUE; + case 2: + *R = armcp15->TCMSize; + return TRUE; + default: + *R = armcp15->IDCode; + return TRUE; + } + } + return FALSE; + case 1: + if((opcode1==0) && (opcode2==0) && (CRm==0)) + { + *R = armcp15->ctrl; + //LOG("CP15: CPtoARM ctrl %08X\n", armcp15->ctrl); + return TRUE; + } + return FALSE; + + case 2: + if((opcode1==0) && (CRm==0)) + { + switch(opcode2) + { + case 0: + *R = armcp15->DCConfig; + return TRUE; + case 1: + *R = armcp15->ICConfig; + return TRUE; + default: + return FALSE; + } + } + return FALSE; + case 3: + if((opcode1==0) && (opcode2==0) && (CRm==0)) + { + *R = armcp15->writeBuffCtrl; + //LOG("CP15: CPtoARM writeBuffer ctrl %08X\n", armcp15->writeBuffCtrl); + return TRUE; + } + return FALSE; + case 5: + if((opcode1==0) && (CRm==0)) + { + switch(opcode2) + { + case 2: + *R = armcp15->DaccessPerm; + return TRUE; + case 3: + *R = armcp15->IaccessPerm; + return TRUE; + default: + return FALSE; + } + } + return FALSE; + case 6: + if((opcode1==0) && (opcode2==0)) + { + switch(CRm) + { + case 0: + *R = armcp15->protectBaseSize0; + return TRUE; + case 1: + *R = armcp15->protectBaseSize1; + return TRUE; + case 2: + *R = armcp15->protectBaseSize2; + return TRUE; + case 3: + *R = armcp15->protectBaseSize3; + return TRUE; + case 4: + *R = armcp15->protectBaseSize4; + return TRUE; + case 5: + *R = armcp15->protectBaseSize5; + return TRUE; + case 6: + *R = armcp15->protectBaseSize6; + return TRUE; + case 7: + *R = armcp15->protectBaseSize7; + return TRUE; + default: + return FALSE; + } + } + return FALSE; + case 9: + if((opcode1==0)) + { + switch(CRm) + { + case 0: + switch(opcode2) + { + case 0: + *R = armcp15->DcacheLock; + return TRUE; + case 1: + *R = armcp15->IcacheLock; + return TRUE; + default: + return FALSE; + } + case 1: + switch(opcode2) + { + case 0: + *R = armcp15->DTCMRegion; + return TRUE; + case 1: + *R = armcp15->ITCMRegion; + return TRUE; + default: + return FALSE; + } + } + } + return FALSE; + default: + LOG("Unsupported CP15 operation : MRC\n"); + return FALSE; + } +} + +static u32 CP15wait4IRQ(armcpu_t *cpu) +{ + cpu->waitIRQ = TRUE; + cpu->halt_IE_and_IF = TRUE; + //IME set deliberately omitted: only SWI sets IME to 1 + return 1; +} + +BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2) +{ + if(armcp15->cpu->CPSR.bits.mode == USR) return FALSE; + + switch(CRn) + { + case 1: + if((opcode1==0) && (opcode2==0) && (CRm==0)) + { + + //On the NDS bit0,2,7,12..19 are R/W, Bit3..6 are always set, all other bits are always zero. + armcp15->ctrl = (val & 0x000FF085) | 0x00000078; + MMU.ARM9_RW_MODE = BIT7(val); + //zero 31-jan-2010: change from 0x0FFF0000 to 0xFFFF0000 per gbatek + armcp15->cpu->intVector = 0xFFFF0000 * (BIT13(val)); + armcp15->cpu->LDTBit = !BIT15(val); //TBit + //LOG("CP15: ARMtoCP ctrl %08X (val %08X)\n", armcp15->ctrl, val); + return TRUE; + } + return FALSE; + case 2: + if((opcode1==0) && (CRm==0)) + { + switch(opcode2) + { + case 0: + armcp15->DCConfig = val; + return TRUE; + case 1: + armcp15->ICConfig = val; + return TRUE; + default: + return FALSE; + } + } + return FALSE; + case 3: + if((opcode1==0) && (opcode2==0) && (CRm==0)) + { + armcp15->writeBuffCtrl = val; + //LOG("CP15: ARMtoCP writeBuffer ctrl %08X\n", armcp15->writeBuffCtrl); + return TRUE; + } + return FALSE; + case 5: + if((opcode1==0) && (CRm==0)) + { + switch(opcode2) + { + case 2: + armcp15->DaccessPerm = val; + armcp15_maskPrecalc(armcp15); + return TRUE; + case 3: + armcp15->IaccessPerm = val; + armcp15_maskPrecalc(armcp15); + return TRUE; + default: + return FALSE; + } + } + return FALSE; + case 6: + if((opcode1==0) && (opcode2==0)) + { + switch(CRm) + { + case 0: + armcp15->protectBaseSize0 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 1: + armcp15->protectBaseSize1 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 2: + armcp15->protectBaseSize2 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 3: + armcp15->protectBaseSize3 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 4: + armcp15->protectBaseSize4 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 5: + armcp15->protectBaseSize5 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 6: + armcp15->protectBaseSize6 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 7: + armcp15->protectBaseSize7 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + default: + return FALSE; + } + } + return FALSE; + case 7: + if((CRm==0)&&(opcode1==0)&&((opcode2==4))) + { + CP15wait4IRQ(armcp15->cpu); + return TRUE; + } + return FALSE; + case 9: + if((opcode1==0)) + { + switch(CRm) + { + case 0: + switch(opcode2) + { + case 0: + armcp15->DcacheLock = val; + return TRUE; + case 1: + armcp15->IcacheLock = val; + return TRUE; + default: + return FALSE; + } + case 1: + switch(opcode2) + { + case 0: + MMU.DTCMRegion = armcp15->DTCMRegion = val & 0x0FFFF000; + return TRUE; + case 1: + armcp15->ITCMRegion = val; + //ITCM base is not writeable! + MMU.ITCMRegion = 0; + return TRUE; + default: + return FALSE; + } + } + } + return FALSE; + default: + return FALSE; + } +} + + + diff --git a/jni/desmume/src/cp15.h b/jni/desmume/src/cp15.h new file mode 100755 index 0000000..90d1b6a --- /dev/null +++ b/jni/desmume/src/cp15.h @@ -0,0 +1,91 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2006-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __CP15_H__ +#define __CP15_H__ + +#include "armcpu.h" + +struct armcp15_t +{ + u32 IDCode; + u32 cacheType; + u32 TCMSize; + u32 ctrl; + u32 DCConfig; + u32 ICConfig; + u32 writeBuffCtrl; + u32 und; + u32 DaccessPerm; + u32 IaccessPerm; + u32 protectBaseSize0; + u32 protectBaseSize1; + u32 protectBaseSize2; + u32 protectBaseSize3; + u32 protectBaseSize4; + u32 protectBaseSize5; + u32 protectBaseSize6; + u32 protectBaseSize7; + u32 cacheOp; + u32 DcacheLock; + u32 IcacheLock; + u32 ITCMRegion; + u32 DTCMRegion; + u32 processID; + u32 RAM_TAG; + u32 testState; + u32 cacheDbg; + /* calculated bitmasks for the regions to decide rights uppon */ + /* calculation is done in the MCR instead of on mem access for performance */ + u32 regionWriteMask_USR[8] ; + u32 regionWriteMask_SYS[8] ; + u32 regionReadMask_USR[8] ; + u32 regionReadMask_SYS[8] ; + u32 regionExecuteMask_USR[8] ; + u32 regionExecuteMask_SYS[8] ; + u32 regionWriteSet_USR[8] ; + u32 regionWriteSet_SYS[8] ; + u32 regionReadSet_USR[8] ; + u32 regionReadSet_SYS[8] ; + u32 regionExecuteSet_USR[8] ; + u32 regionExecuteSet_SYS[8] ; + + armcpu_t * cpu; + +}; + +armcp15_t *armcp15_new(armcpu_t *c); +BOOL armcp15_dataProcess(armcp15_t *armcp15, u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2); +BOOL armcp15_load(armcp15_t *armcp15, u8 CRd, u8 adr); +BOOL armcp15_store(armcp15_t *armcp15, u8 CRd, u8 adr); +BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2); +BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2); +BOOL armcp15_isAccessAllowed(armcp15_t *armcp15,u32 address,u32 access); + + +#define CP15_ACCESS_WRITE 0 +#define CP15_ACCESS_READ 2 +#define CP15_ACCESS_EXECUTE 4 +#define CP15_ACCESS_WRITEUSR CP15_ACCESS_WRITE +#define CP15_ACCESS_WRITESYS 1 +#define CP15_ACCESS_READUSR CP15_ACCESS_READ +#define CP15_ACCESS_READSYS 3 +#define CP15_ACCESS_EXECUSR CP15_ACCESS_EXECUTE +#define CP15_ACCESS_EXECSYS 5 + +#endif /* __CP15_H__*/ diff --git a/jni/desmume/src/ctrlssdl.cpp b/jni/desmume/src/ctrlssdl.cpp new file mode 100755 index 0000000..8590a5f --- /dev/null +++ b/jni/desmume/src/ctrlssdl.cpp @@ -0,0 +1,553 @@ +/* + Copyright (C) 2007 Pascal Giard + Copyright (C) 2007-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "ctrlssdl.h" +#include "saves.h" +#include "SPU.h" +#include "commandline.h" +#include "NDSSystem.h" +#include "GPU_osd.h" +#ifdef FAKE_MIC +#include "mic.h" +#endif + +u16 keyboard_cfg[NB_KEYS]; +u16 joypad_cfg[NB_KEYS]; +u16 nbr_joy; +mouse_status mouse; + +static SDL_Joystick **open_joysticks = NULL; + +/* Keypad key names */ +const char *key_names[NB_KEYS] = +{ + "A", "B", "Select", "Start", + "Right", "Left", "Up", "Down", + "R", "L", "X", "Y", + "Debug", "Boost" +}; + +/* Joypad Key Codes -- 4-digit Hexadecimal number + * 1st digit: device ID (0 is first joypad, 1 is second, etc.) + * 2nd digit: 0 - Axis, 1 - Hat/POV/D-Pad, 2 - Button + * 3rd & 4th digit: (depends on input type) + * Negative Axis - 2 * axis index + * Positive Axis - 2 * axis index + 1 + * Hat Right - 4 * hat index + * Hat Left - 4 * hat index + 1 + * Hat Up - 4 * hat index + 2 + * Hat Down - 4 * hat index + 3 + * Button - button index + */ + +/* Default joypad configuration */ +const u16 default_joypad_cfg[NB_KEYS] = + { 0x0201, // A + 0x0200, // B + 0x0205, // select + 0x0208, // start + 0x0001, // Right + 0x0000, // Left + 0x0002, // Up + 0x0003, // Down + 0x0207, // R + 0x0206, // L + 0x0204, // X + 0x0203, // Y + 0xFFFF, // DEBUG + 0xFFFF // BOOST + }; + +/* Load default joystick and keyboard configurations */ +void load_default_config(const u16 kbCfg[]) +{ + memcpy(keyboard_cfg, kbCfg, sizeof(keyboard_cfg)); + memcpy(joypad_cfg, default_joypad_cfg, sizeof(joypad_cfg)); +} + +/* Set all buttons at once */ +static void set_joy_keys(const u16 joyCfg[]) +{ + memcpy(joypad_cfg, joyCfg, sizeof(joypad_cfg)); +} + +/* Initialize joysticks */ +BOOL init_joy( void) { + int i; + BOOL joy_init_good = TRUE; + + //user asked for no joystick + if(_commandline_linux_nojoy) { + printf("skipping joystick init\n"); + return TRUE; + } + + set_joy_keys(default_joypad_cfg); + + if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) + { + fprintf(stderr, "Error trying to initialize joystick support: %s\n", + SDL_GetError()); + return FALSE; + } + + nbr_joy = SDL_NumJoysticks(); + + if ( nbr_joy > 0) { + printf("Found %d joysticks\n", nbr_joy); + open_joysticks = + (SDL_Joystick**)calloc( sizeof ( SDL_Joystick *), nbr_joy); + + if ( open_joysticks != NULL) { + for (i = 0; i < nbr_joy; i++) + { + SDL_Joystick * joy = SDL_JoystickOpen(i); + printf("Joystick %d %s\n", i, SDL_JoystickName(i)); + printf("Axes: %d\n", SDL_JoystickNumAxes(joy)); + printf("Buttons: %d\n", SDL_JoystickNumButtons(joy)); + printf("Trackballs: %d\n", SDL_JoystickNumBalls(joy)); + printf("Hats: %d\n\n", SDL_JoystickNumHats(joy)); + } + } + else { + joy_init_good = FALSE; + } + } + + return joy_init_good; +} + +/* Unload joysticks */ +void uninit_joy( void) +{ + int i; + + if ( open_joysticks != NULL) { + for (i = 0; i < SDL_NumJoysticks(); i++) { + SDL_JoystickClose( open_joysticks[i]); + } + + free( open_joysticks); + } + + open_joysticks = NULL; + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); +} + +/* Return keypad vector with given key set to 1 */ +u16 lookup_joy_key (u16 keyval) { + int i; + u16 Key = 0; + + for(i = 0; i < NB_KEYS; i++) + if(keyval == joypad_cfg[i]) { + Key = KEYMASK_(i); + break; + } + + return Key; +} + +/* Return keypad vector with given key set to 1 */ +u16 lookup_key (u16 keyval) { + int i; + u16 Key = 0; + + for(i = 0; i < NB_KEYS; i++) + if(keyval == keyboard_cfg[i]) { + Key = KEYMASK_(i); + break; + } + + return Key; +} + +/* Get pressed joystick key */ +u16 get_joy_key(int index) { + BOOL done = FALSE; + SDL_Event event; + u16 key = joypad_cfg[index]; + + /* Enable joystick events if needed */ + if( SDL_JoystickEventState(SDL_QUERY) == SDL_IGNORE ) + SDL_JoystickEventState(SDL_ENABLE); + + while(SDL_WaitEvent(&event) && !done) + { + switch(event.type) + { + case SDL_JOYBUTTONDOWN: + printf( "Device: %d; Button: %d\n", event.jbutton.which, event.jbutton.button ); + key = ((event.jbutton.which & 15) << 12) | JOY_BUTTON << 8 | (event.jbutton.button & 255); + done = TRUE; + break; + case SDL_JOYAXISMOTION: + /* Dead zone of 50% */ + if( (abs(event.jaxis.value) >> 14) != 0 ) + { + key = ((event.jaxis.which & 15) << 12) | JOY_AXIS << 8 | ((event.jaxis.axis & 127) << 1); + if (event.jaxis.value > 0) { + printf( "Device: %d; Axis: %d (+)\n", event.jaxis.which, event.jaxis.axis ); + key |= 1; + } + else + printf( "Device: %d; Axis: %d (-)\n", event.jaxis.which, event.jaxis.axis ); + done = TRUE; + } + break; + case SDL_JOYHATMOTION: + /* Diagonal positions will be treated as two separate keys being activated, rather than a single diagonal key. */ + /* JOY_HAT_* are sequential integers, rather than a bitmask */ + if (event.jhat.value != SDL_HAT_CENTERED) { + key = ((event.jhat.which & 15) << 12) | JOY_HAT << 8 | ((event.jhat.hat & 63) << 2); + /* Can't just use a switch here because SDL_HAT_* make up a bitmask. We only want one of these when assigning keys. */ + if ((event.jhat.value & SDL_HAT_UP) != 0) { + key |= JOY_HAT_UP; + printf( "Device: %d; Hat: %d (Up)\n", event.jhat.which, event.jhat.hat ); + } + else if ((event.jhat.value & SDL_HAT_RIGHT) != 0) { + key |= JOY_HAT_RIGHT; + printf( "Device: %d; Hat: %d (Right)\n", event.jhat.which, event.jhat.hat ); + } + else if ((event.jhat.value & SDL_HAT_DOWN) != 0) { + key |= JOY_HAT_DOWN; + printf( "Device: %d; Hat: %d (Down)\n", event.jhat.which, event.jhat.hat ); + } + else if ((event.jhat.value & SDL_HAT_LEFT) != 0) { + key |= JOY_HAT_LEFT; + printf( "Device: %d; Hat: %d (Left)\n", event.jhat.which, event.jhat.hat ); + } + done = TRUE; + } + break; + } + } + + if( SDL_JoystickEventState(SDL_QUERY) == SDL_ENABLE ) + SDL_JoystickEventState(SDL_IGNORE); + + return key; +} + +/* Get and set a new joystick key */ +u16 get_set_joy_key(int index) { + joypad_cfg[index] = get_joy_key(index); + + return joypad_cfg[index]; +} + +static signed long +screen_to_touch_range( signed long scr, float size_ratio) { + return (signed long)((float)scr * size_ratio); +} + +/* Set mouse coordinates */ +static void set_mouse_coord(signed long x,signed long y) +{ + if(x<0) x = 0; else if(x>255) x = 255; + if(y<0) y = 0; else if(y>192) y = 192; + mouse.x = x; + mouse.y = y; +} + +/* Update NDS keypad */ +void update_keypad(u16 keys) +{ + NDS_beginProcessingInput(); + UserButtons& input = NDS_getProcessingUserInput().buttons; + input.G = (keys>>12)&1; + input.E = (keys>>8)&1; + input.W = (keys>>9)&1; + input.X = (keys>>10)&1; + input.Y = (keys>>11)&1; + input.A = (keys>>0)&1; + input.B = (keys>>1)&1; + input.S = (keys>>3)&1; + input.T = (keys>>2)&1; + input.U = (keys>>6)&1; + input.D = (keys>>7)&1; + input.L = (keys>>5)&1; + input.R = (keys>>4)&1; + input.F = 0; + NDS_endProcessingInput(); +} + +/* Retrieve current NDS keypad */ +u16 get_keypad( void) +{ + u16 keypad; + keypad = ~MMU.ARM7_REG[0x136]; + keypad = (keypad & 0x3) << 10; +#ifdef WORDS_BIGENDIAN + keypad |= ~(MMU.ARM9_REG[0x130] | (MMU.ARM9_REG[0x131] << 8)) & 0x3FF; +#else + keypad |= ~((u16 *)MMU.ARM9_REG)[0x130>>1] & 0x3FF; +#endif + return keypad; +} + +/* + * The internal joystick events processing function + */ +static int +do_process_joystick_events( u16 *keypad, SDL_Event *event) { + int processed = 1; + u16 key_code; + u16 key; + u16 key_o; + u16 key_u; + u16 key_r; + u16 key_d; + u16 key_l; + + switch ( event->type) + { + /* Joystick axis motion + Note: button constants have a 1bit offset. */ + case SDL_JOYAXISMOTION: + key_code = ((event->jaxis.which & 15) << 12) | JOY_AXIS << 8 | ((event->jaxis.axis & 127) << 1); + if( (abs(event->jaxis.value) >> 14) != 0 ) + { + if (event->jaxis.value > 0) + key_code |= 1; + key = lookup_joy_key( key_code ); + key_o = lookup_joy_key( key_code ^ 1 ); + if (key != 0) + ADD_KEY( *keypad, key ); + if (key_o != 0) + RM_KEY( *keypad, key_o ); + } + else + { + // Axis is zeroed + key = lookup_joy_key( key_code ); + key_o = lookup_joy_key( key_code ^ 1 ); + if (key != 0) + RM_KEY( *keypad, key ); + if (key_o != 0) + RM_KEY( *keypad, key_o ); + } + break; + + case SDL_JOYHATMOTION: + /* Diagonal positions will be treated as two separate keys being activated, rather than a single diagonal key. */ + /* JOY_HAT_* are sequential integers, rather than a bitmask */ + key_code = ((event->jhat.which & 15) << 12) | JOY_HAT << 8 | ((event->jhat.hat & 63) << 2); + key_u = lookup_joy_key( key_code | JOY_HAT_UP ); + key_r = lookup_joy_key( key_code | JOY_HAT_RIGHT ); + key_d = lookup_joy_key( key_code | JOY_HAT_DOWN ); + key_l = lookup_joy_key( key_code | JOY_HAT_LEFT ); + if ((key_u != 0) && ((event->jhat.value & SDL_HAT_UP) != 0)) + ADD_KEY( *keypad, key_u ); + else if (key_u != 0) + RM_KEY( *keypad, key_u ); + if ((key_r != 0) && ((event->jhat.value & SDL_HAT_RIGHT) != 0)) + ADD_KEY( *keypad, key_r ); + else if (key_r != 0) + RM_KEY( *keypad, key_r ); + if ((key_d != 0) && ((event->jhat.value & SDL_HAT_DOWN) != 0)) + ADD_KEY( *keypad, key_d ); + else if (key_d != 0) + RM_KEY( *keypad, key_d ); + if ((key_l != 0) && ((event->jhat.value & SDL_HAT_LEFT) != 0)) + ADD_KEY( *keypad, key_l ); + else if (key_l != 0) + RM_KEY( *keypad, key_l ); + break; + + /* Joystick button pressed */ + /* FIXME: Add support for BOOST */ + case SDL_JOYBUTTONDOWN: + key_code = ((event->jbutton.which & 15) << 12) | JOY_BUTTON << 8 | (event->jbutton.button & 255); + key = lookup_joy_key( key_code ); + if (key != 0) + ADD_KEY( *keypad, key ); + break; + + /* Joystick button released */ + case SDL_JOYBUTTONUP: + key_code = ((event->jbutton.which & 15) << 12) | JOY_BUTTON << 8 | (event->jbutton.button & 255); + key = lookup_joy_key( key_code ); + if (key != 0) + RM_KEY( *keypad, key ); + break; + + default: + processed = 0; + break; + } + + return processed; +} + +/* + * Process only the joystick events + */ +void +process_joystick_events( u16 *keypad) { + SDL_Event event; + + /* IMPORTANT: Reenable joystick events iif needed. */ + if(SDL_JoystickEventState(SDL_QUERY) == SDL_IGNORE) + SDL_JoystickEventState(SDL_ENABLE); + + /* There's an event waiting to be processed? */ + while (SDL_PollEvent(&event)) + { + do_process_joystick_events( keypad, &event); + } +} + +u16 shift_pressed; + +void +process_ctrls_event( SDL_Event& event, + struct ctrls_event_config *cfg) +{ + u16 key; + if ( !do_process_joystick_events( &cfg->keypad, &event)) { + switch (event.type) + { + case SDL_VIDEORESIZE: + cfg->resize_cb( event.resize.w, event.resize.h, cfg->screen_texture); + break; + + case SDL_ACTIVEEVENT: + if (cfg->auto_pause && (event.active.state & SDL_APPINPUTFOCUS )) { + if (event.active.gain) { + cfg->focused = 1; + SPU_Pause(0); + osd->addLine("Auto pause disabled"); + } else { + cfg->focused = 0; + SPU_Pause(1); + } + } + break; + + case SDL_KEYDOWN: + switch(event.key.keysym.sym){ + case SDLK_LSHIFT: + shift_pressed |= 1; + break; + case SDLK_RSHIFT: + shift_pressed |= 2; + break; + default: + key = lookup_key(event.key.keysym.sym); + ADD_KEY( cfg->keypad, key ); + break; + } + break; + + case SDL_KEYUP: + switch(event.key.keysym.sym){ + case SDLK_ESCAPE: + cfg->sdl_quit = 1; + break; + +#ifdef FAKE_MIC + case SDLK_m: + cfg->fake_mic = !cfg->fake_mic; + Mic_DoNoise(cfg->fake_mic); + if (cfg->fake_mic) + osd->addLine("Fake mic enabled"); + else + osd->addLine("Fake mic disabled"); + break; +#endif + + case SDLK_o: + cfg->boost = !cfg->boost; + if (cfg->boost) + osd->addLine("Boost mode enabled"); + else + osd->addLine("Boost mode disabled"); + break; + + case SDLK_LSHIFT: + shift_pressed &= ~1; + break; + case SDLK_RSHIFT: + shift_pressed &= ~2; + break; + + case SDLK_F1: + case SDLK_F2: + case SDLK_F3: + case SDLK_F4: + case SDLK_F5: + case SDLK_F6: + case SDLK_F7: + case SDLK_F8: + case SDLK_F9: + case SDLK_F10: + int prevexec; + prevexec = execute; + execute = FALSE; + SPU_Pause(1); + if(!shift_pressed){ + loadstate_slot(event.key.keysym.sym - SDLK_F1 + 1); + }else{ + savestate_slot(event.key.keysym.sym - SDLK_F1 + 1); + } + execute = prevexec; + SPU_Pause(!execute); + break; + default: + key = lookup_key(event.key.keysym.sym); + RM_KEY( cfg->keypad, key ); + break; + } + break; + + case SDL_MOUSEBUTTONDOWN: + if(event.button.button==1) + mouse.down = TRUE; + + case SDL_MOUSEMOTION: + if(!mouse.down) + break; + else { + signed long scaled_x = + screen_to_touch_range( event.button.x, + cfg->nds_screen_size_ratio); + signed long scaled_y = + screen_to_touch_range( event.button.y, + cfg->nds_screen_size_ratio); + + if( scaled_y >= 192) + set_mouse_coord( scaled_x, scaled_y - 192); + } + break; + + case SDL_MOUSEBUTTONUP: + if(mouse.down) mouse.click = TRUE; + mouse.down = FALSE; + break; + + case SDL_QUIT: + cfg->sdl_quit = 1; + break; + + default: + break; + } + } +} + diff --git a/jni/desmume/src/ctrlssdl.h b/jni/desmume/src/ctrlssdl.h new file mode 100755 index 0000000..a09766f --- /dev/null +++ b/jni/desmume/src/ctrlssdl.h @@ -0,0 +1,118 @@ +/* + Copyright (C) 2007 Pascal Giard + Copyright (C) 2007-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef CTRLSSDL_H +#define CTRLSSDL_H + +#ifdef HAVE_GL_GL_H +#include <GL/gl.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <SDL.h> +#include "MMU.h" + +#include "types.h" + +#define ADD_KEY(keypad,key) ( (keypad) |= (key) ) +#define RM_KEY(keypad,key) ( (keypad) &= ~(key) ) +#define KEYMASK_(k) (1 << (k)) + +#define JOY_AXIS 0 +#define JOY_HAT 1 +#define JOY_BUTTON 2 + +#define JOY_HAT_RIGHT 0 +#define JOY_HAT_LEFT 1 +#define JOY_HAT_UP 2 +#define JOY_HAT_DOWN 3 + +#define NB_KEYS 14 +#define KEY_NONE 0 +#define KEY_A 1 +#define KEY_B 2 +#define KEY_SELECT 3 +#define KEY_START 4 +#define KEY_RIGHT 5 +#define KEY_LEFT 6 +#define KEY_UP 7 +#define KEY_DOWN 8 +#define KEY_R 9 +#define KEY_L 10 +#define KEY_X 11 +#define KEY_Y 12 +#define KEY_DEBUG 13 +#define KEY_BOOST 14 + +/* Keypad key names */ +extern const char *key_names[NB_KEYS]; +/* Current keyboard configuration */ +extern u16 keyboard_cfg[NB_KEYS]; +/* Current joypad configuration */ +extern u16 joypad_cfg[NB_KEYS]; +/* Number of detected joypads */ +extern u16 nbr_joy; + +#ifndef GTK_UI +struct mouse_status +{ + signed long x; + signed long y; + BOOL click; + BOOL down; +}; + +extern mouse_status mouse; +#endif // !GTK_UI + +struct ctrls_event_config { + unsigned short keypad; + float nds_screen_size_ratio; + int auto_pause; + int focused; + int sdl_quit; + int boost; + int fake_mic; +#ifdef HAVE_GL_GL_H + GLuint *screen_texture; + void (*resize_cb)(u16 width, u16 height, GLuint *screen_texture); +#else + void *screen_texture; + void (*resize_cb)(u16 width, u16 height, void *screen_texture); +#endif +}; + +void load_default_config(const u16 kbCfg[]); +BOOL init_joy( void); +void uninit_joy( void); +u16 get_joy_key(int index); +u16 get_set_joy_key(int index); +void update_keypad(u16 keys); +u16 get_keypad( void); +u16 lookup_key (u16 keyval); +u16 lookup_joy_key (u16 keyval); +void +process_ctrls_event( SDL_Event& event, + struct ctrls_event_config *cfg); + +void +process_joystick_events( u16 *keypad); + +#endif /* CTRLSSDL_H */ diff --git a/jni/desmume/src/debug.cpp b/jni/desmume/src/debug.cpp new file mode 100755 index 0000000..5f4a9c3 --- /dev/null +++ b/jni/desmume/src/debug.cpp @@ -0,0 +1,419 @@ +/* + Copyright (C) 2006 Guillaume Duhamel + Copyright (C) 2006-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "debug.h" + +#include <algorithm> +#include <stdarg.h> +#include <stdio.h> +#include "MMU.h" +#include "armcpu.h" +#include "arm_instructions.h" +#include "thumb_instructions.h" +#include "cp15.h" +#include "NDSSystem.h" +#include "utils/xstring.h" +#include "movie.h" + +#ifdef HAVE_LUA +#include "lua-engine.h" +#endif + +armcpu_t* TDebugEventData::cpu() { return procnum==0?&NDS_ARM9:&NDS_ARM7; } + +TDebugEventData DebugEventData; +u32 debugFlag; + +//DEBUG CONFIGURATION +const bool debug_acl = false; +const bool debug_cacheMiss = false; + +static bool acl_check_access(u32 adr, u32 access) { + + //non-user modes get separate access handling, so check that here + if(NDS_ARM9.CPSR.bits.mode != USR) + access |= 1; + + if (armcp15_isAccessAllowed((armcp15_t *)NDS_ARM9.coproc[15],adr,access)==FALSE) { + HandleDebugEvent(DEBUG_EVENT_ACL_EXCEPTION); + } + return true; +} + +void HandleDebugEvent_ACL_Exception() +{ + printf("ACL EXCEPTION!\n"); + if(DebugEventData.memAccessType == MMU_AT_CODE) + armcpu_exception(DebugEventData.cpu(),EXCEPTION_PREFETCH_ABORT); + else if(DebugEventData.memAccessType == MMU_AT_DATA) + armcpu_exception(DebugEventData.cpu(),EXCEPTION_DATA_ABORT); +} + + +static bool CheckRange(u32 adr, u32 min, u32 len) +{ + return (adr>=min && adr<min+len); +} + +void HandleDebugEvent_Read() +{ + if(!debug_acl) return; + if(DebugEventData.procnum != ARMCPU_ARM9) return; //acl only valid on arm9 + acl_check_access(DebugEventData.addr,CP15_ACCESS_READ); +} + +void HandleDebugEvent_Write() +{ + if(!debug_acl) return; + if(DebugEventData.procnum != ARMCPU_ARM9) return; //acl only valid on arm9 + acl_check_access(DebugEventData.addr,CP15_ACCESS_WRITE); +} + +void HandleDebugEvent_Execute() +{ + //HACKY BREAKPOINTS! + //extern bool nds_debug_continuing[2]; + //if(!nds_debug_continuing[DebugEventData.procnum]) //dont keep hitting the same breakpoint + //{ + // if((DebugEventData.addr & 0xFFFFFFF0) == 0x02000000) + // { + // void NDS_debug_break(); + // NDS_debug_break(); + // } + //} + if(!debug_acl) return; + if(DebugEventData.procnum != ARMCPU_ARM9) return; //acl only valid on arm9 + acl_check_access(DebugEventData.addr,CP15_ACCESS_EXECUTE); +} + +void HandleDebugEvent_CacheMiss() +{ + if(!debug_cacheMiss) return; + extern int currFrameCounter; + if(currFrameCounter<200) return; + static FILE* outf = NULL; + if(!outf) outf = fopen("c:\\miss.txt","wb"); + fprintf(outf,"%05d,%08X,%d\n",currFrameCounter,DebugEventData.addr,DebugEventData.size); +} + +//------------------------------------------------ +DebugStatistics DEBUG_statistics; + +DebugStatistics::DebugStatistics() +{ +} + +DebugStatistics::InstructionHits::InstructionHits() +{ + memset(&arm,0,sizeof(arm)); + memset(&thumb,0,sizeof(thumb)); +} + + +static DebugStatistics::InstructionHits combinedHits[2]; + +template<int proc, int which> +static bool debugStatsSort(int num1, int num2) { + if(which==0) { + if(combinedHits[proc].arm[num2] == combinedHits[proc].arm[num1]) return false; + if(combinedHits[proc].arm[num1] == 0xFFFFFFFF) return false; + if(combinedHits[proc].arm[num2] == 0xFFFFFFFF) return true; + return combinedHits[proc].arm[num2] < combinedHits[proc].arm[num1]; + } + else { + if(combinedHits[proc].thumb[num2] == combinedHits[proc].thumb[num1]) return false; + if(combinedHits[proc].thumb[num1] == 0xFFFFFFFF) return false; + if(combinedHits[proc].thumb[num2] == 0xFFFFFFFF) return true; + return combinedHits[proc].thumb[num2] < combinedHits[proc].thumb[num1]; + } +} + +void DebugStatistics::print() +{ + //consolidate opcodes with the same names + for(int i=0;i<2;i++) { + combinedHits[i] = DEBUG_statistics.instructionHits[i]; + + for(int j=0;j<4096;j++) { + if(combinedHits[i].arm[j] == 0xFFFFFFFF) + continue; + std::string name = arm_instruction_names[j]; + for(int k=j+1;k<4096;k++) { + if(combinedHits[i].arm[k] == 0xFFFFFFFF) + continue; + if(name == arm_instruction_names[k]) { + //printf("combining %s with %d and %d\n",name.c_str(),combinedHits[i].arm[j],combinedHits[i].arm[k]); + combinedHits[i].arm[j] += combinedHits[i].arm[k]; + combinedHits[i].arm[k] = 0xFFFFFFFF; + } + + } + } + + for(int j=0;j<1024;j++) { + if(combinedHits[i].thumb[j] == 0xFFFFFFFF) + continue; + std::string name = thumb_instruction_names[j]; + for(int k=j+1;k<1024;k++) { + if(combinedHits[i].thumb[k] == 0xFFFFFFFF) + continue; + if(name == thumb_instruction_names[k]) { + //printf("combining %s with %d and %d\n",name.c_str(),combinedHits[i].arm[j],combinedHits[i].arm[k]); + combinedHits[i].thumb[j] += combinedHits[i].thumb[k]; + combinedHits[i].thumb[k] = 0xFFFFFFFF; + } + + } + } + } + + InstructionHits sorts[2]; + for(int i=0;i<2;i++) { + for(int j=0;j<4096;j++) sorts[i].arm[j] = j; + for(int j=0;j<1024;j++) sorts[i].thumb[j] = j; + } + std::sort(sorts[0].arm, sorts[0].arm+4096, debugStatsSort<0,0>); + std::sort(sorts[0].thumb, sorts[0].thumb+1024, debugStatsSort<0,1>); + std::sort(sorts[1].arm, sorts[1].arm+4096, debugStatsSort<1,0>); + std::sort(sorts[1].thumb, sorts[1].thumb+1024, debugStatsSort<1,1>); + + for(int i=0;i<2;i++) { + printf("Top arm instructions for ARM%d:\n",7+i*2); + for(int j=0;j<10;j++) { + int val = sorts[i].arm[j]; + printf("%08d: %s\n", combinedHits[i].arm[val], arm_instruction_names[val]); + } + printf("Top thumb instructions for ARM%d:\n",7+i*2); + for(int j=0;j<10;j++) { + int val = sorts[i].thumb[j]; + printf("%08d: %s\n", combinedHits[i].thumb[val], thumb_instruction_names[val]); + } + } +} + +void DebugStatistics::printSequencerExecutionCounters() +{ + for(int i=0;i<21;i++) printf("%06d ",sequencerExecutionCounters[i]); + printf("\n"); +} + +void DEBUG_reset() +{ + //for now, just enable all debugging in developer builds +#ifdef DEVELOPER + debugFlag = 1; +#endif + + DEBUG_Notify = DebugNotify(); + DEBUG_statistics = DebugStatistics(); + printf("DEBUG_reset: %08X\n",&DebugStatistics::print); //force a reference to this function +} + +static void DEBUG_dumpMemory_fill(EMUFILE *fp, u32 size) +{ + static std::vector<u8> buf; + buf.resize(size); + memset(&buf[0],0,size); + fp->fwrite(&buf[0],size); +} + +void DEBUG_dumpMemory(EMUFILE* fp) +{ + fp->fseek(0x000000,SEEK_SET); fp->fwrite(MMU.MAIN_MEM,0x800000); //arm9 main mem (8192K) + fp->fseek(0x900000,SEEK_SET); fp->fwrite(MMU.ARM9_DTCM,0x4000); //arm9 DTCM (16K) + fp->fseek(0xA00000,SEEK_SET); fp->fwrite(MMU.ARM9_ITCM,0x8000); //arm9 ITCM (32K) + fp->fseek(0xB00000,SEEK_SET); fp->fwrite(MMU.ARM9_LCD,0xA4000); //LCD mem 656K + fp->fseek(0xC00000,SEEK_SET); fp->fwrite(MMU.ARM9_VMEM,0x800); //OAM + fp->fseek(0xD00000,SEEK_SET); fp->fwrite(MMU.ARM7_ERAM,0x10000); //arm7 WRAM (64K) + fp->fseek(0xE00000,SEEK_SET); fp->fwrite(MMU.ARM7_WIRAM,0x10000); //arm7 wifi RAM ? + fp->fseek(0xF00000,SEEK_SET); fp->fwrite(MMU.SWIRAM,0x8000); //arm9/arm7 shared WRAM (32KB) +} + +//---------------------------------------------------- + +std::vector<Logger *> Logger::channels; + + +static void defaultCallback(const Logger& logger, const char * message) { + logger.getOutput() << message; +} + +Logger::Logger() { + out = &std::cout; + callback = defaultCallback; + flags = 0; +} + +Logger::~Logger() { + for(int i=0;i<(int)channels.size();i++) + delete channels[i]; +} + +void Logger::vprintf(const char * format, va_list l, const char * file, unsigned int line) { + char buffer[1024]; + char * cur = buffer; + + if (flags & Logger::FILE) cur += sprintf(cur, "%s:", file); + if (flags & Logger::LINE) cur += sprintf(cur, "%d:", line); + if (flags) cur += sprintf(cur, " "); + + ::vsnprintf(cur, 1024, format, l); + callback(*this, buffer); +} + +void Logger::setOutput(std::ostream * o) { + out = o; +} + +void Logger::setCallback(void (*cback)(const Logger& logger, const char * message)) { + callback = cback; +} + +void Logger::setFlag(unsigned int flag) { + this->flags = flag; +} + +void Logger::fixSize(unsigned int channel) { + while(channel >= channels.size()) { + channels.push_back(new Logger()); + } +} + +std::ostream& Logger::getOutput() const { + return *out; +} + +void Logger::log(unsigned int channel, const char * file, unsigned int line, const char * format, ...) { + fixSize(channel); + + va_list l; + va_start(l, format); + channels[channel]->vprintf(format, l, file, line); + va_end(l); +} + +void Logger::log(unsigned int channel, const char * file, unsigned int line, std::ostream& os) { + fixSize(channel); + + channels[channel]->setOutput(&os); +} + +void Logger::log(unsigned int channel, const char * file, unsigned int line, unsigned int flag) { + fixSize(channel); + + channels[channel]->setFlag(flag); +} + +void Logger::log(unsigned int channel, const char * file, unsigned int line, void (*callback)(const Logger& logger, const char * message)) { + fixSize(channel); + + channels[channel]->setCallback(callback); +} + +void IdeasLog(armcpu_t* cpu) +{ + u32 adr = cpu->R[0]; + for(;;) { + u8 c = _MMU_read08(cpu->proc_ID, MMU_AT_DEBUG, adr); + adr++; + if(!c) break; + printf("%c",c); + } + //don't emit a newline. that is a pain in the butt. +} + +void NocashMessage(armcpu_t* cpu, int offset) +{ + u32 adr = cpu->instruct_adr + offset; + + std::string todo; + for(;;) { + u8 c = _MMU_read08(cpu->proc_ID, MMU_AT_DEBUG, adr); + adr++; + if(!c) break; + todo.push_back(c); + } + + //r0,r1,r2,...,r15 show register content (displayed as 32bit Hex number) + //sp,lr,pc alias for r13,r14,r15 + //scanline show current scanline number + //frame show total number of frames since coldboot + //totalclks show total number of clock cycles since coldboot + //lastclks show number of cycles since previous lastclks (or zeroclks) + //zeroclks resets the 'lastclks' counter + + //this is very inefficiently coded! + char tmp[100]; + todo = mass_replace(todo,"%sp%","%r13%"); + todo = mass_replace(todo,"%lr%","%r14%"); + todo = mass_replace(todo,"%pc%","%r15%"); + sprintf(tmp,"%08X",cpu->R[0]); todo = mass_replace(todo,"%r0%",tmp); + sprintf(tmp,"%08X",cpu->R[1]); todo = mass_replace(todo,"%r1%",tmp); + sprintf(tmp,"%08X",cpu->R[2]); todo = mass_replace(todo,"%r2%",tmp); + sprintf(tmp,"%08X",cpu->R[3]); todo = mass_replace(todo,"%r3%",tmp); + sprintf(tmp,"%08X",cpu->R[4]); todo = mass_replace(todo,"%r4%",tmp); + sprintf(tmp,"%08X",cpu->R[5]); todo = mass_replace(todo,"%r5%",tmp); + sprintf(tmp,"%08X",cpu->R[6]); todo = mass_replace(todo,"%r6%",tmp); + sprintf(tmp,"%08X",cpu->R[7]); todo = mass_replace(todo,"%r7%",tmp); + sprintf(tmp,"%08X",cpu->R[8]); todo = mass_replace(todo,"%r8%",tmp); + sprintf(tmp,"%08X",cpu->R[9]); todo = mass_replace(todo,"%r9%",tmp); + sprintf(tmp,"%08X",cpu->R[10]); todo = mass_replace(todo,"%r10%",tmp); + sprintf(tmp,"%08X",cpu->R[11]); todo = mass_replace(todo,"%r11%",tmp); + sprintf(tmp,"%08X",cpu->R[12]); todo = mass_replace(todo,"%r12%",tmp); + sprintf(tmp,"%08X",cpu->R[13]); todo = mass_replace(todo,"%r13%",tmp); + sprintf(tmp,"%08X",cpu->R[14]); todo = mass_replace(todo,"%r14%",tmp); + sprintf(tmp,"%08X",cpu->R[15]); todo = mass_replace(todo,"%r15%",tmp); + sprintf(tmp,"%d",nds.VCount); todo = mass_replace(todo,"%scanline%",tmp); + sprintf(tmp,"%d",currFrameCounter); todo = mass_replace(todo,"%frame%",tmp); + sprintf(tmp,"%lld",nds_timer); todo = mass_replace(todo,"%totalclks%",tmp); + + printf("%s",todo.c_str()); +} + +//------- +DebugNotify DEBUG_Notify; + +//enable bits arent being used right now. +//if you want exhaustive logging, move the print before the early return (or comment the early return) + +//the intent of this system is to provide a compact dialog box showing which debug notifies have been +//triggered in this frame (with a glowing LED!) and which debug notifies have been triggered EVER +//which can be cleared, like a clip indicator in an audio tool. +//obviously all this isnt implemented yet. + +void DebugNotify::NextFrame() +{ +#ifdef DEVELOPER + pingBits.reset(); +#endif +} + +void DebugNotify::ReadBeyondEndOfCart(u32 addr, u32 romsize) +{ +#ifdef DEVELOPER + if(!ping(DEBUG_NOTIFY_READ_BEYOND_END_OF_CART)) return; + INFO("Reading beyond end of cart! ... %08X >= %08X\n",addr,romsize); +#endif +} + +bool DebugNotify::ping(EDEBUG_NOTIFY which) +{ + bool wasPinged = pingBits[(int)which]; + pingBits[(int)which] = true; + return !wasPinged; +} diff --git a/jni/desmume/src/debug.h b/jni/desmume/src/debug.h new file mode 100755 index 0000000..2656605 --- /dev/null +++ b/jni/desmume/src/debug.h @@ -0,0 +1,218 @@ +/* + Copyright (C) 2006 Guillaume Duhamel + Copyright (C) 2006-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef DEBUG_H +#define DEBUG_H + +#include <vector> +#include <iostream> +#include <cstdarg> +#include <bitset> + +#include "types.h" +#include "mem.h" +#include "emufile.h" + +struct DebugStatistics +{ + DebugStatistics(); + struct InstructionHits { + InstructionHits(); + u32 thumb[1024]; + u32 arm[4096]; + } instructionHits[2]; //one for each cpu + + s32 sequencerExecutionCounters[32]; + + void print(); + void printSequencerExecutionCounters(); +}; + +extern DebugStatistics DEBUG_statistics; + +void DEBUG_reset(); +void DEBUG_dumpMemory(EMUFILE* fp); + +struct armcpu_t; + +class Logger { +protected: + void (*callback)(const Logger& logger, const char * format); + std::ostream * out; + unsigned int flags; + + static void fixSize(unsigned int channel); +public: + Logger(); + ~Logger(); + + void vprintf(const char * format, va_list l, const char * filename, unsigned int line); + void setOutput(std::ostream * o); + void setCallback(void (*cback)(const Logger& logger, const char * message)); + void setFlag(unsigned int flag); + + std::ostream& getOutput() const; + + static const int LINE = 1; + static const int FILE = 2; + + static std::vector<Logger *> channels; + + static void log(unsigned int channel, const char * file, unsigned int line, const char * format, ...); + static void log(unsigned int channel, const char * file, unsigned int line, std::ostream& os); + static void log(unsigned int channel, const char * file, unsigned int line, unsigned int flag); + static void log(unsigned int channel, const char * file, unsigned int line, void (*callback)(const Logger& logger, const char * message)); +}; + +#if defined(DEBUG) || defined(GPUDEBUG) || defined(DIVDEBUG) || defined(SQRTDEBUG) || defined(DMADEBUG) || defined(DEVELOPER) +#define LOGC(channel, ...) Logger::log(channel, __FILE__, __LINE__, __VA_ARGS__) +#else +#define LOGC(...) {} +#endif + +#ifdef DEBUG +#define LOG(...) LOGC(0, __VA_ARGS__) +#else +#define LOG(...) {} +#endif + +#ifdef GPUDEBUG +#define GPULOG(...) LOGC(1, __VA_ARGS__) +#else +#define GPULOG(...) {} +#endif + +#ifdef DIVDEBUG +#define DIVLOG(...) LOGC(2, __VA_ARGS__) +#else +#define DIVLOG(...) {} +#endif + +#ifdef SQRTDEBUG +#define SQRTLOG(...) LOGC(3, __VA_ARGS__) +#else +#define SQRTLOG(...) {} +#endif + +#ifdef DMADEBUG +#define DMALOG(...) LOGC(4, __VA_ARGS__) +#else +#define DMALOG(...) {} +#endif + +#ifdef CFLASHDEBUG +#define CFLASHLOG(...) LOGC(5, __VA_ARGS__) +#else +#define CFLASHLOG(...) {} +#endif + +#ifdef UNTESTEDOPCODEDEBUG +#define UNTESTEDOPCODELOG(...) LOGC(6, __VA_ARGS__) +#else +#define UNTESTEDOPCODELOG(...) {} +#endif + + +#ifdef DEVELOPER +#define PROGINFO(...) LOGC(7, __VA_ARGS__) +#else +#define PROGINFO(...) {} +#endif + + +#define INFOC(channel, ...) Logger::log(channel, __FILE__, __LINE__, __VA_ARGS__) +#define INFO(...) INFOC(10, __VA_ARGS__) + +void IdeasLog(armcpu_t* cpu); +void NocashMessage(armcpu_t* cpu, int offset); + +enum EDEBUG_EVENT +{ + DEBUG_EVENT_READ=1, //read from arm9 or arm7 bus, including cpu prefetch + DEBUG_EVENT_WRITE=2, //write on arm9 or arm7 bus + DEBUG_EVENT_EXECUTE=3, //prefetch on arm9 or arm7, triggered after the read event + DEBUG_EVENT_ACL_EXCEPTION=4, //acl exception on arm9 + DEBUG_EVENT_CACHE_MISS=5, //cache miss on arm9 +}; + +enum EDEBUG_NOTIFY +{ + DEBUG_NOTIFY_READ_BEYOND_END_OF_CART, + DEBUG_NOTIFY_MAX +}; + +class DebugNotify +{ +public: + void NextFrame(); + void ReadBeyondEndOfCart(u32 addr, u32 romsize); +private: + std::bitset<DEBUG_NOTIFY_MAX> pingBits; + std::bitset<DEBUG_NOTIFY_MAX> enableBits; + bool ping(EDEBUG_NOTIFY which); +}; + +extern DebugNotify DEBUG_Notify; +struct armcpu_t; + +//information about a debug event will be stuffed into here by the generator +struct TDebugEventData +{ + MMU_ACCESS_TYPE memAccessType; + u32 procnum, addr, size, val; + armcpu_t* cpu(); +}; + +extern TDebugEventData DebugEventData; + +//bits in here are set according to what debug handlers are installed? +//for now it is just a single bit +extern u32 debugFlag; + +FORCEINLINE bool CheckDebugEvent(EDEBUG_EVENT event) +{ + //for now, debug events are only handled in dev+ builds +#ifndef DEVELOPER + return false; +#endif + + if(!debugFlag) return false; + + return true; +} + +void HandleDebugEvent_Read(); +void HandleDebugEvent_Write(); +void HandleDebugEvent_Execute(); +void HandleDebugEvent_ACL_Exception(); +void HandleDebugEvent_CacheMiss(); + +inline void HandleDebugEvent(EDEBUG_EVENT event) +{ + switch(event) + { + case DEBUG_EVENT_READ: HandleDebugEvent_Read(); return; + case DEBUG_EVENT_WRITE: HandleDebugEvent_Write(); return; + case DEBUG_EVENT_EXECUTE: HandleDebugEvent_Execute(); return; + case DEBUG_EVENT_ACL_EXCEPTION: HandleDebugEvent_ACL_Exception(); return; + case DEBUG_EVENT_CACHE_MISS: HandleDebugEvent_CacheMiss(); return; + } +} + + +#endif diff --git a/jni/desmume/src/desmume.mk b/jni/desmume/src/desmume.mk new file mode 100755 index 0000000..cfdf610 --- /dev/null +++ b/jni/desmume/src/desmume.mk @@ -0,0 +1,3 @@ +AM_CFLAGS = +AM_CPPFLAGS = -I$(top_srcdir)/src +AM_LDFLAGS = \ No newline at end of file diff --git a/jni/desmume/src/desmume_config.cpp b/jni/desmume/src/desmume_config.cpp new file mode 100755 index 0000000..8032e3d --- /dev/null +++ b/jni/desmume/src/desmume_config.cpp @@ -0,0 +1,147 @@ +/* + Copyright (C) 2009-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <glib.h> +#include <glib/gstdio.h> + +#include "ctrlssdl.h" +#include "desmume_config.h" + +static const gchar *desmume_old_config_file = ".desmume.ini"; +static const gchar *desmume_config_dir = "desmume"; +static const gchar *desmume_config_file = "config"; + +GKeyFile *desmume_config_read_file(const u16 *kb_cfg) +{ + gchar *config_file, *config_dir, *old_config_file; + GKeyFile *keyfile; + GError *error = NULL; + gboolean ret; + + old_config_file = g_build_filename(g_get_home_dir(), desmume_old_config_file, NULL); + config_file = g_build_filename(g_get_user_config_dir(), desmume_config_dir, desmume_config_file, NULL); + + config_dir = g_build_filename(g_get_user_config_dir(), desmume_config_dir, NULL); + g_mkdir_with_parents(config_dir, 0755); + + if (!g_file_test(config_file, G_FILE_TEST_IS_REGULAR) && g_file_test(old_config_file, G_FILE_TEST_IS_REGULAR)) { + ret = g_rename(old_config_file, config_file); + if (ret) { + g_printerr("Failed to move old config file %s to new location %s \n", old_config_file, config_file); + } + } + + keyfile = g_key_file_new(); + ret = g_key_file_load_from_file(keyfile, config_file, G_KEY_FILE_NONE, &error); + if (!ret) { + g_error_free(error); + } + + g_free(config_file); + g_free(config_dir); + g_free(old_config_file); + + load_default_config(kb_cfg); + desmume_config_read_keys(keyfile); + desmume_config_read_joykeys(keyfile); + + return keyfile; +} + +void desmume_config_dispose(GKeyFile *keyfile) +{ + g_key_file_free(keyfile); +} + +static gboolean desmume_config_write_file(GKeyFile *keyfile) +{ + gchar *config_file; + gchar *config_dir; + gchar *data; + GError *error = NULL; + gsize length; + gboolean ret = TRUE; + + config_dir = g_build_filename(g_get_user_config_dir(), desmume_config_dir, NULL); + g_mkdir_with_parents(config_dir, 0755); + config_file = g_build_filename(g_get_user_config_dir(), desmume_config_dir, desmume_config_file, NULL); + data = g_key_file_to_data(keyfile, &length, NULL); + ret = g_file_set_contents(config_file, data, length, &error); + if (!ret) { + g_error_free(error); + } + + g_free(config_file); + g_free(config_dir); + g_free(data); + + return ret; +} + +gboolean desmume_config_update_keys(GKeyFile *keyfile) +{ + for(int i = 0; i < NB_KEYS; i++) { + g_key_file_set_integer(keyfile, "KEYS", key_names[i], keyboard_cfg[i]); + } + + return desmume_config_write_file(keyfile); +} + +gboolean desmume_config_update_joykeys(GKeyFile *keyfile) +{ + for(int i = 0; i < NB_KEYS; i++) { + g_key_file_set_integer(keyfile, "JOYKEYS", key_names[i], joypad_cfg[i]); + } + + return desmume_config_write_file(keyfile); +} + +gboolean desmume_config_read_keys(GKeyFile *keyfile) +{ + GError *error = NULL; + + if (!g_key_file_has_group(keyfile, "KEYS")) + return TRUE; + + for (int i = 0; i < NB_KEYS; i++) { + keyboard_cfg[i] = g_key_file_get_integer(keyfile, "KEYS", key_names[i], &error); + if (error != NULL) { + g_error_free(error); + return FALSE; + } + } + + return TRUE; +} + +gboolean desmume_config_read_joykeys(GKeyFile *keyfile) +{ + GError *error = NULL; + + if (!g_key_file_has_group(keyfile, "JOYKEYS")) + return TRUE; + + for (int i = 0; i < NB_KEYS; i++) { + joypad_cfg[i] = g_key_file_get_integer(keyfile, "JOYKEYS", key_names[i], &error); + if (error != NULL) { + g_error_free(error); + return FALSE; + } + } + + return TRUE; +} diff --git a/jni/desmume/src/desmume_config.h b/jni/desmume/src/desmume_config.h new file mode 100755 index 0000000..f99bcc8 --- /dev/null +++ b/jni/desmume/src/desmume_config.h @@ -0,0 +1,29 @@ +/* + Copyright (C) 2009-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _DESMUME_GTK_CONFIG +#define _DESMUME_GTK_CONFIG + +GKeyFile *desmume_config_read_file(const u16 *); +void desmume_config_dispose(GKeyFile *); + +gboolean desmume_config_update_keys(GKeyFile*); +gboolean desmume_config_update_joykeys(GKeyFile*); +gboolean desmume_config_read_keys(GKeyFile*); +gboolean desmume_config_read_joykeys(GKeyFile*); + +#endif diff --git a/jni/desmume/src/driver.cpp b/jni/desmume/src/driver.cpp new file mode 100755 index 0000000..417d600 --- /dev/null +++ b/jni/desmume/src/driver.cpp @@ -0,0 +1,236 @@ +/* + Copyright (C) 2009-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "types.h" +#include "driver.h" +#include "rasterize.h" +#include "gfx3d.h" +#include "texcache.h" + + +#ifdef HAVE_WX +#include "wx/wxprec.h" +#include "wx/wx.h" +#include "wxdlg/wxdlg3dViewer.h" + +const int kViewportWidth = 256; +const int kViewportHeight = 192; + +static SoftRasterizerEngine engine; +static Fragment _screen[kViewportWidth*kViewportHeight]; +static FragmentColor _screenColor[kViewportWidth*kViewportHeight]; + +extern void _HACK_Viewer_ExecUnit(SoftRasterizerEngine* engine); + +class Mywxdlg3dViewer : public wxdlg3dViewer +{ +public: + Mywxdlg3dViewer() + : wxdlg3dViewer(NULL) + {} + + virtual void RepaintPanel() + { + Refresh(false); + Update(); + } + + void NewFrame() + { + listPolys->SetItemCount(viewer3d_state->polylist.count); + labelFrameCounter->SetLabel(wxString::Format(wxT("Frame: %d"),viewer3d_state->frameNumber)); + labelUserPolycount->SetLabel(wxString::Format(wxT("User Polys: %d"),viewer3d_state->polylist.count)); + labelFinalPolycount->SetLabel(wxString::Format(wxT("Final Polys: %d"),viewer3d_state->polylist.count)); + //tree->DeleteAllItems(); + //tree->Freeze(); + //wxTreeItemId root = tree->AddRoot(""); + //for(int i=0;i<viewer3d_state->polylist.count;i++) + //{ + // tree->AppendItem(root,"hai kirin"); + //} + //tree->Thaw(); + } + + virtual wxString OnGetItemText(const wxListCtrl* list, long item, long column) const + { + return wxT("hi"); + } + + virtual void OnListPolysSelected( wxListEvent& event ) + { + panelTexture->Refresh(false); + engine._debug_drawClippedUserPoly = GetSelectedListviewItem(listPolys); + } + + void RedrawPanel(wxClientDC* dc) + { + //------------ + //do the 3d work.. + engine.polylist = &viewer3d_state->polylist; + engine.vertlist = &viewer3d_state->vertlist; + engine.indexlist = &viewer3d_state->indexlist; + engine.screen = _screen; + engine.screenColor = _screenColor; + engine.width = kViewportWidth; + engine.height = kViewportHeight; + + engine.updateFogTable(); + + engine.initFramebuffer(kViewportWidth,kViewportHeight,gfx3d.state.enableClearImage?true:false); + engine.updateToonTable(); + engine.updateFloatColors(); + engine.performClipping(checkMaterialInterpolate->IsChecked()); + engine.performViewportTransforms<true>(kViewportWidth,kViewportHeight); + engine.performBackfaceTests(); + engine.performCoordAdjustment(false); + engine.setupTextures(false); + + _HACK_Viewer_ExecUnit(&engine); + //------------ + + //dc.SetBackground(*wxGREEN_BRUSH); dc.Clear(); + u8 framebuffer[kViewportWidth*kViewportHeight*3]; + for(int y=0,i=0;y<kViewportHeight;y++) + for(int x=0;x<kViewportWidth;x++,i++) { + framebuffer[i*3] = _screenColor[i].r<<2; + framebuffer[i*3+1] = _screenColor[i].g<<2; + framebuffer[i*3+2] = _screenColor[i].b<<2; + } + wxImage image(kViewportWidth,kViewportHeight,framebuffer,true); + wxBitmap bitmap(image); + dc->DrawBitmap(bitmap,0,0); + } + + virtual void _OnPaintPanel( wxPaintEvent& event ) + { + wxClientDC dc(wxDynamicCast(event.GetEventObject(), wxWindow)); + RedrawPanel(&dc); + } + + int GetSelectedListviewItem(wxListCtrl* list) + { + return list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); + } + + virtual void OnPaintPanelTexture( wxPaintEvent& event ) + { + wxPaintDC dc(wxDynamicCast(event.GetEventObject(), wxWindow)); + dc.SetBackground(*wxBLACK_BRUSH); dc.Clear(); + + int selection = GetSelectedListviewItem(listPolys); + if(selection < 0) return; + if(selection>=viewer3d_state->polylist.count) return; + + POLY& poly = viewer3d_state->polylist.list[selection]; + + TexCacheItem* texkey = TexCache_SetTexture(TexFormat_32bpp,poly.texParam,poly.texPalette); + const u32 w = texkey->sizeX; + const u32 h = texkey->sizeY; + u8* const bmpdata = new u8[w*h*4]; + for(u32 i=0;i<w*h;i++) { + bmpdata[i*3] = texkey->decoded[i*4]; + bmpdata[i*3+1] = texkey->decoded[i*4+1]; + bmpdata[i*3+2] = texkey->decoded[i*4+2]; + } + for(u32 i=0;i<w*h;i++) + bmpdata[w*h*3+i] = texkey->decoded[i*4+3]; + + + wxImage image(w,h,false); + image.InitAlpha(); + image.SetData(bmpdata,true); + image.SetAlpha(bmpdata+w*h*3,true); + wxBitmap bitmap(image); + double xscale = (double)panelTexture->GetSize().x / w; + double yscale = (double)panelTexture->GetSize().y / h; + + dc.SetUserScale(xscale,yscale); + dc.DrawBitmap(bitmap,0,0); + delete[] bmpdata; + } +}; + +class VIEW3D_Driver_WX : public VIEW3D_Driver +{ +public: + VIEW3D_Driver_WX() + : viewer(NULL) + {} + ~VIEW3D_Driver_WX() + { + delete viewer; + } + + virtual bool IsRunning() { return viewer != NULL; } + + virtual void Launch() + { + if(viewer) return; + delete viewer; + viewer = new Mywxdlg3dViewer(); + viewer->Show(true); + } + + void Close() + { + delete viewer; + viewer = NULL; + } + + virtual void NewFrame() + { + if(!viewer) return; + if(!viewer->IsShown()) { + Close(); + return; + } + + viewer->NewFrame(); + viewer->RepaintPanel(); + } + +private: + Mywxdlg3dViewer *viewer; +}; + +#endif + +static VIEW3D_Driver nullView3d; +BaseDriver::BaseDriver() +: view3d(NULL) +{ + VIEW3D_Shutdown(); +} + +void BaseDriver::VIEW3D_Shutdown() +{ + if(view3d != &nullView3d) delete view3d; + view3d = &nullView3d; +} + +void BaseDriver::VIEW3D_Init() +{ + VIEW3D_Shutdown(); +#ifdef HAVE_WX + view3d = new VIEW3D_Driver_WX(); +#endif +} + +BaseDriver::~BaseDriver() +{ +} + diff --git a/jni/desmume/src/driver.h b/jni/desmume/src/driver.h new file mode 100755 index 0000000..57bff2c --- /dev/null +++ b/jni/desmume/src/driver.h @@ -0,0 +1,127 @@ +/* + Copyright (C) 2009-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _DRIVER_H_ +#define _DRIVER_H_ + +#include "types.h" +#include "debug.h" +#include <stdio.h> + +#ifdef EXPERIMENTAL_WIFI_COMM +#include <pcap.h> +#endif + +class VIEW3D_Driver +{ +public: + virtual void Launch() {} + virtual void NewFrame() {} + virtual bool IsRunning() { return false; } +}; + +//each platform needs to implement this, although it doesnt need to implement any functions +class BaseDriver { +public: + BaseDriver(); + ~BaseDriver(); + +#ifdef EXPERIMENTAL_WIFI_COMM + virtual bool WIFI_SocketsAvailable() { return true; } + virtual bool WIFI_PCapAvailable() { return false; } + + virtual void WIFI_GetUniqueMAC(u8* mac) {} + + virtual bool WIFI_WFCWarning() { return false; } + + virtual int PCAP_findalldevs(pcap_if_t** alldevs, char* errbuf) { return -1; } + virtual void PCAP_freealldevs(pcap_if_t* alldevs) {} + virtual pcap_t* PCAP_open(const char* source, int snaplen, int flags, int readtimeout, char* errbuf) { return NULL; } + virtual void PCAP_close(pcap_t* dev) {} + virtual int PCAP_setnonblock(pcap_t* dev, int nonblock, char* errbuf) { return -1; } + virtual int PCAP_sendpacket(pcap_t* dev, const u_char* data, int len) { return -1; } + virtual int PCAP_dispatch(pcap_t* dev, int num, pcap_handler callback, u_char* userdata) { return -1; } +#endif + + virtual void AVI_SoundUpdate(void* soundData, int soundLen) {} + virtual bool AVI_IsRecording() { return FALSE; } + virtual bool WAV_IsRecording() { return FALSE; } + + virtual void USR_InfoMessage(const char *message) { LOG("%s\n", message); } + virtual void USR_RefreshScreen() {} + virtual void USR_SetDisplayPostpone(int milliseconds, bool drawNextFrame) {} // -1 == indefinitely, 0 == don't pospone, 500 == don't draw for 0.5 seconds + + enum eStepMainLoopResult + { + ESTEP_NOT_IMPLEMENTED = -1, + ESTEP_CALL_AGAIN = 0, + ESTEP_DONE = 1, + }; + virtual eStepMainLoopResult EMU_StepMainLoop(bool allowSleep, bool allowPause, int frameSkip, bool disableUser, bool disableCore) { return ESTEP_NOT_IMPLEMENTED; } // -1 frameSkip == useCurrentDefault + virtual void EMU_PauseEmulation(bool pause) {} + virtual bool EMU_IsEmulationPaused() { return false; } + virtual bool EMU_IsFastForwarding() { return false; } + virtual bool EMU_HasEmulationStarted() { return true; } + virtual bool EMU_IsAtFrameBoundary() { return true; } + virtual void EMU_DebugIdleUpdate() {} + + enum eDebug_IOReg + { + EDEBUG_IOREG_DMA + }; + + virtual void DEBUG_UpdateIORegView(eDebug_IOReg category) { } + + VIEW3D_Driver* view3d; + void VIEW3D_Shutdown(); + void VIEW3D_Init(); +}; +extern BaseDriver* driver; + +#ifndef _WINDOWS +class UnixDriver : public BaseDriver +{ +#ifdef EXPERIMENTAL_WIFI_COMM + virtual bool WIFI_SocketsAvailable() { return true; } + virtual bool WIFI_PCapAvailable() { return true; } + virtual bool WIFI_WFCWarning() { return false; } + + virtual int PCAP_findalldevs(pcap_if_t** alldevs, char* errbuf) { + return pcap_findalldevs(alldevs, errbuf); } + + virtual void PCAP_freealldevs(pcap_if_t* alldevs) { + pcap_freealldevs(alldevs); } + + virtual pcap_t* PCAP_open(const char* source, int snaplen, int flags, int readtimeout, char* errbuf) { + return pcap_open_live(source, snaplen, flags, readtimeout, errbuf); } + + virtual void PCAP_close(pcap_t* dev) { + pcap_close(dev); } + + virtual int PCAP_setnonblock(pcap_t* dev, int nonblock, char* errbuf) { + return pcap_setnonblock(dev, nonblock, errbuf); } + + virtual int PCAP_sendpacket(pcap_t* dev, const u_char* data, int len) { + return pcap_sendpacket(dev, data, len); } + + virtual int PCAP_dispatch(pcap_t* dev, int num, pcap_handler callback, u_char* userdata) { + return pcap_dispatch(dev, num, callback, userdata); } +#endif +}; +#endif + +#endif //_DRIVER_H_ diff --git a/jni/desmume/src/emufile.cpp b/jni/desmume/src/emufile.cpp new file mode 100755 index 0000000..f4e4a9a --- /dev/null +++ b/jni/desmume/src/emufile.cpp @@ -0,0 +1,260 @@ +/* +The MIT License + +Copyright (C) 2009-2010 DeSmuME team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "emufile.h" + +#include <vector> + +bool EMUFILE::readAllBytes(std::vector<u8>* dstbuf, const std::string& fname) +{ + EMUFILE_FILE file(fname.c_str(),"rb"); + if(file.fail()) return false; + int size = file.size(); + dstbuf->resize(size); + file.fread(&dstbuf->at(0),size); + return true; +} + +size_t EMUFILE_MEMORY::_fread(const void *ptr, size_t bytes){ + u32 remain = len-pos; + u32 todo = std::min<u32>(remain,(u32)bytes); + if(len==0) + { + failbit = true; + return 0; + } + if(todo<=4) + { + u8* src = buf()+pos; + u8* dst = (u8*)ptr; + for(size_t i=0;i<todo;i++) + *dst++ = *src++; + } + else + { + memcpy((void*)ptr,buf()+pos,todo); + } + pos += todo; + if(todo<bytes) + failbit = true; + return todo; +} + +void EMUFILE_FILE::truncate(s32 length) +{ + ::fflush(fp); + #ifdef _MSC_VER + _chsize(_fileno(fp),length); + #else + ftruncate(fileno(fp),length); + #endif + fclose(fp); + fp = NULL; + open(fname.c_str(),mode); +} + + +EMUFILE* EMUFILE_FILE::memwrap() +{ + EMUFILE_MEMORY* mem = new EMUFILE_MEMORY(size()); + if(size()==0) return mem; + fread(mem->buf(),size()); + return mem; +} + +EMUFILE* EMUFILE_MEMORY::memwrap() +{ + return this; +} + +void EMUFILE::write64le(u64* val) +{ + write64le(*val); +} + +void EMUFILE::write64le(u64 val) +{ +#ifdef LOCAL_BE + u8 s[8]; + s[0]=(u8)val; + s[1]=(u8)(val>>8); + s[2]=(u8)(val>>16); + s[3]=(u8)(val>>24); + s[4]=(u8)(val>>32); + s[5]=(u8)(val>>40); + s[6]=(u8)(val>>48); + s[7]=(u8)(val>>56); + fwrite((char*)&s,8); +#else + fwrite(&val,8); +#endif +} + + +size_t EMUFILE::read64le(u64 *Bufo) +{ + u64 buf; + if(fread((char*)&buf,8) != 8) + return 0; +#ifndef LOCAL_BE + *Bufo=buf; +#else + *Bufo = LE_TO_LOCAL_64(buf); +#endif + return 1; +} + +u64 EMUFILE::read64le() +{ + u64 temp; + read64le(&temp); + return temp; +} + +void EMUFILE::write32le(u32* val) +{ + write32le(*val); +} + +void EMUFILE::write32le(u32 val) +{ +#ifdef LOCAL_BE + u8 s[4]; + s[0]=(u8)val; + s[1]=(u8)(val>>8); + s[2]=(u8)(val>>16); + s[3]=(u8)(val>>24); + fwrite(s,4); +#else + fwrite(&val,4); +#endif +} + +size_t EMUFILE::read32le(s32* Bufo) { return read32le((u32*)Bufo); } + +size_t EMUFILE::read32le(u32* Bufo) +{ + u32 buf; + if(fread(&buf,4)<4) + return 0; +#ifndef LOCAL_BE + *(u32*)Bufo=buf; +#else + *(u32*)Bufo=((buf&0xFF)<<24)|((buf&0xFF00)<<8)|((buf&0xFF0000)>>8)|((buf&0xFF000000)>>24); +#endif + return 1; +} + +u32 EMUFILE::read32le() +{ + u32 ret; + read32le(&ret); + return ret; +} + +void EMUFILE::write16le(u16* val) +{ + write16le(*val); +} + +void EMUFILE::write16le(u16 val) +{ +#ifdef LOCAL_BE + u8 s[2]; + s[0]=(u8)val; + s[1]=(u8)(val>>8); + fwrite(s,2); +#else + fwrite(&val,2); +#endif +} + +size_t EMUFILE::read16le(s16* Bufo) { return read16le((u16*)Bufo); } + +size_t EMUFILE::read16le(u16* Bufo) +{ + u32 buf; + if(fread(&buf,2)<2) + return 0; +#ifndef LOCAL_BE + *(u16*)Bufo=buf; +#else + *Bufo = LE_TO_LOCAL_16(buf); +#endif + return 1; +} + +u16 EMUFILE::read16le() +{ + u16 ret; + read16le(&ret); + return ret; +} + +void EMUFILE::write8le(u8* val) +{ + write8le(*val); +} + + +void EMUFILE::write8le(u8 val) +{ + fwrite(&val,1); +} + +size_t EMUFILE::read8le(u8* val) +{ + return fread(val,1); +} + +u8 EMUFILE::read8le() +{ + u8 temp; + fread(&temp,1); + return temp; +} + +void EMUFILE::writedouble(double* val) +{ + write64le(double_to_u64(*val)); +} +void EMUFILE::writedouble(double val) +{ + write64le(double_to_u64(val)); +} + +double EMUFILE::readdouble() +{ + double temp; + readdouble(&temp); + return temp; +} + +size_t EMUFILE::readdouble(double* val) +{ + u64 temp; + size_t ret = read64le(&temp); + *val = u64_to_double(temp); + return ret; +} diff --git a/jni/desmume/src/emufile.h b/jni/desmume/src/emufile.h new file mode 100755 index 0000000..4a0af94 --- /dev/null +++ b/jni/desmume/src/emufile.h @@ -0,0 +1,351 @@ +/* +The MIT License + +Copyright (C) 2009-2012 DeSmuME team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +//don't use emufile for files bigger than 2GB! you have been warned! some day this will be fixed. + +#ifndef EMUFILE_H +#define EMUFILE_H + +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include <vector> +#include <algorithm> +#include <string> +#include <stdarg.h> + +#include "emufile_types.h" + +#ifdef _MSC_VER +#include <io.h> +#else +#include <unistd.h> +#endif + +class EMUFILE { +protected: + bool failbit; + +public: + EMUFILE() + : failbit(false) + {} + + + //returns a new EMUFILE which is guranteed to be in memory. the EMUFILE you call this on may be deleted. use the returned EMUFILE in its place + virtual EMUFILE* memwrap() = 0; + + virtual ~EMUFILE() {} + + static bool readAllBytes(std::vector<u8>* buf, const std::string& fname); + + bool fail(bool unset=false) { bool ret = failbit; if(unset) unfail(); return ret; } + void unfail() { failbit=false; } + + bool eof() { return size()==ftell(); } + + size_t fread(const void *ptr, size_t bytes){ + return _fread(ptr,bytes); + } + + void unget() { fseek(-1,SEEK_CUR); } + + //virtuals +public: + + virtual FILE *get_fp() = 0; + + virtual int fprintf(const char *format, ...) = 0; + + virtual int fgetc() = 0; + virtual int fputc(int c) = 0; + + virtual size_t _fread(const void *ptr, size_t bytes) = 0; + + //removing these return values for now so we can find any code that might be using them and make sure + //they handle the return values correctly + + virtual void fwrite(const void *ptr, size_t bytes) = 0; + + void write64le(u64* val); + void write64le(u64 val); + size_t read64le(u64* val); + u64 read64le(); + void write32le(u32* val); + void write32le(s32* val) { write32le((u32*)val); } + void write32le(u32 val); + size_t read32le(u32* val); + size_t read32le(s32* val); + u32 read32le(); + void write16le(u16* val); + void write16le(s16* val) { write16le((u16*)val); } + void write16le(u16 val); + size_t read16le(s16* Bufo); + size_t read16le(u16* val); + u16 read16le(); + void write8le(u8* val); + void write8le(u8 val); + size_t read8le(u8* val); + u8 read8le(); + void writedouble(double* val); + void writedouble(double val); + double readdouble(); + size_t readdouble(double* val); + + virtual int fseek(int offset, int origin) = 0; + + virtual int ftell() = 0; + virtual int size() = 0; + virtual void fflush() = 0; + + virtual void truncate(s32 length) = 0; +}; + +//todo - handle read-only specially? +class EMUFILE_MEMORY : public EMUFILE { +protected: + std::vector<u8> *vec; + bool ownvec; + s32 pos, len; + + void reserve(u32 amt) { + if(vec->size() < amt) + vec->resize(amt); + } + +public: + + EMUFILE_MEMORY(std::vector<u8> *underlying) : vec(underlying), ownvec(false), pos(0), len((s32)underlying->size()) { } + EMUFILE_MEMORY(u32 preallocate) : vec(new std::vector<u8>()), ownvec(true), pos(0), len(0) { + vec->resize(preallocate); + len = preallocate; + } + EMUFILE_MEMORY() : vec(new std::vector<u8>()), ownvec(true), pos(0), len(0) { vec->reserve(1024); } + EMUFILE_MEMORY(void* buf, s32 size) : vec(new std::vector<u8>()), ownvec(true), pos(0), len(size) { + vec->resize(size); + if(size != 0) + memcpy(&vec->front(),buf,size); + } + + ~EMUFILE_MEMORY() { + if(ownvec) delete vec; + } + + virtual EMUFILE* memwrap(); + + virtual void truncate(s32 length) + { + vec->resize(length); + len = length; + if(pos>length) pos=length; + } + + u8* buf() { + if(size()==0) reserve(1); + return &(*vec)[0]; + } + + std::vector<u8>* get_vec() { return vec; }; + + virtual FILE *get_fp() { return NULL; } + + virtual int fprintf(const char *format, ...) { + va_list argptr; + va_start(argptr, format); + + //we dont generate straight into the buffer because it will null terminate (one more byte than we want) + int amt = vsnprintf(0,0,format,argptr); + char* tempbuf = new char[amt+1]; + + va_end(argptr); + va_start(argptr, format); + vsprintf(tempbuf,format,argptr); + + fwrite(tempbuf,amt); + delete[] tempbuf; + + va_end(argptr); + return amt; + }; + + virtual int fgetc() { + u8 temp; + + //need an optimized codepath + //if(_fread(&temp,1) != 1) + // return EOF; + //else return temp; + u32 remain = len-pos; + if(remain<1) { + failbit = true; + return -1; + } + temp = buf()[pos]; + pos++; + return temp; + } + virtual int fputc(int c) { + u8 temp = (u8)c; + //TODO + //if(fwrite(&temp,1)!=1) return EOF; + fwrite(&temp,1); + + return 0; + } + + virtual size_t _fread(const void *ptr, size_t bytes); + + //removing these return values for now so we can find any code that might be using them and make sure + //they handle the return values correctly + + virtual void fwrite(const void *ptr, size_t bytes){ + reserve(pos+(s32)bytes); + memcpy(buf()+pos,ptr,bytes); + pos += (s32)bytes; + len = std::max(pos,len); + } + + virtual int fseek(int offset, int origin){ + //work differently for read-only...? + switch(origin) { + case SEEK_SET: + pos = offset; + break; + case SEEK_CUR: + pos += offset; + break; + case SEEK_END: + pos = size()+offset; + break; + default: + assert(false); + } + reserve(pos); + return 0; + } + + virtual int ftell() { + return pos; + } + + virtual void fflush() {} + + void trim() + { + vec->resize(len); + } + + virtual int size() { return (int)len; } +}; + +class EMUFILE_FILE : public EMUFILE { +protected: + FILE* fp; + std::string fname; + char mode[16]; + +private: + void open(const char* fname, const char* mode) + { + fp = fopen(fname,mode); + if(!fp) + failbit = true; + this->fname = fname; + strcpy(this->mode,mode); + } + +public: + + EMUFILE_FILE(const std::string& fname, const char* mode) { open(fname.c_str(),mode); } + EMUFILE_FILE(const char* fname, const char* mode) { open(fname,mode); } + + virtual ~EMUFILE_FILE() { + if(NULL != fp) + fclose(fp); + } + + virtual FILE *get_fp() { + return fp; + } + + virtual EMUFILE* memwrap(); + + bool is_open() { return fp != NULL; } + + virtual void truncate(s32 length); + + virtual int fprintf(const char *format, ...) { + va_list argptr; + va_start(argptr, format); + int ret = ::vfprintf(fp, format, argptr); + va_end(argptr); + return ret; + }; + + virtual int fgetc() { + return ::fgetc(fp); + } + virtual int fputc(int c) { + return ::fputc(c, fp); + } + + virtual size_t _fread(const void *ptr, size_t bytes){ + size_t ret = ::fread((void*)ptr, 1, bytes, fp); + if(ret < bytes) + failbit = true; + return ret; + } + + //removing these return values for now so we can find any code that might be using them and make sure + //they handle the return values correctly + + virtual void fwrite(const void *ptr, size_t bytes){ + size_t ret = ::fwrite((void*)ptr, 1, bytes, fp); + if(ret < bytes) + failbit = true; + } + + virtual int fseek(int offset, int origin) { + return ::fseek(fp, offset, origin); + } + + virtual int ftell() { + return (u32)::ftell(fp); + } + + virtual int size() { + int oldpos = ftell(); + fseek(0,SEEK_END); + int len = ftell(); + fseek(oldpos,SEEK_SET); + return len; + } + + virtual void fflush() { + ::fflush(fp); + } + +}; + +#endif diff --git a/jni/desmume/src/emufile_types.h b/jni/desmume/src/emufile_types.h new file mode 100755 index 0000000..c3cba54 --- /dev/null +++ b/jni/desmume/src/emufile_types.h @@ -0,0 +1,6 @@ +#ifndef EMUFILE_TYPES_H +#define EMUFILE_TYPES_H + +#include "types.h" + +#endif //EMUFILE_TYPES_H diff --git a/jni/desmume/src/filter/2xsai.cpp b/jni/desmume/src/filter/2xsai.cpp new file mode 100755 index 0000000..5cd35a7 --- /dev/null +++ b/jni/desmume/src/filter/2xsai.cpp @@ -0,0 +1,1182 @@ +#include "filter.h" +#include "types.h" + +//ref: http://vba-rerecording.googlecode.com/svn/trunk/src/2xsai.cpp + +static u32 colorMask = 0xfefefe; +static u32 lowPixelMask = 0x010101; +static u32 qcolorMask = 0xfcfcfc; +static u32 qlowpixelMask = 0x030303; +static u32 redblueMask = 0xF81F; +static u32 greenMask = 0x7E0; + +int Init_2xSaI(u32 BitFormat, u32 systemColorDepth) +{ + if(systemColorDepth == 16) { + if (BitFormat == 565) { + colorMask = 0xF7DEF7DE; + lowPixelMask = 0x08210821; + qcolorMask = 0xE79CE79C; + qlowpixelMask = 0x18631863; + redblueMask = 0xF81F; + greenMask = 0x7E0; + } else if (BitFormat == 555) { + colorMask = 0x7BDE7BDE; + lowPixelMask = 0x04210421; + qcolorMask = 0x739C739C; + qlowpixelMask = 0x0C630C63; + redblueMask = 0x7C1F; + greenMask = 0x3E0; + } else { + return 0; + } + } else if(systemColorDepth == 32) { + colorMask = 0xfefefe; + lowPixelMask = 0x010101; + qcolorMask = 0xfcfcfc; + qlowpixelMask = 0x030303; + } else + return 0; + + return 1; +} + +static inline int GetResult1 (u32 A, u32 B, u32 C, u32 D, + u32 /* E */) +{ + int x = 0; + int y = 0; + int r = 0; + + if (A == C) + x += 1; + else if (B == C) + y += 1; + if (A == D) + x += 1; + else if (B == D) + y += 1; + if (x <= 1) + r += 1; + if (y <= 1) + r -= 1; + return r; +} + +static inline int GetResult2 (u32 A, u32 B, u32 C, u32 D, + u32 /* E */) +{ + int x = 0; + int y = 0; + int r = 0; + + if (A == C) + x += 1; + else if (B == C) + y += 1; + if (A == D) + x += 1; + else if (B == D) + y += 1; + if (x <= 1) + r -= 1; + if (y <= 1) + r += 1; + return r; +} + +static inline int GetResult (u32 A, u32 B, u32 C, u32 D) +{ + int x = 0; + int y = 0; + int r = 0; + + if (A == C) + x += 1; + else if (B == C) + y += 1; + if (A == D) + x += 1; + else if (B == D) + y += 1; + if (x <= 1) + r += 1; + if (y <= 1) + r -= 1; + return r; +} + +static inline u32 INTERPOLATE (u32 A, u32 B) +{ + if (A != B) { + return (((A & colorMask) >> 1) + ((B & colorMask) >> 1) + + (A & B & lowPixelMask)); + } else + return A; +} + +static inline u32 Q_INTERPOLATE (u32 A, u32 B, u32 C, u32 D) +{ + register u32 x = ((A & qcolorMask) >> 2) + + ((B & qcolorMask) >> 2) + + ((C & qcolorMask) >> 2) + ((D & qcolorMask) >> 2); + register u32 y = (A & qlowpixelMask) + + (B & qlowpixelMask) + (C & qlowpixelMask) + (D & qlowpixelMask); + + y = (y >> 2) & qlowpixelMask; + return x + y; +} + +#define BLUE_MASK565 0x001F001F +#define RED_MASK565 0xF800F800 +#define GREEN_MASK565 0x07E007E0 + +#define BLUE_MASK555 0x001F001F +#define RED_MASK555 0x7C007C00 +#define GREEN_MASK555 0x03E003E0 + +void Super2xSaI (u8 *srcPtr, u32 srcPitch, + u8 * /* deltaPtr */, u8 *dstPtr, u32 dstPitch, + int width, int height) +{ + u16 *bP; + u8 *dP; + u32 inc_bP; + u32 Nextline = srcPitch >> 1; + + { + inc_bP = 1; + + for (; height; height--) { + bP = (u16 *) srcPtr; + dP = (u8 *) dstPtr; + + for (u32 finish = width; finish; finish -= inc_bP) { + u32 color4, color5, color6; + u32 color1, color2, color3; + u32 colorA0, colorA1, colorA2, colorA3, + colorB0, colorB1, colorB2, colorB3, colorS1, colorS2; + u32 product1a, product1b, product2a, product2b; + + //--------------------------------------- B1 B2 + // 4 5 6 S2 + // 1 2 3 S1 + // A1 A2 + + colorB0 = *(bP - Nextline - 1); + colorB1 = *(bP - Nextline); + colorB2 = *(bP - Nextline + 1); + colorB3 = *(bP - Nextline + 2); + + color4 = *(bP - 1); + color5 = *(bP); + color6 = *(bP + 1); + colorS2 = *(bP + 2); + + color1 = *(bP + Nextline - 1); + color2 = *(bP + Nextline); + color3 = *(bP + Nextline + 1); + colorS1 = *(bP + Nextline + 2); + + colorA0 = *(bP + Nextline + Nextline - 1); + colorA1 = *(bP + Nextline + Nextline); + colorA2 = *(bP + Nextline + Nextline + 1); + colorA3 = *(bP + Nextline + Nextline + 2); + + //-------------------------------------- + if (color2 == color6 && color5 != color3) { + product2b = product1b = color2; + } else if (color5 == color3 && color2 != color6) { + product2b = product1b = color5; + } else if (color5 == color3 && color2 == color6) { + register int r = 0; + + r += GetResult (color6, color5, color1, colorA1); + r += GetResult (color6, color5, color4, colorB1); + r += GetResult (color6, color5, colorA2, colorS1); + r += GetResult (color6, color5, colorB2, colorS2); + + if (r > 0) + product2b = product1b = color6; + else if (r < 0) + product2b = product1b = color5; + else { + product2b = product1b = INTERPOLATE (color5, color6); + } + } else { + if (color6 == color3 && color3 == colorA1 + && color2 != colorA2 && color3 != colorA0) + product2b = + Q_INTERPOLATE (color3, color3, color3, color2); + else if (color5 == color2 && color2 == colorA2 + && colorA1 != color3 && color2 != colorA3) + product2b = + Q_INTERPOLATE (color2, color2, color2, color3); + else + product2b = INTERPOLATE (color2, color3); + + if (color6 == color3 && color6 == colorB1 + && color5 != colorB2 && color6 != colorB0) + product1b = + Q_INTERPOLATE (color6, color6, color6, color5); + else if (color5 == color2 && color5 == colorB2 + && colorB1 != color6 && color5 != colorB3) + product1b = + Q_INTERPOLATE (color6, color5, color5, color5); + else + product1b = INTERPOLATE (color5, color6); + } + + if (color5 == color3 && color2 != color6 && color4 == color5 + && color5 != colorA2) + product2a = INTERPOLATE (color2, color5); + else + if (color5 == color1 && color6 == color5 + && color4 != color2 && color5 != colorA0) + product2a = INTERPOLATE (color2, color5); + else + product2a = color2; + + if (color2 == color6 && color5 != color3 && color1 == color2 + && color2 != colorB2) + product1a = INTERPOLATE (color2, color5); + else + if (color4 == color2 && color3 == color2 + && color1 != color5 && color2 != colorB0) + product1a = INTERPOLATE (color2, color5); + else + product1a = color5; + +#ifdef WORDS_BIGENDIAN + product1a = (product1a << 16) | product1b; + product2a = (product2a << 16) | product2b; +#else + product1a = product1a | (product1b << 16); + product2a = product2a | (product2b << 16); +#endif + + *((u32 *) dP) = product1a; + *((u32 *) (dP + dstPitch)) = product2a; + + bP += inc_bP; + dP += sizeof (u32); + } // end of for ( finish= width etc..) + + srcPtr += srcPitch; + dstPtr += dstPitch * 2; +// deltaPtr += srcPitch; + } // endof: for (; height; height--) + } +} + +void Super2xSaI32 (u8 *srcPtr, u32 srcPitch, + u8 * /* deltaPtr */, u8 *dstPtr, u32 dstPitch, + int width, int height) +{ + u32 *bP; + u32 *dP; + u32 inc_bP; + u32 Nextline = srcPitch >> 2; + inc_bP = 1; + + for (; height; height--) { + bP = (u32 *) srcPtr; + dP = (u32 *) dstPtr; + + for (u32 finish = width; finish; finish -= inc_bP) { + u32 color4, color5, color6; + u32 color1, color2, color3; + u32 colorA0, colorA1, colorA2, colorA3, + colorB0, colorB1, colorB2, colorB3, colorS1, colorS2; + u32 product1a, product1b, product2a, product2b; + + //--------------------------------------- B1 B2 + // 4 5 6 S2 + // 1 2 3 S1 + // A1 A2 + + colorB0 = *(bP - Nextline - 1); + colorB1 = *(bP - Nextline); + colorB2 = *(bP - Nextline + 1); + colorB3 = *(bP - Nextline + 2); + + color4 = *(bP - 1); + color5 = *(bP); + color6 = *(bP + 1); + colorS2 = *(bP + 2); + + color1 = *(bP + Nextline - 1); + color2 = *(bP + Nextline); + color3 = *(bP + Nextline + 1); + colorS1 = *(bP + Nextline + 2); + + colorA0 = *(bP + Nextline + Nextline - 1); + colorA1 = *(bP + Nextline + Nextline); + colorA2 = *(bP + Nextline + Nextline + 1); + colorA3 = *(bP + Nextline + Nextline + 2); + + //-------------------------------------- + if (color2 == color6 && color5 != color3) { + product2b = product1b = color2; + } else if (color5 == color3 && color2 != color6) { + product2b = product1b = color5; + } else if (color5 == color3 && color2 == color6) { + register int r = 0; + + r += GetResult (color6, color5, color1, colorA1); + r += GetResult (color6, color5, color4, colorB1); + r += GetResult (color6, color5, colorA2, colorS1); + r += GetResult (color6, color5, colorB2, colorS2); + + if (r > 0) + product2b = product1b = color6; + else if (r < 0) + product2b = product1b = color5; + else { + product2b = product1b = INTERPOLATE (color5, color6); + } + } else { + if (color6 == color3 && color3 == colorA1 + && color2 != colorA2 && color3 != colorA0) + product2b = + Q_INTERPOLATE (color3, color3, color3, color2); + else if (color5 == color2 && color2 == colorA2 + && colorA1 != color3 && color2 != colorA3) + product2b = + Q_INTERPOLATE (color2, color2, color2, color3); + else + product2b = INTERPOLATE (color2, color3); + + if (color6 == color3 && color6 == colorB1 + && color5 != colorB2 && color6 != colorB0) + product1b = + Q_INTERPOLATE (color6, color6, color6, color5); + else if (color5 == color2 && color5 == colorB2 + && colorB1 != color6 && color5 != colorB3) + product1b = + Q_INTERPOLATE (color6, color5, color5, color5); + else + product1b = INTERPOLATE (color5, color6); + } + + if (color5 == color3 && color2 != color6 && color4 == color5 + && color5 != colorA2) + product2a = INTERPOLATE (color2, color5); + else + if (color5 == color1 && color6 == color5 + && color4 != color2 && color5 != colorA0) + product2a = INTERPOLATE (color2, color5); + else + product2a = color2; + + if (color2 == color6 && color5 != color3 && color1 == color2 + && color2 != colorB2) + product1a = INTERPOLATE (color2, color5); + else + if (color4 == color2 && color3 == color2 + && color1 != color5 && color2 != colorB0) + product1a = INTERPOLATE (color2, color5); + else + product1a = color5; + *(dP) = product1a; + *(dP+1) = product1b; + *(dP + (dstPitch >> 2)) = product2a; + *(dP + (dstPitch >> 2) + 1) = product2b; + + bP += inc_bP; + dP += 2; + } // end of for ( finish= width etc..) + + srcPtr += srcPitch; + dstPtr += dstPitch * 2; +// deltaPtr += srcPitch; + } // endof: for (; height; height--) +} + +void SuperEagle (u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u8 *dP; + u16 *bP; +// u16 *xP; + u32 inc_bP; + + { + inc_bP = 1; + + u32 Nextline = srcPitch >> 1; + + for (; height; height--) { + bP = (u16 *) srcPtr; +// xP = (u16 *) deltaPtr; + dP = dstPtr; + for (u32 finish = width; finish; finish -= inc_bP) { + u32 color4, color5, color6; + u32 color1, color2, color3; + u32 colorA1, colorA2, colorB1, colorB2, colorS1, colorS2; + u32 product1a, product1b, product2a, product2b; + + colorB1 = *(bP - Nextline); + colorB2 = *(bP - Nextline + 1); + + color4 = *(bP - 1); + color5 = *(bP); + color6 = *(bP + 1); + colorS2 = *(bP + 2); + + color1 = *(bP + Nextline - 1); + color2 = *(bP + Nextline); + color3 = *(bP + Nextline + 1); + colorS1 = *(bP + Nextline + 2); + + colorA1 = *(bP + Nextline + Nextline); + colorA2 = *(bP + Nextline + Nextline + 1); + + // -------------------------------------- + if (color2 == color6 && color5 != color3) { + product1b = product2a = color2; + if ((color1 == color2) || (color6 == colorB2)) { + product1a = INTERPOLATE (color2, color5); + product1a = INTERPOLATE (color2, product1a); + // product1a = color2; + } else { + product1a = INTERPOLATE (color5, color6); + } + + if ((color6 == colorS2) || (color2 == colorA1)) { + product2b = INTERPOLATE (color2, color3); + product2b = INTERPOLATE (color2, product2b); + // product2b = color2; + } else { + product2b = INTERPOLATE (color2, color3); + } + } else if (color5 == color3 && color2 != color6) { + product2b = product1a = color5; + + if ((colorB1 == color5) || (color3 == colorS1)) { + product1b = INTERPOLATE (color5, color6); + product1b = INTERPOLATE (color5, product1b); + // product1b = color5; + } else { + product1b = INTERPOLATE (color5, color6); + } + + if ((color3 == colorA2) || (color4 == color5)) { + product2a = INTERPOLATE (color5, color2); + product2a = INTERPOLATE (color5, product2a); + // product2a = color5; + } else { + product2a = INTERPOLATE (color2, color3); + } + + } else if (color5 == color3 && color2 == color6) { + register int r = 0; + + r += GetResult (color6, color5, color1, colorA1); + r += GetResult (color6, color5, color4, colorB1); + r += GetResult (color6, color5, colorA2, colorS1); + r += GetResult (color6, color5, colorB2, colorS2); + + if (r > 0) { + product1b = product2a = color2; + product1a = product2b = INTERPOLATE (color5, color6); + } else if (r < 0) { + product2b = product1a = color5; + product1b = product2a = INTERPOLATE (color5, color6); + } else { + product2b = product1a = color5; + product1b = product2a = color2; + } + } else { + product2b = product1a = INTERPOLATE (color2, color6); + product2b = + Q_INTERPOLATE (color3, color3, color3, product2b); + product1a = + Q_INTERPOLATE (color5, color5, color5, product1a); + + product2a = product1b = INTERPOLATE (color5, color3); + product2a = + Q_INTERPOLATE (color2, color2, color2, product2a); + product1b = + Q_INTERPOLATE (color6, color6, color6, product1b); + + // product1a = color5; + // product1b = color6; + // product2a = color2; + // product2b = color3; + } +#ifdef WORDS_BIGENDIAN + product1a = (product1a << 16) | product1b; + product2a = (product2a << 16) | product2b; +#else + product1a = product1a | (product1b << 16); + product2a = product2a | (product2b << 16); +#endif + + *((u32 *) dP) = product1a; + *((u32 *) (dP + dstPitch)) = product2a; +// *xP = color5; + + bP += inc_bP; +// xP += inc_bP; + dP += sizeof (u32); + } // end of for ( finish= width etc..) + + srcPtr += srcPitch; + dstPtr += dstPitch * 2; +// deltaPtr += srcPitch; + } // endof: for (height; height; height--) + } +} + +void SuperEagle32 (u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u32 *dP; + u32 *bP; +// u32 *xP; + u32 inc_bP; + + inc_bP = 1; + + u32 Nextline = srcPitch >> 2; + + for (; height; height--) { + bP = (u32 *) srcPtr; +// xP = (u32 *) deltaPtr; + dP = (u32 *)dstPtr; + for (u32 finish = width; finish; finish -= inc_bP) { + u32 color4, color5, color6; + u32 color1, color2, color3; + u32 colorA1, colorA2, colorB1, colorB2, colorS1, colorS2; + u32 product1a, product1b, product2a, product2b; + + colorB1 = *(bP - Nextline); + colorB2 = *(bP - Nextline + 1); + + color4 = *(bP - 1); + color5 = *(bP); + color6 = *(bP + 1); + colorS2 = *(bP + 2); + + color1 = *(bP + Nextline - 1); + color2 = *(bP + Nextline); + color3 = *(bP + Nextline + 1); + colorS1 = *(bP + Nextline + 2); + + colorA1 = *(bP + Nextline + Nextline); + colorA2 = *(bP + Nextline + Nextline + 1); + + // -------------------------------------- + if (color2 == color6 && color5 != color3) { + product1b = product2a = color2; + if ((color1 == color2) || (color6 == colorB2)) { + product1a = INTERPOLATE (color2, color5); + product1a = INTERPOLATE (color2, product1a); + // product1a = color2; + } else { + product1a = INTERPOLATE (color5, color6); + } + + if ((color6 == colorS2) || (color2 == colorA1)) { + product2b = INTERPOLATE (color2, color3); + product2b = INTERPOLATE (color2, product2b); + // product2b = color2; + } else { + product2b = INTERPOLATE (color2, color3); + } + } else if (color5 == color3 && color2 != color6) { + product2b = product1a = color5; + + if ((colorB1 == color5) || (color3 == colorS1)) { + product1b = INTERPOLATE (color5, color6); + product1b = INTERPOLATE (color5, product1b); + // product1b = color5; + } else { + product1b = INTERPOLATE (color5, color6); + } + + if ((color3 == colorA2) || (color4 == color5)) { + product2a = INTERPOLATE (color5, color2); + product2a = INTERPOLATE (color5, product2a); + // product2a = color5; + } else { + product2a = INTERPOLATE (color2, color3); + } + + } else if (color5 == color3 && color2 == color6) { + register int r = 0; + + r += GetResult (color6, color5, color1, colorA1); + r += GetResult (color6, color5, color4, colorB1); + r += GetResult (color6, color5, colorA2, colorS1); + r += GetResult (color6, color5, colorB2, colorS2); + + if (r > 0) { + product1b = product2a = color2; + product1a = product2b = INTERPOLATE (color5, color6); + } else if (r < 0) { + product2b = product1a = color5; + product1b = product2a = INTERPOLATE (color5, color6); + } else { + product2b = product1a = color5; + product1b = product2a = color2; + } + } else { + product2b = product1a = INTERPOLATE (color2, color6); + product2b = + Q_INTERPOLATE (color3, color3, color3, product2b); + product1a = + Q_INTERPOLATE (color5, color5, color5, product1a); + + product2a = product1b = INTERPOLATE (color5, color3); + product2a = + Q_INTERPOLATE (color2, color2, color2, product2a); + product1b = + Q_INTERPOLATE (color6, color6, color6, product1b); + + // product1a = color5; + // product1b = color6; + // product2a = color2; + // product2b = color3; + } + *(dP) = product1a; + *(dP+1) = product1b; + *(dP + (dstPitch >> 2)) = product2a; + *(dP + (dstPitch >> 2) +1) = product2b; +// *xP = color5; + + bP += inc_bP; +// xP += inc_bP; + dP += 2; + } // end of for ( finish= width etc..) + + srcPtr += srcPitch; + dstPtr += dstPitch * 2; +// deltaPtr += srcPitch; + } // endof: for (height; height; height--) +} + +void _2xSaI (u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u8 *dP; + u16 *bP; + u32 inc_bP; + + { + inc_bP = 1; + + u32 Nextline = srcPitch >> 1; + + for (; height; height--) { + bP = (u16 *) srcPtr; + dP = dstPtr; + + for (u32 finish = width; finish; finish -= inc_bP) { + + register u32 colorA, colorB; + u32 colorC, colorD, + colorE, colorF, colorG, colorH, + colorI, colorJ, colorK, colorL, + + colorM, colorN, colorO, colorP; + u32 product, product1, product2; + + //--------------------------------------- + // Map of the pixels: I|E F|J + // G|A B|K + // H|C D|L + // M|N O|P + colorI = *(bP - Nextline - 1); + colorE = *(bP - Nextline); + colorF = *(bP - Nextline + 1); + colorJ = *(bP - Nextline + 2); + + colorG = *(bP - 1); + colorA = *(bP); + colorB = *(bP + 1); + colorK = *(bP + 2); + + colorH = *(bP + Nextline - 1); + colorC = *(bP + Nextline); + colorD = *(bP + Nextline + 1); + colorL = *(bP + Nextline + 2); + + colorM = *(bP + Nextline + Nextline - 1); + colorN = *(bP + Nextline + Nextline); + colorO = *(bP + Nextline + Nextline + 1); + colorP = *(bP + Nextline + Nextline + 2); + + if ((colorA == colorD) && (colorB != colorC)) { + if (((colorA == colorE) && (colorB == colorL)) || + ((colorA == colorC) && (colorA == colorF) + && (colorB != colorE) && (colorB == colorJ))) { + product = colorA; + } else { + product = INTERPOLATE (colorA, colorB); + } + + if (((colorA == colorG) && (colorC == colorO)) || + ((colorA == colorB) && (colorA == colorH) + && (colorG != colorC) && (colorC == colorM))) { + product1 = colorA; + } else { + product1 = INTERPOLATE (colorA, colorC); + } + product2 = colorA; + } else if ((colorB == colorC) && (colorA != colorD)) { + if (((colorB == colorF) && (colorA == colorH)) || + ((colorB == colorE) && (colorB == colorD) + && (colorA != colorF) && (colorA == colorI))) { + product = colorB; + } else { + product = INTERPOLATE (colorA, colorB); + } + + if (((colorC == colorH) && (colorA == colorF)) || + ((colorC == colorG) && (colorC == colorD) + && (colorA != colorH) && (colorA == colorI))) { + product1 = colorC; + } else { + product1 = INTERPOLATE (colorA, colorC); + } + product2 = colorB; + } else if ((colorA == colorD) && (colorB == colorC)) { + if (colorA == colorB) { + product = colorA; + product1 = colorA; + product2 = colorA; + } else { + register int r = 0; + + product1 = INTERPOLATE (colorA, colorC); + product = INTERPOLATE (colorA, colorB); + + r += GetResult1 (colorA, colorB, colorG, colorE, colorI); + r += GetResult2 (colorB, colorA, colorK, colorF, colorJ); + r += GetResult2 (colorB, colorA, colorH, colorN, colorM); + r += GetResult1 (colorA, colorB, colorL, colorO, colorP); + + if (r > 0) + product2 = colorA; + else if (r < 0) + product2 = colorB; + else { + product2 = Q_INTERPOLATE (colorA, colorB, colorC, colorD); + } + } + } else { + product2 = Q_INTERPOLATE (colorA, colorB, colorC, colorD); + + if ((colorA == colorC) && (colorA == colorF) + && (colorB != colorE) && (colorB == colorJ)) { + product = colorA; + } else if ((colorB == colorE) && (colorB == colorD) + && (colorA != colorF) && (colorA == colorI)) { + product = colorB; + } else { + product = INTERPOLATE (colorA, colorB); + } + + if ((colorA == colorB) && (colorA == colorH) + && (colorG != colorC) && (colorC == colorM)) { + product1 = colorA; + } else if ((colorC == colorG) && (colorC == colorD) + && (colorA != colorH) && (colorA == colorI)) { + product1 = colorC; + } else { + product1 = INTERPOLATE (colorA, colorC); + } + } + +#ifdef WORDS_BIGENDIAN + product = (colorA << 16) | product ; + product1 = (product1 << 16) | product2 ; +#else + product = colorA | (product << 16); + product1 = product1 | (product2 << 16); +#endif + *((s32 *) dP) = product; + *((u32 *) (dP + dstPitch)) = product1; + + bP += inc_bP; + dP += sizeof (u32); + } // end of for ( finish= width etc..) + + srcPtr += srcPitch; + dstPtr += dstPitch * 2; +// deltaPtr += srcPitch; + } // endof: for (height; height; height--) + } +} + +void _2xSaI32 (u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u32 *dP; + u32 *bP; + u32 inc_bP = 1; + + u32 Nextline = srcPitch >> 2; + + for (; height; height--) { + bP = (u32 *) srcPtr; + dP = (u32 *) dstPtr; + + for (u32 finish = width; finish; finish -= inc_bP) { + register u32 colorA, colorB; + u32 colorC, colorD, + colorE, colorF, colorG, colorH, + colorI, colorJ, colorK, colorL, + + colorM, colorN, colorO, colorP; + u32 product, product1, product2; + + //--------------------------------------- + // Map of the pixels: I|E F|J + // G|A B|K + // H|C D|L + // M|N O|P + colorI = *(bP - Nextline - 1); + colorE = *(bP - Nextline); + colorF = *(bP - Nextline + 1); + colorJ = *(bP - Nextline + 2); + + colorG = *(bP - 1); + colorA = *(bP); + colorB = *(bP + 1); + colorK = *(bP + 2); + + colorH = *(bP + Nextline - 1); + colorC = *(bP + Nextline); + colorD = *(bP + Nextline + 1); + colorL = *(bP + Nextline + 2); + + colorM = *(bP + Nextline + Nextline - 1); + colorN = *(bP + Nextline + Nextline); + colorO = *(bP + Nextline + Nextline + 1); + colorP = *(bP + Nextline + Nextline + 2); + + if ((colorA == colorD) && (colorB != colorC)) { + if (((colorA == colorE) && (colorB == colorL)) || + ((colorA == colorC) && (colorA == colorF) + && (colorB != colorE) && (colorB == colorJ))) { + product = colorA; + } else { + product = INTERPOLATE (colorA, colorB); + } + + if (((colorA == colorG) && (colorC == colorO)) || + ((colorA == colorB) && (colorA == colorH) + && (colorG != colorC) && (colorC == colorM))) { + product1 = colorA; + } else { + product1 = INTERPOLATE (colorA, colorC); + } + product2 = colorA; + } else if ((colorB == colorC) && (colorA != colorD)) { + if (((colorB == colorF) && (colorA == colorH)) || + ((colorB == colorE) && (colorB == colorD) + && (colorA != colorF) && (colorA == colorI))) { + product = colorB; + } else { + product = INTERPOLATE (colorA, colorB); + } + + if (((colorC == colorH) && (colorA == colorF)) || + ((colorC == colorG) && (colorC == colorD) + && (colorA != colorH) && (colorA == colorI))) { + product1 = colorC; + } else { + product1 = INTERPOLATE (colorA, colorC); + } + product2 = colorB; + } else if ((colorA == colorD) && (colorB == colorC)) { + if (colorA == colorB) { + product = colorA; + product1 = colorA; + product2 = colorA; + } else { + register int r = 0; + + product1 = INTERPOLATE (colorA, colorC); + product = INTERPOLATE (colorA, colorB); + + r += GetResult1 (colorA, colorB, colorG, colorE, colorI); + r += GetResult2 (colorB, colorA, colorK, colorF, colorJ); + r += GetResult2 (colorB, colorA, colorH, colorN, colorM); + r += GetResult1 (colorA, colorB, colorL, colorO, colorP); + + if (r > 0) + product2 = colorA; + else if (r < 0) + product2 = colorB; + else { + product2 = Q_INTERPOLATE (colorA, colorB, colorC, colorD); + } + } + } else { + product2 = Q_INTERPOLATE (colorA, colorB, colorC, colorD); + + if ((colorA == colorC) && (colorA == colorF) + && (colorB != colorE) && (colorB == colorJ)) { + product = colorA; + } else if ((colorB == colorE) && (colorB == colorD) + && (colorA != colorF) && (colorA == colorI)) { + product = colorB; + } else { + product = INTERPOLATE (colorA, colorB); + } + + if ((colorA == colorB) && (colorA == colorH) + && (colorG != colorC) && (colorC == colorM)) { + product1 = colorA; + } else if ((colorC == colorG) && (colorC == colorD) + && (colorA != colorH) && (colorA == colorI)) { + product1 = colorC; + } else { + product1 = INTERPOLATE (colorA, colorC); + } + } + *(dP) = colorA; + *(dP + 1) = product; + *(dP + (dstPitch >> 2)) = product1; + *(dP + (dstPitch >> 2) + 1) = product2; + + bP += inc_bP; + dP += 2; + } // end of for ( finish= width etc..) + + srcPtr += srcPitch; + dstPtr += dstPitch * 2; +// deltaPtr += srcPitch; + } // endof: for (height; height; height--) +} + +static u32 Bilinear (u32 A, u32 B, u32 x) +{ + unsigned long areaA, areaB; + unsigned long result; + + if (A == B) + return A; + + areaB = (x >> 11) & 0x1f; // reduce 16 bit fraction to 5 bits + areaA = 0x20 - areaB; + + A = (A & redblueMask) | ((A & greenMask) << 16); + B = (B & redblueMask) | ((B & greenMask) << 16); + + result = ((areaA * A) + (areaB * B)) >> 5; + + return (result & redblueMask) | ((result >> 16) & greenMask); +} + +static u32 Bilinear4 (u32 A, u32 B, u32 C, u32 D, u32 x, + u32 y) +{ + unsigned long areaA, areaB, areaC, areaD; + unsigned long result, xy; + + x = (x >> 11) & 0x1f; + y = (y >> 11) & 0x1f; + xy = (x * y) >> 5; + + A = (A & redblueMask) | ((A & greenMask) << 16); + B = (B & redblueMask) | ((B & greenMask) << 16); + C = (C & redblueMask) | ((C & greenMask) << 16); + D = (D & redblueMask) | ((D & greenMask) << 16); + + areaA = 0x20 + xy - x - y; + areaB = x - xy; + areaC = y - xy; + areaD = xy; + + result = ((areaA * A) + (areaB * B) + (areaC * C) + (areaD * D)) >> 5; + + return (result & redblueMask) | ((result >> 16) & greenMask); +} + +void Scale_2xSaI (u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, + u32 dstWidth, u32 dstHeight, int width, int height) +{ + u8 *dP; + u16 *bP; + + u32 w; + u32 h; + u32 dw; + u32 dh; + u32 hfinish; + u32 wfinish; + + u32 Nextline = srcPitch >> 1; + + wfinish = (width - 1) << 16; // convert to fixed point + dw = wfinish / (dstWidth - 1); + hfinish = (height - 1) << 16; // convert to fixed point + dh = hfinish / (dstHeight - 1); + + for (h = 0; h < hfinish; h += dh) { + u32 y1, y2; + + y1 = h & 0xffff; // fraction part of fixed point + bP = (u16 *) (srcPtr + ((h >> 16) * srcPitch)); + dP = dstPtr; + y2 = 0x10000 - y1; + + w = 0; + + for (; w < wfinish;) { + u32 A, B, C, D; + u32 E, F, G, H; + u32 I, J, K, L; + u32 x1, x2, a1, f1, f2; + u32 position, product1; + + position = w >> 16; + A = bP[position]; // current pixel + B = bP[position + 1]; // next pixel + C = bP[position + Nextline]; + D = bP[position + Nextline + 1]; + E = bP[position - Nextline]; + F = bP[position - Nextline + 1]; + G = bP[position - 1]; + H = bP[position + Nextline - 1]; + I = bP[position + 2]; + J = bP[position + Nextline + 2]; + K = bP[position + Nextline + Nextline]; + L = bP[position + Nextline + Nextline + 1]; + + x1 = w & 0xffff; // fraction part of fixed point + x2 = 0x10000 - x1; + + /*0*/ + if (A == B && C == D && A == C) + product1 = A; + else /*1*/ if (A == D && B != C) { + f1 = (x1 >> 1) + (0x10000 >> 2); + f2 = (y1 >> 1) + (0x10000 >> 2); + if (y1 <= f1 && A == J && A != E) // close to B + { + a1 = f1 - y1; + product1 = Bilinear (A, B, a1); + } else if (y1 >= f1 && A == G && A != L) // close to C + { + a1 = y1 - f1; + product1 = Bilinear (A, C, a1); + } + else if (x1 >= f2 && A == E && A != J) // close to B + { + a1 = x1 - f2; + product1 = Bilinear (A, B, a1); + } + else if (x1 <= f2 && A == L && A != G) // close to C + { + a1 = f2 - x1; + product1 = Bilinear (A, C, a1); + } + else if (y1 >= x1) // close to C + { + a1 = y1 - x1; + product1 = Bilinear (A, C, a1); + } + else if (y1 <= x1) // close to B + { + a1 = x1 - y1; + product1 = Bilinear (A, B, a1); + } + } + else + /*2*/ + if (B == C && A != D) + { + f1 = (x1 >> 1) + (0x10000 >> 2); + f2 = (y1 >> 1) + (0x10000 >> 2); + if (y2 >= f1 && B == H && B != F) // close to A + { + a1 = y2 - f1; + product1 = Bilinear (B, A, a1); + } + else if (y2 <= f1 && B == I && B != K) // close to D + { + a1 = f1 - y2; + product1 = Bilinear (B, D, a1); + } + else if (x2 >= f2 && B == F && B != H) // close to A + { + a1 = x2 - f2; + product1 = Bilinear (B, A, a1); + } + else if (x2 <= f2 && B == K && B != I) // close to D + { + a1 = f2 - x2; + product1 = Bilinear (B, D, a1); + } + else if (y2 >= x1) // close to A + { + a1 = y2 - x1; + product1 = Bilinear (B, A, a1); + } + else if (y2 <= x1) // close to D + { + a1 = x1 - y2; + product1 = Bilinear (B, D, a1); + } + } + /*3*/ + else + { + product1 = Bilinear4 (A, B, C, D, x1, y1); + } + + //end First Pixel + *(u32 *) dP = product1; + dP += 2; + w += dw; + } + dstPtr += dstPitch; + } +} + +void Render2xSaI (SSurface Src, SSurface Dst) +{ + unsigned char *lpSrc, *lpDst; + + lpSrc = Src.Surface; + lpDst = Dst.Surface; + + _2xSaI32 (lpSrc, Src.Pitch*2, lpSrc, + lpDst, Dst.Pitch*2, Src.Width, Src.Height); + +} + +void RenderSuper2xSaI (SSurface Src, SSurface Dst) +{ + + unsigned char *lpSrc, *lpDst; + + lpSrc = Src.Surface; + lpDst = Dst.Surface; + + Super2xSaI32 (lpSrc, Src.Pitch*2, + lpSrc, + lpDst, Dst.Pitch*2, Src.Width, Src.Height); + +} + +void RenderSuperEagle (SSurface Src, SSurface Dst) +{ + + unsigned char *lpSrc, *lpDst; + + lpSrc = Src.Surface; + lpDst = Dst.Surface; + + SuperEagle32 (lpSrc, Src.Pitch*2, + lpSrc, + lpDst, Dst.Pitch*2, Src.Width, Src.Height); + +} diff --git a/jni/desmume/src/filter/bilinear.cpp b/jni/desmume/src/filter/bilinear.cpp new file mode 100755 index 0000000..a1a3b49 --- /dev/null +++ b/jni/desmume/src/filter/bilinear.cpp @@ -0,0 +1,443 @@ +/** Code adapted from Exult source code by Forgotten + ** Scale.cc - Trying to scale with bilinear interpolation. + ** + ** Written: 6/14/00 - JSF + **/ + +#include "types.h" + +int systemRedShift = 16; +int systemGreenShift = 8; +int systemBlueShift = 0; +/* +#define RGB1(r,g,b) ((r)>>3) << systemRedShift |\ + ((g) >> 3) << systemGreenShift |\ + ((b) >> 3) << systemBlueShift\ +*/ +#define RGB1(r,g,b) (((r))<<systemRedShift) | (((g)) << systemGreenShift) | (((b)) << systemBlueShift) + +static void fill_rgb_row_16(u16 *from, int src_width, u8 *row, int width) +{ + u8 *copy_start = row + src_width*3; + u8 *all_stop = row + width*3; + while (row < copy_start) { + u16 color = *from++; + *row++ = ((color >> systemRedShift) & 0x1f) << 3; + *row++ = ((color >> systemGreenShift) & 0x1f) << 3; + *row++ = ((color >> systemBlueShift) & 0x1f) << 3; + } + // any remaining elements to be written to 'row' are a replica of the + // preceding pixel + u8 *p = row-3; + while (row < all_stop) { + // we're guaranteed three elements per pixel; could unroll the loop + // further, especially with a Duff's Device, but the gains would be + // probably limited (judging by profiler output) + *row++ = *p++; + *row++ = *p++; + *row++ = *p++; + } +} + +static void fill_rgb_row_32(u32 *from, int src_width, u8 *row, int width) +{ + u8 *copy_start = row + src_width*3; + u8 *all_stop = row + width*3; + while (row < copy_start) { + u32 color = *from++; + *row++ = ((color >> (systemRedShift)) ) ; + *row++ = ((color >> (systemGreenShift)) ) ; + *row++ = ((color >> (systemBlueShift)) ) ; + } + // any remaining elements to be written to 'row' are a replica of the + // preceding pixel + u8 *p = row-3; + while (row < all_stop) { + // we're guaranteed three elements per pixel; could unroll the loop + // further, especially with a Duff's Device, but the gains would be + // probably limited (judging by profiler output) + *row++ = *p++; + *row++ = *p++; + *row++ = *p++; + } +} + +void Bilinear(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u8 row_cur[3*322]; + u8 row_next[3*322]; + u8 *rgb_row_cur = row_cur; + u8 *rgb_row_next = row_next; + + u16 *to = (u16 *)dstPtr; + u16 *to_odd = (u16 *)(dstPtr + dstPitch); + + int from_width = width; + u16 *from = (u16 *)srcPtr; + fill_rgb_row_16(from, from_width, rgb_row_cur, width+1); + + for(int y = 0; y < height; y++) { + u16 *from_orig = from; + u16 *to_orig = to; + + if (y+1 < height) + fill_rgb_row_16(from+width, from_width, rgb_row_next, + width+1); + else + fill_rgb_row_16(from, from_width, rgb_row_next, width+1); + + // every pixel in the src region, is extended to 4 pixels in the + // destination, arranged in a square 'quad'; if the current src + // pixel is 'a', then in what follows 'b' is the src pixel to the + // right, 'c' is the src pixel below, and 'd' is the src pixel to + // the right and down + u8 *cur_row = rgb_row_cur; + u8 *next_row = rgb_row_next; + u8 *ar = cur_row++; + u8 *ag = cur_row++; + u8 *ab = cur_row++; + u8 *cr = next_row++; + u8 *cg = next_row++; + u8 *cb = next_row++; + for(int x=0; x < width; x++) { + u8 *br = cur_row++; + u8 *bg = cur_row++; + u8 *bb = cur_row++; + u8 *dr = next_row++; + u8 *dg = next_row++; + u8 *db = next_row++; + + // upper left pixel in quad: just copy it in + *to++ = RGB1(*ar, *ag, *ab); + + // upper right + *to++ = RGB1((*ar+*br)>>1, (*ag+*bg)>>1, (*ab+*bb)>>1); + + // lower left + *to_odd++ = RGB1((*ar+*cr)>>1, (*ag+*cg)>>1, (*ab+*cb)>>1); + + // lower right + *to_odd++ = RGB1((*ar+*br+*cr+*dr)>>2, + (*ag+*bg+*cg+*dg)>>2, + (*ab+*bb+*cb+*db)>>2); + + // 'b' becomes 'a', 'd' becomes 'c' + ar = br; + ag = bg; + ab = bb; + cr = dr; + cg = dg; + cb = db; + } + + // the "next" rgb row becomes the current; the old current rgb row is + // recycled and serves as the new "next" row + u8 *temp; + temp = rgb_row_cur; + rgb_row_cur = rgb_row_next; + rgb_row_next = temp; + + // update the pointers for start of next pair of lines + from = (u16 *)((u8 *)from_orig + srcPitch); + to = (u16 *)((u8 *)to_orig + (dstPitch << 1)); + to_odd = (u16 *)((u8 *)to + dstPitch); + } +} + +struct SSurface { + unsigned char *Surface; + + unsigned int Pitch; + unsigned int Width, Height; +}; + +void BilinearPlus(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u8 row_cur[3*322]; + u8 row_next[3*322]; + u8 *rgb_row_cur = row_cur; + u8 *rgb_row_next = row_next; + + u16 *to = (u16 *)dstPtr; + u16 *to_odd = (u16 *)(dstPtr + dstPitch); + + int from_width = width; + u16 *from = (u16 *)srcPtr; + fill_rgb_row_16(from, from_width, rgb_row_cur, width+1); + + for(int y = 0; y < height; y++) { + u16 *from_orig = from; + u16 *to_orig = to; + + if (y+1 < height) + fill_rgb_row_16(from+width, from_width, rgb_row_next, + width+1); + else + fill_rgb_row_16(from, from_width, rgb_row_next, width+1); + + // every pixel in the src region, is extended to 4 pixels in the + // destination, arranged in a square 'quad'; if the current src + // pixel is 'a', then in what follows 'b' is the src pixel to the + // right, 'c' is the src pixel below, and 'd' is the src pixel to + // the right and down + u8 *cur_row = rgb_row_cur; + u8 *next_row = rgb_row_next; + u8 *ar = cur_row++; + u8 *ag = cur_row++; + u8 *ab = cur_row++; + u8 *cr = next_row++; + u8 *cg = next_row++; + u8 *cb = next_row++; + for(int x=0; x < width; x++) { + u8 *br = cur_row++; + u8 *bg = cur_row++; + u8 *bb = cur_row++; + u8 *dr = next_row++; + u8 *dg = next_row++; + u8 *db = next_row++; + + // upper left pixel in quad: just copy it in + //*to++ = manip.rgb(*ar, *ag, *ab); +#ifdef USE_ORIGINAL_BILINEAR_PLUS + *to++ = RGB( + (((*ar)<<2) +((*ar)) + (*cr+*br+*br) )>> 3, + (((*ag)<<2) +((*ag)) + (*cg+*bg+*bg) )>> 3, + (((*ab)<<2) +((*ab)) + (*cb+*bb+*bb) )>> 3); +#else + *to++ = RGB1( + (((*ar)<<3) +((*ar)<<1) + (*cr+*br+*br+*cr) )>> 4, + (((*ag)<<3) +((*ag)<<1) + (*cg+*bg+*bg+*cg) )>> 4, + (((*ab)<<3) +((*ab)<<1) + (*cb+*bb+*bb+*cb) )>> 4); +#endif + + // upper right + *to++ = RGB1((*ar+*br)>>1, (*ag+*bg)>>1, (*ab+*bb)>>1); + + // lower left + *to_odd++ = RGB1((*ar+*cr)>>1, (*ag+*cg)>>1, (*ab+*cb)>>1); + + // lower right + *to_odd++ = RGB1((*ar+*br+*cr+*dr)>>2, + (*ag+*bg+*cg+*dg)>>2, + (*ab+*bb+*cb+*db)>>2); + + // 'b' becomes 'a', 'd' becomes 'c' + ar = br; + ag = bg; + ab = bb; + cr = dr; + cg = dg; + cb = db; + } + + // the "next" rgb row becomes the current; the old current rgb row is + // recycled and serves as the new "next" row + u8 *temp; + temp = rgb_row_cur; + rgb_row_cur = rgb_row_next; + rgb_row_next = temp; + + // update the pointers for start of next pair of lines + from = (u16 *)((u8 *)from_orig + srcPitch); + to = (u16 *)((u8 *)to_orig + (dstPitch << 1)); + to_odd = (u16 *)((u8 *)to + dstPitch); + } +} + +void Bilinear32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u8 row_cur[3*322]; + u8 row_next[3*322]; + u8 *rgb_row_cur = row_cur; + u8 *rgb_row_next = row_next; + + u32 *to = (u32 *)dstPtr; + u32 *to_odd = (u32 *)(dstPtr + dstPitch); + + int from_width = width; + + u32 *from = (u32 *)srcPtr; + fill_rgb_row_32(from, from_width, rgb_row_cur, width+1); + + for(int y = 0; y < height; y++) { + u32 *from_orig = from; + u32 *to_orig = to; + + if (y+1 < height) + fill_rgb_row_32(from+width+1, from_width, rgb_row_next, + width+1); + else + fill_rgb_row_32(from, from_width, rgb_row_next, width+1); + + // every pixel in the src region, is extended to 4 pixels in the + // destination, arranged in a square 'quad'; if the current src + // pixel is 'a', then in what follows 'b' is the src pixel to the + // right, 'c' is the src pixel below, and 'd' is the src pixel to + // the right and down + u8 *cur_row = rgb_row_cur; + u8 *next_row = rgb_row_next; + u8 *ar = cur_row++; + u8 *ag = cur_row++; + u8 *ab = cur_row++; + u8 *cr = next_row++; + u8 *cg = next_row++; + u8 *cb = next_row++; + for(int x=0; x < width; x++) { + u8 *br = cur_row++; + u8 *bg = cur_row++; + u8 *bb = cur_row++; + u8 *dr = next_row++; + u8 *dg = next_row++; + u8 *db = next_row++; + + // upper left pixel in quad: just copy it in + int m = *ar; + int mm = *ag; + int mmmm = *ab; + int mmm = RGB1(*ar, *ag, *ab); + *to++ = RGB1(*ar, *ag, *ab); + + // upper right + *to++ = RGB1((*ar+*br)>>1, (*ag+*bg)>>1, (*ab+*bb)>>1); + + // lower left + *to_odd++ = RGB1((*ar+*cr)>>1, (*ag+*cg)>>1, (*ab+*cb)>>1); + + // lower right + *to_odd++ = RGB1((*ar+*br+*cr+*dr)>>2, + (*ag+*bg+*cg+*dg)>>2, + (*ab+*bb+*cb+*db)>>2); + + // 'b' becomes 'a', 'd' becomes 'c' + ar = br; + ag = bg; + ab = bb; + cr = dr; + cg = dg; + cb = db; + } + + // the "next" rgb row becomes the current; the old current rgb row is + // recycled and serves as the new "next" row + u8 *temp; + temp = rgb_row_cur; + rgb_row_cur = rgb_row_next; + rgb_row_next = temp; + + // update the pointers for start of next pair of lines + from = (u32 *)((u8 *)from_orig + srcPitch); + to = (u32 *)((u8 *)to_orig + (dstPitch << 1)); + to_odd = (u32 *)((u8 *)to + dstPitch); + } +} + +void BilinearPlus32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u8 row_cur[3*322]; + u8 row_next[3*322]; + u8 *rgb_row_cur = row_cur; + u8 *rgb_row_next = row_next; + + u32 *to = (u32 *)dstPtr; + u32 *to_odd = (u32 *)(dstPtr + dstPitch); + + int from_width = width; + + u32 *from = (u32 *)srcPtr; + fill_rgb_row_32(from, from_width, rgb_row_cur, width+1); + + for(int y = 0; y < height; y++) { + u32 *from_orig = from; + u32 *to_orig = to; + + if (y+1 < height) + fill_rgb_row_32(from+width+1, from_width, rgb_row_next, + width+1); + else + fill_rgb_row_32(from, from_width, rgb_row_next, width+1); + + // every pixel in the src region, is extended to 4 pixels in the + // destination, arranged in a square 'quad'; if the current src + // pixel is 'a', then in what follows 'b' is the src pixel to the + // right, 'c' is the src pixel below, and 'd' is the src pixel to + // the right and down + u8 *cur_row = rgb_row_cur; + u8 *next_row = rgb_row_next; + u8 *ar = cur_row++; + u8 *ag = cur_row++; + u8 *ab = cur_row++; + u8 *cr = next_row++; + u8 *cg = next_row++; + u8 *cb = next_row++; + for(int x=0; x < width; x++) { + u8 *br = cur_row++; + u8 *bg = cur_row++; + u8 *bb = cur_row++; + u8 *dr = next_row++; + u8 *dg = next_row++; + u8 *db = next_row++; + + // upper left pixel in quad: just copy it in + //*to++ = manip.rgb(*ar, *ag, *ab); +#ifdef USE_ORIGINAL_BILINEAR_PLUS + *to++ = RGB( + (((*ar)<<2) +((*ar)) + (*cr+*br+*br) )>> 3, + (((*ag)<<2) +((*ag)) + (*cg+*bg+*bg) )>> 3, + (((*ab)<<2) +((*ab)) + (*cb+*bb+*bb) )>> 3); +#else + *to++ = RGB1( + (((*ar)<<3) +((*ar)<<1) + (*cr+*br+*br+*cr) )>> 4, + (((*ag)<<3) +((*ag)<<1) + (*cg+*bg+*bg+*cg) )>> 4, + (((*ab)<<3) +((*ab)<<1) + (*cb+*bb+*bb+*cb) )>> 4); +#endif + + // upper right + *to++ = RGB1((*ar+*br)>>1, (*ag+*bg)>>1, (*ab+*bb)>>1); + + // lower left + *to_odd++ = RGB1((*ar+*cr)>>1, (*ag+*cg)>>1, (*ab+*cb)>>1); + + // lower right + *to_odd++ = RGB1((*ar+*br+*cr+*dr)>>2, + (*ag+*bg+*cg+*dg)>>2, + (*ab+*bb+*cb+*db)>>2); + + // 'b' becomes 'a', 'd' becomes 'c' + ar = br; + ag = bg; + ab = bb; + cr = dr; + cg = dg; + cb = db; + } + + // the "next" rgb row becomes the current; the old current rgb row is + // recycled and serves as the new "next" row + u8 *temp; + temp = rgb_row_cur; + rgb_row_cur = rgb_row_next; + rgb_row_next = temp; + + // update the pointers for start of next pair of lines + from = (u32 *)((u8 *)from_orig + srcPitch); + to = (u32 *)((u8 *)to_orig + (dstPitch << 1)); + to_odd = (u32 *)((u8 *)to + dstPitch); + } +} +void RenderBilinear (SSurface Src, SSurface Dst) +{ + + unsigned char *lpSrc, *lpDst; + + lpSrc = Src.Surface; + lpDst = Dst.Surface; + + Bilinear32 (lpSrc, Src.Pitch*2, + lpSrc, + lpDst, Dst.Pitch*2, Src.Width, Src.Height); +} + diff --git a/jni/desmume/src/filter/epx.cpp b/jni/desmume/src/filter/epx.cpp new file mode 100755 index 0000000..78dd827 --- /dev/null +++ b/jni/desmume/src/filter/epx.cpp @@ -0,0 +1,316 @@ +/* Copyright (C) 2009 DeSmuME team + + This file is part of DeSmuME + + DeSmuME 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. + + DeSmuME 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 DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "filter.h" +#include "types.h" +#include "interp.h" + +// transforms each 1 pixel into a 2x2 block of output pixels +// where each corner is selected based on equivalence of neighboring pixels +void RenderEPX (SSurface Src, SSurface Dst) +{ + uint32 *lpSrc; + + const uint32 srcHeight = Src.Height; + const uint32 srcWidth = Src.Width; + + const unsigned int srcPitch = Src.Pitch >> 1; + lpSrc = reinterpret_cast<uint32 *>(Src.Surface); + + const unsigned int dstPitch = Dst.Pitch >> 1; + uint32 *lpDst = (uint32*)Dst.Surface; + + for(uint32 j = 0; j < srcHeight; j++) + { + uint32* SrcLine = lpSrc + srcPitch*j; + uint32* DstLine1 = lpDst + dstPitch*(j*2); + uint32* DstLine2 = lpDst + dstPitch*(j*2+1); + for(uint32 i = 0; i < srcWidth; i++) + { + uint32 L = *(SrcLine-1); + uint32 C = *(SrcLine); + uint32 R = *(SrcLine+1); + if(L != R) + { + uint32 U = *(SrcLine-srcPitch); + uint32 D = *(SrcLine+srcPitch); + if(U != D) + { + *DstLine1++ = (U == L) ? U : C; + *DstLine1++ = (R == U) ? R : C; + *DstLine2++ = (L == D) ? L : C; + *DstLine2++ = (D == R) ? D : C; + SrcLine++; + continue; + } + } + *DstLine1++ = C; + *DstLine1++ = C; + *DstLine2++ = C; + *DstLine2++ = C; + SrcLine++; + } + } +} + +// transforms each 2x2 block of pixels into a 3x3 block of output pixels +// where each pixel is selected based on equivalence of neighboring pixels +void RenderEPX_1Point5x (SSurface Src, SSurface Dst) +{ + u32 *lpSrc; + + u32 srcHeight = Src.Height; + u32 srcWidth = Src.Width; + u32 dstHeight = Dst.Height; + u32 dstWidth = Dst.Width; + + const unsigned int srcPitch = Src.Pitch >> 1; + lpSrc = reinterpret_cast<u32 *>(Src.Surface); + + const unsigned int dstPitch = Dst.Pitch >> 1; + u32 *lpDst = (u32*)Dst.Surface; + + for(uint32 yi=0, yo=0; yi < srcHeight; yi+=2, yo+=3) + { + u32* SrcLine = lpSrc + srcPitch*yi; + u32* DstLine1 = lpDst + dstPitch*(yo); + u32* DstLine2 = lpDst + dstPitch*(yo+1); + u32* DstLine3 = lpDst + dstPitch*(yo+2); + for(uint32 xi=0; xi < srcWidth; xi+=2) + { + u32 s10 = *(SrcLine-srcPitch), s20 = *(SrcLine-srcPitch+1), s30 = *(SrcLine-srcPitch+2); + u32 s01 = *(SrcLine-1), s11 = *(SrcLine), s21 = *(SrcLine+1), s31 = *(SrcLine+2); + u32 s02 = *(SrcLine+srcPitch-1), s12 = *(SrcLine+srcPitch), s22 = *(SrcLine+srcPitch+1), s32 = *(SrcLine+srcPitch+2); + u32 s03 = *(SrcLine+2*srcPitch-1), s13 = *(SrcLine+2*srcPitch), s23 = *(SrcLine+2*srcPitch+1), s33 = *(SrcLine+2*srcPitch+2); + *DstLine1++ = s01==s10 && s10!=s21 && s01!=s12 + ? s01:s11; + *DstLine1++ = s10==s21 && s10!=s01 && s21!=s12 + ? s21:s11; + *DstLine1++ = (s11==s20 && s20!=s31 && s11!=s22 && s21!=s30) + || (s20==s31 && s20!=s11 && s31!=s22 && s21!=s10) ? s20:s21; + *DstLine2++ = s01==s12 && s01!=s10 && s12!=s21 + ? s01:s11; + *DstLine2++ = s12==s21 && s01!=s12 && s10!=s21 + ? s21:s11; + *DstLine2++ = (s11==s22 && s11!=s20 && s22!=s31 && s21!=s32) + || (s22==s31 && s11!=s22 && s20!=s31 && s21!=s12) ? s22:s21; + *DstLine3++ = (s02==s11 && s11!=s22 && s02!=s13 && s12!=s03) + || (s02==s13 && s02!=s11 && s13!=s22 && s12!=s01) ? s02:s12; + *DstLine3++ = (s11==s22 && s11!=s02 && s22!=s13 && s12!=s23) + || (s13==s22 && s02!=s13 && s11!=s22 && s12!=s21) ? s22:s12; + *DstLine3++ = s22; + SrcLine+=2; + } + } +} + +static u32 min(u32 a, u32 b) { return (a < b) ? a : b; } +static u32 min3(u32 a, u32 b, u32 c) { return min(a,min(b,c)); } +static u32 dist(u32 a, u32 b) +{ + return ABS( (a & 0x0000FF) - (b & 0x0000FF))*2 + + ABS(((a & 0x00FF00)>>8) - ((b & 0x00FF00)>>8))*3 + + ABS(((a & 0xFF0000)>>16) - ((b & 0xFF0000)>>16))*3; +} +// note: we only use mix to make the arbitrary choice between two almost-equal colors. +// this filter doesn't really do much interpolating or have the appearance of doing any. +#define mix interp_32_11 + +// transforms each 1 pixel into a 2x2 block of output pixels +// where each corner is selected based on relative equivalence of neighboring pixels +void RenderEPXPlus (SSurface Src, SSurface Dst) +{ + uint32 *lpSrc; + + const uint32 srcHeight = Src.Height; + const uint32 srcWidth = Src.Width; + + const unsigned int srcPitch = Src.Pitch >> 1; + lpSrc = reinterpret_cast<uint32 *>(Src.Surface); + + const unsigned int dstPitch = Dst.Pitch >> 1; + uint32 *lpDst = (uint32*)Dst.Surface; + + for(uint32 j = 0; j < srcHeight; j++) + { + uint32* SrcLine = lpSrc + srcPitch*j; + uint32* DstLine1 = lpDst + dstPitch*(j*2); + uint32* DstLine2 = lpDst + dstPitch*(j*2+1); + for(uint32 i = 0; i < srcWidth; i++) + { + uint32 L = *(SrcLine-1); + uint32 C = *(SrcLine); + uint32 R = *(SrcLine+1); + uint32 U = *(SrcLine-srcPitch); + uint32 D = *(SrcLine+srcPitch); + *DstLine1++ = dist(L,U) < min(dist(L,D),dist(R,U)) ? mix(L,U) : C; + *DstLine1++ = dist(R,U) < min(dist(L,U),dist(R,D)) ? mix(R,U) : C; + *DstLine2++ = dist(L,D) < min(dist(L,U),dist(R,D)) ? mix(L,D) : C; + *DstLine2++ = dist(R,D) < min(dist(L,D),dist(R,U)) ? mix(R,D) : C; + SrcLine++; + } + } +} + +// transforms each 2x2 block of pixels into a 3x3 block of output pixels +// where each pixel is selected based on relative equivalence of neighboring pixels +void RenderEPXPlus_1Point5x (SSurface Src, SSurface Dst) +{ + u32 *lpSrc; + + u32 srcHeight = Src.Height; + u32 srcWidth = Src.Width; + u32 dstHeight = Dst.Height; + u32 dstWidth = Dst.Width; + + const unsigned int srcPitch = Src.Pitch >> 1; + lpSrc = reinterpret_cast<u32 *>(Src.Surface); + + const unsigned int dstPitch = Dst.Pitch >> 1; + u32 *lpDst = (u32*)Dst.Surface; + + for(uint32 yi=0, yo=0; yi < srcHeight; yi+=2, yo+=3) + { + u32* SrcLine = lpSrc + srcPitch*yi; + u32* DstLine1 = lpDst + dstPitch*(yo); + u32* DstLine2 = lpDst + dstPitch*(yo+1); + u32* DstLine3 = lpDst + dstPitch*(yo+2); + for(uint32 xi=0; xi < srcWidth; xi+=2) + { + u32 s10 = *(SrcLine-srcPitch), s20 = *(SrcLine-srcPitch+1), s30 = *(SrcLine-srcPitch+2); + u32 s01 = *(SrcLine-1), s11 = *(SrcLine), s21 = *(SrcLine+1), s31 = *(SrcLine+2); + u32 s02 = *(SrcLine+srcPitch-1), s12 = *(SrcLine+srcPitch), s22 = *(SrcLine+srcPitch+1), s32 = *(SrcLine+srcPitch+2); + u32 s03 = *(SrcLine+2*srcPitch-1), s13 = *(SrcLine+2*srcPitch), s23 = *(SrcLine+2*srcPitch+1), s33 = *(SrcLine+2*srcPitch+2); + *DstLine1++ = dist(s01,s10) < min( dist(s10,s21),dist(s01,s12)) + ? mix(s01,s10):s11; + *DstLine1++ = dist(s10,s21) < min( dist(s10,s01),dist(s21,s12)) + ? mix(s10,s21):s11; + *DstLine1++ = dist(s11,s20) < min3(dist(s20,s31),dist(s11,s22),dist(s21,s30)) ? mix(s11,s20): + dist(s20,s31) < min3(dist(s20,s11),dist(s31,s22),dist(s21,s10)) ? mix(s20,s31):s21; + *DstLine2++ = dist(s01,s12) < min( dist(s01,s10),dist(s12,s21)) + ? mix(s01,s12):s11; + *DstLine2++ = dist(s12,s21) < min( dist(s01,s12),dist(s10,s21)) + ? mix(s12,s21):s11; + *DstLine2++ = dist(s11,s22) < min3(dist(s11,s20),dist(s22,s31),dist(s21,s32)) ? mix(s11,s22): + dist(s22,s31) < min3(dist(s11,s22),dist(s20,s31),dist(s21,s12)) ? mix(s22,s31):s21; + *DstLine3++ = dist(s02,s11) < min3(dist(s11,s22),dist(s02,s13),dist(s12,s03)) ? mix(s02,s11): + dist(s02,s13) < min3(dist(s02,s11),dist(s13,s22),dist(s12,s01)) ? mix(s02,s13):s12; + *DstLine3++ = dist(s11,s22) < min3(dist(s11,s02),dist(s22,s13),dist(s12,s23)) ? mix(s11,s22): + dist(s13,s22) < min3(dist(s02,s13),dist(s11,s22),dist(s12,s21)) ? mix(s13,s22):s12; + *DstLine3++ = s22; + SrcLine+=2; + } + } +} + + + +// transforms each 2x2 block of pixels into 3x3 output which is +// a 2x2 block that has 1 block of padding on the right and bottom sides +// which are selected stupidly from neighboring pixels in the original 2x2 block +void RenderNearest_1Point5x (SSurface Src, SSurface Dst) +{ + uint32 *lpSrc; + + uint32 srcHeight = Src.Height; + uint32 srcWidth = Src.Width; + uint32 dstHeight = Dst.Height; + uint32 dstWidth = Dst.Width; + + const unsigned int srcPitch = Src.Pitch >> 1; + lpSrc = reinterpret_cast<uint32 *>(Src.Surface); + + const unsigned int dstPitch = Dst.Pitch >> 1; + uint32 *lpDst = (uint32*)Dst.Surface; + + for(uint32 yi = 0, yo = 0; yi < srcHeight; yi+=2, yo+=3) + { + u32* srcPix1 = lpSrc + srcPitch*(yi); + u32* srcPix2 = lpSrc + srcPitch*(yi+1); + u32* dstPix1 = lpDst + dstPitch*(yo); + u32* dstPix2 = lpDst + dstPitch*(yo+1); + u32* dstPix3 = lpDst + dstPitch*(yo+2); + + for(uint32 xi = 0; xi < srcWidth; xi+=2) + { + *dstPix1++ = *srcPix1++; + *dstPix1++ = *srcPix1; + *dstPix1++ = *srcPix1++; + *dstPix2++ = *srcPix2; + *dstPix3++ = *srcPix2++; + *dstPix2++ = *srcPix2; + *dstPix3++ = *srcPix2; + *dstPix2++ = *srcPix2; + *dstPix3++ = *srcPix2++; + } + } +} + +int CLAMP(const int value, const int high) +{ + int low = 0; + return value < low ? low : (value >= high ? high-1 : value); +} + +// transforms each 2x2 block of pixels into 3x3 output which is +// a 2x2 block that has 1 block of padding on the right and bottom sides +// which are selected from neighboring pixels depending on matching diagonals +void RenderNearestPlus_1Point5x (SSurface Src, SSurface Dst) +{ + uint32 *lpSrc; + + uint32 srcHeight = Src.Height; + uint32 srcWidth = Src.Width; + uint32 dstHeight = Dst.Height; + uint32 dstWidth = Dst.Width; + + const unsigned int srcPitch = Src.Pitch >> 1; + lpSrc = reinterpret_cast<uint32 *>(Src.Surface); + + const unsigned int dstPitch = Dst.Pitch >> 1; + uint32 *lpDst = (uint32*)Dst.Surface; + + u32* srcPix = lpSrc; + u32* dstPix = lpDst; + + for(uint32 j = 0, y = 0; j < srcHeight; j+=2, y+=3) + { + +#define GET(dx,dy) *(srcPix+(CLAMP((dy)+j,srcHeight))*srcPitch+(CLAMP((dx)+i,srcWidth))) +#define SET(dx,dy,val) *(dstPix+(dy+y)*dstPitch+(dx+x)) = (val) +#define BETTER(dx,dy,dx2,dy2) (GET(dx,dy) == GET(dx2,dy2) && GET(dx2,dy) != GET(dx,dy2)) + + for(uint32 i = 0, x = 0; i < srcWidth; i+=2, x+=3) //, srcPix+=2, dstPix+=3 + { + SET(0,0,GET(0,0)); + SET(1,0,GET(1,0)); + SET(2,0,GET(BETTER(2,0,1,-1)? 2:1,0)); + SET(0,1,GET(0,1)); + SET(1,1,GET(1,1)); + SET(2,1,GET(BETTER(1,0, 2,1)? 2:1,1)); + SET(0,2,GET(BETTER(0,2,-1,1)?-1:0,1)); + SET(1,2,GET(BETTER(0,1, 1,2)? 0:1,1)); + SET(2,2,GET(BETTER(2,1, 1,2)? 2:1,1)); + } + +#undef GET +#undef SET +#undef BETTER + } +} diff --git a/jni/desmume/src/filter/filter.h b/jni/desmume/src/filter/filter.h new file mode 100755 index 0000000..a3900f5 --- /dev/null +++ b/jni/desmume/src/filter/filter.h @@ -0,0 +1,42 @@ +/* +Copyright (C) 2009-2011 DeSmuME team + +This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + + +typedef struct { + unsigned char *Surface; + + unsigned int Pitch; + unsigned int Width, Height; +} SSurface; + +void RenderNearest2X (SSurface Src, SSurface Dst); +void RenderLQ2X (SSurface Src, SSurface Dst); +void RenderLQ2XS (SSurface Src, SSurface Dst); +void RenderHQ2X (SSurface Src, SSurface Dst); +void RenderHQ4X (SSurface Src, SSurface Dst); +void RenderHQ2XS (SSurface Src, SSurface Dst); +void Render2xSaI (SSurface Src, SSurface Dst); +void RenderSuper2xSaI (SSurface Src, SSurface Dst); +void RenderSuperEagle (SSurface Src, SSurface Dst); +void RenderScanline( SSurface Src, SSurface Dst); +void RenderBilinear( SSurface Src, SSurface Dst); +void RenderEPX( SSurface Src, SSurface Dst); +void RenderEPXPlus( SSurface Src, SSurface Dst); +void RenderEPX_1Point5x( SSurface Src, SSurface Dst); +void RenderEPXPlus_1Point5x( SSurface Src, SSurface Dst); +void RenderNearest_1Point5x( SSurface Src, SSurface Dst); +void RenderNearestPlus_1Point5x( SSurface Src, SSurface Dst); diff --git a/jni/desmume/src/filter/hq2x.cpp b/jni/desmume/src/filter/hq2x.cpp new file mode 100755 index 0000000..5bddcf4 --- /dev/null +++ b/jni/desmume/src/filter/hq2x.cpp @@ -0,0 +1,679 @@ +/* + * This file is part of the Advance project. + * + * Copyright (C) 2003 Andrea Mazzoleni + * + * 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. + * + * In addition, as a special exception, Andrea Mazzoleni + * gives permission to link the code of this program with + * the MAME library (or with modified versions of MAME that use the + * same license as MAME), and distribute linked combinations including + * the two. You must obey the GNU General Public License in all + * respects for all of the code used other than MAME. If you modify + * this file, you may extend this exception to your version of the + * file, but you are not obligated to do so. If you do not wish to + * do so, delete this exception statement from your version. + */ + +#include "filter.h" +#include "interp.h" + +// +///***************************************************************************/ +///* HQ2x C implementation */ +// +///* +// * This effect is a rewritten implementation of the hq2x effect made by Maxim Stepin +// */ +// +//static void hq2x_16_def(u16* dst0, u16* dst1, const u16* src0, const u16* src1, const u16* src2, unsigned count) +//{ +// unsigned i; +// +// for(i=0;i<count;++i) { +// unsigned char mask; +// +// u16 c[9]; +// +// c[1] = src0[0]; +// c[4] = src1[0]; +// c[7] = src2[0]; +// +// if (i>0) { +// c[0] = src0[-1]; +// c[3] = src1[-1]; +// c[6] = src2[-1]; +// } else { +// c[0] = c[1]; +// c[3] = c[4]; +// c[6] = c[7]; +// } +// +// if (i<count-1) { +// c[2] = src0[1]; +// c[5] = src1[1]; +// c[8] = src2[1]; +// } else { +// c[2] = c[1]; +// c[5] = c[4]; +// c[8] = c[7]; +// } +// +// mask = 0; +// +// if (interp_16_diff(c[0], c[4])) +// mask |= 1 << 0; +// if (interp_16_diff(c[1], c[4])) +// mask |= 1 << 1; +// if (interp_16_diff(c[2], c[4])) +// mask |= 1 << 2; +// if (interp_16_diff(c[3], c[4])) +// mask |= 1 << 3; +// if (interp_16_diff(c[5], c[4])) +// mask |= 1 << 4; +// if (interp_16_diff(c[6], c[4])) +// mask |= 1 << 5; +// if (interp_16_diff(c[7], c[4])) +// mask |= 1 << 6; +// if (interp_16_diff(c[8], c[4])) +// mask |= 1 << 7; +// +//#define P0 dst0[0] +//#define P1 dst0[1] +//#define P2 dst1[0] +//#define P3 dst1[1] +//#define MUR interp_16_diff(c[1], c[5]) // top-right +//#define MDR interp_16_diff(c[5], c[7]) // bottom-right +//#define MDL interp_16_diff(c[7], c[3]) // bottom-left +//#define MUL interp_16_diff(c[3], c[1]) // top-left +//#define IC(p0) c[p0] +//#define I11(p0,p1) interp_16_11(c[p0], c[p1]) +//#define I211(p0,p1,p2) interp_16_211(c[p0], c[p1], c[p2]) +//#define I31(p0,p1) interp_16_31(c[p0], c[p1]) +//#define I332(p0,p1,p2) interp_16_332(c[p0], c[p1], c[p2]) +//#define I431(p0,p1,p2) interp_16_431(c[p0], c[p1], c[p2]) +//#define I521(p0,p1,p2) interp_16_521(c[p0], c[p1], c[p2]) +//#define I53(p0,p1) interp_16_53(c[p0], c[p1]) +//#define I611(p0,p1,p2) interp_16_611(c[p0], c[p1], c[p2]) +//#define I71(p0,p1) interp_16_71(c[p0], c[p1]) +//#define I772(p0,p1,p2) interp_16_772(c[p0], c[p1], c[p2]) +//#define I97(p0,p1) interp_16_97(c[p0], c[p1]) +//#define I1411(p0,p1,p2) interp_16_1411(c[p0], c[p1], c[p2]) +//#define I151(p0,p1) interp_16_151(c[p0], c[p1]) +// +// switch (mask) { +//#include "hq2x.h" +// } +// +//#undef P0 +//#undef P1 +//#undef P2 +//#undef P3 +//#undef MUR +//#undef MDR +//#undef MDL +//#undef MUL +//#undef IC +//#undef I11 +//#undef I211 +//#undef I31 +//#undef I332 +//#undef I431 +//#undef I521 +//#undef I53 +//#undef I611 +//#undef I71 +//#undef I772 +//#undef I97 +//#undef I1411 +//#undef I151 +// +// src0 += 1; +// src1 += 1; +// src2 += 1; +// dst0 += 2; +// dst1 += 2; +// } +//} + +static void hq2x_32_def(u32* dst0, u32* dst1, const u32* src0, const u32* src1, const u32* src2, unsigned count) +{ + unsigned i; + + for(i=0;i<count;++i) { + unsigned char mask; + + u32 c[9]; + + c[1] = src0[0]; + c[4] = src1[0]; + c[7] = src2[0]; + + if (i>0) { + c[0] = src0[-1]; + c[3] = src1[-1]; + c[6] = src2[-1]; + } else { + c[0] = c[1]; + c[3] = c[4]; + c[6] = c[7]; + } + + if (i<count-1) { + c[2] = src0[1]; + c[5] = src1[1]; + c[8] = src2[1]; + } else { + c[2] = c[1]; + c[5] = c[4]; + c[8] = c[7]; + } + + mask = 0; + + if (interp_32_diff(c[0], c[4])) + mask |= 1 << 0; + if (interp_32_diff(c[1], c[4])) + mask |= 1 << 1; + if (interp_32_diff(c[2], c[4])) + mask |= 1 << 2; + if (interp_32_diff(c[3], c[4])) + mask |= 1 << 3; + if (interp_32_diff(c[5], c[4])) + mask |= 1 << 4; + if (interp_32_diff(c[6], c[4])) + mask |= 1 << 5; + if (interp_32_diff(c[7], c[4])) + mask |= 1 << 6; + if (interp_32_diff(c[8], c[4])) + mask |= 1 << 7; + +#define P0 dst0[0] +#define P1 dst0[1] +#define P2 dst1[0] +#define P3 dst1[1] +#define MUR interp_32_diff(c[1], c[5]) // top-right +#define MDR interp_32_diff(c[5], c[7]) // bottom-right +#define MDL interp_32_diff(c[7], c[3]) // bottom-left +#define MUL interp_32_diff(c[3], c[1]) // top-left +#define IC(p0) c[p0] +#define I11(p0,p1) interp_32_11(c[p0], c[p1]) +#define I211(p0,p1,p2) interp_32_211(c[p0], c[p1], c[p2]) +#define I31(p0,p1) interp_32_31(c[p0], c[p1]) +#define I332(p0,p1,p2) interp_32_332(c[p0], c[p1], c[p2]) +#define I431(p0,p1,p2) interp_32_431(c[p0], c[p1], c[p2]) +#define I521(p0,p1,p2) interp_32_521(c[p0], c[p1], c[p2]) +#define I53(p0,p1) interp_32_53(c[p0], c[p1]) +#define I611(p0,p1,p2) interp_32_611(c[p0], c[p1], c[p2]) +#define I71(p0,p1) interp_32_71(c[p0], c[p1]) +#define I772(p0,p1,p2) interp_32_772(c[p0], c[p1], c[p2]) +#define I97(p0,p1) interp_32_97(c[p0], c[p1]) +#define I1411(p0,p1,p2) interp_32_1411(c[p0], c[p1], c[p2]) +#define I151(p0,p1) interp_32_151(c[p0], c[p1]) + + switch (mask) { +#include "hq2x.h" + } + +#undef P0 +#undef P1 +#undef P2 +#undef P3 +#undef MUR +#undef MDR +#undef MDL +#undef MUL +#undef IC +#undef I11 +#undef I211 +#undef I31 +#undef I332 +#undef I431 +#undef I521 +#undef I53 +#undef I611 +#undef I71 +#undef I772 +#undef I97 +#undef I1411 +#undef I151 + + src0 += 1; + src1 += 1; + src2 += 1; + dst0 += 2; + dst1 += 2; + } +} + +/***************************************************************************/ +/* HQ2xS C implementation */ + +/* + * This effect is derived from the hq2x effect made by Maxim Stepin + */ + +//static void hq2xS_16_def(u16* dst0, u16* dst1, const u16* src0, const u16* src1, const u16* src2, unsigned count) +//{ +// unsigned i; +// +// for(i=0;i<count;++i) { +// unsigned char mask; +// +// u16 c[9]; +// +// c[1] = src0[0]; +// c[4] = src1[0]; +// c[7] = src2[0]; +// +// if (i>0) { +// c[0] = src0[-1]; +// c[3] = src1[-1]; +// c[6] = src2[-1]; +// } else { +// c[0] = c[1]; +// c[3] = c[4]; +// c[6] = c[7]; +// } +// +// if (i<count-1) { +// c[2] = src0[1]; +// c[5] = src1[1]; +// c[8] = src2[1]; +// } else { +// c[2] = c[1]; +// c[5] = c[4]; +// c[8] = c[7]; +// } +// +// mask = 0; +// +// // hq2xS dynamic edge detection: +// // simply comparing the center color against its surroundings will give bad results in many cases, +// // so, instead, compare the center color relative to the max difference in brightness of this 3x3 block +// int brightArray[9]; +// int maxBright = 0, minBright = 999999; +// for(int j = 0 ; j < 9 ; j++) +// { +// int r,g,b; +// if (interp_bits_per_pixel == 16) { +// b = (int)((c[j] & 0x1F)) << 3; +// g = (int)((c[j] & 0x7E0)) >> 3; +// r = (int)((c[j] & 0xF800)) >> 8; +// } else { +// b = (int)((c[j] & 0x1F)) << 3; +// g = (int)((c[j] & 0x3E0)) >> 2; +// r = (int)((c[j] & 0x7C00)) >> 7; +// } +// const int bright = r+r+r + g+g+g + b+b; +// if(bright > maxBright) maxBright = bright; +// if(bright < minBright) minBright = bright; +// +// brightArray[j] = bright; +// } +// int diffBright = ((maxBright - minBright) * 7) >> 4; +// if(diffBright > 7) +// { +// const int centerBright = brightArray[4]; +// if(ABS(brightArray[0] - centerBright) > diffBright) +// mask |= 1 << 0; +// if(ABS(brightArray[1] - centerBright) > diffBright) +// mask |= 1 << 1; +// if(ABS(brightArray[2] - centerBright) > diffBright) +// mask |= 1 << 2; +// if(ABS(brightArray[3] - centerBright) > diffBright) +// mask |= 1 << 3; +// if(ABS(brightArray[5] - centerBright) > diffBright) +// mask |= 1 << 4; +// if(ABS(brightArray[6] - centerBright) > diffBright) +// mask |= 1 << 5; +// if(ABS(brightArray[7] - centerBright) > diffBright) +// mask |= 1 << 6; +// if(ABS(brightArray[8] - centerBright) > diffBright) +// mask |= 1 << 7; +// } +// +//#define P0 dst0[0] +//#define P1 dst0[1] +//#define P2 dst1[0] +//#define P3 dst1[1] +//#define MUR false//(ABS(brightArray[1] - brightArray[5]) > diffBright) // top-right +//#define MDR false//(ABS(brightArray[5] - brightArray[7]) > diffBright) // bottom-right +//#define MDL false//(ABS(brightArray[7] - brightArray[3]) > diffBright) // bottom-left +//#define MUL false//(ABS(brightArray[3] - brightArray[1]) > diffBright) // top-left +//#define IC(p0) c[p0] +//#define I11(p0,p1) interp_16_11(c[p0], c[p1]) +//#define I211(p0,p1,p2) interp_16_211(c[p0], c[p1], c[p2]) +//#define I31(p0,p1) interp_16_31(c[p0], c[p1]) +//#define I332(p0,p1,p2) interp_16_332(c[p0], c[p1], c[p2]) +//#define I431(p0,p1,p2) interp_16_431(c[p0], c[p1], c[p2]) +//#define I521(p0,p1,p2) interp_16_521(c[p0], c[p1], c[p2]) +//#define I53(p0,p1) interp_16_53(c[p0], c[p1]) +//#define I611(p0,p1,p2) interp_16_611(c[p0], c[p1], c[p2]) +//#define I71(p0,p1) interp_16_71(c[p0], c[p1]) +//#define I772(p0,p1,p2) interp_16_772(c[p0], c[p1], c[p2]) +//#define I97(p0,p1) interp_16_97(c[p0], c[p1]) +//#define I1411(p0,p1,p2) interp_16_1411(c[p0], c[p1], c[p2]) +//#define I151(p0,p1) interp_16_151(c[p0], c[p1]) +// +// switch (mask) { +//#include "hq2x.h" +// } +// +//#undef P0 +//#undef P1 +//#undef P2 +//#undef P3 +//#undef MUR +//#undef MDR +//#undef MDL +//#undef MUL +//#undef IC +//#undef I11 +//#undef I211 +//#undef I31 +//#undef I332 +//#undef I431 +//#undef I521 +//#undef I53 +//#undef I611 +//#undef I71 +//#undef I772 +//#undef I97 +//#undef I1411 +//#undef I151 +// +// src0 += 1; +// src1 += 1; +// src2 += 1; +// dst0 += 2; +// dst1 += 2; +// } +//} + +static void hq2xS_32_def(u32* dst0, u32* dst1, const u32* src0, const u32* src1, const u32* src2, unsigned count) +{ + unsigned i; + + for(i=0;i<count;++i) { + unsigned char mask; + + u32 c[9]; + + c[1] = src0[0]; + c[4] = src1[0]; + c[7] = src2[0]; + + if (i>0) { + c[0] = src0[-1]; + c[3] = src1[-1]; + c[6] = src2[-1]; + } else { + c[0] = src0[0]; + c[3] = src1[0]; + c[6] = src2[0]; + } + + if (i<count-1) { + c[2] = src0[1]; + c[5] = src1[1]; + c[8] = src2[1]; + } else { + c[2] = src0[0]; + c[5] = src1[0]; + c[8] = src2[0]; + } + + mask = 0; + // hq2xS dynamic edge detection: + // simply comparing the center color against its surroundings will give bad results in many cases, + // so, instead, compare the center color relative to the max difference in brightness of this 3x3 block + int brightArray[9]; + int maxBright = 0, minBright = 999999; + for(int j = 0 ; j < 9 ; j++) + { + const int b = (int)((c[j] & 0xF8)); + const int g = (int)((c[j] & 0xF800)) >> 8; + const int r = (int)((c[j] & 0xF80000)) >> 16; + const int bright = r+r+r + g+g+g + b+b; + if(bright > maxBright) maxBright = bright; + if(bright < minBright) minBright = bright; + + brightArray[j] = bright; + } + int diffBright = ((maxBright - minBright) * 7) >> 4; + if(diffBright > 7) + { + const int centerBright = brightArray[4]; + if(ABS(brightArray[0] - centerBright) > diffBright) + mask |= 1 << 0; + if(ABS(brightArray[1] - centerBright) > diffBright) + mask |= 1 << 1; + if(ABS(brightArray[2] - centerBright) > diffBright) + mask |= 1 << 2; + if(ABS(brightArray[3] - centerBright) > diffBright) + mask |= 1 << 3; + if(ABS(brightArray[5] - centerBright) > diffBright) + mask |= 1 << 4; + if(ABS(brightArray[6] - centerBright) > diffBright) + mask |= 1 << 5; + if(ABS(brightArray[7] - centerBright) > diffBright) + mask |= 1 << 6; + if(ABS(brightArray[8] - centerBright) > diffBright) + mask |= 1 << 7; + } +#define P0 dst0[0] +#define P1 dst0[1] +#define P2 dst1[0] +#define P3 dst1[1] +#define MUR false//(ABS(brightArray[1] - brightArray[5]) > diffBright) // top-right +#define MDR false//(ABS(brightArray[5] - brightArray[7]) > diffBright) // bottom-right +#define MDL false//(ABS(brightArray[7] - brightArray[3]) > diffBright) // bottom-left +#define MUL false//(ABS(brightArray[3] - brightArray[1]) > diffBright) // top-left +#define IC(p0) c[p0] +#define I11(p0,p1) interp_32_11(c[p0], c[p1]) +#define I211(p0,p1,p2) interp_32_211(c[p0], c[p1], c[p2]) +#define I31(p0,p1) interp_32_31(c[p0], c[p1]) +#define I332(p0,p1,p2) interp_32_332(c[p0], c[p1], c[p2]) +#define I431(p0,p1,p2) interp_32_431(c[p0], c[p1], c[p2]) +#define I521(p0,p1,p2) interp_32_521(c[p0], c[p1], c[p2]) +#define I53(p0,p1) interp_32_53(c[p0], c[p1]) +#define I611(p0,p1,p2) interp_32_611(c[p0], c[p1], c[p2]) +#define I71(p0,p1) interp_32_71(c[p0], c[p1]) +#define I772(p0,p1,p2) interp_32_772(c[p0], c[p1], c[p2]) +#define I97(p0,p1) interp_32_97(c[p0], c[p1]) +#define I1411(p0,p1,p2) interp_32_1411(c[p0], c[p1], c[p2]) +#define I151(p0,p1) interp_32_151(c[p0], c[p1]) + + switch (mask) { +#include "hq2x.h" + } + +#undef P0 +#undef P1 +#undef P2 +#undef P3 +#undef MUR +#undef MDR +#undef MDL +#undef MUL +#undef IC +#undef I11 +#undef I211 +#undef I31 +#undef I332 +#undef I431 +#undef I521 +#undef I53 +#undef I611 +#undef I71 +#undef I772 +#undef I97 +#undef I1411 +#undef I151 + + src0 += 1; + src1 += 1; + src2 += 1; + dst0 += 2; + dst1 += 2; + } +} +// +//void hq2x(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, +// u8 *dstPtr, u32 dstPitch, int width, int height) +//{ +// u16 *dst0 = (u16 *)dstPtr; +// u16 *dst1 = dst0 + (dstPitch >> 1); +// +// u16 *src0 = (u16 *)srcPtr; +// u16 *src1 = src0 + (srcPitch >> 1); +// u16 *src2 = src1 + (srcPitch >> 1); +// +// hq2x_16_def(dst0, dst1, src0, src0, src1, width); +// +// int count = height; +// +// count -= 2; +// while(count) { +// dst0 += dstPitch; +// dst1 += dstPitch; +// hq2x_16_def(dst0, dst1, src0, src1, src2, width); +// src0 = src1; +// src1 = src2; +// src2 += srcPitch >> 1; +// --count; +// } +// dst0 += dstPitch; +// dst1 += dstPitch; +// hq2x_16_def(dst0, dst1, src0, src1, src1, width); +//} + +void hq2x32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u32 *dst0 = (u32 *)dstPtr; + u32 *dst1 = dst0 + (dstPitch >> 2); + + u32 *src0 = (u32 *)srcPtr; + u32 *src1 = src0 + (srcPitch >> 2); + u32 *src2 = src1 + (srcPitch >> 2); + hq2x_32_def(dst0, dst1, src0, src0, src1, width); + + int count = height; + + count -= 2; + while(count) { + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + hq2x_32_def(dst0, dst1, src0, src1, src2, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 2; + --count; + } + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + hq2x_32_def(dst0, dst1, src0, src1, src1, width); +} +// +//void hq2xS(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, +// u8 *dstPtr, u32 dstPitch, int width, int height) +//{ +// u16 *dst0 = (u16 *)dstPtr; +// u16 *dst1 = dst0 + (dstPitch >> 1); +// +// u16 *src0 = (u16 *)srcPtr; +// u16 *src1 = src0 + (srcPitch >> 1); +// u16 *src2 = src1 + (srcPitch >> 1); +// +// hq2xS_16_def(dst0, dst1, src0, src0, src1, width); +// +// int count = height; +// +// count -= 2; +// while(count) { +// dst0 += dstPitch; +// dst1 += dstPitch; +// hq2xS_16_def(dst0, dst1, src0, src1, src2, width); +// src0 = src1; +// src1 = src2; +// src2 += srcPitch >> 1; +// --count; +// } +// dst0 += dstPitch; +// dst1 += dstPitch; +// hq2xS_16_def(dst0, dst1, src0, src1, src1, width); +//} + +void hq2xS32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u32 *dst0 = (u32 *)dstPtr; + u32 *dst1 = dst0 + (dstPitch >> 2); + + u32 *src0 = (u32 *)srcPtr; + u32 *src1 = src0 + (srcPitch >> 2); + u32 *src2 = src1 + (srcPitch >> 2); + hq2xS_32_def(dst0, dst1, src0, src0, src1, width); + + int count = height; + + count -= 2; + while(count) { + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + hq2xS_32_def(dst0, dst1, src0, src1, src2, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 2; + --count; + } + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + hq2xS_32_def(dst0, dst1, src0, src1, src1, width); +} + +//void hq2x_init(unsigned bits_per_pixel) +//{ +// interp_set(bits_per_pixel); +//} + +void RenderHQ2X (SSurface Src, SSurface Dst) +{ + + unsigned char *lpSrc, *lpDst; + + lpSrc = Src.Surface; + lpDst = Dst.Surface; + + hq2x32 (lpSrc, Src.Pitch*2, + lpSrc, + lpDst, Dst.Pitch*2 , Src.Width, Src.Height); +} + +void RenderHQ2XS (SSurface Src, SSurface Dst) +{ + + unsigned char *lpSrc, *lpDst; + + lpSrc = Src.Surface; + lpDst = Dst.Surface; + + hq2xS32 (lpSrc, Src.Pitch*2, + lpSrc, + lpDst, Dst.Pitch*2 , Src.Width, Src.Height); +} diff --git a/jni/desmume/src/filter/hq2x.h b/jni/desmume/src/filter/hq2x.h new file mode 100755 index 0000000..64c5778 --- /dev/null +++ b/jni/desmume/src/filter/hq2x.h @@ -0,0 +1,1824 @@ +case 0 : +case 1 : +case 4 : +case 5 : +case 32 : +case 33 : +case 36 : +case 37 : +case 128 : +case 129 : +case 132 : +case 133 : +case 160 : +case 161 : +case 164 : +case 165 : +{ + P0 = I211(4, 1, 3); + P1 = I211(4, 1, 5); + P2 = I211(4, 3, 7); + P3 = I211(4, 5, 7); +} break; +case 2 : +case 34 : +case 130 : +case 162 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I211(4, 3, 7); + P3 = I211(4, 5, 7); +} break; +case 3 : +case 35 : +case 131 : +case 163 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I211(4, 3, 7); + P3 = I211(4, 5, 7); +} break; +case 6 : +case 38 : +case 134 : +case 166 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P2 = I211(4, 3, 7); + P3 = I211(4, 5, 7); +} break; +case 7 : +case 39 : +case 135 : +case 167 : +{ + P0 = I31(4, 3); + P1 = I31(4, 5); + P2 = I211(4, 3, 7); + P3 = I211(4, 5, 7); +} break; +case 8 : +case 12 : +case 136 : +case 140 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + P2 = I31(4, 6); + P3 = I211(4, 5, 7); +} break; +case 9 : +case 13 : +case 137 : +case 141 : +{ + P0 = I31(4, 1); + P1 = I211(4, 1, 5); + P2 = I31(4, 6); + P3 = I211(4, 5, 7); +} break; +case 10 : +case 138 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 11 : +case 139 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 14 : +case 142 : +{ + P2 = I31(4, 6); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = I31(4, 0); + P1 = I31(4, 5); + } else { + P0 = I332(1, 3, 4); + P1 = I521(4, 1, 5); + } +} break; +case 15 : +case 143 : +{ + P2 = I31(4, 6); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = IC(4); + P1 = I31(4, 5); + } else { + P0 = I332(1, 3, 4); + P1 = I521(4, 1, 5); + } +} break; +case 16 : +case 17 : +case 48 : +case 49 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + P2 = I211(4, 3, 7); + P3 = I31(4, 8); +} break; +case 18 : +case 50 : +{ + P0 = I31(4, 0); + P2 = I211(4, 3, 7); + P3 = I31(4, 8); + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 19 : +case 51 : +{ + P2 = I211(4, 3, 7); + P3 = I31(4, 8); + if (MUR) { + P0 = I31(4, 3); + P1 = I31(4, 2); + } else { + P0 = I521(4, 1, 3); + P1 = I332(1, 5, 4); + } +} break; +case 20 : +case 21 : +case 52 : +case 53 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 1); + P2 = I211(4, 3, 7); + P3 = I31(4, 8); +} break; +case 22 : +case 54 : +{ + P0 = I31(4, 0); + P2 = I211(4, 3, 7); + P3 = I31(4, 8); + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 23 : +case 55 : +{ + P2 = I211(4, 3, 7); + P3 = I31(4, 8); + if (MUR) { + P0 = I31(4, 3); + P1 = IC(4); + } else { + P0 = I521(4, 1, 3); + P1 = I332(1, 5, 4); + } +} break; +case 24 : +case 66 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 25 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 26 : +case 31 : +case 95 : +{ + P2 = I31(4, 6); + P3 = I31(4, 8); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 27 : +case 75 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 8); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 28 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 29 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 30 : +case 86 : +{ + P0 = I31(4, 0); + P2 = I31(4, 6); + P3 = I31(4, 8); + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 40 : +case 44 : +case 168 : +case 172 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + P2 = I31(4, 7); + P3 = I211(4, 5, 7); +} break; +case 41 : +case 45 : +case 169 : +case 173 : +{ + P0 = I31(4, 1); + P1 = I211(4, 1, 5); + P2 = I31(4, 7); + P3 = I211(4, 5, 7); +} break; +case 42 : +case 170 : +{ + P1 = I31(4, 2); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = I31(4, 0); + P2 = I31(4, 7); + } else { + P0 = I332(1, 3, 4); + P2 = I521(4, 3, 7); + } +} break; +case 43 : +case 171 : +{ + P1 = I31(4, 2); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = IC(4); + P2 = I31(4, 7); + } else { + P0 = I332(1, 3, 4); + P2 = I521(4, 3, 7); + } +} break; +case 46 : +case 174 : +{ + P1 = I31(4, 5); + P2 = I31(4, 7); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } +} break; +case 47 : +case 175 : +{ + P1 = I31(4, 5); + P2 = I31(4, 7); + P3 = I211(4, 5, 7); + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } +} break; +case 56 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 7); + P3 = I31(4, 8); +} break; +case 57 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + P2 = I31(4, 7); + P3 = I31(4, 8); +} break; +case 58 : +{ + P2 = I31(4, 7); + P3 = I31(4, 8); + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 59 : +{ + P2 = I31(4, 7); + P3 = I31(4, 8); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 60 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + P2 = I31(4, 7); + P3 = I31(4, 8); +} break; +case 61 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + P2 = I31(4, 7); + P3 = I31(4, 8); +} break; +case 62 : +{ + P0 = I31(4, 0); + P2 = I31(4, 7); + P3 = I31(4, 8); + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 63 : +{ + P2 = I31(4, 7); + P3 = I31(4, 8); + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 64 : +case 65 : +case 68 : +case 69 : +{ + P0 = I211(4, 1, 3); + P1 = I211(4, 1, 5); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 67 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 70 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 71 : +{ + P0 = I31(4, 3); + P1 = I31(4, 5); + P2 = I31(4, 6); + P3 = I31(4, 8); +} break; +case 72 : +case 76 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + P3 = I31(4, 8); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I211(4, 3, 7); + } +} break; +case 73 : +case 77 : +{ + P1 = I211(4, 1, 5); + P3 = I31(4, 8); + if (MDL) { + P0 = I31(4, 1); + P2 = I31(4, 6); + } else { + P0 = I521(4, 3, 1); + P2 = I332(3, 7, 4); + } +} break; +case 74 : +case 107 : +case 123 : +{ + P1 = I31(4, 2); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 78 : +{ + P1 = I31(4, 5); + P3 = I31(4, 8); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } +} break; +case 79 : +{ + P1 = I31(4, 5); + P3 = I31(4, 8); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 80 : +case 81 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + P2 = I31(4, 6); + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 82 : +case 214 : +case 222 : +{ + P0 = I31(4, 0); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 83 : +{ + P0 = I31(4, 3); + P2 = I31(4, 6); + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 84 : +case 85 : +{ + P0 = I211(4, 1, 3); + P2 = I31(4, 6); + if (MDR) { + P1 = I31(4, 1); + P3 = I31(4, 8); + } else { + P1 = I521(4, 5, 1); + P3 = I332(5, 7, 4); + } +} break; +case 87 : +{ + P0 = I31(4, 3); + P2 = I31(4, 6); + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 88 : +case 248 : +case 250 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 89 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } +} break; +case 90 : +{ + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 91 : +{ + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 92 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } +} break; +case 93 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } +} break; +case 94 : +{ + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 96 : +case 97 : +case 100 : +case 101 : +{ + P0 = I211(4, 1, 3); + P1 = I211(4, 1, 5); + P2 = I31(4, 3); + P3 = I31(4, 8); +} break; +case 98 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 3); + P3 = I31(4, 8); +} break; +case 99 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I31(4, 3); + P3 = I31(4, 8); +} break; +case 102 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P2 = I31(4, 3); + P3 = I31(4, 8); +} break; +case 103 : +{ + P0 = I31(4, 3); + P1 = I31(4, 5); + P2 = I31(4, 3); + P3 = I31(4, 8); +} break; +case 104 : +case 108 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } +} break; +case 105 : +case 109 : +{ + P1 = I211(4, 1, 5); + P3 = I31(4, 8); + if (MDL) { + P0 = I31(4, 1); + P2 = IC(4); + } else { + P0 = I521(4, 3, 1); + P2 = I332(3, 7, 4); + } +} break; +case 106 : +case 120 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } +} break; +case 110 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } +} break; +case 111 : +{ + P1 = I31(4, 5); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } +} break; +case 112 : +case 113 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + if (MDR) { + P2 = I31(4, 3); + P3 = I31(4, 8); + } else { + P2 = I521(4, 7, 3); + P3 = I332(5, 7, 4); + } +} break; +case 114 : +{ + P0 = I31(4, 0); + P2 = I31(4, 3); + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 115 : +{ + P0 = I31(4, 3); + P2 = I31(4, 3); + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 116 : +case 117 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 1); + P2 = I31(4, 3); + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } +} break; +case 118 : +{ + P0 = I31(4, 0); + P2 = I31(4, 3); + P3 = I31(4, 8); + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 119 : +{ + P2 = I31(4, 3); + P3 = I31(4, 8); + if (MUR) { + P0 = I31(4, 3); + P1 = IC(4); + } else { + P0 = I521(4, 1, 3); + P1 = I332(1, 5, 4); + } +} break; +case 121 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } +} break; +case 122 : +{ + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MDR) { + P3 = I31(4, 8); + } else { + P3 = I611(4, 5, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 124 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } +} break; +case 125 : +{ + P1 = I31(4, 1); + P3 = I31(4, 8); + if (MDL) { + P0 = I31(4, 1); + P2 = IC(4); + } else { + P0 = I521(4, 3, 1); + P2 = I332(3, 7, 4); + } +} break; +case 126 : +{ + P0 = I31(4, 0); + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 127 : +{ + P3 = I31(4, 8); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 144 : +case 145 : +case 176 : +case 177 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + P2 = I211(4, 3, 7); + P3 = I31(4, 7); +} break; +case 146 : +case 178 : +{ + P0 = I31(4, 0); + P2 = I211(4, 3, 7); + if (MUR) { + P1 = I31(4, 2); + P3 = I31(4, 7); + } else { + P1 = I332(1, 5, 4); + P3 = I521(4, 5, 7); + } +} break; +case 147 : +case 179 : +{ + P0 = I31(4, 3); + P2 = I211(4, 3, 7); + P3 = I31(4, 7); + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 148 : +case 149 : +case 180 : +case 181 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 1); + P2 = I211(4, 3, 7); + P3 = I31(4, 7); +} break; +case 150 : +case 182 : +{ + P0 = I31(4, 0); + P2 = I211(4, 3, 7); + if (MUR) { + P1 = IC(4); + P3 = I31(4, 7); + } else { + P1 = I332(1, 5, 4); + P3 = I521(4, 5, 7); + } +} break; +case 151 : +case 183 : +{ + P0 = I31(4, 3); + P2 = I211(4, 3, 7); + P3 = I31(4, 7); + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 152 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 7); +} break; +case 153 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 7); +} break; +case 154 : +{ + P2 = I31(4, 6); + P3 = I31(4, 7); + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 155 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 7); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 156 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + P2 = I31(4, 6); + P3 = I31(4, 7); +} break; +case 157 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + P2 = I31(4, 6); + P3 = I31(4, 7); +} break; +case 158 : +{ + P2 = I31(4, 6); + P3 = I31(4, 7); + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 159 : +{ + P2 = I31(4, 6); + P3 = I31(4, 7); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 184 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 7); + P3 = I31(4, 7); +} break; +case 185 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + P2 = I31(4, 7); + P3 = I31(4, 7); +} break; +case 186 : +{ + P2 = I31(4, 7); + P3 = I31(4, 7); + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 187 : +{ + P1 = I31(4, 2); + P3 = I31(4, 7); + if (MUL) { + P0 = IC(4); + P2 = I31(4, 7); + } else { + P0 = I332(1, 3, 4); + P2 = I521(4, 3, 7); + } +} break; +case 188 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + P2 = I31(4, 7); + P3 = I31(4, 7); +} break; +case 189 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + P2 = I31(4, 7); + P3 = I31(4, 7); +} break; +case 190 : +{ + P0 = I31(4, 0); + P2 = I31(4, 7); + if (MUR) { + P1 = IC(4); + P3 = I31(4, 7); + } else { + P1 = I332(1, 5, 4); + P3 = I521(4, 5, 7); + } +} break; +case 191 : +{ + P2 = I31(4, 7); + P3 = I31(4, 7); + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 192 : +case 193 : +case 196 : +case 197 : +{ + P0 = I211(4, 1, 3); + P1 = I211(4, 1, 5); + P2 = I31(4, 6); + P3 = I31(4, 5); +} break; +case 194 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 5); +} break; +case 195 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 5); +} break; +case 198 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P2 = I31(4, 6); + P3 = I31(4, 5); +} break; +case 199 : +{ + P0 = I31(4, 3); + P1 = I31(4, 5); + P2 = I31(4, 6); + P3 = I31(4, 5); +} break; +case 200 : +case 204 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + if (MDL) { + P2 = I31(4, 6); + P3 = I31(4, 5); + } else { + P2 = I332(3, 7, 4); + P3 = I521(4, 7, 5); + } +} break; +case 201 : +case 205 : +{ + P0 = I31(4, 1); + P1 = I211(4, 1, 5); + P3 = I31(4, 5); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } +} break; +case 202 : +{ + P1 = I31(4, 2); + P3 = I31(4, 5); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } +} break; +case 203 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + P3 = I31(4, 5); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 206 : +{ + P1 = I31(4, 5); + P3 = I31(4, 5); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } +} break; +case 207 : +{ + P2 = I31(4, 6); + P3 = I31(4, 5); + if (MUL) { + P0 = IC(4); + P1 = I31(4, 5); + } else { + P0 = I332(1, 3, 4); + P1 = I521(4, 1, 5); + } +} break; +case 208 : +case 209 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 210 : +case 216 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 211 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 212 : +case 213 : +{ + P0 = I211(4, 1, 3); + P2 = I31(4, 6); + if (MDR) { + P1 = I31(4, 1); + P3 = IC(4); + } else { + P1 = I521(4, 5, 1); + P3 = I332(5, 7, 4); + } +} break; +case 215 : +{ + P0 = I31(4, 3); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 217 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 218 : +{ + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 219 : +{ + P1 = I31(4, 2); + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 220 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + if (MDL) { + P2 = I31(4, 6); + } else { + P2 = I611(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 221 : +{ + P0 = I31(4, 1); + P2 = I31(4, 6); + if (MDR) { + P1 = I31(4, 1); + P3 = IC(4); + } else { + P1 = I521(4, 5, 1); + P3 = I332(5, 7, 4); + } +} break; +case 223 : +{ + P2 = I31(4, 6); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 224 : +case 225 : +case 228 : +case 229 : +{ + P0 = I211(4, 1, 3); + P1 = I211(4, 1, 5); + P2 = I31(4, 3); + P3 = I31(4, 5); +} break; +case 226 : +{ + P0 = I31(4, 0); + P1 = I31(4, 2); + P2 = I31(4, 3); + P3 = I31(4, 5); +} break; +case 227 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + P2 = I31(4, 3); + P3 = I31(4, 5); +} break; +case 230 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + P2 = I31(4, 3); + P3 = I31(4, 5); +} break; +case 231 : +{ + P0 = I31(4, 3); + P1 = I31(4, 5); + P2 = I31(4, 3); + P3 = I31(4, 5); +} break; +case 232 : +case 236 : +{ + P0 = I31(4, 0); + P1 = I211(4, 1, 5); + if (MDL) { + P2 = IC(4); + P3 = I31(4, 5); + } else { + P2 = I332(3, 7, 4); + P3 = I521(4, 7, 5); + } +} break; +case 233 : +case 237 : +{ + P0 = I31(4, 1); + P1 = I211(4, 1, 5); + P3 = I31(4, 5); + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } +} break; +case 234 : +{ + P1 = I31(4, 2); + P3 = I31(4, 5); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MUL) { + P0 = I31(4, 0); + } else { + P0 = I611(4, 1, 3); + } +} break; +case 235 : +{ + P1 = I31(4, 2); + P3 = I31(4, 5); + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 238 : +{ + P0 = I31(4, 0); + P1 = I31(4, 5); + if (MDL) { + P2 = IC(4); + P3 = I31(4, 5); + } else { + P2 = I332(3, 7, 4); + P3 = I521(4, 7, 5); + } +} break; +case 239 : +{ + P1 = I31(4, 5); + P3 = I31(4, 5); + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } +} break; +case 240 : +case 241 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 2); + if (MDR) { + P2 = I31(4, 3); + P3 = IC(4); + } else { + P2 = I521(4, 7, 3); + P3 = I332(5, 7, 4); + } +} break; +case 242 : +{ + P0 = I31(4, 0); + P2 = I31(4, 3); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUR) { + P1 = I31(4, 2); + } else { + P1 = I611(4, 1, 5); + } +} break; +case 243 : +{ + P0 = I31(4, 3); + P1 = I31(4, 2); + if (MDR) { + P2 = I31(4, 3); + P3 = IC(4); + } else { + P2 = I521(4, 7, 3); + P3 = I332(5, 7, 4); + } +} break; +case 244 : +case 245 : +{ + P0 = I211(4, 1, 3); + P1 = I31(4, 1); + P2 = I31(4, 3); + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } +} break; +case 246 : +{ + P0 = I31(4, 0); + P2 = I31(4, 3); + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 247 : +{ + P0 = I31(4, 3); + P2 = I31(4, 3); + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 249 : +{ + P0 = I31(4, 1); + P1 = I31(4, 2); + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } +} break; +case 251 : +{ + P1 = I31(4, 2); + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 252 : +{ + P0 = I31(4, 0); + P1 = I31(4, 1); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } +} break; +case 253 : +{ + P0 = I31(4, 1); + P1 = I31(4, 1); + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } +} break; +case 254 : +{ + P0 = I31(4, 0); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 255 : +{ + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; diff --git a/jni/desmume/src/filter/hq4x.cpp b/jni/desmume/src/filter/hq4x.cpp new file mode 100755 index 0000000..9679029 --- /dev/null +++ b/jni/desmume/src/filter/hq4x.cpp @@ -0,0 +1,135 @@ +/* + * This file is part of the Advance project. + * + * Copyright (C) 2003, 2008 Andrea Mazzoleni + * + * 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. + * + * In addition, as a special exception, Andrea Mazzoleni + * gives permission to link the code of this program with + * the MAME library (or with modified versions of MAME that use the + * same license as MAME), and distribute linked combinations including + * the two. You must obey the GNU General Public License in all + * respects for all of the code used other than MAME. If you modify + * this file, you may extend this exception to your version of the + * file, but you are not obligated to do so. If you do not wish to + * do so, delete this exception statement from your version. + */ + +#include "filter.h" +#include "interp.h" + +/***************************************************************************/ +/* HQ4x C implementation */ + +/* + * This effect is a rewritten implementation of the hq4x effect made by Maxim Stepin + */ + + +void hq4x_32_def(u32* dst0, u32* dst1, u32* dst2, u32* dst3, const u32* src0, const u32* src1, const u32* src2, unsigned count, unsigned flag) +{ + unsigned i; + + for(i=0;i<count;++i) { + unsigned char mask; + + u32 c[9]; + + c[1] = src0[0]; + c[4] = src1[0]; + c[7] = src2[0]; + + c[0] = src0[-1]; + c[3] = src1[-1]; + c[6] = src2[-1]; + + c[2] = src0[1]; + c[5] = src1[1]; + c[8] = src2[1]; + + mask = 0; + + if (interp_32_diff(c[0], c[4])) + mask |= 1 << 0; + if (interp_32_diff(c[1], c[4])) + mask |= 1 << 1; + if (interp_32_diff(c[2], c[4])) + mask |= 1 << 2; + if (interp_32_diff(c[3], c[4])) + mask |= 1 << 3; + if (interp_32_diff(c[5], c[4])) + mask |= 1 << 4; + if (interp_32_diff(c[6], c[4])) + mask |= 1 << 5; + if (interp_32_diff(c[7], c[4])) + mask |= 1 << 6; + if (interp_32_diff(c[8], c[4])) + mask |= 1 << 7; + +#define P(a, b) dst##b[a] +#define MUR interp_32_diff(c[1], c[5]) +#define MDR interp_32_diff(c[5], c[7]) +#define MDL interp_32_diff(c[7], c[3]) +#define MUL interp_32_diff(c[3], c[1]) +#define I1(p0) c[p0] +#define I2(i0, i1, p0, p1) interp_32_##i0##i1(c[p0], c[p1]) +#define I3(i0, i1, i2, p0, p1, p2) interp_32_##i0##i1##i2(c[p0], c[p1], c[p2]) + + switch (mask) { + #include "hq4x.dat" + } + +#undef P +#undef MUR +#undef MDR +#undef MDL +#undef MUL +#undef I1 +#undef I2 +#undef I3 + + src0 += 1; + src1 += 1; + src2 += 1; + dst0 += 4; + dst1 += 4; + dst2 += 4; + dst3 += 4; + } +} + + +void RenderHQ4X (SSurface Src, SSurface Dst) +{ + + u32 *lpSrc, *lpDst; + + lpSrc = (u32*)Src.Surface; + lpDst = (u32*)Dst.Surface; + + int dp = Dst.Pitch/2; + int sp = Src.Pitch/2; + for(int i=0;i<Src.Height;i++) + { + hq4x_32_def(lpDst,lpDst+dp,lpDst+dp*2,lpDst+dp*3,lpSrc,lpSrc+sp,lpSrc+sp*2,Src.Width,0); + lpDst += Dst.Pitch*2; + lpSrc += Src.Pitch/2; + } + + //hq4x_32_def (lpSrc, Src.Pitch*2, + // lpSrc, + // lpDst, Dst.Pitch*2 , Src.Width, Src.Height); +} diff --git a/jni/desmume/src/filter/hq4x.dat b/jni/desmume/src/filter/hq4x.dat new file mode 100755 index 0000000..2778adf --- /dev/null +++ b/jni/desmume/src/filter/hq4x.dat @@ -0,0 +1,4244 @@ +/* + * This file is part of the Advance project. + * + * Copyright (C) 2004 Andrea Mazzoleni + * + * 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. + * + * In addition, as a special exception, Andrea Mazzoleni + * gives permission to link the code of this program with + * the MAME library (or with modified versions of MAME that use the + * same license as MAME), and distribute linked combinations including + * the two. You must obey the GNU General Public License in all + * respects for all of the code used other than MAME. If you modify + * this file, you may extend this exception to your version of the + * file, but you are not obligated to do so. If you do not wish to + * do so, delete this exception statement from your version. + */ + +/* + * This effect is a rewritten implementation of the hq effect made by Maxim Stepin + */ + +case 0 : +case 1 : +case 4 : +case 5 : +case 32 : +case 33 : +case 36 : +case 37 : +case 128 : +case 129 : +case 132 : +case 133 : +case 160 : +case 161 : +case 164 : +case 165 : +{ +P(0, 0) = I3(2, 1, 1, 4, 1, 3); +P(1, 0) = I3(5, 2, 1, 4, 1, 3); +P(2, 0) = I3(5, 2, 1, 4, 1, 5); +P(3, 0) = I3(2, 1, 1, 4, 1, 5); +P(0, 1) = I3(5, 2, 1, 4, 3, 1); +P(1, 1) = I3(6, 1, 1, 4, 1, 3); +P(2, 1) = I3(6, 1, 1, 4, 1, 5); +P(3, 1) = I3(5, 2, 1, 4, 5, 1); +P(0, 2) = I3(5, 2, 1, 4, 3, 7); +P(1, 2) = I3(6, 1, 1, 4, 3, 7); +P(2, 2) = I3(6, 1, 1, 4, 5, 7); +P(3, 2) = I3(5, 2, 1, 4, 5, 7); +P(0, 3) = I3(2, 1, 1, 4, 3, 7); +P(1, 3) = I3(5, 2, 1, 4, 7, 3); +P(2, 3) = I3(5, 2, 1, 4, 7, 5); +P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} break; +case 2 : +case 34 : +case 130 : +case 162 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(0, 2) = I3(5, 2, 1, 4, 3, 7); +P(1, 2) = I3(6, 1, 1, 4, 3, 7); +P(2, 2) = I3(6, 1, 1, 4, 5, 7); +P(3, 2) = I3(5, 2, 1, 4, 5, 7); +P(0, 3) = I3(2, 1, 1, 4, 3, 7); +P(1, 3) = I3(5, 2, 1, 4, 7, 3); +P(2, 3) = I3(5, 2, 1, 4, 7, 5); +P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} break; +case 3 : +case 35 : +case 131 : +case 163 : +{ +P(0, 0) = I2(5, 3, 4, 3); +P(1, 0) = I2(7, 1, 4, 3); +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(0, 2) = I3(5, 2, 1, 4, 3, 7); +P(1, 2) = I3(6, 1, 1, 4, 3, 7); +P(2, 2) = I3(6, 1, 1, 4, 5, 7); +P(3, 2) = I3(5, 2, 1, 4, 5, 7); +P(0, 3) = I3(2, 1, 1, 4, 3, 7); +P(1, 3) = I3(5, 2, 1, 4, 7, 3); +P(2, 3) = I3(5, 2, 1, 4, 7, 5); +P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} break; +case 6 : +case 38 : +case 134 : +case 166 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(2, 0) = I2(7, 1, 4, 5); +P(3, 0) = I2(5, 3, 4, 5); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(0, 2) = I3(5, 2, 1, 4, 3, 7); +P(1, 2) = I3(6, 1, 1, 4, 3, 7); +P(2, 2) = I3(6, 1, 1, 4, 5, 7); +P(3, 2) = I3(5, 2, 1, 4, 5, 7); +P(0, 3) = I3(2, 1, 1, 4, 3, 7); +P(1, 3) = I3(5, 2, 1, 4, 7, 3); +P(2, 3) = I3(5, 2, 1, 4, 7, 5); +P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} break; +case 7 : +case 39 : +case 135 : +case 167 : +{ +P(0, 0) = I2(5, 3, 4, 3); +P(1, 0) = I2(7, 1, 4, 3); +P(2, 0) = I2(7, 1, 4, 5); +P(3, 0) = I2(5, 3, 4, 5); +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(0, 2) = I3(5, 2, 1, 4, 3, 7); +P(1, 2) = I3(6, 1, 1, 4, 3, 7); +P(2, 2) = I3(6, 1, 1, 4, 5, 7); +P(3, 2) = I3(5, 2, 1, 4, 5, 7); +P(0, 3) = I3(2, 1, 1, 4, 3, 7); +P(1, 3) = I3(5, 2, 1, 4, 7, 3); +P(2, 3) = I3(5, 2, 1, 4, 7, 5); +P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} break; +case 8 : +case 12 : +case 136 : +case 140 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I3(5, 2, 1, 4, 1, 5); +P(3, 0) = I3(2, 1, 1, 4, 1, 5); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I3(6, 1, 1, 4, 1, 5); +P(3, 1) = I3(5, 2, 1, 4, 5, 1); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I3(6, 1, 1, 4, 5, 7); +P(3, 2) = I3(5, 2, 1, 4, 5, 7); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I3(5, 2, 1, 4, 7, 5); +P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} break; +case 9 : +case 13 : +case 137 : +case 141 : +{ +P(0, 0) = I2(5, 3, 4, 1); +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I3(5, 2, 1, 4, 1, 5); +P(3, 0) = I3(2, 1, 1, 4, 1, 5); +P(0, 1) = I2(7, 1, 4, 1); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I3(6, 1, 1, 4, 1, 5); +P(3, 1) = I3(5, 2, 1, 4, 5, 1); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I3(6, 1, 1, 4, 5, 7); +P(3, 2) = I3(5, 2, 1, 4, 5, 7); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I3(5, 2, 1, 4, 7, 5); +P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} break; +case 10 : +case 138 : +{ +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I3(6, 1, 1, 4, 5, 7); +P(3, 2) = I3(5, 2, 1, 4, 5, 7); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I3(5, 2, 1, 4, 7, 5); +P(3, 3) = I3(2, 1, 1, 4, 5, 7); +if (MUL) { + P(0, 0) = I2(5, 3, 4, 0); + P(1, 0) = I2(3, 1, 4, 0); + P(0, 1) = I2(3, 1, 4, 0); + P(1, 1) = I2(7, 1, 4, 0); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(1, 1, 1, 4); + P(0, 1) = I2(1, 1, 3, 4); + P(1, 1) = I1(4); +} +} break; +case 11 : +case 139 : +{ +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(1, 1) = I1(4); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I3(6, 1, 1, 4, 5, 7); +P(3, 2) = I3(5, 2, 1, 4, 5, 7); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I3(5, 2, 1, 4, 7, 5); +P(3, 3) = I3(2, 1, 1, 4, 5, 7); +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(0, 1) = I1(4); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(1, 1, 1, 4); + P(0, 1) = I2(1, 1, 3, 4); +} +} break; +case 14 : +case 142 : +{ +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I3(6, 1, 1, 4, 5, 7); +P(3, 2) = I3(5, 2, 1, 4, 5, 7); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I3(5, 2, 1, 4, 7, 5); +P(3, 3) = I3(2, 1, 1, 4, 5, 7); +if (MUL) { + P(0, 0) = I2(5, 3, 4, 0); + P(1, 0) = I2(3, 1, 4, 0); + P(2, 0) = I2(7, 1, 4, 5); + P(3, 0) = I2(5, 3, 4, 5); + P(0, 1) = I2(3, 1, 4, 0); + P(1, 1) = I2(7, 1, 4, 0); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(5, 3, 1, 3); + P(2, 0) = I2(3, 1, 1, 4); + P(3, 0) = I2(3, 1, 4, 1); + P(0, 1) = I3(2, 1, 1, 3, 1, 4); + P(1, 1) = I3(6, 1, 1, 4, 1, 3); +} +} break; +case 15 : +case 143 : +{ +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I3(6, 1, 1, 4, 5, 7); +P(3, 2) = I3(5, 2, 1, 4, 5, 7); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I3(5, 2, 1, 4, 7, 5); +P(3, 3) = I3(2, 1, 1, 4, 5, 7); +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(2, 0) = I2(7, 1, 4, 5); + P(3, 0) = I2(5, 3, 4, 5); + P(0, 1) = I1(4); + P(1, 1) = I1(4); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(5, 3, 1, 3); + P(2, 0) = I2(3, 1, 1, 4); + P(3, 0) = I2(3, 1, 4, 1); + P(0, 1) = I3(2, 1, 1, 3, 1, 4); + P(1, 1) = I3(6, 1, 1, 4, 1, 3); +} +} break; +case 16 : +case 17 : +case 48 : +case 49 : +{ +P(0, 0) = I3(2, 1, 1, 4, 1, 3); +P(1, 0) = I3(5, 2, 1, 4, 1, 3); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I3(5, 2, 1, 4, 3, 1); +P(1, 1) = I3(6, 1, 1, 4, 1, 3); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I3(5, 2, 1, 4, 3, 7); +P(1, 2) = I3(6, 1, 1, 4, 3, 7); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I3(2, 1, 1, 4, 3, 7); +P(1, 3) = I3(5, 2, 1, 4, 7, 3); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +} break; +case 18 : +case 50 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(0, 2) = I3(5, 2, 1, 4, 3, 7); +P(1, 2) = I3(6, 1, 1, 4, 3, 7); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I3(2, 1, 1, 4, 3, 7); +P(1, 3) = I3(5, 2, 1, 4, 7, 3); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MUR) { + P(2, 0) = I2(3, 1, 4, 2); + P(3, 0) = I2(5, 3, 4, 2); + P(2, 1) = I2(7, 1, 4, 2); + P(3, 1) = I2(3, 1, 4, 2); +} else { + P(2, 0) = I2(1, 1, 1, 4); + P(3, 0) = I2(1, 1, 1, 5); + P(2, 1) = I1(4); + P(3, 1) = I2(1, 1, 4, 5); +} +} break; +case 19 : +case 51 : +{ +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(0, 2) = I3(5, 2, 1, 4, 3, 7); +P(1, 2) = I3(6, 1, 1, 4, 3, 7); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I3(2, 1, 1, 4, 3, 7); +P(1, 3) = I3(5, 2, 1, 4, 7, 3); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MUR) { + P(0, 0) = I2(5, 3, 4, 3); + P(1, 0) = I2(7, 1, 4, 3); + P(2, 0) = I2(3, 1, 4, 2); + P(3, 0) = I2(5, 3, 4, 2); + P(2, 1) = I2(7, 1, 4, 2); + P(3, 1) = I2(3, 1, 4, 2); +} else { + P(0, 0) = I2(3, 1, 4, 1); + P(1, 0) = I2(3, 1, 1, 4); + P(2, 0) = I2(5, 3, 1, 5); + P(3, 0) = I2(1, 1, 1, 5); + P(2, 1) = I3(6, 1, 1, 4, 1, 5); + P(3, 1) = I3(2, 1, 1, 5, 1, 4); +} +} break; +case 20 : +case 21 : +case 52 : +case 53 : +{ +P(0, 0) = I3(2, 1, 1, 4, 1, 3); +P(1, 0) = I3(5, 2, 1, 4, 1, 3); +P(2, 0) = I2(5, 3, 4, 1); +P(3, 0) = I2(5, 3, 4, 1); +P(0, 1) = I3(5, 2, 1, 4, 3, 1); +P(1, 1) = I3(6, 1, 1, 4, 1, 3); +P(2, 1) = I2(7, 1, 4, 1); +P(3, 1) = I2(7, 1, 4, 1); +P(0, 2) = I3(5, 2, 1, 4, 3, 7); +P(1, 2) = I3(6, 1, 1, 4, 3, 7); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I3(2, 1, 1, 4, 3, 7); +P(1, 3) = I3(5, 2, 1, 4, 7, 3); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +} break; +case 22 : +case 54 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I1(4); +P(0, 2) = I3(5, 2, 1, 4, 3, 7); +P(1, 2) = I3(6, 1, 1, 4, 3, 7); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I3(2, 1, 1, 4, 3, 7); +P(1, 3) = I3(5, 2, 1, 4, 7, 3); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MUR) { + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(3, 1) = I1(4); +} else { + P(2, 0) = I2(1, 1, 1, 4); + P(3, 0) = I2(1, 1, 1, 5); + P(3, 1) = I2(1, 1, 4, 5); +} +} break; +case 23 : +case 55 : +{ +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(0, 2) = I3(5, 2, 1, 4, 3, 7); +P(1, 2) = I3(6, 1, 1, 4, 3, 7); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I3(2, 1, 1, 4, 3, 7); +P(1, 3) = I3(5, 2, 1, 4, 7, 3); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MUR) { + P(0, 0) = I2(5, 3, 4, 3); + P(1, 0) = I2(7, 1, 4, 3); + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(2, 1) = I1(4); + P(3, 1) = I1(4); +} else { + P(0, 0) = I2(3, 1, 4, 1); + P(1, 0) = I2(3, 1, 1, 4); + P(2, 0) = I2(5, 3, 1, 5); + P(3, 0) = I2(1, 1, 1, 5); + P(2, 1) = I3(6, 1, 1, 4, 1, 5); + P(3, 1) = I3(2, 1, 1, 5, 1, 4); +} +} break; +case 24 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +} break; +case 25 : +{ +P(0, 0) = I2(5, 3, 4, 1); +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(7, 1, 4, 1); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +} break; +case 26 : +case 31 : +{ +P(1, 1) = I1(4); +P(2, 1) = I1(4); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(0, 1) = I1(4); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(1, 1, 1, 4); + P(0, 1) = I2(1, 1, 3, 4); +} +if (MUR) { + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(3, 1) = I1(4); +} else { + P(2, 0) = I2(1, 1, 1, 4); + P(3, 0) = I2(1, 1, 1, 5); + P(3, 1) = I2(1, 1, 4, 5); +} +} break; +case 27 : +{ +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(1, 1) = I1(4); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(0, 1) = I1(4); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(1, 1, 1, 4); + P(0, 1) = I2(1, 1, 3, 4); +} +} break; +case 28 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I2(5, 3, 4, 1); +P(3, 0) = I2(5, 3, 4, 1); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 1); +P(3, 1) = I2(7, 1, 4, 1); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +} break; +case 29 : +{ +P(0, 0) = I2(5, 3, 4, 1); +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I2(5, 3, 4, 1); +P(3, 0) = I2(5, 3, 4, 1); +P(0, 1) = I2(7, 1, 4, 1); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I2(7, 1, 4, 1); +P(3, 1) = I2(7, 1, 4, 1); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +} break; +case 30 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I1(4); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MUR) { + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(3, 1) = I1(4); +} else { + P(2, 0) = I2(1, 1, 1, 4); + P(3, 0) = I2(1, 1, 1, 5); + P(3, 1) = I2(1, 1, 4, 5); +} +} break; +case 40 : +case 44 : +case 168 : +case 172 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I3(5, 2, 1, 4, 1, 5); +P(3, 0) = I3(2, 1, 1, 4, 1, 5); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I3(6, 1, 1, 4, 1, 5); +P(3, 1) = I3(5, 2, 1, 4, 5, 1); +P(0, 2) = I2(7, 1, 4, 7); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I3(6, 1, 1, 4, 5, 7); +P(3, 2) = I3(5, 2, 1, 4, 5, 7); +P(0, 3) = I2(5, 3, 4, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I3(5, 2, 1, 4, 7, 5); +P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} break; +case 41 : +case 45 : +case 169 : +case 173 : +{ +P(0, 0) = I2(5, 3, 4, 1); +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I3(5, 2, 1, 4, 1, 5); +P(3, 0) = I3(2, 1, 1, 4, 1, 5); +P(0, 1) = I2(7, 1, 4, 1); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I3(6, 1, 1, 4, 1, 5); +P(3, 1) = I3(5, 2, 1, 4, 5, 1); +P(0, 2) = I2(7, 1, 4, 7); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I3(6, 1, 1, 4, 5, 7); +P(3, 2) = I3(5, 2, 1, 4, 5, 7); +P(0, 3) = I2(5, 3, 4, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I3(5, 2, 1, 4, 7, 5); +P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} break; +case 42 : +case 170 : +{ +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I3(6, 1, 1, 4, 5, 7); +P(3, 2) = I3(5, 2, 1, 4, 5, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I3(5, 2, 1, 4, 7, 5); +P(3, 3) = I3(2, 1, 1, 4, 5, 7); +if (MUL) { + P(0, 0) = I2(5, 3, 4, 0); + P(1, 0) = I2(3, 1, 4, 0); + P(0, 1) = I2(3, 1, 4, 0); + P(1, 1) = I2(7, 1, 4, 0); + P(0, 2) = I2(7, 1, 4, 7); + P(0, 3) = I2(5, 3, 4, 7); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I3(2, 1, 1, 1, 3, 4); + P(0, 1) = I2(5, 3, 3, 1); + P(1, 1) = I3(6, 1, 1, 4, 1, 3); + P(0, 2) = I2(3, 1, 3, 4); + P(0, 3) = I2(3, 1, 4, 3); +} +} break; +case 43 : +case 171 : +{ +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I3(6, 1, 1, 4, 5, 7); +P(3, 2) = I3(5, 2, 1, 4, 5, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I3(5, 2, 1, 4, 7, 5); +P(3, 3) = I3(2, 1, 1, 4, 5, 7); +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(0, 1) = I1(4); + P(1, 1) = I1(4); + P(0, 2) = I2(7, 1, 4, 7); + P(0, 3) = I2(5, 3, 4, 7); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I3(2, 1, 1, 1, 3, 4); + P(0, 1) = I2(5, 3, 3, 1); + P(1, 1) = I3(6, 1, 1, 4, 1, 3); + P(0, 2) = I2(3, 1, 3, 4); + P(0, 3) = I2(3, 1, 4, 3); +} +} break; +case 46 : +case 174 : +{ +P(2, 0) = I2(7, 1, 4, 5); +P(3, 0) = I2(5, 3, 4, 5); +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(0, 2) = I2(7, 1, 4, 7); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I3(6, 1, 1, 4, 5, 7); +P(3, 2) = I3(5, 2, 1, 4, 5, 7); +P(0, 3) = I2(5, 3, 4, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I3(5, 2, 1, 4, 7, 5); +P(3, 3) = I3(2, 1, 1, 4, 5, 7); +if (MUL) { + P(0, 0) = I2(5, 3, 4, 0); + P(1, 0) = I2(3, 1, 4, 0); + P(0, 1) = I2(3, 1, 4, 0); + P(1, 1) = I2(7, 1, 4, 0); +} else { + P(0, 0) = I3(2, 1, 1, 4, 1, 3); + P(1, 0) = I2(3, 1, 4, 1); + P(0, 1) = I2(3, 1, 4, 3); + P(1, 1) = I1(4); +} +} break; +case 47 : +case 175 : +{ +P(1, 0) = I1(4); +P(2, 0) = I2(7, 1, 4, 5); +P(3, 0) = I2(5, 3, 4, 5); +P(0, 1) = I1(4); +P(1, 1) = I1(4); +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(0, 2) = I2(7, 1, 4, 7); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I3(6, 1, 1, 4, 5, 7); +P(3, 2) = I3(5, 2, 1, 4, 5, 7); +P(0, 3) = I2(5, 3, 4, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I3(5, 2, 1, 4, 7, 5); +P(3, 3) = I3(2, 1, 1, 4, 5, 7); +if (MUL) { + P(0, 0) = I1(4); +} else { + P(0, 0) = I3(2, 1, 1, 4, 1, 3); +} +} break; +case 56 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I2(7, 1, 4, 7); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I2(5, 3, 4, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +} break; +case 57 : +{ +P(0, 0) = I2(5, 3, 4, 1); +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(7, 1, 4, 1); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I2(7, 1, 4, 7); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I2(5, 3, 4, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +} break; +case 58 : +{ +P(0, 2) = I2(7, 1, 4, 7); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I2(5, 3, 4, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MUL) { + P(0, 0) = I2(5, 3, 4, 0); + P(1, 0) = I2(3, 1, 4, 0); + P(0, 1) = I2(3, 1, 4, 0); + P(1, 1) = I2(7, 1, 4, 0); +} else { + P(0, 0) = I3(2, 1, 1, 4, 1, 3); + P(1, 0) = I2(3, 1, 4, 1); + P(0, 1) = I2(3, 1, 4, 3); + P(1, 1) = I1(4); +} +if (MUR) { + P(2, 0) = I2(3, 1, 4, 2); + P(3, 0) = I2(5, 3, 4, 2); + P(2, 1) = I2(7, 1, 4, 2); + P(3, 1) = I2(3, 1, 4, 2); +} else { + P(2, 0) = I2(3, 1, 4, 1); + P(3, 0) = I3(2, 1, 1, 4, 1, 5); + P(2, 1) = I1(4); + P(3, 1) = I2(3, 1, 4, 5); +} +} break; +case 59 : +{ +P(1, 1) = I1(4); +P(0, 2) = I2(7, 1, 4, 7); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I2(5, 3, 4, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(0, 1) = I1(4); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(1, 1, 1, 4); + P(0, 1) = I2(1, 1, 3, 4); +} +if (MUR) { + P(2, 0) = I2(3, 1, 4, 2); + P(3, 0) = I2(5, 3, 4, 2); + P(2, 1) = I2(7, 1, 4, 2); + P(3, 1) = I2(3, 1, 4, 2); +} else { + P(2, 0) = I2(3, 1, 4, 1); + P(3, 0) = I3(2, 1, 1, 4, 1, 5); + P(2, 1) = I1(4); + P(3, 1) = I2(3, 1, 4, 5); +} +} break; +case 60 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I2(5, 3, 4, 1); +P(3, 0) = I2(5, 3, 4, 1); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 1); +P(3, 1) = I2(7, 1, 4, 1); +P(0, 2) = I2(7, 1, 4, 7); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I2(5, 3, 4, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +} break; +case 61 : +{ +P(0, 0) = I2(5, 3, 4, 1); +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I2(5, 3, 4, 1); +P(3, 0) = I2(5, 3, 4, 1); +P(0, 1) = I2(7, 1, 4, 1); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I2(7, 1, 4, 1); +P(3, 1) = I2(7, 1, 4, 1); +P(0, 2) = I2(7, 1, 4, 7); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I2(5, 3, 4, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +} break; +case 62 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I1(4); +P(0, 2) = I2(7, 1, 4, 7); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I2(5, 3, 4, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MUR) { + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(3, 1) = I1(4); +} else { + P(2, 0) = I2(1, 1, 1, 4); + P(3, 0) = I2(1, 1, 1, 5); + P(3, 1) = I2(1, 1, 4, 5); +} +} break; +case 63 : +{ +P(1, 0) = I1(4); +P(0, 1) = I1(4); +P(1, 1) = I1(4); +P(2, 1) = I1(4); +P(0, 2) = I2(7, 1, 4, 7); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I2(5, 3, 4, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I3(5, 2, 1, 4, 7, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MUL) { + P(0, 0) = I1(4); +} else { + P(0, 0) = I3(2, 1, 1, 4, 1, 3); +} +if (MUR) { + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(3, 1) = I1(4); +} else { + P(2, 0) = I2(1, 1, 1, 4); + P(3, 0) = I2(1, 1, 1, 5); + P(3, 1) = I2(1, 1, 4, 5); +} +} break; +case 64 : +case 65 : +case 68 : +case 69 : +{ +P(0, 0) = I3(2, 1, 1, 4, 1, 3); +P(1, 0) = I3(5, 2, 1, 4, 1, 3); +P(2, 0) = I3(5, 2, 1, 4, 1, 5); +P(3, 0) = I3(2, 1, 1, 4, 1, 5); +P(0, 1) = I3(5, 2, 1, 4, 3, 1); +P(1, 1) = I3(6, 1, 1, 4, 1, 3); +P(2, 1) = I3(6, 1, 1, 4, 1, 5); +P(3, 1) = I3(5, 2, 1, 4, 5, 1); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +} break; +case 66 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +} break; +case 67 : +{ +P(0, 0) = I2(5, 3, 4, 3); +P(1, 0) = I2(7, 1, 4, 3); +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +} break; +case 70 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(2, 0) = I2(7, 1, 4, 5); +P(3, 0) = I2(5, 3, 4, 5); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +} break; +case 71 : +{ +P(0, 0) = I2(5, 3, 4, 3); +P(1, 0) = I2(7, 1, 4, 3); +P(2, 0) = I2(7, 1, 4, 5); +P(3, 0) = I2(5, 3, 4, 5); +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +} break; +case 72 : +case 76 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I3(5, 2, 1, 4, 1, 5); +P(3, 0) = I3(2, 1, 1, 4, 1, 5); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I3(6, 1, 1, 4, 1, 5); +P(3, 1) = I3(5, 2, 1, 4, 5, 1); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MDL) { + P(0, 2) = I2(3, 1, 4, 6); + P(1, 2) = I2(7, 1, 4, 6); + P(0, 3) = I2(5, 3, 4, 6); + P(1, 3) = I2(3, 1, 4, 6); +} else { + P(0, 2) = I2(1, 1, 3, 4); + P(1, 2) = I1(4); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(1, 1, 4, 7); +} +} break; +case 73 : +case 77 : +{ +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I3(5, 2, 1, 4, 1, 5); +P(3, 0) = I3(2, 1, 1, 4, 1, 5); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I3(6, 1, 1, 4, 1, 5); +P(3, 1) = I3(5, 2, 1, 4, 5, 1); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MDL) { + P(0, 0) = I2(5, 3, 4, 1); + P(0, 1) = I2(7, 1, 4, 1); + P(0, 2) = I2(3, 1, 4, 6); + P(1, 2) = I2(7, 1, 4, 6); + P(0, 3) = I2(5, 3, 4, 6); + P(1, 3) = I2(3, 1, 4, 6); +} else { + P(0, 0) = I2(3, 1, 4, 3); + P(0, 1) = I2(3, 1, 3, 4); + P(0, 2) = I2(5, 3, 3, 7); + P(1, 2) = I3(6, 1, 1, 4, 3, 7); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I3(2, 1, 1, 7, 3, 4); +} +} break; +case 74 : +case 107 : +{ +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(1, 1) = I1(4); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(1, 2) = I1(4); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MDL) { + P(0, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); +} else { + P(0, 2) = I2(1, 1, 3, 4); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(1, 1, 4, 7); +} +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(0, 1) = I1(4); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(1, 1, 1, 4); + P(0, 1) = I2(1, 1, 3, 4); +} +} break; +case 75 : +{ +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(1, 1) = I1(4); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(0, 1) = I1(4); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(1, 1, 1, 4); + P(0, 1) = I2(1, 1, 3, 4); +} +} break; +case 78 : +{ +P(2, 0) = I2(7, 1, 4, 5); +P(3, 0) = I2(5, 3, 4, 5); +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MDL) { + P(0, 2) = I2(3, 1, 4, 6); + P(1, 2) = I2(7, 1, 4, 6); + P(0, 3) = I2(5, 3, 4, 6); + P(1, 3) = I2(3, 1, 4, 6); +} else { + P(0, 2) = I2(3, 1, 4, 3); + P(1, 2) = I1(4); + P(0, 3) = I3(2, 1, 1, 4, 3, 7); + P(1, 3) = I2(3, 1, 4, 7); +} +if (MUL) { + P(0, 0) = I2(5, 3, 4, 0); + P(1, 0) = I2(3, 1, 4, 0); + P(0, 1) = I2(3, 1, 4, 0); + P(1, 1) = I2(7, 1, 4, 0); +} else { + P(0, 0) = I3(2, 1, 1, 4, 1, 3); + P(1, 0) = I2(3, 1, 4, 1); + P(0, 1) = I2(3, 1, 4, 3); + P(1, 1) = I1(4); +} +} break; +case 79 : +{ +P(2, 0) = I2(7, 1, 4, 5); +P(3, 0) = I2(5, 3, 4, 5); +P(1, 1) = I1(4); +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MDL) { + P(0, 2) = I2(3, 1, 4, 6); + P(1, 2) = I2(7, 1, 4, 6); + P(0, 3) = I2(5, 3, 4, 6); + P(1, 3) = I2(3, 1, 4, 6); +} else { + P(0, 2) = I2(3, 1, 4, 3); + P(1, 2) = I1(4); + P(0, 3) = I3(2, 1, 1, 4, 3, 7); + P(1, 3) = I2(3, 1, 4, 7); +} +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(0, 1) = I1(4); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(1, 1, 1, 4); + P(0, 1) = I2(1, 1, 3, 4); +} +} break; +case 80 : +case 81 : +{ +P(0, 0) = I3(2, 1, 1, 4, 1, 3); +P(1, 0) = I3(5, 2, 1, 4, 1, 3); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I3(5, 2, 1, 4, 3, 1); +P(1, 1) = I3(6, 1, 1, 4, 1, 3); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +if (MDR) { + P(2, 2) = I2(7, 1, 4, 8); + P(3, 2) = I2(3, 1, 4, 8); + P(2, 3) = I2(3, 1, 4, 8); + P(3, 3) = I2(5, 3, 4, 8); +} else { + P(2, 2) = I1(4); + P(3, 2) = I2(1, 1, 4, 5); + P(2, 3) = I2(1, 1, 4, 7); + P(3, 3) = I2(1, 1, 5, 7); +} +} break; +case 82 : +case 214 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I1(4); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I1(4); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +if (MDR) { + P(3, 2) = I1(4); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(3, 2) = I2(1, 1, 4, 5); + P(2, 3) = I2(1, 1, 4, 7); + P(3, 3) = I2(1, 1, 5, 7); +} +if (MUR) { + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(3, 1) = I1(4); +} else { + P(2, 0) = I2(1, 1, 1, 4); + P(3, 0) = I2(1, 1, 1, 5); + P(3, 1) = I2(1, 1, 4, 5); +} +} break; +case 83 : +{ +P(0, 0) = I2(5, 3, 4, 3); +P(1, 0) = I2(7, 1, 4, 3); +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +if (MDR) { + P(2, 2) = I2(7, 1, 4, 8); + P(3, 2) = I2(3, 1, 4, 8); + P(2, 3) = I2(3, 1, 4, 8); + P(3, 3) = I2(5, 3, 4, 8); +} else { + P(2, 2) = I1(4); + P(3, 2) = I2(3, 1, 4, 5); + P(2, 3) = I2(3, 1, 4, 7); + P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} +if (MUR) { + P(2, 0) = I2(3, 1, 4, 2); + P(3, 0) = I2(5, 3, 4, 2); + P(2, 1) = I2(7, 1, 4, 2); + P(3, 1) = I2(3, 1, 4, 2); +} else { + P(2, 0) = I2(3, 1, 4, 1); + P(3, 0) = I3(2, 1, 1, 4, 1, 5); + P(2, 1) = I1(4); + P(3, 1) = I2(3, 1, 4, 5); +} +} break; +case 84 : +case 85 : +{ +P(0, 0) = I3(2, 1, 1, 4, 1, 3); +P(1, 0) = I3(5, 2, 1, 4, 1, 3); +P(2, 0) = I2(5, 3, 4, 1); +P(0, 1) = I3(5, 2, 1, 4, 3, 1); +P(1, 1) = I3(6, 1, 1, 4, 1, 3); +P(2, 1) = I2(7, 1, 4, 1); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +if (MDR) { + P(3, 0) = I2(5, 3, 4, 1); + P(3, 1) = I2(7, 1, 4, 1); + P(2, 2) = I2(7, 1, 4, 8); + P(3, 2) = I2(3, 1, 4, 8); + P(2, 3) = I2(3, 1, 4, 8); + P(3, 3) = I2(5, 3, 4, 8); +} else { + P(3, 0) = I2(3, 1, 4, 5); + P(3, 1) = I2(3, 1, 5, 4); + P(2, 2) = I3(6, 1, 1, 4, 5, 7); + P(3, 2) = I2(5, 3, 5, 7); + P(2, 3) = I3(2, 1, 1, 7, 4, 5); + P(3, 3) = I2(1, 1, 5, 7); +} +} break; +case 86 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I1(4); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MUR) { + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(3, 1) = I1(4); +} else { + P(2, 0) = I2(1, 1, 1, 4); + P(3, 0) = I2(1, 1, 1, 5); + P(3, 1) = I2(1, 1, 4, 5); +} +} break; +case 87 : +{ +P(0, 0) = I2(5, 3, 4, 3); +P(1, 0) = I2(7, 1, 4, 3); +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(2, 1) = I1(4); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +if (MDR) { + P(2, 2) = I2(7, 1, 4, 8); + P(3, 2) = I2(3, 1, 4, 8); + P(2, 3) = I2(3, 1, 4, 8); + P(3, 3) = I2(5, 3, 4, 8); +} else { + P(2, 2) = I1(4); + P(3, 2) = I2(3, 1, 4, 5); + P(2, 3) = I2(3, 1, 4, 7); + P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} +if (MUR) { + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(3, 1) = I1(4); +} else { + P(2, 0) = I2(1, 1, 1, 4); + P(3, 0) = I2(1, 1, 1, 5); + P(3, 1) = I2(1, 1, 4, 5); +} +} break; +case 88 : +case 248 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(1, 2) = I1(4); +P(2, 2) = I1(4); +if (MDL) { + P(0, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); +} else { + P(0, 2) = I2(1, 1, 3, 4); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(1, 1, 4, 7); +} +if (MDR) { + P(3, 2) = I1(4); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(3, 2) = I2(1, 1, 4, 5); + P(2, 3) = I2(1, 1, 4, 7); + P(3, 3) = I2(1, 1, 5, 7); +} +} break; +case 89 : +{ +P(0, 0) = I2(5, 3, 4, 1); +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(7, 1, 4, 1); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +if (MDL) { + P(0, 2) = I2(3, 1, 4, 6); + P(1, 2) = I2(7, 1, 4, 6); + P(0, 3) = I2(5, 3, 4, 6); + P(1, 3) = I2(3, 1, 4, 6); +} else { + P(0, 2) = I2(3, 1, 4, 3); + P(1, 2) = I1(4); + P(0, 3) = I3(2, 1, 1, 4, 3, 7); + P(1, 3) = I2(3, 1, 4, 7); +} +if (MDR) { + P(2, 2) = I2(7, 1, 4, 8); + P(3, 2) = I2(3, 1, 4, 8); + P(2, 3) = I2(3, 1, 4, 8); + P(3, 3) = I2(5, 3, 4, 8); +} else { + P(2, 2) = I1(4); + P(3, 2) = I2(3, 1, 4, 5); + P(2, 3) = I2(3, 1, 4, 7); + P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} +} break; +case 90 : +{ +if (MDL) { + P(0, 2) = I2(3, 1, 4, 6); + P(1, 2) = I2(7, 1, 4, 6); + P(0, 3) = I2(5, 3, 4, 6); + P(1, 3) = I2(3, 1, 4, 6); +} else { + P(0, 2) = I2(3, 1, 4, 3); + P(1, 2) = I1(4); + P(0, 3) = I3(2, 1, 1, 4, 3, 7); + P(1, 3) = I2(3, 1, 4, 7); +} +if (MDR) { + P(2, 2) = I2(7, 1, 4, 8); + P(3, 2) = I2(3, 1, 4, 8); + P(2, 3) = I2(3, 1, 4, 8); + P(3, 3) = I2(5, 3, 4, 8); +} else { + P(2, 2) = I1(4); + P(3, 2) = I2(3, 1, 4, 5); + P(2, 3) = I2(3, 1, 4, 7); + P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} +if (MUL) { + P(0, 0) = I2(5, 3, 4, 0); + P(1, 0) = I2(3, 1, 4, 0); + P(0, 1) = I2(3, 1, 4, 0); + P(1, 1) = I2(7, 1, 4, 0); +} else { + P(0, 0) = I3(2, 1, 1, 4, 1, 3); + P(1, 0) = I2(3, 1, 4, 1); + P(0, 1) = I2(3, 1, 4, 3); + P(1, 1) = I1(4); +} +if (MUR) { + P(2, 0) = I2(3, 1, 4, 2); + P(3, 0) = I2(5, 3, 4, 2); + P(2, 1) = I2(7, 1, 4, 2); + P(3, 1) = I2(3, 1, 4, 2); +} else { + P(2, 0) = I2(3, 1, 4, 1); + P(3, 0) = I3(2, 1, 1, 4, 1, 5); + P(2, 1) = I1(4); + P(3, 1) = I2(3, 1, 4, 5); +} +} break; +case 91 : +{ +P(1, 1) = I1(4); +if (MDL) { + P(0, 2) = I2(3, 1, 4, 6); + P(1, 2) = I2(7, 1, 4, 6); + P(0, 3) = I2(5, 3, 4, 6); + P(1, 3) = I2(3, 1, 4, 6); +} else { + P(0, 2) = I2(3, 1, 4, 3); + P(1, 2) = I1(4); + P(0, 3) = I3(2, 1, 1, 4, 3, 7); + P(1, 3) = I2(3, 1, 4, 7); +} +if (MDR) { + P(2, 2) = I2(7, 1, 4, 8); + P(3, 2) = I2(3, 1, 4, 8); + P(2, 3) = I2(3, 1, 4, 8); + P(3, 3) = I2(5, 3, 4, 8); +} else { + P(2, 2) = I1(4); + P(3, 2) = I2(3, 1, 4, 5); + P(2, 3) = I2(3, 1, 4, 7); + P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(0, 1) = I1(4); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(1, 1, 1, 4); + P(0, 1) = I2(1, 1, 3, 4); +} +if (MUR) { + P(2, 0) = I2(3, 1, 4, 2); + P(3, 0) = I2(5, 3, 4, 2); + P(2, 1) = I2(7, 1, 4, 2); + P(3, 1) = I2(3, 1, 4, 2); +} else { + P(2, 0) = I2(3, 1, 4, 1); + P(3, 0) = I3(2, 1, 1, 4, 1, 5); + P(2, 1) = I1(4); + P(3, 1) = I2(3, 1, 4, 5); +} +} break; +case 92 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I2(5, 3, 4, 1); +P(3, 0) = I2(5, 3, 4, 1); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 1); +P(3, 1) = I2(7, 1, 4, 1); +if (MDL) { + P(0, 2) = I2(3, 1, 4, 6); + P(1, 2) = I2(7, 1, 4, 6); + P(0, 3) = I2(5, 3, 4, 6); + P(1, 3) = I2(3, 1, 4, 6); +} else { + P(0, 2) = I2(3, 1, 4, 3); + P(1, 2) = I1(4); + P(0, 3) = I3(2, 1, 1, 4, 3, 7); + P(1, 3) = I2(3, 1, 4, 7); +} +if (MDR) { + P(2, 2) = I2(7, 1, 4, 8); + P(3, 2) = I2(3, 1, 4, 8); + P(2, 3) = I2(3, 1, 4, 8); + P(3, 3) = I2(5, 3, 4, 8); +} else { + P(2, 2) = I1(4); + P(3, 2) = I2(3, 1, 4, 5); + P(2, 3) = I2(3, 1, 4, 7); + P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} +} break; +case 93 : +{ +P(0, 0) = I2(5, 3, 4, 1); +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I2(5, 3, 4, 1); +P(3, 0) = I2(5, 3, 4, 1); +P(0, 1) = I2(7, 1, 4, 1); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I2(7, 1, 4, 1); +P(3, 1) = I2(7, 1, 4, 1); +if (MDL) { + P(0, 2) = I2(3, 1, 4, 6); + P(1, 2) = I2(7, 1, 4, 6); + P(0, 3) = I2(5, 3, 4, 6); + P(1, 3) = I2(3, 1, 4, 6); +} else { + P(0, 2) = I2(3, 1, 4, 3); + P(1, 2) = I1(4); + P(0, 3) = I3(2, 1, 1, 4, 3, 7); + P(1, 3) = I2(3, 1, 4, 7); +} +if (MDR) { + P(2, 2) = I2(7, 1, 4, 8); + P(3, 2) = I2(3, 1, 4, 8); + P(2, 3) = I2(3, 1, 4, 8); + P(3, 3) = I2(5, 3, 4, 8); +} else { + P(2, 2) = I1(4); + P(3, 2) = I2(3, 1, 4, 5); + P(2, 3) = I2(3, 1, 4, 7); + P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} +} break; +case 94 : +{ +P(2, 1) = I1(4); +if (MDL) { + P(0, 2) = I2(3, 1, 4, 6); + P(1, 2) = I2(7, 1, 4, 6); + P(0, 3) = I2(5, 3, 4, 6); + P(1, 3) = I2(3, 1, 4, 6); +} else { + P(0, 2) = I2(3, 1, 4, 3); + P(1, 2) = I1(4); + P(0, 3) = I3(2, 1, 1, 4, 3, 7); + P(1, 3) = I2(3, 1, 4, 7); +} +if (MDR) { + P(2, 2) = I2(7, 1, 4, 8); + P(3, 2) = I2(3, 1, 4, 8); + P(2, 3) = I2(3, 1, 4, 8); + P(3, 3) = I2(5, 3, 4, 8); +} else { + P(2, 2) = I1(4); + P(3, 2) = I2(3, 1, 4, 5); + P(2, 3) = I2(3, 1, 4, 7); + P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} +if (MUL) { + P(0, 0) = I2(5, 3, 4, 0); + P(1, 0) = I2(3, 1, 4, 0); + P(0, 1) = I2(3, 1, 4, 0); + P(1, 1) = I2(7, 1, 4, 0); +} else { + P(0, 0) = I3(2, 1, 1, 4, 1, 3); + P(1, 0) = I2(3, 1, 4, 1); + P(0, 1) = I2(3, 1, 4, 3); + P(1, 1) = I1(4); +} +if (MUR) { + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(3, 1) = I1(4); +} else { + P(2, 0) = I2(1, 1, 1, 4); + P(3, 0) = I2(1, 1, 1, 5); + P(3, 1) = I2(1, 1, 4, 5); +} +} break; +case 95 : +{ +P(1, 1) = I1(4); +P(2, 1) = I1(4); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(0, 1) = I1(4); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(1, 1, 1, 4); + P(0, 1) = I2(1, 1, 3, 4); +} +if (MUR) { + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(3, 1) = I1(4); +} else { + P(2, 0) = I2(1, 1, 1, 4); + P(3, 0) = I2(1, 1, 1, 5); + P(3, 1) = I2(1, 1, 4, 5); +} +} break; +case 96 : +case 97 : +case 100 : +case 101 : +{ +P(0, 0) = I3(2, 1, 1, 4, 1, 3); +P(1, 0) = I3(5, 2, 1, 4, 1, 3); +P(2, 0) = I3(5, 2, 1, 4, 1, 5); +P(3, 0) = I3(2, 1, 1, 4, 1, 5); +P(0, 1) = I3(5, 2, 1, 4, 3, 1); +P(1, 1) = I3(6, 1, 1, 4, 1, 3); +P(2, 1) = I3(6, 1, 1, 4, 1, 5); +P(3, 1) = I3(5, 2, 1, 4, 5, 1); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(0, 3) = I2(5, 3, 4, 3); +P(1, 3) = I2(7, 1, 4, 3); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +} break; +case 98 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(0, 3) = I2(5, 3, 4, 3); +P(1, 3) = I2(7, 1, 4, 3); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +} break; +case 99 : +{ +P(0, 0) = I2(5, 3, 4, 3); +P(1, 0) = I2(7, 1, 4, 3); +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(0, 3) = I2(5, 3, 4, 3); +P(1, 3) = I2(7, 1, 4, 3); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +} break; +case 102 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(2, 0) = I2(7, 1, 4, 5); +P(3, 0) = I2(5, 3, 4, 5); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(0, 3) = I2(5, 3, 4, 3); +P(1, 3) = I2(7, 1, 4, 3); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +} break; +case 103 : +{ +P(0, 0) = I2(5, 3, 4, 3); +P(1, 0) = I2(7, 1, 4, 3); +P(2, 0) = I2(7, 1, 4, 5); +P(3, 0) = I2(5, 3, 4, 5); +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(0, 3) = I2(5, 3, 4, 3); +P(1, 3) = I2(7, 1, 4, 3); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +} break; +case 104 : +case 108 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I3(5, 2, 1, 4, 1, 5); +P(3, 0) = I3(2, 1, 1, 4, 1, 5); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I3(6, 1, 1, 4, 1, 5); +P(3, 1) = I3(5, 2, 1, 4, 5, 1); +P(1, 2) = I1(4); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MDL) { + P(0, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); +} else { + P(0, 2) = I2(1, 1, 3, 4); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(1, 1, 4, 7); +} +} break; +case 105 : +case 109 : +{ +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I3(5, 2, 1, 4, 1, 5); +P(3, 0) = I3(2, 1, 1, 4, 1, 5); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I3(6, 1, 1, 4, 1, 5); +P(3, 1) = I3(5, 2, 1, 4, 5, 1); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MDL) { + P(0, 0) = I2(5, 3, 4, 1); + P(0, 1) = I2(7, 1, 4, 1); + P(0, 2) = I1(4); + P(1, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); +} else { + P(0, 0) = I2(3, 1, 4, 3); + P(0, 1) = I2(3, 1, 3, 4); + P(0, 2) = I2(5, 3, 3, 7); + P(1, 2) = I3(6, 1, 1, 4, 3, 7); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I3(2, 1, 1, 7, 3, 4); +} +} break; +case 106 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(1, 2) = I1(4); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MDL) { + P(0, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); +} else { + P(0, 2) = I2(1, 1, 3, 4); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(1, 1, 4, 7); +} +} break; +case 110 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(2, 0) = I2(7, 1, 4, 5); +P(3, 0) = I2(5, 3, 4, 5); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(1, 2) = I1(4); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MDL) { + P(0, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); +} else { + P(0, 2) = I2(1, 1, 3, 4); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(1, 1, 4, 7); +} +} break; +case 111 : +{ +P(1, 0) = I1(4); +P(2, 0) = I2(7, 1, 4, 5); +P(3, 0) = I2(5, 3, 4, 5); +P(0, 1) = I1(4); +P(1, 1) = I1(4); +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(1, 2) = I1(4); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I3(5, 2, 1, 4, 5, 8); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MDL) { + P(0, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); +} else { + P(0, 2) = I2(1, 1, 3, 4); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(1, 1, 4, 7); +} +if (MUL) { + P(0, 0) = I1(4); +} else { + P(0, 0) = I3(2, 1, 1, 4, 1, 3); +} +} break; +case 112 : +case 113 : +{ +P(0, 0) = I3(2, 1, 1, 4, 1, 3); +P(1, 0) = I3(5, 2, 1, 4, 1, 3); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I3(5, 2, 1, 4, 3, 1); +P(1, 1) = I3(6, 1, 1, 4, 1, 3); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +if (MDR) { + P(2, 2) = I2(7, 1, 4, 8); + P(3, 2) = I2(3, 1, 4, 8); + P(0, 3) = I2(5, 3, 4, 3); + P(1, 3) = I2(7, 1, 4, 3); + P(2, 3) = I2(3, 1, 4, 8); + P(3, 3) = I2(5, 3, 4, 8); +} else { + P(2, 2) = I3(6, 1, 1, 4, 5, 7); + P(3, 2) = I3(2, 1, 1, 5, 4, 7); + P(0, 3) = I2(3, 1, 4, 7); + P(1, 3) = I2(3, 1, 7, 4); + P(2, 3) = I2(5, 3, 7, 5); + P(3, 3) = I2(1, 1, 5, 7); +} +} break; +case 114 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +P(0, 3) = I2(5, 3, 4, 3); +P(1, 3) = I2(7, 1, 4, 3); +if (MDR) { + P(2, 2) = I2(7, 1, 4, 8); + P(3, 2) = I2(3, 1, 4, 8); + P(2, 3) = I2(3, 1, 4, 8); + P(3, 3) = I2(5, 3, 4, 8); +} else { + P(2, 2) = I1(4); + P(3, 2) = I2(3, 1, 4, 5); + P(2, 3) = I2(3, 1, 4, 7); + P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} +if (MUR) { + P(2, 0) = I2(3, 1, 4, 2); + P(3, 0) = I2(5, 3, 4, 2); + P(2, 1) = I2(7, 1, 4, 2); + P(3, 1) = I2(3, 1, 4, 2); +} else { + P(2, 0) = I2(3, 1, 4, 1); + P(3, 0) = I3(2, 1, 1, 4, 1, 5); + P(2, 1) = I1(4); + P(3, 1) = I2(3, 1, 4, 5); +} +} break; +case 115 : +{ +P(0, 0) = I2(5, 3, 4, 3); +P(1, 0) = I2(7, 1, 4, 3); +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +P(0, 3) = I2(5, 3, 4, 3); +P(1, 3) = I2(7, 1, 4, 3); +if (MDR) { + P(2, 2) = I2(7, 1, 4, 8); + P(3, 2) = I2(3, 1, 4, 8); + P(2, 3) = I2(3, 1, 4, 8); + P(3, 3) = I2(5, 3, 4, 8); +} else { + P(2, 2) = I1(4); + P(3, 2) = I2(3, 1, 4, 5); + P(2, 3) = I2(3, 1, 4, 7); + P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} +if (MUR) { + P(2, 0) = I2(3, 1, 4, 2); + P(3, 0) = I2(5, 3, 4, 2); + P(2, 1) = I2(7, 1, 4, 2); + P(3, 1) = I2(3, 1, 4, 2); +} else { + P(2, 0) = I2(3, 1, 4, 1); + P(3, 0) = I3(2, 1, 1, 4, 1, 5); + P(2, 1) = I1(4); + P(3, 1) = I2(3, 1, 4, 5); +} +} break; +case 116 : +case 117 : +{ +P(0, 0) = I3(2, 1, 1, 4, 1, 3); +P(1, 0) = I3(5, 2, 1, 4, 1, 3); +P(2, 0) = I2(5, 3, 4, 1); +P(3, 0) = I2(5, 3, 4, 1); +P(0, 1) = I3(5, 2, 1, 4, 3, 1); +P(1, 1) = I3(6, 1, 1, 4, 1, 3); +P(2, 1) = I2(7, 1, 4, 1); +P(3, 1) = I2(7, 1, 4, 1); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +P(0, 3) = I2(5, 3, 4, 3); +P(1, 3) = I2(7, 1, 4, 3); +if (MDR) { + P(2, 2) = I2(7, 1, 4, 8); + P(3, 2) = I2(3, 1, 4, 8); + P(2, 3) = I2(3, 1, 4, 8); + P(3, 3) = I2(5, 3, 4, 8); +} else { + P(2, 2) = I1(4); + P(3, 2) = I2(3, 1, 4, 5); + P(2, 3) = I2(3, 1, 4, 7); + P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} +} break; +case 118 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I1(4); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I2(5, 3, 4, 3); +P(1, 3) = I2(7, 1, 4, 3); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MUR) { + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(3, 1) = I1(4); +} else { + P(2, 0) = I2(1, 1, 1, 4); + P(3, 0) = I2(1, 1, 1, 5); + P(3, 1) = I2(1, 1, 4, 5); +} +} break; +case 119 : +{ +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(0, 3) = I2(5, 3, 4, 3); +P(1, 3) = I2(7, 1, 4, 3); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MUR) { + P(0, 0) = I2(5, 3, 4, 3); + P(1, 0) = I2(7, 1, 4, 3); + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(2, 1) = I1(4); + P(3, 1) = I1(4); +} else { + P(0, 0) = I2(3, 1, 4, 1); + P(1, 0) = I2(3, 1, 1, 4); + P(2, 0) = I2(5, 3, 1, 5); + P(3, 0) = I2(1, 1, 1, 5); + P(2, 1) = I3(6, 1, 1, 4, 1, 5); + P(3, 1) = I3(2, 1, 1, 5, 1, 4); +} +} break; +case 120 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(1, 2) = I1(4); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MDL) { + P(0, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); +} else { + P(0, 2) = I2(1, 1, 3, 4); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(1, 1, 4, 7); +} +} break; +case 121 : +{ +P(0, 0) = I2(5, 3, 4, 1); +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(7, 1, 4, 1); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(1, 2) = I1(4); +if (MDL) { + P(0, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); +} else { + P(0, 2) = I2(1, 1, 3, 4); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(1, 1, 4, 7); +} +if (MDR) { + P(2, 2) = I2(7, 1, 4, 8); + P(3, 2) = I2(3, 1, 4, 8); + P(2, 3) = I2(3, 1, 4, 8); + P(3, 3) = I2(5, 3, 4, 8); +} else { + P(2, 2) = I1(4); + P(3, 2) = I2(3, 1, 4, 5); + P(2, 3) = I2(3, 1, 4, 7); + P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} +} break; +case 122 : +{ +P(1, 2) = I1(4); +if (MDL) { + P(0, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); +} else { + P(0, 2) = I2(1, 1, 3, 4); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(1, 1, 4, 7); +} +if (MDR) { + P(2, 2) = I2(7, 1, 4, 8); + P(3, 2) = I2(3, 1, 4, 8); + P(2, 3) = I2(3, 1, 4, 8); + P(3, 3) = I2(5, 3, 4, 8); +} else { + P(2, 2) = I1(4); + P(3, 2) = I2(3, 1, 4, 5); + P(2, 3) = I2(3, 1, 4, 7); + P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} +if (MUL) { + P(0, 0) = I2(5, 3, 4, 0); + P(1, 0) = I2(3, 1, 4, 0); + P(0, 1) = I2(3, 1, 4, 0); + P(1, 1) = I2(7, 1, 4, 0); +} else { + P(0, 0) = I3(2, 1, 1, 4, 1, 3); + P(1, 0) = I2(3, 1, 4, 1); + P(0, 1) = I2(3, 1, 4, 3); + P(1, 1) = I1(4); +} +if (MUR) { + P(2, 0) = I2(3, 1, 4, 2); + P(3, 0) = I2(5, 3, 4, 2); + P(2, 1) = I2(7, 1, 4, 2); + P(3, 1) = I2(3, 1, 4, 2); +} else { + P(2, 0) = I2(3, 1, 4, 1); + P(3, 0) = I3(2, 1, 1, 4, 1, 5); + P(2, 1) = I1(4); + P(3, 1) = I2(3, 1, 4, 5); +} +} break; +case 123 : +{ +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(1, 1) = I1(4); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(1, 2) = I1(4); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MDL) { + P(0, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); +} else { + P(0, 2) = I2(1, 1, 3, 4); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(1, 1, 4, 7); +} +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(0, 1) = I1(4); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(1, 1, 1, 4); + P(0, 1) = I2(1, 1, 3, 4); +} +} break; +case 124 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I2(5, 3, 4, 1); +P(3, 0) = I2(5, 3, 4, 1); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 1); +P(3, 1) = I2(7, 1, 4, 1); +P(1, 2) = I1(4); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MDL) { + P(0, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); +} else { + P(0, 2) = I2(1, 1, 3, 4); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(1, 1, 4, 7); +} +} break; +case 125 : +{ +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I2(5, 3, 4, 1); +P(3, 0) = I2(5, 3, 4, 1); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I2(7, 1, 4, 1); +P(3, 1) = I2(7, 1, 4, 1); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MDL) { + P(0, 0) = I2(5, 3, 4, 1); + P(0, 1) = I2(7, 1, 4, 1); + P(0, 2) = I1(4); + P(1, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); +} else { + P(0, 0) = I2(3, 1, 4, 3); + P(0, 1) = I2(3, 1, 3, 4); + P(0, 2) = I2(5, 3, 3, 7); + P(1, 2) = I3(6, 1, 1, 4, 3, 7); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I3(2, 1, 1, 7, 3, 4); +} +} break; +case 126 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I1(4); +P(1, 2) = I1(4); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MDL) { + P(0, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); +} else { + P(0, 2) = I2(1, 1, 3, 4); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(1, 1, 4, 7); +} +if (MUR) { + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(3, 1) = I1(4); +} else { + P(2, 0) = I2(1, 1, 1, 4); + P(3, 0) = I2(1, 1, 1, 5); + P(3, 1) = I2(1, 1, 4, 5); +} +} break; +case 127 : +{ +P(1, 0) = I1(4); +P(0, 1) = I1(4); +P(1, 1) = I1(4); +P(2, 1) = I1(4); +P(1, 2) = I1(4); +P(2, 2) = I2(7, 1, 4, 8); +P(3, 2) = I2(3, 1, 4, 8); +P(2, 3) = I2(3, 1, 4, 8); +P(3, 3) = I2(5, 3, 4, 8); +if (MDL) { + P(0, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); +} else { + P(0, 2) = I2(1, 1, 3, 4); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(1, 1, 4, 7); +} +if (MUL) { + P(0, 0) = I1(4); +} else { + P(0, 0) = I3(2, 1, 1, 4, 1, 3); +} +if (MUR) { + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(3, 1) = I1(4); +} else { + P(2, 0) = I2(1, 1, 1, 4); + P(3, 0) = I2(1, 1, 1, 5); + P(3, 1) = I2(1, 1, 4, 5); +} +} break; +case 144 : +case 145 : +case 176 : +case 177 : +{ +P(0, 0) = I3(2, 1, 1, 4, 1, 3); +P(1, 0) = I3(5, 2, 1, 4, 1, 3); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I3(5, 2, 1, 4, 3, 1); +P(1, 1) = I3(6, 1, 1, 4, 1, 3); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I3(5, 2, 1, 4, 3, 7); +P(1, 2) = I3(6, 1, 1, 4, 3, 7); +P(2, 2) = I2(7, 1, 4, 7); +P(3, 2) = I2(7, 1, 4, 7); +P(0, 3) = I3(2, 1, 1, 4, 3, 7); +P(1, 3) = I3(5, 2, 1, 4, 7, 3); +P(2, 3) = I2(5, 3, 4, 7); +P(3, 3) = I2(5, 3, 4, 7); +} break; +case 146 : +case 178 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(0, 2) = I3(5, 2, 1, 4, 3, 7); +P(1, 2) = I3(6, 1, 1, 4, 3, 7); +P(2, 2) = I2(7, 1, 4, 7); +P(0, 3) = I3(2, 1, 1, 4, 3, 7); +P(1, 3) = I3(5, 2, 1, 4, 7, 3); +P(2, 3) = I2(5, 3, 4, 7); +if (MUR) { + P(2, 0) = I2(3, 1, 4, 2); + P(3, 0) = I2(5, 3, 4, 2); + P(2, 1) = I2(7, 1, 4, 2); + P(3, 1) = I2(3, 1, 4, 2); + P(3, 2) = I2(7, 1, 4, 7); + P(3, 3) = I2(5, 3, 4, 7); +} else { + P(2, 0) = I3(2, 1, 1, 1, 4, 5); + P(3, 0) = I2(1, 1, 1, 5); + P(2, 1) = I3(6, 1, 1, 4, 1, 5); + P(3, 1) = I2(5, 3, 5, 1); + P(3, 2) = I2(3, 1, 5, 4); + P(3, 3) = I2(3, 1, 4, 5); +} +} break; +case 147 : +case 179 : +{ +P(0, 0) = I2(5, 3, 4, 3); +P(1, 0) = I2(7, 1, 4, 3); +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(0, 2) = I3(5, 2, 1, 4, 3, 7); +P(1, 2) = I3(6, 1, 1, 4, 3, 7); +P(2, 2) = I2(7, 1, 4, 7); +P(3, 2) = I2(7, 1, 4, 7); +P(0, 3) = I3(2, 1, 1, 4, 3, 7); +P(1, 3) = I3(5, 2, 1, 4, 7, 3); +P(2, 3) = I2(5, 3, 4, 7); +P(3, 3) = I2(5, 3, 4, 7); +if (MUR) { + P(2, 0) = I2(3, 1, 4, 2); + P(3, 0) = I2(5, 3, 4, 2); + P(2, 1) = I2(7, 1, 4, 2); + P(3, 1) = I2(3, 1, 4, 2); +} else { + P(2, 0) = I2(3, 1, 4, 1); + P(3, 0) = I3(2, 1, 1, 4, 1, 5); + P(2, 1) = I1(4); + P(3, 1) = I2(3, 1, 4, 5); +} +} break; +case 148 : +case 149 : +case 180 : +case 181 : +{ +P(0, 0) = I3(2, 1, 1, 4, 1, 3); +P(1, 0) = I3(5, 2, 1, 4, 1, 3); +P(2, 0) = I2(5, 3, 4, 1); +P(3, 0) = I2(5, 3, 4, 1); +P(0, 1) = I3(5, 2, 1, 4, 3, 1); +P(1, 1) = I3(6, 1, 1, 4, 1, 3); +P(2, 1) = I2(7, 1, 4, 1); +P(3, 1) = I2(7, 1, 4, 1); +P(0, 2) = I3(5, 2, 1, 4, 3, 7); +P(1, 2) = I3(6, 1, 1, 4, 3, 7); +P(2, 2) = I2(7, 1, 4, 7); +P(3, 2) = I2(7, 1, 4, 7); +P(0, 3) = I3(2, 1, 1, 4, 3, 7); +P(1, 3) = I3(5, 2, 1, 4, 7, 3); +P(2, 3) = I2(5, 3, 4, 7); +P(3, 3) = I2(5, 3, 4, 7); +} break; +case 150 : +case 182 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(0, 2) = I3(5, 2, 1, 4, 3, 7); +P(1, 2) = I3(6, 1, 1, 4, 3, 7); +P(2, 2) = I2(7, 1, 4, 7); +P(0, 3) = I3(2, 1, 1, 4, 3, 7); +P(1, 3) = I3(5, 2, 1, 4, 7, 3); +P(2, 3) = I2(5, 3, 4, 7); +if (MUR) { + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(2, 1) = I1(4); + P(3, 1) = I1(4); + P(3, 2) = I2(7, 1, 4, 7); + P(3, 3) = I2(5, 3, 4, 7); +} else { + P(2, 0) = I3(2, 1, 1, 1, 4, 5); + P(3, 0) = I2(1, 1, 1, 5); + P(2, 1) = I3(6, 1, 1, 4, 1, 5); + P(3, 1) = I2(5, 3, 5, 1); + P(3, 2) = I2(3, 1, 5, 4); + P(3, 3) = I2(3, 1, 4, 5); +} +} break; +case 151 : +case 183 : +{ +P(0, 0) = I2(5, 3, 4, 3); +P(1, 0) = I2(7, 1, 4, 3); +P(2, 0) = I1(4); +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(2, 1) = I1(4); +P(3, 1) = I1(4); +P(0, 2) = I3(5, 2, 1, 4, 3, 7); +P(1, 2) = I3(6, 1, 1, 4, 3, 7); +P(2, 2) = I2(7, 1, 4, 7); +P(3, 2) = I2(7, 1, 4, 7); +P(0, 3) = I3(2, 1, 1, 4, 3, 7); +P(1, 3) = I3(5, 2, 1, 4, 7, 3); +P(2, 3) = I2(5, 3, 4, 7); +P(3, 3) = I2(5, 3, 4, 7); +if (MUR) { + P(3, 0) = I1(4); +} else { + P(3, 0) = I3(2, 1, 1, 4, 1, 5); +} +} break; +case 152 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 7); +P(3, 2) = I2(7, 1, 4, 7); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I2(5, 3, 4, 7); +P(3, 3) = I2(5, 3, 4, 7); +} break; +case 153 : +{ +P(0, 0) = I2(5, 3, 4, 1); +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(7, 1, 4, 1); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 7); +P(3, 2) = I2(7, 1, 4, 7); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I2(5, 3, 4, 7); +P(3, 3) = I2(5, 3, 4, 7); +} break; +case 154 : +{ +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 7); +P(3, 2) = I2(7, 1, 4, 7); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I2(5, 3, 4, 7); +P(3, 3) = I2(5, 3, 4, 7); +if (MUL) { + P(0, 0) = I2(5, 3, 4, 0); + P(1, 0) = I2(3, 1, 4, 0); + P(0, 1) = I2(3, 1, 4, 0); + P(1, 1) = I2(7, 1, 4, 0); +} else { + P(0, 0) = I3(2, 1, 1, 4, 1, 3); + P(1, 0) = I2(3, 1, 4, 1); + P(0, 1) = I2(3, 1, 4, 3); + P(1, 1) = I1(4); +} +if (MUR) { + P(2, 0) = I2(3, 1, 4, 2); + P(3, 0) = I2(5, 3, 4, 2); + P(2, 1) = I2(7, 1, 4, 2); + P(3, 1) = I2(3, 1, 4, 2); +} else { + P(2, 0) = I2(3, 1, 4, 1); + P(3, 0) = I3(2, 1, 1, 4, 1, 5); + P(2, 1) = I1(4); + P(3, 1) = I2(3, 1, 4, 5); +} +} break; +case 155 : +{ +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(1, 1) = I1(4); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 7); +P(3, 2) = I2(7, 1, 4, 7); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I2(5, 3, 4, 7); +P(3, 3) = I2(5, 3, 4, 7); +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(0, 1) = I1(4); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(1, 1, 1, 4); + P(0, 1) = I2(1, 1, 3, 4); +} +} break; +case 156 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I2(5, 3, 4, 1); +P(3, 0) = I2(5, 3, 4, 1); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 1); +P(3, 1) = I2(7, 1, 4, 1); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 7); +P(3, 2) = I2(7, 1, 4, 7); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I2(5, 3, 4, 7); +P(3, 3) = I2(5, 3, 4, 7); +} break; +case 157 : +{ +P(0, 0) = I2(5, 3, 4, 1); +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I2(5, 3, 4, 1); +P(3, 0) = I2(5, 3, 4, 1); +P(0, 1) = I2(7, 1, 4, 1); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I2(7, 1, 4, 1); +P(3, 1) = I2(7, 1, 4, 1); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 7); +P(3, 2) = I2(7, 1, 4, 7); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I2(5, 3, 4, 7); +P(3, 3) = I2(5, 3, 4, 7); +} break; +case 158 : +{ +P(2, 1) = I1(4); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 7); +P(3, 2) = I2(7, 1, 4, 7); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I2(5, 3, 4, 7); +P(3, 3) = I2(5, 3, 4, 7); +if (MUL) { + P(0, 0) = I2(5, 3, 4, 0); + P(1, 0) = I2(3, 1, 4, 0); + P(0, 1) = I2(3, 1, 4, 0); + P(1, 1) = I2(7, 1, 4, 0); +} else { + P(0, 0) = I3(2, 1, 1, 4, 1, 3); + P(1, 0) = I2(3, 1, 4, 1); + P(0, 1) = I2(3, 1, 4, 3); + P(1, 1) = I1(4); +} +if (MUR) { + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(3, 1) = I1(4); +} else { + P(2, 0) = I2(1, 1, 1, 4); + P(3, 0) = I2(1, 1, 1, 5); + P(3, 1) = I2(1, 1, 4, 5); +} +} break; +case 159 : +{ +P(2, 0) = I1(4); +P(1, 1) = I1(4); +P(2, 1) = I1(4); +P(3, 1) = I1(4); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 7); +P(3, 2) = I2(7, 1, 4, 7); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I3(5, 2, 1, 4, 7, 6); +P(2, 3) = I2(5, 3, 4, 7); +P(3, 3) = I2(5, 3, 4, 7); +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(0, 1) = I1(4); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(1, 1, 1, 4); + P(0, 1) = I2(1, 1, 3, 4); +} +if (MUR) { + P(3, 0) = I1(4); +} else { + P(3, 0) = I3(2, 1, 1, 4, 1, 5); +} +} break; +case 184 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I2(7, 1, 4, 7); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I2(7, 1, 4, 7); +P(3, 2) = I2(7, 1, 4, 7); +P(0, 3) = I2(5, 3, 4, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I2(5, 3, 4, 7); +P(3, 3) = I2(5, 3, 4, 7); +} break; +case 185 : +{ +P(0, 0) = I2(5, 3, 4, 1); +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(7, 1, 4, 1); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I2(7, 1, 4, 7); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I2(7, 1, 4, 7); +P(3, 2) = I2(7, 1, 4, 7); +P(0, 3) = I2(5, 3, 4, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I2(5, 3, 4, 7); +P(3, 3) = I2(5, 3, 4, 7); +} break; +case 186 : +{ +P(0, 2) = I2(7, 1, 4, 7); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I2(7, 1, 4, 7); +P(3, 2) = I2(7, 1, 4, 7); +P(0, 3) = I2(5, 3, 4, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I2(5, 3, 4, 7); +P(3, 3) = I2(5, 3, 4, 7); +if (MUL) { + P(0, 0) = I2(5, 3, 4, 0); + P(1, 0) = I2(3, 1, 4, 0); + P(0, 1) = I2(3, 1, 4, 0); + P(1, 1) = I2(7, 1, 4, 0); +} else { + P(0, 0) = I3(2, 1, 1, 4, 1, 3); + P(1, 0) = I2(3, 1, 4, 1); + P(0, 1) = I2(3, 1, 4, 3); + P(1, 1) = I1(4); +} +if (MUR) { + P(2, 0) = I2(3, 1, 4, 2); + P(3, 0) = I2(5, 3, 4, 2); + P(2, 1) = I2(7, 1, 4, 2); + P(3, 1) = I2(3, 1, 4, 2); +} else { + P(2, 0) = I2(3, 1, 4, 1); + P(3, 0) = I3(2, 1, 1, 4, 1, 5); + P(2, 1) = I1(4); + P(3, 1) = I2(3, 1, 4, 5); +} +} break; +case 187 : +{ +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I2(7, 1, 4, 7); +P(3, 2) = I2(7, 1, 4, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I2(5, 3, 4, 7); +P(3, 3) = I2(5, 3, 4, 7); +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(0, 1) = I1(4); + P(1, 1) = I1(4); + P(0, 2) = I2(7, 1, 4, 7); + P(0, 3) = I2(5, 3, 4, 7); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I3(2, 1, 1, 1, 3, 4); + P(0, 1) = I2(5, 3, 3, 1); + P(1, 1) = I3(6, 1, 1, 4, 1, 3); + P(0, 2) = I2(3, 1, 3, 4); + P(0, 3) = I2(3, 1, 4, 3); +} +} break; +case 188 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I2(5, 3, 4, 1); +P(3, 0) = I2(5, 3, 4, 1); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 1); +P(3, 1) = I2(7, 1, 4, 1); +P(0, 2) = I2(7, 1, 4, 7); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I2(7, 1, 4, 7); +P(3, 2) = I2(7, 1, 4, 7); +P(0, 3) = I2(5, 3, 4, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I2(5, 3, 4, 7); +P(3, 3) = I2(5, 3, 4, 7); +} break; +case 189 : +{ +P(0, 0) = I2(5, 3, 4, 1); +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I2(5, 3, 4, 1); +P(3, 0) = I2(5, 3, 4, 1); +P(0, 1) = I2(7, 1, 4, 1); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I2(7, 1, 4, 1); +P(3, 1) = I2(7, 1, 4, 1); +P(0, 2) = I2(7, 1, 4, 7); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I2(7, 1, 4, 7); +P(3, 2) = I2(7, 1, 4, 7); +P(0, 3) = I2(5, 3, 4, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I2(5, 3, 4, 7); +P(3, 3) = I2(5, 3, 4, 7); +} break; +case 190 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(0, 2) = I2(7, 1, 4, 7); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I2(7, 1, 4, 7); +P(0, 3) = I2(5, 3, 4, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I2(5, 3, 4, 7); +if (MUR) { + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(2, 1) = I1(4); + P(3, 1) = I1(4); + P(3, 2) = I2(7, 1, 4, 7); + P(3, 3) = I2(5, 3, 4, 7); +} else { + P(2, 0) = I3(2, 1, 1, 1, 4, 5); + P(3, 0) = I2(1, 1, 1, 5); + P(2, 1) = I3(6, 1, 1, 4, 1, 5); + P(3, 1) = I2(5, 3, 5, 1); + P(3, 2) = I2(3, 1, 5, 4); + P(3, 3) = I2(3, 1, 4, 5); +} +} break; +case 191 : +{ +P(1, 0) = I1(4); +P(2, 0) = I1(4); +P(0, 1) = I1(4); +P(1, 1) = I1(4); +P(2, 1) = I1(4); +P(3, 1) = I1(4); +P(0, 2) = I2(7, 1, 4, 7); +P(1, 2) = I2(7, 1, 4, 7); +P(2, 2) = I2(7, 1, 4, 7); +P(3, 2) = I2(7, 1, 4, 7); +P(0, 3) = I2(5, 3, 4, 7); +P(1, 3) = I2(5, 3, 4, 7); +P(2, 3) = I2(5, 3, 4, 7); +P(3, 3) = I2(5, 3, 4, 7); +if (MUL) { + P(0, 0) = I1(4); +} else { + P(0, 0) = I3(2, 1, 1, 4, 1, 3); +} +if (MUR) { + P(3, 0) = I1(4); +} else { + P(3, 0) = I3(2, 1, 1, 4, 1, 5); +} +} break; +case 192 : +case 193 : +case 196 : +case 197 : +{ +P(0, 0) = I3(2, 1, 1, 4, 1, 3); +P(1, 0) = I3(5, 2, 1, 4, 1, 3); +P(2, 0) = I3(5, 2, 1, 4, 1, 5); +P(3, 0) = I3(2, 1, 1, 4, 1, 5); +P(0, 1) = I3(5, 2, 1, 4, 3, 1); +P(1, 1) = I3(6, 1, 1, 4, 1, 3); +P(2, 1) = I3(6, 1, 1, 4, 1, 5); +P(3, 1) = I3(5, 2, 1, 4, 5, 1); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +P(2, 3) = I2(7, 1, 4, 5); +P(3, 3) = I2(5, 3, 4, 5); +} break; +case 194 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +P(2, 3) = I2(7, 1, 4, 5); +P(3, 3) = I2(5, 3, 4, 5); +} break; +case 195 : +{ +P(0, 0) = I2(5, 3, 4, 3); +P(1, 0) = I2(7, 1, 4, 3); +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +P(2, 3) = I2(7, 1, 4, 5); +P(3, 3) = I2(5, 3, 4, 5); +} break; +case 198 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(2, 0) = I2(7, 1, 4, 5); +P(3, 0) = I2(5, 3, 4, 5); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +P(2, 3) = I2(7, 1, 4, 5); +P(3, 3) = I2(5, 3, 4, 5); +} break; +case 199 : +{ +P(0, 0) = I2(5, 3, 4, 3); +P(1, 0) = I2(7, 1, 4, 3); +P(2, 0) = I2(7, 1, 4, 5); +P(3, 0) = I2(5, 3, 4, 5); +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +P(2, 3) = I2(7, 1, 4, 5); +P(3, 3) = I2(5, 3, 4, 5); +} break; +case 200 : +case 204 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I3(5, 2, 1, 4, 1, 5); +P(3, 0) = I3(2, 1, 1, 4, 1, 5); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I3(6, 1, 1, 4, 1, 5); +P(3, 1) = I3(5, 2, 1, 4, 5, 1); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +if (MDL) { + P(0, 2) = I2(3, 1, 4, 6); + P(1, 2) = I2(7, 1, 4, 6); + P(0, 3) = I2(5, 3, 4, 6); + P(1, 3) = I2(3, 1, 4, 6); + P(2, 3) = I2(7, 1, 4, 5); + P(3, 3) = I2(5, 3, 4, 5); +} else { + P(0, 2) = I3(2, 1, 1, 3, 4, 7); + P(1, 2) = I3(6, 1, 1, 4, 3, 7); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(5, 3, 7, 3); + P(2, 3) = I2(3, 1, 7, 4); + P(3, 3) = I2(3, 1, 4, 7); +} +} break; +case 201 : +case 205 : +{ +P(0, 0) = I2(5, 3, 4, 1); +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I3(5, 2, 1, 4, 1, 5); +P(3, 0) = I3(2, 1, 1, 4, 1, 5); +P(0, 1) = I2(7, 1, 4, 1); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I3(6, 1, 1, 4, 1, 5); +P(3, 1) = I3(5, 2, 1, 4, 5, 1); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +P(2, 3) = I2(7, 1, 4, 5); +P(3, 3) = I2(5, 3, 4, 5); +if (MDL) { + P(0, 2) = I2(3, 1, 4, 6); + P(1, 2) = I2(7, 1, 4, 6); + P(0, 3) = I2(5, 3, 4, 6); + P(1, 3) = I2(3, 1, 4, 6); +} else { + P(0, 2) = I2(3, 1, 4, 3); + P(1, 2) = I1(4); + P(0, 3) = I3(2, 1, 1, 4, 3, 7); + P(1, 3) = I2(3, 1, 4, 7); +} +} break; +case 202 : +{ +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +P(2, 3) = I2(7, 1, 4, 5); +P(3, 3) = I2(5, 3, 4, 5); +if (MDL) { + P(0, 2) = I2(3, 1, 4, 6); + P(1, 2) = I2(7, 1, 4, 6); + P(0, 3) = I2(5, 3, 4, 6); + P(1, 3) = I2(3, 1, 4, 6); +} else { + P(0, 2) = I2(3, 1, 4, 3); + P(1, 2) = I1(4); + P(0, 3) = I3(2, 1, 1, 4, 3, 7); + P(1, 3) = I2(3, 1, 4, 7); +} +if (MUL) { + P(0, 0) = I2(5, 3, 4, 0); + P(1, 0) = I2(3, 1, 4, 0); + P(0, 1) = I2(3, 1, 4, 0); + P(1, 1) = I2(7, 1, 4, 0); +} else { + P(0, 0) = I3(2, 1, 1, 4, 1, 3); + P(1, 0) = I2(3, 1, 4, 1); + P(0, 1) = I2(3, 1, 4, 3); + P(1, 1) = I1(4); +} +} break; +case 203 : +{ +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(1, 1) = I1(4); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +P(2, 3) = I2(7, 1, 4, 5); +P(3, 3) = I2(5, 3, 4, 5); +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(0, 1) = I1(4); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(1, 1, 1, 4); + P(0, 1) = I2(1, 1, 3, 4); +} +} break; +case 206 : +{ +P(2, 0) = I2(7, 1, 4, 5); +P(3, 0) = I2(5, 3, 4, 5); +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +P(2, 3) = I2(7, 1, 4, 5); +P(3, 3) = I2(5, 3, 4, 5); +if (MDL) { + P(0, 2) = I2(3, 1, 4, 6); + P(1, 2) = I2(7, 1, 4, 6); + P(0, 3) = I2(5, 3, 4, 6); + P(1, 3) = I2(3, 1, 4, 6); +} else { + P(0, 2) = I2(3, 1, 4, 3); + P(1, 2) = I1(4); + P(0, 3) = I3(2, 1, 1, 4, 3, 7); + P(1, 3) = I2(3, 1, 4, 7); +} +if (MUL) { + P(0, 0) = I2(5, 3, 4, 0); + P(1, 0) = I2(3, 1, 4, 0); + P(0, 1) = I2(3, 1, 4, 0); + P(1, 1) = I2(7, 1, 4, 0); +} else { + P(0, 0) = I3(2, 1, 1, 4, 1, 3); + P(1, 0) = I2(3, 1, 4, 1); + P(0, 1) = I2(3, 1, 4, 3); + P(1, 1) = I1(4); +} +} break; +case 207 : +{ +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +P(2, 3) = I2(7, 1, 4, 5); +P(3, 3) = I2(5, 3, 4, 5); +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(2, 0) = I2(7, 1, 4, 5); + P(3, 0) = I2(5, 3, 4, 5); + P(0, 1) = I1(4); + P(1, 1) = I1(4); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(5, 3, 1, 3); + P(2, 0) = I2(3, 1, 1, 4); + P(3, 0) = I2(3, 1, 4, 1); + P(0, 1) = I3(2, 1, 1, 3, 1, 4); + P(1, 1) = I3(6, 1, 1, 4, 1, 3); +} +} break; +case 208 : +case 209 : +{ +P(0, 0) = I3(2, 1, 1, 4, 1, 3); +P(1, 0) = I3(5, 2, 1, 4, 1, 3); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I3(5, 2, 1, 4, 3, 1); +P(1, 1) = I3(6, 1, 1, 4, 1, 3); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I1(4); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +if (MDR) { + P(3, 2) = I1(4); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(3, 2) = I2(1, 1, 4, 5); + P(2, 3) = I2(1, 1, 4, 7); + P(3, 3) = I2(1, 1, 5, 7); +} +} break; +case 210 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I1(4); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +if (MDR) { + P(3, 2) = I1(4); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(3, 2) = I2(1, 1, 4, 5); + P(2, 3) = I2(1, 1, 4, 7); + P(3, 3) = I2(1, 1, 5, 7); +} +} break; +case 211 : +{ +P(0, 0) = I2(5, 3, 4, 3); +P(1, 0) = I2(7, 1, 4, 3); +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I1(4); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +if (MDR) { + P(3, 2) = I1(4); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(3, 2) = I2(1, 1, 4, 5); + P(2, 3) = I2(1, 1, 4, 7); + P(3, 3) = I2(1, 1, 5, 7); +} +} break; +case 212 : +case 213 : +{ +P(0, 0) = I3(2, 1, 1, 4, 1, 3); +P(1, 0) = I3(5, 2, 1, 4, 1, 3); +P(2, 0) = I2(5, 3, 4, 1); +P(0, 1) = I3(5, 2, 1, 4, 3, 1); +P(1, 1) = I3(6, 1, 1, 4, 1, 3); +P(2, 1) = I2(7, 1, 4, 1); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +if (MDR) { + P(3, 0) = I2(5, 3, 4, 1); + P(3, 1) = I2(7, 1, 4, 1); + P(2, 2) = I1(4); + P(3, 2) = I1(4); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(3, 0) = I2(3, 1, 4, 5); + P(3, 1) = I2(3, 1, 5, 4); + P(2, 2) = I3(6, 1, 1, 4, 5, 7); + P(3, 2) = I2(5, 3, 5, 7); + P(2, 3) = I3(2, 1, 1, 7, 4, 5); + P(3, 3) = I2(1, 1, 5, 7); +} +} break; +case 215 : +{ +P(0, 0) = I2(5, 3, 4, 3); +P(1, 0) = I2(7, 1, 4, 3); +P(2, 0) = I1(4); +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(2, 1) = I1(4); +P(3, 1) = I1(4); +P(0, 2) = I3(5, 2, 1, 4, 3, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I1(4); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +if (MDR) { + P(3, 2) = I1(4); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(3, 2) = I2(1, 1, 4, 5); + P(2, 3) = I2(1, 1, 4, 7); + P(3, 3) = I2(1, 1, 5, 7); +} +if (MUR) { + P(3, 0) = I1(4); +} else { + P(3, 0) = I3(2, 1, 1, 4, 1, 5); +} +} break; +case 216 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I1(4); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +if (MDR) { + P(3, 2) = I1(4); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(3, 2) = I2(1, 1, 4, 5); + P(2, 3) = I2(1, 1, 4, 7); + P(3, 3) = I2(1, 1, 5, 7); +} +} break; +case 217 : +{ +P(0, 0) = I2(5, 3, 4, 1); +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(7, 1, 4, 1); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I1(4); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +if (MDR) { + P(3, 2) = I1(4); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(3, 2) = I2(1, 1, 4, 5); + P(2, 3) = I2(1, 1, 4, 7); + P(3, 3) = I2(1, 1, 5, 7); +} +} break; +case 218 : +{ +P(2, 2) = I1(4); +if (MDL) { + P(0, 2) = I2(3, 1, 4, 6); + P(1, 2) = I2(7, 1, 4, 6); + P(0, 3) = I2(5, 3, 4, 6); + P(1, 3) = I2(3, 1, 4, 6); +} else { + P(0, 2) = I2(3, 1, 4, 3); + P(1, 2) = I1(4); + P(0, 3) = I3(2, 1, 1, 4, 3, 7); + P(1, 3) = I2(3, 1, 4, 7); +} +if (MDR) { + P(3, 2) = I1(4); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(3, 2) = I2(1, 1, 4, 5); + P(2, 3) = I2(1, 1, 4, 7); + P(3, 3) = I2(1, 1, 5, 7); +} +if (MUL) { + P(0, 0) = I2(5, 3, 4, 0); + P(1, 0) = I2(3, 1, 4, 0); + P(0, 1) = I2(3, 1, 4, 0); + P(1, 1) = I2(7, 1, 4, 0); +} else { + P(0, 0) = I3(2, 1, 1, 4, 1, 3); + P(1, 0) = I2(3, 1, 4, 1); + P(0, 1) = I2(3, 1, 4, 3); + P(1, 1) = I1(4); +} +if (MUR) { + P(2, 0) = I2(3, 1, 4, 2); + P(3, 0) = I2(5, 3, 4, 2); + P(2, 1) = I2(7, 1, 4, 2); + P(3, 1) = I2(3, 1, 4, 2); +} else { + P(2, 0) = I2(3, 1, 4, 1); + P(3, 0) = I3(2, 1, 1, 4, 1, 5); + P(2, 1) = I1(4); + P(3, 1) = I2(3, 1, 4, 5); +} +} break; +case 219 : +{ +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(1, 1) = I1(4); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I1(4); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +if (MDR) { + P(3, 2) = I1(4); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(3, 2) = I2(1, 1, 4, 5); + P(2, 3) = I2(1, 1, 4, 7); + P(3, 3) = I2(1, 1, 5, 7); +} +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(0, 1) = I1(4); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(1, 1, 1, 4); + P(0, 1) = I2(1, 1, 3, 4); +} +} break; +case 220 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I2(5, 3, 4, 1); +P(3, 0) = I2(5, 3, 4, 1); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 1); +P(3, 1) = I2(7, 1, 4, 1); +P(2, 2) = I1(4); +if (MDL) { + P(0, 2) = I2(3, 1, 4, 6); + P(1, 2) = I2(7, 1, 4, 6); + P(0, 3) = I2(5, 3, 4, 6); + P(1, 3) = I2(3, 1, 4, 6); +} else { + P(0, 2) = I2(3, 1, 4, 3); + P(1, 2) = I1(4); + P(0, 3) = I3(2, 1, 1, 4, 3, 7); + P(1, 3) = I2(3, 1, 4, 7); +} +if (MDR) { + P(3, 2) = I1(4); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(3, 2) = I2(1, 1, 4, 5); + P(2, 3) = I2(1, 1, 4, 7); + P(3, 3) = I2(1, 1, 5, 7); +} +} break; +case 221 : +{ +P(0, 0) = I2(5, 3, 4, 1); +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I2(5, 3, 4, 1); +P(0, 1) = I2(7, 1, 4, 1); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I2(7, 1, 4, 1); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +if (MDR) { + P(3, 0) = I2(5, 3, 4, 1); + P(3, 1) = I2(7, 1, 4, 1); + P(2, 2) = I1(4); + P(3, 2) = I1(4); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(3, 0) = I2(3, 1, 4, 5); + P(3, 1) = I2(3, 1, 5, 4); + P(2, 2) = I3(6, 1, 1, 4, 5, 7); + P(3, 2) = I2(5, 3, 5, 7); + P(2, 3) = I3(2, 1, 1, 7, 4, 5); + P(3, 3) = I2(1, 1, 5, 7); +} +} break; +case 222 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I1(4); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I1(4); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +if (MDR) { + P(3, 2) = I1(4); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(3, 2) = I2(1, 1, 4, 5); + P(2, 3) = I2(1, 1, 4, 7); + P(3, 3) = I2(1, 1, 5, 7); +} +if (MUR) { + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(3, 1) = I1(4); +} else { + P(2, 0) = I2(1, 1, 1, 4); + P(3, 0) = I2(1, 1, 1, 5); + P(3, 1) = I2(1, 1, 4, 5); +} +} break; +case 223 : +{ +P(2, 0) = I1(4); +P(1, 1) = I1(4); +P(2, 1) = I1(4); +P(3, 1) = I1(4); +P(0, 2) = I2(3, 1, 4, 6); +P(1, 2) = I2(7, 1, 4, 6); +P(2, 2) = I1(4); +P(0, 3) = I2(5, 3, 4, 6); +P(1, 3) = I2(3, 1, 4, 6); +if (MDR) { + P(3, 2) = I1(4); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(3, 2) = I2(1, 1, 4, 5); + P(2, 3) = I2(1, 1, 4, 7); + P(3, 3) = I2(1, 1, 5, 7); +} +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(0, 1) = I1(4); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(1, 1, 1, 4); + P(0, 1) = I2(1, 1, 3, 4); +} +if (MUR) { + P(3, 0) = I1(4); +} else { + P(3, 0) = I3(2, 1, 1, 4, 1, 5); +} +} break; +case 224 : +case 225 : +case 228 : +case 229 : +{ +P(0, 0) = I3(2, 1, 1, 4, 1, 3); +P(1, 0) = I3(5, 2, 1, 4, 1, 3); +P(2, 0) = I3(5, 2, 1, 4, 1, 5); +P(3, 0) = I3(2, 1, 1, 4, 1, 5); +P(0, 1) = I3(5, 2, 1, 4, 3, 1); +P(1, 1) = I3(6, 1, 1, 4, 1, 3); +P(2, 1) = I3(6, 1, 1, 4, 1, 5); +P(3, 1) = I3(5, 2, 1, 4, 5, 1); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +P(0, 3) = I2(5, 3, 4, 3); +P(1, 3) = I2(7, 1, 4, 3); +P(2, 3) = I2(7, 1, 4, 5); +P(3, 3) = I2(5, 3, 4, 5); +} break; +case 226 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +P(0, 3) = I2(5, 3, 4, 3); +P(1, 3) = I2(7, 1, 4, 3); +P(2, 3) = I2(7, 1, 4, 5); +P(3, 3) = I2(5, 3, 4, 5); +} break; +case 227 : +{ +P(0, 0) = I2(5, 3, 4, 3); +P(1, 0) = I2(7, 1, 4, 3); +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +P(0, 3) = I2(5, 3, 4, 3); +P(1, 3) = I2(7, 1, 4, 3); +P(2, 3) = I2(7, 1, 4, 5); +P(3, 3) = I2(5, 3, 4, 5); +} break; +case 230 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(2, 0) = I2(7, 1, 4, 5); +P(3, 0) = I2(5, 3, 4, 5); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +P(0, 3) = I2(5, 3, 4, 3); +P(1, 3) = I2(7, 1, 4, 3); +P(2, 3) = I2(7, 1, 4, 5); +P(3, 3) = I2(5, 3, 4, 5); +} break; +case 231 : +{ +P(0, 0) = I2(5, 3, 4, 3); +P(1, 0) = I2(7, 1, 4, 3); +P(2, 0) = I2(7, 1, 4, 5); +P(3, 0) = I2(5, 3, 4, 5); +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +P(0, 3) = I2(5, 3, 4, 3); +P(1, 3) = I2(7, 1, 4, 3); +P(2, 3) = I2(7, 1, 4, 5); +P(3, 3) = I2(5, 3, 4, 5); +} break; +case 232 : +case 236 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I3(5, 2, 1, 4, 1, 5); +P(3, 0) = I3(2, 1, 1, 4, 1, 5); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I3(6, 1, 1, 4, 1, 5); +P(3, 1) = I3(5, 2, 1, 4, 5, 1); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +if (MDL) { + P(0, 2) = I1(4); + P(1, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); + P(2, 3) = I2(7, 1, 4, 5); + P(3, 3) = I2(5, 3, 4, 5); +} else { + P(0, 2) = I3(2, 1, 1, 3, 4, 7); + P(1, 2) = I3(6, 1, 1, 4, 3, 7); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(5, 3, 7, 3); + P(2, 3) = I2(3, 1, 7, 4); + P(3, 3) = I2(3, 1, 4, 7); +} +} break; +case 233 : +case 237 : +{ +P(0, 0) = I2(5, 3, 4, 1); +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I3(5, 2, 1, 4, 1, 5); +P(3, 0) = I3(2, 1, 1, 4, 1, 5); +P(0, 1) = I2(7, 1, 4, 1); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I3(6, 1, 1, 4, 1, 5); +P(3, 1) = I3(5, 2, 1, 4, 5, 1); +P(0, 2) = I1(4); +P(1, 2) = I1(4); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +P(1, 3) = I1(4); +P(2, 3) = I2(7, 1, 4, 5); +P(3, 3) = I2(5, 3, 4, 5); +if (MDL) { + P(0, 3) = I1(4); +} else { + P(0, 3) = I3(2, 1, 1, 4, 3, 7); +} +} break; +case 234 : +{ +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(1, 2) = I1(4); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +P(2, 3) = I2(7, 1, 4, 5); +P(3, 3) = I2(5, 3, 4, 5); +if (MDL) { + P(0, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); +} else { + P(0, 2) = I2(1, 1, 3, 4); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(1, 1, 4, 7); +} +if (MUL) { + P(0, 0) = I2(5, 3, 4, 0); + P(1, 0) = I2(3, 1, 4, 0); + P(0, 1) = I2(3, 1, 4, 0); + P(1, 1) = I2(7, 1, 4, 0); +} else { + P(0, 0) = I3(2, 1, 1, 4, 1, 3); + P(1, 0) = I2(3, 1, 4, 1); + P(0, 1) = I2(3, 1, 4, 3); + P(1, 1) = I1(4); +} +} break; +case 235 : +{ +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(1, 1) = I1(4); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I3(5, 2, 1, 4, 5, 2); +P(0, 2) = I1(4); +P(1, 2) = I1(4); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +P(1, 3) = I1(4); +P(2, 3) = I2(7, 1, 4, 5); +P(3, 3) = I2(5, 3, 4, 5); +if (MDL) { + P(0, 3) = I1(4); +} else { + P(0, 3) = I3(2, 1, 1, 4, 3, 7); +} +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(0, 1) = I1(4); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(1, 1, 1, 4); + P(0, 1) = I2(1, 1, 3, 4); +} +} break; +case 238 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(2, 0) = I2(7, 1, 4, 5); +P(3, 0) = I2(5, 3, 4, 5); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +if (MDL) { + P(0, 2) = I1(4); + P(1, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); + P(2, 3) = I2(7, 1, 4, 5); + P(3, 3) = I2(5, 3, 4, 5); +} else { + P(0, 2) = I3(2, 1, 1, 3, 4, 7); + P(1, 2) = I3(6, 1, 1, 4, 3, 7); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(5, 3, 7, 3); + P(2, 3) = I2(3, 1, 7, 4); + P(3, 3) = I2(3, 1, 4, 7); +} +} break; +case 239 : +{ +P(1, 0) = I1(4); +P(2, 0) = I2(7, 1, 4, 5); +P(3, 0) = I2(5, 3, 4, 5); +P(0, 1) = I1(4); +P(1, 1) = I1(4); +P(2, 1) = I2(7, 1, 4, 5); +P(3, 1) = I2(5, 3, 4, 5); +P(0, 2) = I1(4); +P(1, 2) = I1(4); +P(2, 2) = I2(7, 1, 4, 5); +P(3, 2) = I2(5, 3, 4, 5); +P(1, 3) = I1(4); +P(2, 3) = I2(7, 1, 4, 5); +P(3, 3) = I2(5, 3, 4, 5); +if (MDL) { + P(0, 3) = I1(4); +} else { + P(0, 3) = I3(2, 1, 1, 4, 3, 7); +} +if (MUL) { + P(0, 0) = I1(4); +} else { + P(0, 0) = I3(2, 1, 1, 4, 1, 3); +} +} break; +case 240 : +case 241 : +{ +P(0, 0) = I3(2, 1, 1, 4, 1, 3); +P(1, 0) = I3(5, 2, 1, 4, 1, 3); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I3(5, 2, 1, 4, 3, 1); +P(1, 1) = I3(6, 1, 1, 4, 1, 3); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +if (MDR) { + P(2, 2) = I1(4); + P(3, 2) = I1(4); + P(0, 3) = I2(5, 3, 4, 3); + P(1, 3) = I2(7, 1, 4, 3); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(2, 2) = I3(6, 1, 1, 4, 5, 7); + P(3, 2) = I3(2, 1, 1, 5, 4, 7); + P(0, 3) = I2(3, 1, 4, 7); + P(1, 3) = I2(3, 1, 7, 4); + P(2, 3) = I2(5, 3, 7, 5); + P(3, 3) = I2(1, 1, 5, 7); +} +} break; +case 242 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +P(2, 2) = I1(4); +P(0, 3) = I2(5, 3, 4, 3); +P(1, 3) = I2(7, 1, 4, 3); +if (MDR) { + P(3, 2) = I1(4); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(3, 2) = I2(1, 1, 4, 5); + P(2, 3) = I2(1, 1, 4, 7); + P(3, 3) = I2(1, 1, 5, 7); +} +if (MUR) { + P(2, 0) = I2(3, 1, 4, 2); + P(3, 0) = I2(5, 3, 4, 2); + P(2, 1) = I2(7, 1, 4, 2); + P(3, 1) = I2(3, 1, 4, 2); +} else { + P(2, 0) = I2(3, 1, 4, 1); + P(3, 0) = I3(2, 1, 1, 4, 1, 5); + P(2, 1) = I1(4); + P(3, 1) = I2(3, 1, 4, 5); +} +} break; +case 243 : +{ +P(0, 0) = I2(5, 3, 4, 3); +P(1, 0) = I2(7, 1, 4, 3); +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +if (MDR) { + P(2, 2) = I1(4); + P(3, 2) = I1(4); + P(0, 3) = I2(5, 3, 4, 3); + P(1, 3) = I2(7, 1, 4, 3); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(2, 2) = I3(6, 1, 1, 4, 5, 7); + P(3, 2) = I3(2, 1, 1, 5, 4, 7); + P(0, 3) = I2(3, 1, 4, 7); + P(1, 3) = I2(3, 1, 7, 4); + P(2, 3) = I2(5, 3, 7, 5); + P(3, 3) = I2(1, 1, 5, 7); +} +} break; +case 244 : +case 245 : +{ +P(0, 0) = I3(2, 1, 1, 4, 1, 3); +P(1, 0) = I3(5, 2, 1, 4, 1, 3); +P(2, 0) = I2(5, 3, 4, 1); +P(3, 0) = I2(5, 3, 4, 1); +P(0, 1) = I3(5, 2, 1, 4, 3, 1); +P(1, 1) = I3(6, 1, 1, 4, 1, 3); +P(2, 1) = I2(7, 1, 4, 1); +P(3, 1) = I2(7, 1, 4, 1); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +P(2, 2) = I1(4); +P(3, 2) = I1(4); +P(0, 3) = I2(5, 3, 4, 3); +P(1, 3) = I2(7, 1, 4, 3); +P(2, 3) = I1(4); +if (MDR) { + P(3, 3) = I1(4); +} else { + P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} +} break; +case 246 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(0, 1) = I3(5, 2, 1, 4, 3, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I1(4); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +P(2, 2) = I1(4); +P(3, 2) = I1(4); +P(0, 3) = I2(5, 3, 4, 3); +P(1, 3) = I2(7, 1, 4, 3); +P(2, 3) = I1(4); +if (MDR) { + P(3, 3) = I1(4); +} else { + P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} +if (MUR) { + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(3, 1) = I1(4); +} else { + P(2, 0) = I2(1, 1, 1, 4); + P(3, 0) = I2(1, 1, 1, 5); + P(3, 1) = I2(1, 1, 4, 5); +} +} break; +case 247 : +{ +P(0, 0) = I2(5, 3, 4, 3); +P(1, 0) = I2(7, 1, 4, 3); +P(2, 0) = I1(4); +P(0, 1) = I2(5, 3, 4, 3); +P(1, 1) = I2(7, 1, 4, 3); +P(2, 1) = I1(4); +P(3, 1) = I1(4); +P(0, 2) = I2(5, 3, 4, 3); +P(1, 2) = I2(7, 1, 4, 3); +P(2, 2) = I1(4); +P(3, 2) = I1(4); +P(0, 3) = I2(5, 3, 4, 3); +P(1, 3) = I2(7, 1, 4, 3); +P(2, 3) = I1(4); +if (MDR) { + P(3, 3) = I1(4); +} else { + P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} +if (MUR) { + P(3, 0) = I1(4); +} else { + P(3, 0) = I3(2, 1, 1, 4, 1, 5); +} +} break; +case 249 : +{ +P(0, 0) = I2(5, 3, 4, 1); +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I3(5, 2, 1, 4, 1, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(7, 1, 4, 1); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I1(4); +P(1, 2) = I1(4); +P(2, 2) = I1(4); +P(1, 3) = I1(4); +if (MDL) { + P(0, 3) = I1(4); +} else { + P(0, 3) = I3(2, 1, 1, 4, 3, 7); +} +if (MDR) { + P(3, 2) = I1(4); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(3, 2) = I2(1, 1, 4, 5); + P(2, 3) = I2(1, 1, 4, 7); + P(3, 3) = I2(1, 1, 5, 7); +} +} break; +case 250 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(1, 2) = I1(4); +P(2, 2) = I1(4); +if (MDL) { + P(0, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); +} else { + P(0, 2) = I2(1, 1, 3, 4); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(1, 1, 4, 7); +} +if (MDR) { + P(3, 2) = I1(4); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(3, 2) = I2(1, 1, 4, 5); + P(2, 3) = I2(1, 1, 4, 7); + P(3, 3) = I2(1, 1, 5, 7); +} +} break; +case 251 : +{ +P(2, 0) = I2(3, 1, 4, 2); +P(3, 0) = I2(5, 3, 4, 2); +P(1, 1) = I1(4); +P(2, 1) = I2(7, 1, 4, 2); +P(3, 1) = I2(3, 1, 4, 2); +P(0, 2) = I1(4); +P(1, 2) = I1(4); +P(2, 2) = I1(4); +P(1, 3) = I1(4); +if (MDL) { + P(0, 3) = I1(4); +} else { + P(0, 3) = I3(2, 1, 1, 4, 3, 7); +} +if (MDR) { + P(3, 2) = I1(4); + P(2, 3) = I1(4); + P(3, 3) = I1(4); +} else { + P(3, 2) = I2(1, 1, 4, 5); + P(2, 3) = I2(1, 1, 4, 7); + P(3, 3) = I2(1, 1, 5, 7); +} +if (MUL) { + P(0, 0) = I1(4); + P(1, 0) = I1(4); + P(0, 1) = I1(4); +} else { + P(0, 0) = I2(1, 1, 1, 3); + P(1, 0) = I2(1, 1, 1, 4); + P(0, 1) = I2(1, 1, 3, 4); +} +} break; +case 252 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I3(5, 2, 1, 4, 1, 0); +P(2, 0) = I2(5, 3, 4, 1); +P(3, 0) = I2(5, 3, 4, 1); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I2(7, 1, 4, 1); +P(3, 1) = I2(7, 1, 4, 1); +P(1, 2) = I1(4); +P(2, 2) = I1(4); +P(3, 2) = I1(4); +P(2, 3) = I1(4); +if (MDL) { + P(0, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); +} else { + P(0, 2) = I2(1, 1, 3, 4); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(1, 1, 4, 7); +} +if (MDR) { + P(3, 3) = I1(4); +} else { + P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} +} break; +case 253 : +{ +P(0, 0) = I2(5, 3, 4, 1); +P(1, 0) = I2(5, 3, 4, 1); +P(2, 0) = I2(5, 3, 4, 1); +P(3, 0) = I2(5, 3, 4, 1); +P(0, 1) = I2(7, 1, 4, 1); +P(1, 1) = I2(7, 1, 4, 1); +P(2, 1) = I2(7, 1, 4, 1); +P(3, 1) = I2(7, 1, 4, 1); +P(0, 2) = I1(4); +P(1, 2) = I1(4); +P(2, 2) = I1(4); +P(3, 2) = I1(4); +P(1, 3) = I1(4); +P(2, 3) = I1(4); +if (MDL) { + P(0, 3) = I1(4); +} else { + P(0, 3) = I3(2, 1, 1, 4, 3, 7); +} +if (MDR) { + P(3, 3) = I1(4); +} else { + P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} +} break; +case 254 : +{ +P(0, 0) = I2(5, 3, 4, 0); +P(1, 0) = I2(3, 1, 4, 0); +P(0, 1) = I2(3, 1, 4, 0); +P(1, 1) = I2(7, 1, 4, 0); +P(2, 1) = I1(4); +P(1, 2) = I1(4); +P(2, 2) = I1(4); +P(3, 2) = I1(4); +P(2, 3) = I1(4); +if (MDL) { + P(0, 2) = I1(4); + P(0, 3) = I1(4); + P(1, 3) = I1(4); +} else { + P(0, 2) = I2(1, 1, 3, 4); + P(0, 3) = I2(1, 1, 3, 7); + P(1, 3) = I2(1, 1, 4, 7); +} +if (MDR) { + P(3, 3) = I1(4); +} else { + P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} +if (MUR) { + P(2, 0) = I1(4); + P(3, 0) = I1(4); + P(3, 1) = I1(4); +} else { + P(2, 0) = I2(1, 1, 1, 4); + P(3, 0) = I2(1, 1, 1, 5); + P(3, 1) = I2(1, 1, 4, 5); +} +} break; +case 255 : +{ +P(1, 0) = I1(4); +P(2, 0) = I1(4); +P(0, 1) = I1(4); +P(1, 1) = I1(4); +P(2, 1) = I1(4); +P(3, 1) = I1(4); +P(0, 2) = I1(4); +P(1, 2) = I1(4); +P(2, 2) = I1(4); +P(3, 2) = I1(4); +P(1, 3) = I1(4); +P(2, 3) = I1(4); +if (MDL) { + P(0, 3) = I1(4); +} else { + P(0, 3) = I3(2, 1, 1, 4, 3, 7); +} +if (MDR) { + P(3, 3) = I1(4); +} else { + P(3, 3) = I3(2, 1, 1, 4, 5, 7); +} +if (MUL) { + P(0, 0) = I1(4); +} else { + P(0, 0) = I3(2, 1, 1, 4, 1, 3); +} +if (MUR) { + P(3, 0) = I1(4); +} else { + P(3, 0) = I3(2, 1, 1, 4, 1, 5); +} +} break; diff --git a/jni/desmume/src/filter/hq4x.h b/jni/desmume/src/filter/hq4x.h new file mode 100755 index 0000000..ac47a01 --- /dev/null +++ b/jni/desmume/src/filter/hq4x.h @@ -0,0 +1,40 @@ +/* + * This file is part of the Advance project. + * + * Copyright (C) 2003, 2004, 2008 Andrea Mazzoleni + * + * 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. + * + * In addition, as a special exception, Andrea Mazzoleni + * gives permission to link the code of this program with + * the MAME library (or with modified versions of MAME that use the + * same license as MAME), and distribute linked combinations including + * the two. You must obey the GNU General Public License in all + * respects for all of the code used other than MAME. If you modify + * this file, you may extend this exception to your version of the + * file, but you are not obligated to do so. If you do not wish to + * do so, delete this exception statement from your version. + */ + +#ifndef __HQ4X_H +#define __HQ4X_H + +#include "segment.h" + +void hq4x_16_def(interp_uint16* dst0, interp_uint16* dst1, interp_uint16* dst2, interp_uint16* dst3, const interp_uint16* src0, const interp_uint16* src1, const interp_uint16* src2, unsigned count, unsigned flag); +void hq4x_32_def(interp_uint32* dst0, interp_uint32* dst1, interp_uint32* dst2, interp_uint32* dst3, const interp_uint32* src0, const interp_uint32* src1, const interp_uint32* src2, unsigned count, unsigned flag); + +#endif + diff --git a/jni/desmume/src/filter/interp.h b/jni/desmume/src/filter/interp.h new file mode 100755 index 0000000..dad92d4 --- /dev/null +++ b/jni/desmume/src/filter/interp.h @@ -0,0 +1,354 @@ +/* + * This file is part of the Advance project. + * + * Copyright (C) 2003 Andrea Mazzoleni + * + * 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. + * + * In addition, as a special exception, Andrea Mazzoleni + * gives permission to link the code of this program with + * the MAME library (or with modified versions of MAME that use the + * same license as MAME), and distribute linked combinations including + * the two. You must obey the GNU General Public License in all + * respects for all of the code used other than MAME. If you modify + * this file, you may extend this exception to your version of the + * file, but you are not obligated to do so. If you do not wish to + * do so, delete this exception statement from your version. + */ + +#ifndef __INTERP_H +#define __INTERP_H + +#include "types.h" + +/***************************************************************************/ +/* Basic types */ + +/***************************************************************************/ +/* interpolation */ + +//extern unsigned interp_mask[2]; +//extern unsigned interp_bits_per_pixel; +// +//#define INTERP_16_MASK_1(v) (v & interp_mask[0]) +//#define INTERP_16_MASK_2(v) (v & interp_mask[1]) +// +//static inline u16 interp_16_521(u16 p1, u16 p2, u16 p3) +//{ +// return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*5 + INTERP_16_MASK_1(p2)*2 + INTERP_16_MASK_1(p3)*1) / 8) +// | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*5 + INTERP_16_MASK_2(p2)*2 + INTERP_16_MASK_2(p3)*1) / 8); +//} +// +//static inline u16 interp_16_332(u16 p1, u16 p2, u16 p3) +//{ +// return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*3 + INTERP_16_MASK_1(p2)*3 + INTERP_16_MASK_1(p3)*2) / 8) +// | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*3 + INTERP_16_MASK_2(p2)*3 + INTERP_16_MASK_2(p3)*2) / 8); +//} +// +//static inline u16 interp_16_611(u16 p1, u16 p2, u16 p3) +//{ +// return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*6 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 8) +// | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*6 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 8); +//} +// +//static inline u16 interp_16_71(u16 p1, u16 p2) +//{ +// return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*7 + INTERP_16_MASK_1(p2)) / 8) +// | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*7 + INTERP_16_MASK_2(p2)) / 8); +//} +// +//static inline u16 interp_16_211(u16 p1, u16 p2, u16 p3) +//{ +// return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*2 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 4) +// | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*2 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 4); +//} +// +//static inline u16 interp_16_772(u16 p1, u16 p2, u16 p3) +//{ +// return INTERP_16_MASK_1(((INTERP_16_MASK_1(p1) + INTERP_16_MASK_1(p2))*7 + INTERP_16_MASK_1(p3)*2) / 16) +// | INTERP_16_MASK_2(((INTERP_16_MASK_2(p1) + INTERP_16_MASK_2(p2))*7 + INTERP_16_MASK_2(p3)*2) / 16); +//} +// +//static inline u16 interp_16_11(u16 p1, u16 p2) +//{ +// return INTERP_16_MASK_1((INTERP_16_MASK_1(p1) + INTERP_16_MASK_1(p2)) / 2) +// | INTERP_16_MASK_2((INTERP_16_MASK_2(p1) + INTERP_16_MASK_2(p2)) / 2); +//} +// +//static inline u16 interp_16_31(u16 p1, u16 p2) +//{ +// return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*3 + INTERP_16_MASK_1(p2)) / 4) +// | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*3 + INTERP_16_MASK_2(p2)) / 4); +//} +// +//static inline u16 interp_16_1411(u16 p1, u16 p2, u16 p3) +//{ +// return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*14 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 16) +// | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*14 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 16); +//} +// +//static inline u16 interp_16_431(u16 p1, u16 p2, u16 p3) +//{ +// return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*4 + INTERP_16_MASK_1(p2)*3 + INTERP_16_MASK_1(p3)) / 8) +// | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*4 + INTERP_16_MASK_2(p2)*3 + INTERP_16_MASK_2(p3)) / 8); +//} +// +//static inline u16 interp_16_53(u16 p1, u16 p2) +//{ +// return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*5 + INTERP_16_MASK_1(p2)*3) / 8) +// | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*5 + INTERP_16_MASK_2(p2)*3) / 8); +//} +// +//static inline u16 interp_16_151(u16 p1, u16 p2) +//{ +// return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*15 + INTERP_16_MASK_1(p2)) / 16) +// | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*15 + INTERP_16_MASK_2(p2)) / 16); +//} +// +//static inline u16 interp_16_97(u16 p1, u16 p2) +//{ +// return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*9 + INTERP_16_MASK_1(p2)*7) / 16) +// | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*9 + INTERP_16_MASK_2(p2)*7) / 16); +//} + +#define INTERP_32_MASK_1(v) (v & 0xFF00FF) +#define INTERP_32_MASK_2(v) (v & 0x00FF00) + +static inline u32 interp_32_521(u32 p1, u32 p2, u32 p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*5 + INTERP_32_MASK_1(p2)*2 + INTERP_32_MASK_1(p3)*1) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*5 + INTERP_32_MASK_2(p2)*2 + INTERP_32_MASK_2(p3)*1) / 8); +} + +static inline u32 interp_32_332(u32 p1, u32 p2, u32 p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*3 + INTERP_32_MASK_1(p2)*3 + INTERP_32_MASK_1(p3)*2) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*3 + INTERP_32_MASK_2(p2)*3 + INTERP_32_MASK_2(p3)*2) / 8); +} + +static inline u32 interp_32_211(u32 p1, u32 p2, u32 p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*2 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 4) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*2 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 4); +} + +static inline u32 interp_32_611(u32 p1, u32 p2, u32 p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*6 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*6 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 8); +} + +static inline u32 interp_32_71(u32 p1, u32 p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*7 + INTERP_32_MASK_1(p2)) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*7 + INTERP_32_MASK_2(p2)) / 8); +} + +static inline u32 interp_32_772(u32 p1, u32 p2, u32 p3) +{ + return INTERP_32_MASK_1(((INTERP_32_MASK_1(p1) + INTERP_32_MASK_1(p2))*7 + INTERP_32_MASK_1(p3)*2) / 16) + | INTERP_32_MASK_2(((INTERP_32_MASK_2(p1) + INTERP_32_MASK_2(p2))*7 + INTERP_32_MASK_2(p3)*2) / 16); +} + +static inline u32 interp_32_11(u32 p1, u32 p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1) + INTERP_32_MASK_1(p2)) / 2) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1) + INTERP_32_MASK_2(p2)) / 2); +} + +static inline u32 interp_32_31(u32 p1, u32 p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*3 + INTERP_32_MASK_1(p2)) / 4) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*3 + INTERP_32_MASK_2(p2)) / 4); +} + +static inline u32 interp_32_1411(u32 p1, u32 p2, u32 p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*14 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 16) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*14 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 16); +} + +static inline u32 interp_32_431(u32 p1, u32 p2, u32 p3) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*4 + INTERP_32_MASK_1(p2)*3 + INTERP_32_MASK_1(p3)) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*4 + INTERP_32_MASK_2(p2)*3 + INTERP_32_MASK_2(p3)) / 8); +} + +static inline u32 interp_32_53(u32 p1, u32 p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*5 + INTERP_32_MASK_1(p2)*3) / 8) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*5 + INTERP_32_MASK_2(p2)*3) / 8); +} + +static inline u32 interp_32_151(u32 p1, u32 p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*15 + INTERP_32_MASK_1(p2)) / 16) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*15 + INTERP_32_MASK_2(p2)) / 16); +} + +static inline u32 interp_32_97(u32 p1, u32 p2) +{ + return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*9 + INTERP_32_MASK_1(p2)*7) / 16) + | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*9 + INTERP_32_MASK_2(p2)*7) / 16); +} + +/***************************************************************************/ +/* diff */ + +#define INTERP_Y_LIMIT (0x30*4) +#define INTERP_U_LIMIT (0x07*4) +#define INTERP_V_LIMIT (0x06*8) +// +//static int interp_16_diff(u16 p1, u16 p2) +//{ +// int r, g, b; +// int y, u, v; +// +// if (p1 == p2) +// return 0; +// +// if (interp_bits_per_pixel == 16) { +// b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3; +// g = (int)((p1 & 0x7E0) - (p2 & 0x7E0)) >> 3; +// r = (int)((p1 & 0xF800) - (p2 & 0xF800)) >> 8; +// } else { +// b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3; +// g = (int)((p1 & 0x3E0) - (p2 & 0x3E0)) >> 2; +// r = (int)((p1 & 0x7C00) - (p2 & 0x7C00)) >> 7; +// } +// +// y = r + g + b; +// u = r - b; +// v = -r + 2*g - b; +// +// if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT) +// return 1; +// +// if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT) +// return 1; +// +// if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT) +// return 1; +// +//return 0; +//} + +static int interp_32_diff(u32 p1, u32 p2) +{ + int r, g, b; + int y, u, v; + + if ((p1 & 0xF8F8F8) == (p2 & 0xF8F8F8)) + return 0; + + b = (int)((p1 & 0xFF) - (p2 & 0xFF)); + g = (int)((p1 & 0xFF00) - (p2 & 0xFF00)) >> 8; + r = (int)((p1 & 0xFF0000) - (p2 & 0xFF0000)) >> 16; + + y = r + g + b; + u = r - b; + v = -r + 2*g - b; + + if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT) + return 1; + + if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT) + return 1; + + if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT) + return 1; + + return 0; +} + + +#define INTERP_LIMIT2 (96000) +//#define ABS(x) ((x) < 0 ? -(x) : (x)) +static FORCEINLINE u32 ABS(s32 x) { return (x+(x>>31))^(x>>31); } // faster +#define MAX(x,y) ((x) > (y) ? (x) : (y)) +#define MIN(x,y) ((x) < (y) ? (x) : (y)) +// +//static int interp_16_diff2(u16 p1, u16 p2) +//{ +// int r, g, b; +// int y, u, v; +// +// if ((p1 & 0xF79E) == (p2 & 0xF79E)) +// return 0; +// +// if (interp_bits_per_pixel == 16) { +// b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3; +// g = (int)((p1 & 0x7E0) - (p2 & 0x7E0)) >> 3; +// r = (int)((p1 & 0xF800) - (p2 & 0xF800)) >> 8; +// } else { +// b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3; +// g = (int)((p1 & 0x3E0) - (p2 & 0x3E0)) >> 2; +// r = (int)((p1 & 0x7C00) - (p2 & 0x7C00)) >> 7; +// } +// +//// yb = 30*r + 58*g + 12*b; +// y = 33*r + 36*g + 31*b; +// u = -14*r - 29*g + 44*b; +// v = 62*r - 51*g - 10*b; +// +// if (11*ABS(y) + 8*ABS(u) + 6*ABS(v) > INTERP_LIMIT2) +// return 1; +// return 0; +//} + +static int interp_32_diff2(u32 p1, u32 p2) +{ + int r, g, b; + int y, u, v; + + if ((p1 & 0xF0F0F0) == (p2 & 0xF0F0F0)) + return 0; + + b = (int)((p1 & 0xF8) - (p2 & 0xF8)); + g = (int)((p1 & 0xF800) - (p2 & 0xF800)) >> 8; + r = (int)((p1 & 0xF80000) - (p2 & 0xF80000)) >> 16; + +// y = 30*r + 58*g + 12*b; + y = 33*r + 36*g + 31*b; + u = -14*r - 29*g + 44*b; + v = 62*r - 51*g - 10*b; + + if (11*ABS(y) + 8*ABS(u) + 6*ABS(v) > INTERP_LIMIT2) + return 1; + + return 0; +} +// +//static void interp_set(unsigned bits_per_pixel) +//{ +// interp_bits_per_pixel = bits_per_pixel; +// +// switch (bits_per_pixel) { +// case 15 : +// interp_mask[0] = 0x7C1F; +// interp_mask[1] = 0x03E0; +// break; +// case 16 : +// interp_mask[0] = 0xF81F; +// interp_mask[1] = 0x07E0; +// break; +// case 32 : +// interp_mask[0] = 0xFF00FF; +// interp_mask[1] = 0x00FF00; +// break; +// } +//} + +#endif diff --git a/jni/desmume/src/filter/lq2x.cpp b/jni/desmume/src/filter/lq2x.cpp new file mode 100755 index 0000000..8892017 --- /dev/null +++ b/jni/desmume/src/filter/lq2x.cpp @@ -0,0 +1,663 @@ +/* + * This file is part of the Advance project. + * + * Copyright (C) 2003 Andrea Mazzoleni + * + * 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. + * + * In addition, as a special exception, Andrea Mazzoleni + * gives permission to link the code of this program with + * the MAME library (or with modified versions of MAME that use the + * same license as MAME), and distribute linked combinations including + * the two. You must obey the GNU General Public License in all + * respects for all of the code used other than MAME. If you modify + * this file, you may extend this exception to your version of the + * file, but you are not obligated to do so. If you do not wish to + * do so, delete this exception statement from your version. + */ + +#include "filter.h" +#include "interp.h" + +//static void lq2x_16_def(u16* dst0, u16* dst1, const u16* src0, const u16* src1, const u16* src2, unsigned count) +//{ +// unsigned i; +// +// for(i=0;i<count;++i) { +// unsigned char mask; +// +// u16 c[9]; +// +// c[1] = src0[0]; +// c[4] = src1[0]; +// c[7] = src2[0]; +// +// if (i>0) { +// c[0] = src0[-1]; +// c[3] = src1[-1]; +// c[6] = src2[-1]; +// } else { +// c[0] = c[1]; +// c[3] = c[4]; +// c[6] = c[7]; +// } +// +// if (i<count-1) { +// c[2] = src0[1]; +// c[5] = src1[1]; +// c[8] = src2[1]; +// } else { +// c[2] = c[1]; +// c[5] = c[4]; +// c[8] = c[7]; +// } +// +// mask = 0; +// +// if (c[0] != c[4]) +// mask |= 1 << 0; +// if (c[1] != c[4]) +// mask |= 1 << 1; +// if (c[2] != c[4]) +// mask |= 1 << 2; +// if (c[3] != c[4]) +// mask |= 1 << 3; +// if (c[5] != c[4]) +// mask |= 1 << 4; +// if (c[6] != c[4]) +// mask |= 1 << 5; +// if (c[7] != c[4]) +// mask |= 1 << 6; +// if (c[8] != c[4]) +// mask |= 1 << 7; +// +//#define P0 dst0[0] +//#define P1 dst0[1] +//#define P2 dst1[0] +//#define P3 dst1[1] +//#define MUR (c[1] != c[5]) +//#define MDR (c[5] != c[7]) +//#define MDL (c[7] != c[3]) +//#define MUL (c[3] != c[1]) +//#define IC(p0) c[p0] +//#define I11(p0,p1) interp_16_11(c[p0], c[p1]) +//#define I211(p0,p1,p2) interp_16_211(c[p0], c[p1], c[p2]) +//#define I31(p0,p1) interp_16_31(c[p0], c[p1]) +//#define I332(p0,p1,p2) interp_16_332(c[p0], c[p1], c[p2]) +//#define I431(p0,p1,p2) interp_16_431(c[p0], c[p1], c[p2]) +//#define I521(p0,p1,p2) interp_16_521(c[p0], c[p1], c[p2]) +//#define I53(p0,p1) interp_16_53(c[p0], c[p1]) +//#define I611(p0,p1,p2) interp_16_611(c[p0], c[p1], c[p2]) +//#define I71(p0,p1) interp_16_71(c[p0], c[p1]) +//#define I772(p0,p1,p2) interp_16_772(c[p0], c[p1], c[p2]) +//#define I97(p0,p1) interp_16_97(c[p0], c[p1]) +//#define I1411(p0,p1,p2) interp_16_1411(c[p0], c[p1], c[p2]) +//#define I151(p0,p1) interp_16_151(c[p0], c[p1]) +// +// switch (mask) { +//#include "lq2x.h" +// } +// +//#undef P0 +//#undef P1 +//#undef P2 +//#undef P3 +//#undef MUR +//#undef MDR +//#undef MDL +//#undef MUL +//#undef IC +//#undef I11 +//#undef I211 +//#undef I31 +//#undef I332 +//#undef I431 +//#undef I521 +//#undef I53 +//#undef I611 +//#undef I71 +//#undef I772 +//#undef I97 +//#undef I1411 +//#undef I151 +// +// src0 += 1; +// src1 += 1; +// src2 += 1; +// dst0 += 2; +// dst1 += 2; +// } +//} +// +//static void lq2xS_16_def(u16* dst0, u16* dst1, const u16* src0, const u16* src1, const u16* src2, unsigned count) +//{ +// unsigned i; +// +// for(i=0;i<count;++i) { +// unsigned char mask; +// +// u16 c[9]; +// +// c[1] = src0[0]; +// c[4] = src1[0]; +// c[7] = src2[0]; +// +// if (i>0) { +// c[0] = src0[-1]; +// c[3] = src1[-1]; +// c[6] = src2[-1]; +// } else { +// c[0] = c[1]; +// c[3] = c[4]; +// c[6] = c[7]; +// } +// +// if (i<count-1) { +// c[2] = src0[1]; +// c[5] = src1[1]; +// c[8] = src2[1]; +// } else { +// c[2] = c[1]; +// c[5] = c[4]; +// c[8] = c[7]; +// } +// +// // lq2xS dynamic edge detection: +// // simply comparing the center color against its surroundings will give bad results in many cases, +// // so, instead, compare the center color relative to the max difference in brightness of this 3x3 block +// int brightArray[9]; +// int maxBright = 0, minBright = 999999; +// for(int j = 0 ; j < 9 ; j++) +// { +// const int b = (int)((c[j] & 0xF8)); +// const int g = (int)((c[j] & 0xF800)) >> 8; +// const int r = (int)((c[j] & 0xF80000)) >> 16; +// const int bright = r+r+r + g+g+g + b+b; +// if(bright > maxBright) maxBright = bright; +// if(bright < minBright) minBright = bright; +// +// brightArray[j] = bright; +// } +// int diffBright = ((maxBright - minBright) * 7) >> 4; +// if(diffBright > 7) +// { +// const int centerBright = brightArray[4]; +// if(ABS(brightArray[0] - centerBright) > diffBright) +// mask |= 1 << 0; +// if(ABS(brightArray[1] - centerBright) > diffBright) +// mask |= 1 << 1; +// if(ABS(brightArray[2] - centerBright) > diffBright) +// mask |= 1 << 2; +// if(ABS(brightArray[3] - centerBright) > diffBright) +// mask |= 1 << 3; +// if(ABS(brightArray[5] - centerBright) > diffBright) +// mask |= 1 << 4; +// if(ABS(brightArray[6] - centerBright) > diffBright) +// mask |= 1 << 5; +// if(ABS(brightArray[7] - centerBright) > diffBright) +// mask |= 1 << 6; +// if(ABS(brightArray[8] - centerBright) > diffBright) +// mask |= 1 << 7; +// } +// +//#define P0 dst0[0] +//#define P1 dst0[1] +//#define P2 dst1[0] +//#define P3 dst1[1] +//#define MUR false +//#define MDR false +//#define MDL false +//#define MUL false +//#define IC(p0) c[p0] +//#define I11(p0,p1) interp_16_11(c[p0], c[p1]) +//#define I211(p0,p1,p2) interp_16_211(c[p0], c[p1], c[p2]) +//#define I31(p0,p1) interp_16_31(c[p0], c[p1]) +//#define I332(p0,p1,p2) interp_16_332(c[p0], c[p1], c[p2]) +//#define I431(p0,p1,p2) interp_16_431(c[p0], c[p1], c[p2]) +//#define I521(p0,p1,p2) interp_16_521(c[p0], c[p1], c[p2]) +//#define I53(p0,p1) interp_16_53(c[p0], c[p1]) +//#define I611(p0,p1,p2) interp_16_611(c[p0], c[p1], c[p2]) +//#define I71(p0,p1) interp_16_71(c[p0], c[p1]) +//#define I772(p0,p1,p2) interp_16_772(c[p0], c[p1], c[p2]) +//#define I97(p0,p1) interp_16_97(c[p0], c[p1]) +//#define I1411(p0,p1,p2) interp_16_1411(c[p0], c[p1], c[p2]) +//#define I151(p0,p1) interp_16_151(c[p0], c[p1]) +// +// switch (mask) { +//#include "lq2x.h" +// } +// +//#undef P0 +//#undef P1 +//#undef P2 +//#undef P3 +//#undef MUR +//#undef MDR +//#undef MDL +//#undef MUL +//#undef IC +//#undef I11 +//#undef I211 +//#undef I31 +//#undef I332 +//#undef I431 +//#undef I521 +//#undef I53 +//#undef I611 +//#undef I71 +//#undef I772 +//#undef I97 +//#undef I1411 +//#undef I151 +// +// src0 += 1; +// src1 += 1; +// src2 += 1; +// dst0 += 2; +// dst1 += 2; +// } +//} + +static void lq2x_32_def(u32* dst0, u32* dst1, const u32* src0, const u32* src1, const u32* src2, unsigned count) +{ + unsigned i; + + for(i=0;i<count;++i) { + unsigned char mask; + + u32 c[9]; + + c[1] = src0[0]; + c[4] = src1[0]; + c[7] = src2[0]; + + if (i>0) { + c[0] = src0[-1]; + c[3] = src1[-1]; + c[6] = src2[-1]; + } else { + c[0] = c[1]; + c[3] = c[4]; + c[6] = c[7]; + } + + if (i<count-1) { + c[2] = src0[1]; + c[5] = src1[1]; + c[8] = src2[1]; + } else { + c[2] = c[1]; + c[5] = c[4]; + c[8] = c[7]; + } + + mask = 0; + + if (c[0] != c[4]) + mask |= 1 << 0; + if (c[1] != c[4]) + mask |= 1 << 1; + if (c[2] != c[4]) + mask |= 1 << 2; + if (c[3] != c[4]) + mask |= 1 << 3; + if (c[5] != c[4]) + mask |= 1 << 4; + if (c[6] != c[4]) + mask |= 1 << 5; + if (c[7] != c[4]) + mask |= 1 << 6; + if (c[8] != c[4]) + mask |= 1 << 7; + +#define P0 dst0[0] +#define P1 dst0[1] +#define P2 dst1[0] +#define P3 dst1[1] +#define MUR (c[1] != c[5]) +#define MDR (c[5] != c[7]) +#define MDL (c[7] != c[3]) +#define MUL (c[3] != c[1]) +#define IC(p0) c[p0] +#define I11(p0,p1) interp_32_11(c[p0], c[p1]) +#define I211(p0,p1,p2) interp_32_211(c[p0], c[p1], c[p2]) +#define I31(p0,p1) interp_32_31(c[p0], c[p1]) +#define I332(p0,p1,p2) interp_32_332(c[p0], c[p1], c[p2]) +#define I431(p0,p1,p2) interp_32_431(c[p0], c[p1], c[p2]) +#define I521(p0,p1,p2) interp_32_521(c[p0], c[p1], c[p2]) +#define I53(p0,p1) interp_32_53(c[p0], c[p1]) +#define I611(p0,p1,p2) interp_32_611(c[p0], c[p1], c[p2]) +#define I71(p0,p1) interp_32_71(c[p0], c[p1]) +#define I772(p0,p1,p2) interp_32_772(c[p0], c[p1], c[p2]) +#define I97(p0,p1) interp_32_97(c[p0], c[p1]) +#define I1411(p0,p1,p2) interp_32_1411(c[p0], c[p1], c[p2]) +#define I151(p0,p1) interp_32_151(c[p0], c[p1]) + + switch (mask) { +#include "lq2x.h" + } + +#undef P0 +#undef P1 +#undef P2 +#undef P3 +#undef MUR +#undef MDR +#undef MDL +#undef MUL +#undef IC +#undef I11 +#undef I211 +#undef I31 +#undef I332 +#undef I431 +#undef I521 +#undef I53 +#undef I611 +#undef I71 +#undef I772 +#undef I97 +#undef I1411 +#undef I151 + + src0 += 1; + src1 += 1; + src2 += 1; + dst0 += 2; + dst1 += 2; + } +} + +static void lq2xS_32_def(u32* dst0, u32* dst1, const u32* src0, const u32* src1, const u32* src2, unsigned count) +{ + unsigned i; + + for(i=0;i<count;++i) { + unsigned char mask = 0; + + u32 c[9]; + + c[1] = src0[0]; + c[4] = src1[0]; + c[7] = src2[0]; + + if (i>0) { + c[0] = src0[-1]; + c[3] = src1[-1]; + c[6] = src2[-1]; + } else { + c[0] = c[1]; + c[3] = c[4]; + c[6] = c[7]; + } + + if (i<count-1) { + c[2] = src0[1]; + c[5] = src1[1]; + c[8] = src2[1]; + } else { + c[2] = c[1]; + c[5] = c[4]; + c[8] = c[7]; + } + + // lq2xS dynamic edge detection: + // simply comparing the center color against its surroundings will give bad results in many cases, + // so, instead, compare the center color relative to the max difference in brightness of this 3x3 block + int brightArray[9]; + int maxBright = 0, minBright = 999999; + for(int j = 0 ; j < 9 ; j++) + { + const int b = (int)((c[j] & 0xF8)); + const int g = (int)((c[j] & 0xF800)) >> 8; + const int r = (int)((c[j] & 0xF80000)) >> 16; + const int bright = r+r+r + g+g+g + b+b; + if(bright > maxBright) maxBright = bright; + if(bright < minBright) minBright = bright; + + brightArray[j] = bright; + } + int diffBright = ((maxBright - minBright) * 7) >> 4; + if(diffBright > 7) + { + const int centerBright = brightArray[4]; + if(ABS(brightArray[0] - centerBright) > diffBright) + mask |= 1 << 0; + if(ABS(brightArray[1] - centerBright) > diffBright) + mask |= 1 << 1; + if(ABS(brightArray[2] - centerBright) > diffBright) + mask |= 1 << 2; + if(ABS(brightArray[3] - centerBright) > diffBright) + mask |= 1 << 3; + if(ABS(brightArray[5] - centerBright) > diffBright) + mask |= 1 << 4; + if(ABS(brightArray[6] - centerBright) > diffBright) + mask |= 1 << 5; + if(ABS(brightArray[7] - centerBright) > diffBright) + mask |= 1 << 6; + if(ABS(brightArray[8] - centerBright) > diffBright) + mask |= 1 << 7; + } + +#define P0 dst0[0] +#define P1 dst0[1] +#define P2 dst1[0] +#define P3 dst1[1] +#define MUR false +#define MDR false +#define MDL false +#define MUL false +#define IC(p0) c[p0] +#define I11(p0,p1) interp_32_11(c[p0], c[p1]) +#define I211(p0,p1,p2) interp_32_211(c[p0], c[p1], c[p2]) +#define I31(p0,p1) interp_32_31(c[p0], c[p1]) +#define I332(p0,p1,p2) interp_32_332(c[p0], c[p1], c[p2]) +#define I431(p0,p1,p2) interp_32_431(c[p0], c[p1], c[p2]) +#define I521(p0,p1,p2) interp_32_521(c[p0], c[p1], c[p2]) +#define I53(p0,p1) interp_32_53(c[p0], c[p1]) +#define I611(p0,p1,p2) interp_32_611(c[p0], c[p1], c[p2]) +#define I71(p0,p1) interp_32_71(c[p0], c[p1]) +#define I772(p0,p1,p2) interp_32_772(c[p0], c[p1], c[p2]) +#define I97(p0,p1) interp_32_97(c[p0], c[p1]) +#define I1411(p0,p1,p2) interp_32_1411(c[p0], c[p1], c[p2]) +#define I151(p0,p1) interp_32_151(c[p0], c[p1]) + + switch (mask) { +#include "lq2x.h" + } + +#undef P0 +#undef P1 +#undef P2 +#undef P3 +#undef MUR +#undef MDR +#undef MDL +#undef MUL +#undef IC +#undef I11 +#undef I211 +#undef I31 +#undef I332 +#undef I431 +#undef I521 +#undef I53 +#undef I611 +#undef I71 +#undef I772 +#undef I97 +#undef I1411 +#undef I151 + + src0 += 1; + src1 += 1; + src2 += 1; + dst0 += 2; + dst1 += 2; + } +} +//void lq2x16(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, +// u8 *dstPtr, u32 dstPitch, int width, int height) +//{ +// u16 *dst0 = (u16 *)dstPtr; +// u16 *dst1 = dst0 + (dstPitch >> 1); +// +// u16 *src0 = (u16 *)srcPtr; +// u16 *src1 = src0 + (srcPitch >> 1); +// u16 *src2 = src1 + (srcPitch >> 1); +// +// lq2x_16_def(dst0, dst1, src0, src0, src1, width); +// if( height == 1 ) return; +// +// int count = height; +// +// count -= 2; +// while(count>0) { +// dst0 += dstPitch; +// dst1 += dstPitch; +// lq2x_16_def(dst0, dst1, src0, src1, src2, width); +// src0 = src1; +// src1 = src2; +// src2 += srcPitch >> 1; +// --count; +// } +// dst0 += dstPitch; +// dst1 += dstPitch; +// lq2x_16_def(dst0, dst1, src0, src1, src1, width); +//} +// +//void lq2xS16(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, +// u8 *dstPtr, u32 dstPitch, int width, int height) +//{ +// u16 *dst0 = (u16 *)dstPtr; +// u16 *dst1 = dst0 + (dstPitch >> 1); +// +// u16 *src0 = (u16 *)srcPtr; +// u16 *src1 = src0 + (srcPitch >> 1); +// u16 *src2 = src1 + (srcPitch >> 1); +// +// int count; +// +// lq2xS_16_def(dst0, dst1, src0, src0, src1, width); +// if( height == 1 ) return; +// +// count = height; +// +// count -= 2; +// while(count>0) { +// dst0 += dstPitch; +// dst1 += dstPitch; +// lq2x_16_def(dst0, dst1, src0, src1, src2, width); +// src0 = src1; +// src1 = src2; +// src2 += srcPitch >> 1; +// --count; +// } +// dst0 += dstPitch; +// dst1 += dstPitch; +// lq2xS_16_def(dst0, dst1, src0, src1, src1, width); +//} + +void lq2x32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u32 *dst0 = (u32 *)dstPtr; + u32 *dst1 = dst0 + (dstPitch >> 2); + + u32 *src0 = (u32 *)srcPtr; + u32 *src1 = src0 + (srcPitch >> 2); + u32 *src2 = src1 + (srcPitch >> 2); + lq2x_32_def(dst0, dst1, src0, src0, src1, width); + if( height == 1 ) return; + + int count = height; + + count -= 2; + while(count>0) { + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + lq2x_32_def(dst0, dst1, src0, src1, src2, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 2; + --count; + } + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + lq2x_32_def(dst0, dst1, src0, src1, src1, width); +} + +void lq2xS32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, + u8 *dstPtr, u32 dstPitch, int width, int height) +{ + u32 *dst0 = (u32 *)dstPtr; + u32 *dst1 = dst0 + (dstPitch >> 2); + + u32 *src0 = (u32 *)srcPtr; + u32 *src1 = src0 + (srcPitch >> 2); + u32 *src2 = src1 + (srcPitch >> 2); + + int count; + + lq2xS_32_def(dst0, dst1, src0, src0, src1, width); + if( height == 1 ) return; + + count = height; + + count -= 2; + while(count>0) { + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + lq2x_32_def(dst0, dst1, src0, src1, src2, width); + src0 = src1; + src1 = src2; + src2 += srcPitch >> 2; + --count; + } + dst0 += dstPitch >> 1; + dst1 += dstPitch >> 1; + lq2xS_32_def(dst0, dst1, src0, src1, src1, width); +} + +//void lq2x_init(unsigned bits_per_pixel) +//{ +// interp_set(bits_per_pixel); +//} + +void RenderLQ2X (SSurface Src, SSurface Dst) +{ + + unsigned char *lpSrc, *lpDst; + + lpSrc = Src.Surface; + lpDst = Dst.Surface; + + lq2x32 (lpSrc, Src.Pitch*2, + lpSrc, + lpDst, Dst.Pitch*2 , Src.Width, Src.Height); +} + +void RenderLQ2XS (SSurface Src, SSurface Dst) +{ + + unsigned char *lpSrc, *lpDst; + + lpSrc = Src.Surface; + lpDst = Dst.Surface; + + lq2xS32 (lpSrc, Src.Pitch*2, + lpSrc, + lpDst, Dst.Pitch*2 , Src.Width, Src.Height); +} diff --git a/jni/desmume/src/filter/lq2x.h b/jni/desmume/src/filter/lq2x.h new file mode 100755 index 0000000..7656d18 --- /dev/null +++ b/jni/desmume/src/filter/lq2x.h @@ -0,0 +1,1284 @@ +case 0 : +case 2 : +case 4 : +case 6 : +case 8 : +case 12 : +case 16 : +case 20 : +case 24 : +case 28 : +case 32 : +case 34 : +case 36 : +case 38 : +case 40 : +case 44 : +case 48 : +case 52 : +case 56 : +case 60 : +case 64 : +case 66 : +case 68 : +case 70 : +case 96 : +case 98 : +case 100 : +case 102 : +case 128 : +case 130 : +case 132 : +case 134 : +case 136 : +case 140 : +case 144 : +case 148 : +case 152 : +case 156 : +case 160 : +case 162 : +case 164 : +case 166 : +case 168 : +case 172 : +case 176 : +case 180 : +case 184 : +case 188 : +case 192 : +case 194 : +case 196 : +case 198 : +case 224 : +case 226 : +case 228 : +case 230 : +{ + P0 = IC(0); + P1 = IC(0); + P2 = IC(0); + P3 = IC(0); +} break; +case 1 : +case 5 : +case 9 : +case 13 : +case 17 : +case 21 : +case 25 : +case 29 : +case 33 : +case 37 : +case 41 : +case 45 : +case 49 : +case 53 : +case 57 : +case 61 : +case 65 : +case 69 : +case 97 : +case 101 : +case 129 : +case 133 : +case 137 : +case 141 : +case 145 : +case 149 : +case 153 : +case 157 : +case 161 : +case 165 : +case 169 : +case 173 : +case 177 : +case 181 : +case 185 : +case 189 : +case 193 : +case 197 : +case 225 : +case 229 : +{ + P0 = IC(1); + P1 = IC(1); + P2 = IC(1); + P3 = IC(1); +} break; +case 3 : +case 35 : +case 67 : +case 99 : +case 131 : +case 163 : +case 195 : +case 227 : +{ + P0 = IC(2); + P1 = IC(2); + P2 = IC(2); + P3 = IC(2); +} break; +case 7 : +case 39 : +case 71 : +case 103 : +case 135 : +case 167 : +case 199 : +case 231 : +{ + P0 = IC(3); + P1 = IC(3); + P2 = IC(3); + P3 = IC(3); +} break; +case 10 : +case 138 : +{ + P1 = IC(0); + P2 = IC(0); + P3 = IC(0); + if (MUL) { + P0 = IC(0); + } else { + P0 = I211(0, 1, 3); + } +} break; +case 11 : +case 27 : +case 75 : +case 139 : +case 155 : +case 203 : +{ + P1 = IC(2); + P2 = IC(2); + P3 = IC(2); + if (MUL) { + P0 = IC(2); + } else { + P0 = I211(2, 1, 3); + } +} break; +case 14 : +case 142 : +{ + P2 = IC(0); + P3 = IC(0); + if (MUL) { + P0 = IC(0); + P1 = IC(0); + } else { + P0 = I332(1, 3, 0); + P1 = I31(0, 1); + } +} break; +case 15 : +case 143 : +case 207 : +{ + P2 = IC(4); + P3 = IC(4); + if (MUL) { + P0 = IC(4); + P1 = IC(4); + } else { + P0 = I332(1, 3, 4); + P1 = I31(4, 1); + } +} break; +case 18 : +case 22 : +case 30 : +case 50 : +case 54 : +case 62 : +case 86 : +case 118 : +{ + P0 = IC(0); + P2 = IC(0); + P3 = IC(0); + if (MUR) { + P1 = IC(0); + } else { + P1 = I211(0, 1, 5); + } +} break; +case 19 : +case 51 : +{ + P2 = IC(2); + P3 = IC(2); + if (MUR) { + P0 = IC(2); + P1 = IC(2); + } else { + P0 = I31(2, 1); + P1 = I332(1, 5, 2); + } +} break; +case 23 : +case 55 : +case 119 : +{ + P2 = IC(3); + P3 = IC(3); + if (MUR) { + P0 = IC(3); + P1 = IC(3); + } else { + P0 = I31(3, 1); + P1 = I332(1, 5, 3); + } +} break; +case 26 : +{ + P2 = IC(0); + P3 = IC(0); + if (MUL) { + P0 = IC(0); + } else { + P0 = I211(0, 1, 3); + } + if (MUR) { + P1 = IC(0); + } else { + P1 = I211(0, 1, 5); + } +} break; +case 31 : +case 95 : +{ + P2 = IC(4); + P3 = IC(4); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 42 : +case 170 : +{ + P1 = IC(0); + P3 = IC(0); + if (MUL) { + P0 = IC(0); + P2 = IC(0); + } else { + P0 = I332(1, 3, 0); + P2 = I31(0, 3); + } +} break; +case 43 : +case 171 : +case 187 : +{ + P1 = IC(2); + P3 = IC(2); + if (MUL) { + P0 = IC(2); + P2 = IC(2); + } else { + P0 = I332(1, 3, 2); + P2 = I31(2, 3); + } +} break; +case 46 : +case 174 : +{ + P1 = IC(0); + P2 = IC(0); + P3 = IC(0); + if (MUL) { + P0 = IC(0); + } else { + P0 = I611(0, 1, 3); + } +} break; +case 47 : +case 175 : +{ + P1 = IC(4); + P2 = IC(4); + P3 = IC(4); + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } +} break; +case 58 : +case 154 : +case 186 : +{ + P2 = IC(0); + P3 = IC(0); + if (MUL) { + P0 = IC(0); + } else { + P0 = I611(0, 1, 3); + } + if (MUR) { + P1 = IC(0); + } else { + P1 = I611(0, 1, 5); + } +} break; +case 59 : +{ + P2 = IC(2); + P3 = IC(2); + if (MUL) { + P0 = IC(2); + } else { + P0 = I211(2, 1, 3); + } + if (MUR) { + P1 = IC(2); + } else { + P1 = I611(2, 1, 5); + } +} break; +case 63 : +{ + P2 = IC(4); + P3 = IC(4); + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 72 : +case 76 : +case 104 : +case 106 : +case 108 : +case 110 : +case 120 : +case 124 : +{ + P0 = IC(0); + P1 = IC(0); + P3 = IC(0); + if (MDL) { + P2 = IC(0); + } else { + P2 = I211(0, 3, 7); + } +} break; +case 73 : +case 77 : +case 105 : +case 109 : +case 125 : +{ + P1 = IC(1); + P3 = IC(1); + if (MDL) { + P0 = IC(1); + P2 = IC(1); + } else { + P0 = I31(1, 3); + P2 = I332(3, 7, 1); + } +} break; +case 74 : +{ + P1 = IC(0); + P3 = IC(0); + if (MDL) { + P2 = IC(0); + } else { + P2 = I211(0, 3, 7); + } + if (MUL) { + P0 = IC(0); + } else { + P0 = I211(0, 1, 3); + } +} break; +case 78 : +case 202 : +case 206 : +{ + P1 = IC(0); + P3 = IC(0); + if (MDL) { + P2 = IC(0); + } else { + P2 = I611(0, 3, 7); + } + if (MUL) { + P0 = IC(0); + } else { + P0 = I611(0, 1, 3); + } +} break; +case 79 : +{ + P1 = IC(4); + P3 = IC(4); + if (MDL) { + P2 = IC(4); + } else { + P2 = I611(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } +} break; +case 80 : +case 208 : +case 210 : +case 216 : +{ + P0 = IC(0); + P1 = IC(0); + P2 = IC(0); + if (MDR) { + P3 = IC(0); + } else { + P3 = I211(0, 5, 7); + } +} break; +case 81 : +case 209 : +case 217 : +{ + P0 = IC(1); + P1 = IC(1); + P2 = IC(1); + if (MDR) { + P3 = IC(1); + } else { + P3 = I211(1, 5, 7); + } +} break; +case 82 : +case 214 : +case 222 : +{ + P0 = IC(0); + P2 = IC(0); + if (MDR) { + P3 = IC(0); + } else { + P3 = I211(0, 5, 7); + } + if (MUR) { + P1 = IC(0); + } else { + P1 = I211(0, 1, 5); + } +} break; +case 83 : +case 115 : +{ + P0 = IC(2); + P2 = IC(2); + if (MDR) { + P3 = IC(2); + } else { + P3 = I611(2, 5, 7); + } + if (MUR) { + P1 = IC(2); + } else { + P1 = I611(2, 1, 5); + } +} break; +case 84 : +case 212 : +{ + P0 = IC(0); + P2 = IC(0); + if (MDR) { + P1 = IC(0); + P3 = IC(0); + } else { + P1 = I31(0, 5); + P3 = I332(5, 7, 0); + } +} break; +case 85 : +case 213 : +case 221 : +{ + P0 = IC(1); + P2 = IC(1); + if (MDR) { + P1 = IC(1); + P3 = IC(1); + } else { + P1 = I31(1, 5); + P3 = I332(5, 7, 1); + } +} break; +case 87 : +{ + P0 = IC(3); + P2 = IC(3); + if (MDR) { + P3 = IC(3); + } else { + P3 = I611(3, 5, 7); + } + if (MUR) { + P1 = IC(3); + } else { + P1 = I211(3, 1, 5); + } +} break; +case 88 : +case 248 : +case 250 : +{ + P0 = IC(0); + P1 = IC(0); + if (MDL) { + P2 = IC(0); + } else { + P2 = I211(0, 3, 7); + } + if (MDR) { + P3 = IC(0); + } else { + P3 = I211(0, 5, 7); + } +} break; +case 89 : +case 93 : +{ + P0 = IC(1); + P1 = IC(1); + if (MDL) { + P2 = IC(1); + } else { + P2 = I611(1, 3, 7); + } + if (MDR) { + P3 = IC(1); + } else { + P3 = I611(1, 5, 7); + } +} break; +case 90 : +{ + if (MDL) { + P2 = IC(0); + } else { + P2 = I611(0, 3, 7); + } + if (MDR) { + P3 = IC(0); + } else { + P3 = I611(0, 5, 7); + } + if (MUL) { + P0 = IC(0); + } else { + P0 = I611(0, 1, 3); + } + if (MUR) { + P1 = IC(0); + } else { + P1 = I611(0, 1, 5); + } +} break; +case 91 : +{ + if (MDL) { + P2 = IC(2); + } else { + P2 = I611(2, 3, 7); + } + if (MDR) { + P3 = IC(2); + } else { + P3 = I611(2, 5, 7); + } + if (MUL) { + P0 = IC(2); + } else { + P0 = I211(2, 1, 3); + } + if (MUR) { + P1 = IC(2); + } else { + P1 = I611(2, 1, 5); + } +} break; +case 92 : +{ + P0 = IC(0); + P1 = IC(0); + if (MDL) { + P2 = IC(0); + } else { + P2 = I611(0, 3, 7); + } + if (MDR) { + P3 = IC(0); + } else { + P3 = I611(0, 5, 7); + } +} break; +case 94 : +{ + if (MDL) { + P2 = IC(0); + } else { + P2 = I611(0, 3, 7); + } + if (MDR) { + P3 = IC(0); + } else { + P3 = I611(0, 5, 7); + } + if (MUL) { + P0 = IC(0); + } else { + P0 = I611(0, 1, 3); + } + if (MUR) { + P1 = IC(0); + } else { + P1 = I211(0, 1, 5); + } +} break; +case 107 : +case 123 : +{ + P1 = IC(2); + P3 = IC(2); + if (MDL) { + P2 = IC(2); + } else { + P2 = I211(2, 3, 7); + } + if (MUL) { + P0 = IC(2); + } else { + P0 = I211(2, 1, 3); + } +} break; +case 111 : +{ + P1 = IC(4); + P3 = IC(4); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } +} break; +case 112 : +case 240 : +{ + P0 = IC(0); + P1 = IC(0); + if (MDR) { + P2 = IC(0); + P3 = IC(0); + } else { + P2 = I31(0, 7); + P3 = I332(5, 7, 0); + } +} break; +case 113 : +case 241 : +{ + P0 = IC(1); + P1 = IC(1); + if (MDR) { + P2 = IC(1); + P3 = IC(1); + } else { + P2 = I31(1, 7); + P3 = I332(5, 7, 1); + } +} break; +case 114 : +{ + P0 = IC(0); + P2 = IC(0); + if (MDR) { + P3 = IC(0); + } else { + P3 = I611(0, 5, 7); + } + if (MUR) { + P1 = IC(0); + } else { + P1 = I611(0, 1, 5); + } +} break; +case 116 : +{ + P0 = IC(0); + P1 = IC(0); + P2 = IC(0); + if (MDR) { + P3 = IC(0); + } else { + P3 = I611(0, 5, 7); + } +} break; +case 117 : +{ + P0 = IC(1); + P1 = IC(1); + P2 = IC(1); + if (MDR) { + P3 = IC(1); + } else { + P3 = I611(1, 5, 7); + } +} break; +case 121 : +{ + P0 = IC(1); + P1 = IC(1); + if (MDL) { + P2 = IC(1); + } else { + P2 = I211(1, 3, 7); + } + if (MDR) { + P3 = IC(1); + } else { + P3 = I611(1, 5, 7); + } +} break; +case 122 : +{ + if (MDL) { + P2 = IC(0); + } else { + P2 = I211(0, 3, 7); + } + if (MDR) { + P3 = IC(0); + } else { + P3 = I611(0, 5, 7); + } + if (MUL) { + P0 = IC(0); + } else { + P0 = I611(0, 1, 3); + } + if (MUR) { + P1 = IC(0); + } else { + P1 = I611(0, 1, 5); + } +} break; +case 126 : +{ + P0 = IC(0); + P3 = IC(0); + if (MDL) { + P2 = IC(0); + } else { + P2 = I211(0, 3, 7); + } + if (MUR) { + P1 = IC(0); + } else { + P1 = I211(0, 1, 5); + } +} break; +case 127 : +{ + P3 = IC(4); + if (MDL) { + P2 = IC(4); + } else { + P2 = I211(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I211(4, 1, 5); + } +} break; +case 146 : +case 150 : +case 178 : +case 182 : +case 190 : +{ + P0 = IC(0); + P2 = IC(0); + if (MUR) { + P1 = IC(0); + P3 = IC(0); + } else { + P1 = I332(1, 5, 0); + P3 = I31(0, 5); + } +} break; +case 147 : +case 179 : +{ + P0 = IC(2); + P2 = IC(2); + P3 = IC(2); + if (MUR) { + P1 = IC(2); + } else { + P1 = I611(2, 1, 5); + } +} break; +case 151 : +case 183 : +{ + P0 = IC(3); + P2 = IC(3); + P3 = IC(3); + if (MUR) { + P1 = IC(3); + } else { + P1 = I1411(3, 1, 5); + } +} break; +case 158 : +{ + P2 = IC(0); + P3 = IC(0); + if (MUL) { + P0 = IC(0); + } else { + P0 = I611(0, 1, 3); + } + if (MUR) { + P1 = IC(0); + } else { + P1 = I211(0, 1, 5); + } +} break; +case 159 : +{ + P2 = IC(4); + P3 = IC(4); + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 191 : +{ + P2 = IC(4); + P3 = IC(4); + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 200 : +case 204 : +case 232 : +case 236 : +case 238 : +{ + P0 = IC(0); + P1 = IC(0); + if (MDL) { + P2 = IC(0); + P3 = IC(0); + } else { + P2 = I332(3, 7, 0); + P3 = I31(0, 7); + } +} break; +case 201 : +case 205 : +{ + P0 = IC(1); + P1 = IC(1); + P3 = IC(1); + if (MDL) { + P2 = IC(1); + } else { + P2 = I611(1, 3, 7); + } +} break; +case 211 : +{ + P0 = IC(2); + P1 = IC(2); + P2 = IC(2); + if (MDR) { + P3 = IC(2); + } else { + P3 = I211(2, 5, 7); + } +} break; +case 215 : +{ + P0 = IC(3); + P2 = IC(3); + if (MDR) { + P3 = IC(3); + } else { + P3 = I211(3, 5, 7); + } + if (MUR) { + P1 = IC(3); + } else { + P1 = I1411(3, 1, 5); + } +} break; +case 218 : +{ + if (MDL) { + P2 = IC(0); + } else { + P2 = I611(0, 3, 7); + } + if (MDR) { + P3 = IC(0); + } else { + P3 = I211(0, 5, 7); + } + if (MUL) { + P0 = IC(0); + } else { + P0 = I611(0, 1, 3); + } + if (MUR) { + P1 = IC(0); + } else { + P1 = I611(0, 1, 5); + } +} break; +case 219 : +{ + P1 = IC(2); + P2 = IC(2); + if (MDR) { + P3 = IC(2); + } else { + P3 = I211(2, 5, 7); + } + if (MUL) { + P0 = IC(2); + } else { + P0 = I211(2, 1, 3); + } +} break; +case 220 : +{ + P0 = IC(0); + P1 = IC(0); + if (MDL) { + P2 = IC(0); + } else { + P2 = I611(0, 3, 7); + } + if (MDR) { + P3 = IC(0); + } else { + P3 = I211(0, 5, 7); + } +} break; +case 223 : +{ + P2 = IC(4); + if (MDR) { + P3 = IC(4); + } else { + P3 = I211(4, 5, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I211(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; +case 233 : +case 237 : +{ + P0 = IC(1); + P1 = IC(1); + P3 = IC(1); + if (MDL) { + P2 = IC(1); + } else { + P2 = I1411(1, 3, 7); + } +} break; +case 234 : +{ + P1 = IC(0); + P3 = IC(0); + if (MDL) { + P2 = IC(0); + } else { + P2 = I211(0, 3, 7); + } + if (MUL) { + P0 = IC(0); + } else { + P0 = I611(0, 1, 3); + } +} break; +case 235 : +{ + P1 = IC(2); + P3 = IC(2); + if (MDL) { + P2 = IC(2); + } else { + P2 = I1411(2, 3, 7); + } + if (MUL) { + P0 = IC(2); + } else { + P0 = I211(2, 1, 3); + } +} break; +case 239 : +{ + P1 = IC(4); + P3 = IC(4); + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } +} break; +case 242 : +{ + P0 = IC(0); + P2 = IC(0); + if (MDR) { + P3 = IC(0); + } else { + P3 = I211(0, 5, 7); + } + if (MUR) { + P1 = IC(0); + } else { + P1 = I611(0, 1, 5); + } +} break; +case 243 : +{ + P0 = IC(2); + P1 = IC(2); + if (MDR) { + P2 = IC(2); + P3 = IC(2); + } else { + P2 = I31(2, 7); + P3 = I332(5, 7, 2); + } +} break; +case 244 : +{ + P0 = IC(0); + P1 = IC(0); + P2 = IC(0); + if (MDR) { + P3 = IC(0); + } else { + P3 = I1411(0, 5, 7); + } +} break; +case 245 : +{ + P0 = IC(1); + P1 = IC(1); + P2 = IC(1); + if (MDR) { + P3 = IC(1); + } else { + P3 = I1411(1, 5, 7); + } +} break; +case 246 : +{ + P0 = IC(0); + P2 = IC(0); + if (MDR) { + P3 = IC(0); + } else { + P3 = I1411(0, 5, 7); + } + if (MUR) { + P1 = IC(0); + } else { + P1 = I211(0, 1, 5); + } +} break; +case 247 : +{ + P0 = IC(3); + P2 = IC(3); + if (MDR) { + P3 = IC(3); + } else { + P3 = I1411(3, 5, 7); + } + if (MUR) { + P1 = IC(3); + } else { + P1 = I1411(3, 1, 5); + } +} break; +case 249 : +{ + P0 = IC(1); + P1 = IC(1); + if (MDL) { + P2 = IC(1); + } else { + P2 = I1411(1, 3, 7); + } + if (MDR) { + P3 = IC(1); + } else { + P3 = I211(1, 5, 7); + } +} break; +case 251 : +{ + P1 = IC(2); + if (MDL) { + P2 = IC(2); + } else { + P2 = I1411(2, 3, 7); + } + if (MDR) { + P3 = IC(2); + } else { + P3 = I211(2, 5, 7); + } + if (MUL) { + P0 = IC(2); + } else { + P0 = I211(2, 1, 3); + } +} break; +case 252 : +{ + P0 = IC(0); + P1 = IC(0); + if (MDL) { + P2 = IC(0); + } else { + P2 = I211(0, 3, 7); + } + if (MDR) { + P3 = IC(0); + } else { + P3 = I1411(0, 5, 7); + } +} break; +case 253 : +{ + P0 = IC(1); + P1 = IC(1); + if (MDL) { + P2 = IC(1); + } else { + P2 = I1411(1, 3, 7); + } + if (MDR) { + P3 = IC(1); + } else { + P3 = I1411(1, 5, 7); + } +} break; +case 254 : +{ + P0 = IC(0); + if (MDL) { + P2 = IC(0); + } else { + P2 = I211(0, 3, 7); + } + if (MDR) { + P3 = IC(0); + } else { + P3 = I1411(0, 5, 7); + } + if (MUR) { + P1 = IC(0); + } else { + P1 = I211(0, 1, 5); + } +} break; +case 255 : +{ + if (MDL) { + P2 = IC(4); + } else { + P2 = I1411(4, 3, 7); + } + if (MDR) { + P3 = IC(4); + } else { + P3 = I1411(4, 5, 7); + } + if (MUL) { + P0 = IC(4); + } else { + P0 = I1411(4, 1, 3); + } + if (MUR) { + P1 = IC(4); + } else { + P1 = I1411(4, 1, 5); + } +} break; diff --git a/jni/desmume/src/filter/scanline.cpp b/jni/desmume/src/filter/scanline.cpp new file mode 100755 index 0000000..b14055f --- /dev/null +++ b/jni/desmume/src/filter/scanline.cpp @@ -0,0 +1,119 @@ +/* Copyright (C) 2009 DeSmuME team + + This file is part of DeSmuME + + DeSmuME 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. + + DeSmuME 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 DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "filter.h" +#include "types.h" +#include <stdio.h> +#include <string.h> + +typedef u64 uint64; + +extern CACHE_ALIGN u16 fadeOutColors[17][0x8000]; + +extern int scanline_filter_a, scanline_filter_b; +static int fac_a, fac_b; + +FORCEINLINE void ScanLine16( uint16 *lpDst, uint16 *lpSrc, unsigned int Width){ + while(Width--){ + *lpDst++ = *lpSrc; + *lpDst++ = fadeOutColors[scanline_filter_a][(*lpSrc++)]; + } +} + +FORCEINLINE void ScanLine16_2( uint16 *lpDst, uint16 *lpSrc, unsigned int Width){ + while(Width--){ + *lpDst++ = fadeOutColors[scanline_filter_a][(*lpSrc)]; + *lpDst++ = fadeOutColors[scanline_filter_b][(*lpSrc++)]; + } +} + +FORCEINLINE void ScanLine32( uint32 *lpDst, uint32 *lpSrc, unsigned int Width){ + while(Width--){ + *lpDst++ = *lpSrc; + u8* u8dst = (u8*)lpDst; + u8* u8src = (u8*)lpSrc; + *u8dst++ = *u8src++ * fac_a / 16; + *u8dst++ = *u8src++ * fac_a / 16; + *u8dst++ = *u8src++ * fac_a / 16; + lpDst++; + lpSrc++; + } +} + +FORCEINLINE void ScanLine32_2( uint32 *lpDst, uint32 *lpSrc, unsigned int Width){ + while(Width--){ + u8* u8dst = (u8*)lpDst; + u8* u8src = (u8*)lpSrc; + *u8dst++ = *u8src++ * fac_a / 16; + *u8dst++ = *u8src++ * fac_a / 16; + *u8dst++ = *u8src++ * fac_a / 16; + u8dst++; + u8src = (u8*)lpSrc; + *u8dst++ = *u8src++ * fac_b / 16; + *u8dst++ = *u8src++ * fac_b / 16; + *u8dst++ = *u8src++ * fac_b / 16; + u8dst++; u8src++; + lpDst+=2; + lpSrc++; + } +} + + +FORCEINLINE void DoubleLine32( uint32 *lpDst, uint32 *lpSrc, unsigned int Width){ + while(Width--){ + *lpDst++ = *lpSrc; + *lpDst++ = *lpSrc++; + } +} + +void RenderScanline( SSurface Src, SSurface Dst) +{ + fac_a = (16-scanline_filter_a); + fac_b = (16-scanline_filter_b); + unsigned int H; + + const uint32 srcHeight = Src.Height; + + const unsigned int srcPitch = Src.Pitch >> 1; + u32* lpSrc = (u32*)Src.Surface; + + const unsigned int dstPitch = Dst.Pitch >> 1; + u32 *lpDst = (u32*)Dst.Surface; + for (H = 0; H < srcHeight; H++, lpSrc += srcPitch) + ScanLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + ScanLine32_2 (lpDst, lpSrc, Src.Width), lpDst += dstPitch; + //memset (lpDst, 0, 512*2), lpDst += dstPitch; +} + +void RenderNearest2X (SSurface Src, SSurface Dst) +{ + uint32 *lpSrc; + unsigned int H; + + const uint32 srcHeight = Src.Height; + + const unsigned int srcPitch = Src.Pitch >> 1; + lpSrc = reinterpret_cast<uint32 *>(Src.Surface); + + const unsigned int dstPitch = Dst.Pitch >> 1; + uint32 *lpDst = (uint32*)Dst.Surface; + for (H = 0; H < srcHeight; H++, lpSrc += srcPitch) + DoubleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + DoubleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch; +} diff --git a/jni/desmume/src/firmware.cpp b/jni/desmume/src/firmware.cpp new file mode 100755 index 0000000..9b88c73 --- /dev/null +++ b/jni/desmume/src/firmware.cpp @@ -0,0 +1,933 @@ +/* + Copyright (C) 2009-2011 DeSmuME Team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "firmware.h" +#include "NDSSystem.h" +#include "path.h" + +#define DWNUM(i) ((i) >> 2) + +bool CFIRMWARE::getKeyBuf() +{ + FILE *file = fopen(CommonSettings.ARM7BIOS, "rb"); + if (!file) return false; + + fseek(file, 0x30, SEEK_SET); + size_t res = fread(keyBuf, 4, 0x412, file); + fclose(file); + return (res == 0x412); +} + +void CFIRMWARE::crypt64BitUp(u32 *ptr) +{ + u32 Y = ptr[0]; + u32 X = ptr[1]; + + for(u32 i = 0x00; i <= 0x0F; i++) + { + u32 Z = (keyBuf[i] ^ X); + X = keyBuf[DWNUM(0x048 + (((Z >> 24) & 0xFF) << 2))]; + X = (keyBuf[DWNUM(0x448 + (((Z >> 16) & 0xFF) << 2))] + X); + X = (keyBuf[DWNUM(0x848 + (((Z >> 8) & 0xFF) << 2))] ^ X); + X = (keyBuf[DWNUM(0xC48 + ((Z & 0xFF) << 2))] + X); + X = (Y ^ X); + Y = Z; + } + + ptr[0] = (X ^ keyBuf[DWNUM(0x40)]); + ptr[1] = (Y ^ keyBuf[DWNUM(0x44)]); +} + +void CFIRMWARE::crypt64BitDown(u32 *ptr) +{ + u32 Y = ptr[0]; + u32 X = ptr[1]; + + for(u32 i = 0x11; i >= 0x02; i--) + { + u32 Z = (keyBuf[i] ^ X); + X = keyBuf[DWNUM(0x048 + (((Z >> 24) & 0xFF) << 2))]; + X = (keyBuf[DWNUM(0x448 + (((Z >> 16) & 0xFF) << 2))] + X); + X = (keyBuf[DWNUM(0x848 + (((Z >> 8) & 0xFF) << 2))] ^ X); + X = (keyBuf[DWNUM(0xC48 + ((Z & 0xFF) << 2))] + X); + X = (Y ^ X); + Y = Z; + } + + ptr[0] = (X ^ keyBuf[DWNUM(0x04)]); + ptr[1] = (Y ^ keyBuf[DWNUM(0x00)]); +} + +#define bswap32(val) (((val & 0x000000FF) << 24) | ((val & 0x0000FF00) << 8) | ((val & 0x00FF0000) >> 8) | ((val & 0xFF000000) >> 24)) +void CFIRMWARE::applyKeycode(u32 modulo) +{ + crypt64BitUp(&keyCode[1]); + crypt64BitUp(&keyCode[0]); + + u32 scratch[2] = {0x00000000, 0x00000000}; + + for(u32 i = 0; i <= 0x44; i += 4) + { + keyBuf[DWNUM(i)] = (keyBuf[DWNUM(i)] ^ bswap32(keyCode[DWNUM(i % modulo)])); + } + + for(u32 i = 0; i <= 0x1040; i += 8) + { + crypt64BitUp(scratch); + keyBuf[DWNUM(i)] = scratch[1]; + keyBuf[DWNUM(i+4)] = scratch[0]; + } +} +#undef bswap32 + +bool CFIRMWARE::initKeycode(u32 idCode, int level, u32 modulo) +{ + if(getKeyBuf() == FALSE) + return FALSE; + + keyCode[0] = idCode; + keyCode[1] = (idCode >> 1); + keyCode[2] = (idCode << 1); + + if(level >= 1) applyKeycode(modulo); + if(level >= 2) applyKeycode(modulo); + + keyCode[1] <<= 1; + keyCode[2] >>= 1; + + if(level >= 3) applyKeycode(modulo); + + return TRUE; +} + +u16 CFIRMWARE::getBootCodeCRC16() +{ + unsigned int i, j; + u32 crc = 0xFFFF; + const u16 val[8] = {0xC0C1, 0xC181, 0xC301, 0xC601, 0xCC01, 0xD801, 0xF001, 0xA001}; + + for(i = 0; i < size9; i++) + { + crc = (crc ^ tmp_data9[i]); + + for(j = 0; j < 8; j++) + { + if(crc & 0x0001) + crc = ((crc >> 1) ^ (val[j] << (7-j))); + else + crc = (crc >> 1); + } + } + + for(i = 0; i < size7; i++) + { + crc = (crc ^ tmp_data7[i]); + + for(j = 0; j < 8; j++) + { + if(crc & 0x0001) + crc = ((crc >> 1) ^ (val[j] << (7-j))); + else + crc = (crc >> 1); + } + } + + return (crc & 0xFFFF); +} + +u32 CFIRMWARE::decrypt(const u8 *in, u8* &out) +{ + u32 curBlock[2] = { 0 }; + u32 blockSize = 0; + u32 xLen = 0; + + u32 i = 0, j = 0; + u32 xIn = 4, xOut = 0; + u32 len = 0; + u32 offset = 0; + u32 windowOffset = 0; + u8 d = 0; + u16 data = 0; + + memcpy(curBlock, in, 8); + crypt64BitDown(curBlock); + blockSize = (curBlock[0] >> 8); + + if (blockSize == 0) return (0); + + out = new u8 [blockSize]; + if (!out ) return (0); + memset(out, 0xFF, blockSize); + + xLen = blockSize; + while(xLen > 0) + { + d = T1ReadByte((u8*)curBlock, (xIn % 8)); + xIn++; + if((xIn % 8) == 0) + { + memcpy(curBlock, in + xIn, 8); + crypt64BitDown(curBlock); + } + + for(i = 0; i < 8; i++) + { + if(d & 0x80) + { + data = (T1ReadByte((u8*)curBlock, (xIn % 8)) << 8); + xIn++; + if((xIn % 8) == 0) + { + memcpy(curBlock, in + xIn, 8); + crypt64BitDown(curBlock); + } + data |= T1ReadByte((u8*)curBlock, (xIn % 8)); + xIn++; + if((xIn % 8) == 0) + { + memcpy(curBlock, in + xIn, 8); + crypt64BitDown(curBlock); + } + + len = (data >> 12) + 3; + offset = (data & 0xFFF); + windowOffset = (xOut - offset - 1); + + for(j = 0; j < len; j++) + { + T1WriteByte(out, xOut, T1ReadByte(out, windowOffset)); + xOut++; + windowOffset++; + + xLen--; + if(xLen == 0) return (blockSize); + } + } + else + { + T1WriteByte(out, xOut, T1ReadByte((u8*)curBlock, (xIn % 8))); + xOut++; + xIn++; + if((xIn % 8) == 0) + { + memcpy(curBlock, in + xIn, 8); + crypt64BitDown(curBlock); + } + + xLen--; + if(xLen == 0) return (blockSize); + } + + d = ((d << 1) & 0xFF); + } + } + + return (blockSize); +} + +u32 CFIRMWARE::decompress(const u8 *in, u8* &out) +{ + u32 curBlock[2] = { 0 }; + u32 blockSize = 0; + u32 xLen = 0; + + u32 i = 0, j = 0; + u32 xIn = 4, xOut = 0; + u32 len = 0; + u32 offset = 0; + u32 windowOffset = 0; + u8 d = 0; + u16 data = 0; + + memcpy(curBlock, in, 8); + blockSize = (curBlock[0] >> 8); + + if (blockSize == 0) return (0); + + out = new u8 [blockSize]; + if (!out ) return (0); + memset(out, 0xFF, blockSize); + + xLen = blockSize; + while(xLen > 0) + { + d = T1ReadByte((u8*)curBlock, (xIn % 8)); + xIn++; + if((xIn % 8) == 0) + { + memcpy(curBlock, in + xIn, 8); + } + + for(i = 0; i < 8; i++) + { + if(d & 0x80) + { + data = (T1ReadByte((u8*)curBlock, (xIn % 8)) << 8); + xIn++; + if((xIn % 8) == 0) + { + memcpy(curBlock, in + xIn, 8); + } + data |= T1ReadByte((u8*)curBlock, (xIn % 8)); + xIn++; + if((xIn % 8) == 0) + { + memcpy(curBlock, in + xIn, 8); + } + + len = (data >> 12) + 3; + offset = (data & 0xFFF); + windowOffset = (xOut - offset - 1); + + for(j = 0; j < len; j++) + { + T1WriteByte(out, xOut, T1ReadByte(out, windowOffset)); + xOut++; + windowOffset++; + + xLen--; + if(xLen == 0) return (blockSize); + } + } + else + { + T1WriteByte(out, xOut, T1ReadByte((u8*)curBlock, (xIn % 8))); + xOut++; + xIn++; + if((xIn % 8) == 0) + { + memcpy(curBlock, in + xIn, 8); + } + + xLen--; + if(xLen == 0) return (blockSize); + } + + d = ((d << 1) & 0xFF); + } + } + + return (blockSize); +} +//================================================================================ +bool CFIRMWARE::load() +{ + u32 size = 0; + u8 *data = NULL; + u16 shift1 = 0, shift2 = 0, shift3 = 0, shift4 = 0; + u32 part1addr = 0, part2addr = 0, part3addr = 0, part4addr = 0, part5addr = 0; + u32 part1ram = 0, part2ram = 0; + + u32 src = 0; + + if (CommonSettings.UseExtFirmware == false) + return false; + if (strlen(CommonSettings.Firmware) == 0) + return false; + + FILE *fp = fopen(CommonSettings.Firmware, "rb"); + if (!fp) + return false; + fseek(fp, 0, SEEK_END); + size = ftell(fp); + fseek(fp, 0, SEEK_SET); + if( (size != 256*1024) && (size != 512*1024) ) + { + fclose(fp); + return false; + } + +#if 1 + if (size == 512*1024) + { + INFO("ERROR: 32Mbit (512Kb) firmware not supported\n"); + fclose(fp); + return false; + } +#endif + + data = new u8 [size]; + if (!data) + { + fclose(fp); + return false; + } + + if (fread(data, 1, size, fp) != size) + { + delete [] data; + fclose(fp); + return false; + } + + memcpy(&header, data, sizeof(header)); + if ((header.fw_identifier[0] != 'M') || + (header.fw_identifier[1] != 'A') || + (header.fw_identifier[2] != 'C')) + { + delete [] data; + fclose(fp); + return false; + } + + shift1 = ((header.shift_amounts >> 0) & 0x07); + shift2 = ((header.shift_amounts >> 3) & 0x07); + shift3 = ((header.shift_amounts >> 6) & 0x07); + shift4 = ((header.shift_amounts >> 9) & 0x07); + + // todo - add support for 512Kb + part1addr = (header.part1_rom_boot9_addr << (2 + shift1)); + part1ram = (0x02800000 - (header.part1_ram_boot9_addr << (2+shift2))); + part2addr = (header.part2_rom_boot7_addr << (2+shift3)); + part2ram = (0x03810000 - (header.part2_ram_boot7_addr << (2+shift4))); + part3addr = (header.part3_rom_gui9_addr << 3); + part4addr = (header.part4_rom_wifi7_addr << 3); + part5addr = (header.part5_data_gfx_addr << 3); + + ARM9bootAddr = part1ram; + ARM7bootAddr = part2ram; + + if(initKeycode(T1ReadLong(data, 0x08), 1, 0xC) == FALSE) + { + delete [] data; + fclose(fp); + return false; + } + +#if 0 + crypt64BitDown((u32*)&data[0x18]); +#else + // fix touch coords + data[0x18] = 0x00; + data[0x19] = 0x00; + data[0x1A] = 0x00; + data[0x1B] = 0x00; + + data[0x1C] = 0x00; + data[0x1D] = 0xFF; + data[0x1E] = 0x00; + data[0x1F] = 0x00; +#endif + + if(initKeycode(T1ReadLong(data, 0x08), 2, 0xC) == FALSE) + { + delete [] data; + fclose(fp); + return false; + } + + size9 = decrypt(data + part1addr, tmp_data9); + if (!tmp_data9) + { + delete [] data; + fclose(fp); + return false; + } + + size7 = decrypt(data + part2addr, tmp_data7); + if (!tmp_data7) + { + delete [] tmp_data9; + delete [] data; + fclose(fp); + return false; + } + + u16 crc16_mine = getBootCodeCRC16(); + + if (crc16_mine != header.part12_boot_crc16) + { + INFO("Firmware: ERROR: the boot code CRC16 (0x%04X) doesn't match the value in the firmware header (0x%04X)", crc16_mine, header.part12_boot_crc16); + delete [] tmp_data9; + delete [] tmp_data7; + delete [] data; + fclose(fp); + return false; + } + + // Copy firmware boot codes to their respective locations + src = 0; + for(u32 i = 0; i < (size9 >> 2); i++) + { + _MMU_write32<ARMCPU_ARM9>(part1ram, T1ReadLong(tmp_data9, src)); + src += 4; part1ram += 4; + } + + src = 0; + for(u32 i = 0; i < (size7 >> 2); i++) + { + _MMU_write32<ARMCPU_ARM7>(part2ram, T1ReadLong(tmp_data7, src)); + src += 4; part2ram += 4; + } + delete [] tmp_data7; + delete [] tmp_data9; + + patched = false; + if (data[0x17C] != 0xFF) + patched = true; + + INFO("Firmware:\n"); + INFO("- path: %s\n", CommonSettings.Firmware); + INFO("- size: %i bytes (%i Mbit)\n", size, size/1024/8); + INFO("- CRC : 0x%04X\n", header.part12_boot_crc16); + INFO("- header: \n"); + INFO(" * size firmware %i\n", ((header.shift_amounts >> 12) & 0xF) * 128 * 1024); + INFO(" * ARM9 boot code address: 0x%08X\n", part1addr); + INFO(" * ARM9 boot code RAM address: 0x%08X\n", ARM9bootAddr); + INFO(" * ARM9 unpacked size: 0x%08X (%i) bytes\n", size9, size9); + INFO(" * ARM9 GUI code address: 0x%08X\n", part3addr); + INFO("\n"); + INFO(" * ARM7 boot code address: 0x%08X\n", part2addr); + INFO(" * ARM7 boot code RAM address: 0x%08X\n", ARM7bootAddr); + INFO(" * ARM7 WiFi code address: 0x%08X\n", part4addr); + INFO(" * ARM7 unpacked size: 0x%08X (%i) bytes\n", size7, size7); + INFO("\n"); + INFO(" * Data/GFX address: 0x%08X\n", part5addr); + + if (patched) + { + u32 patch_offset = 0x3FC80; + if (data[0x17C] > 1) + patch_offset = 0x3F680; + + memcpy(&header, data + patch_offset, sizeof(header)); + + shift1 = ((header.shift_amounts >> 0) & 0x07); + shift2 = ((header.shift_amounts >> 3) & 0x07); + shift3 = ((header.shift_amounts >> 6) & 0x07); + shift4 = ((header.shift_amounts >> 9) & 0x07); + + // todo - add support for 512Kb + part1addr = (header.part1_rom_boot9_addr << (2 + shift1)); + part1ram = (0x02800000 - (header.part1_ram_boot9_addr << (2+shift2))); + part2addr = (header.part2_rom_boot7_addr << (2+shift3)); + part2ram = (0x03810000 - (header.part2_ram_boot7_addr << (2+shift4))); + + ARM9bootAddr = part1ram; + ARM7bootAddr = part2ram; + + size9 = decompress(data + part1addr, tmp_data9); + if (!tmp_data9) + { + delete [] data; + fclose(fp); + return false; + } + + size7 = decompress(data + part2addr, tmp_data7); + if (!tmp_data7) + { + delete [] tmp_data9; + delete [] data; + fclose(fp); + return false; + }; + // Copy firmware boot codes to their respective locations + src = 0; + for(u32 i = 0; i < (size9 >> 2); i++) + { + _MMU_write32<ARMCPU_ARM9>(part1ram, T1ReadLong(tmp_data9, src)); + src += 4; part1ram += 4; + } + + src = 0; + for(u32 i = 0; i < (size7 >> 2); i++) + { + _MMU_write32<ARMCPU_ARM7>(part2ram, T1ReadLong(tmp_data7, src)); + src += 4; part2ram += 4; + } + delete [] tmp_data7; + delete [] tmp_data9; + + INFO("\nFlashme:\n"); + INFO("- header: \n"); + INFO(" * ARM9 boot code address: 0x%08X\n", part1addr); + INFO(" * ARM9 boot code RAM address: 0x%08X\n", ARM9bootAddr); + INFO(" * ARM9 unpacked size: 0x%08X (%i) bytes\n", size9, size9); + INFO("\n"); + INFO(" * ARM7 boot code address: 0x%08X\n", part2addr); + INFO(" * ARM7 boot code RAM address: 0x%08X\n", ARM7bootAddr); + INFO(" * ARM7 unpacked size: 0x%08X (%i) bytes\n", size7, size7); + } + + // Generate the path for the external firmware config file. + std::string extFilePath = CFIRMWARE::GetExternalFilePath(); + strncpy(MMU.fw.userfile, extFilePath.c_str(), MAX_PATH); + + fclose(fp); + fp = fopen(MMU.fw.userfile, "rb"); + if (fp) + { + char buf[0x300]; + memset(buf, 0, 0x300); + if (fread(buf, 1, 0x100, fp) == 0x100) + { + printf("- loaded from %s:\n", MMU.fw.userfile); + memcpy(&data[0x3FE00], &buf[0], 0x100); + memcpy(&data[0x3FF00], &buf[0], 0x100); + printf(" * User settings\n"); + memset(buf, 0, 0x100); + if (fread(buf, 1, 0x1D6, fp) == 0x1D6) + { + memcpy(&data[0x002A], &buf[0], 0x1D6); + printf(" * WiFi settings\n"); + + memset(buf, 0, 0x1D6); + if (fread(buf, 1, 0x300, fp) == 0x300) + { + memcpy(&data[0x3FA00], &buf[0], 0x300); + printf(" * WiFi AP settings\n"); + } + } + + } + fclose(fp); + } + printf("\n"); + + // TODO: add 512Kb support + memcpy(MMU.fw.data, data, 256*1024); + MMU.fw.fp = NULL; + + delete [] data; data = NULL; + return true; +} + +std::string CFIRMWARE::GetExternalFilePath() +{ + std::string fwPath = CommonSettings.Firmware; + std::string fwFileName = Path::GetFileNameFromPathWithoutExt(fwPath); + std::string configPath = path.pathToBattery; + std::string finalPath = configPath + DIRECTORY_DELIMITER_CHAR + fwFileName + FILE_EXT_DELIMITER_CHAR + FW_CONFIG_FILE_EXT; + + return finalPath; +} + +//===================================================================================================== +static u32 +calc_CRC16( u32 start, const u8 *data, int count) { + int i,j; + u32 crc = start & 0xffff; + const u16 val[8] = { 0xC0C1,0xC181,0xC301,0xC601,0xCC01,0xD801,0xF001,0xA001 }; + for(i = 0; i < count; i++) + { + crc = crc ^ data[i]; + + for(j = 0; j < 8; j++) { + int do_bit = 0; + + if ( crc & 0x1) + do_bit = 1; + + crc = crc >> 1; + + if ( do_bit) { + crc = crc ^ (val[j] << (7-j)); + } + } + } + return crc; +} + +int copy_firmware_user_data( u8 *dest_buffer, const u8 *fw_data) +{ + /* + * Determine which of the two user settings in the firmware is the current + * and valid one and then copy this into the destination buffer. + * + * The current setting will have a greater count. + * Settings are only valid if its CRC16 is correct. + */ + int user1_valid = 0; + int user2_valid = 0; + u32 user_settings_offset; + u32 fw_crc; + u32 crc; + int copy_good = 0; + + user_settings_offset = fw_data[0x20]; + user_settings_offset |= fw_data[0x21] << 8; + user_settings_offset <<= 3; + + if ( user_settings_offset <= 0x3FE00) { + s32 copy_settings_offset = -1; + + crc = calc_CRC16( 0xffff, &fw_data[user_settings_offset], + NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT); + fw_crc = fw_data[user_settings_offset + 0x72]; + fw_crc |= fw_data[user_settings_offset + 0x73] << 8; + if ( crc == fw_crc) { + user1_valid = 1; + } + + crc = calc_CRC16( 0xffff, &fw_data[user_settings_offset + 0x100], + NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT); + fw_crc = fw_data[user_settings_offset + 0x100 + 0x72]; + fw_crc |= fw_data[user_settings_offset + 0x100 + 0x73] << 8; + if ( crc == fw_crc) { + user2_valid = 1; + } + + if ( user1_valid) { + if ( user2_valid) { + u16 count1, count2; + + count1 = fw_data[user_settings_offset + 0x70]; + count1 |= fw_data[user_settings_offset + 0x71] << 8; + + count2 = fw_data[user_settings_offset + 0x100 + 0x70]; + count2 |= fw_data[user_settings_offset + 0x100 + 0x71] << 8; + + if ( count2 > count1) { + copy_settings_offset = user_settings_offset + 0x100; + } + else { + copy_settings_offset = user_settings_offset; + } + } + else { + copy_settings_offset = user_settings_offset; + } + } + else if ( user2_valid) { + /* copy the second user settings */ + copy_settings_offset = user_settings_offset + 0x100; + } + + if ( copy_settings_offset > 0) { + memcpy( dest_buffer, &fw_data[copy_settings_offset], + NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT); + copy_good = 1; + } + } + + return copy_good; +} + +static void fill_user_data_area( struct NDS_fw_config_data *user_settings,u8 *data, int count) +{ + u32 crc; + int i; + u8 *ts_cal_data_area; + + memset( data, 0, 0x100); + + // version + data[0x00] = 5; + data[0x01] = 0; + + // colour + data[0x02] = user_settings->fav_colour; + + // birthday month and day + data[0x03] = user_settings->birth_month; + data[0x04] = user_settings->birth_day; + + //nickname and length + for ( i = 0; i < MAX_FW_NICKNAME_LENGTH; i++) { + data[0x06 + (i * 2)] = user_settings->nickname[i] & 0xff; + data[0x06 + (i * 2) + 1] = (user_settings->nickname[i] >> 8) & 0xff; + } + + data[0x1a] = user_settings->nickname_len; + + //Message + for ( i = 0; i < MAX_FW_MESSAGE_LENGTH; i++) { + data[0x1c + (i * 2)] = user_settings->message[i] & 0xff; + data[0x1c + (i * 2) + 1] = (user_settings->message[i] >> 8) & 0xff; + } + + data[0x50] = user_settings->message_len; + + //touch screen calibration + ts_cal_data_area = &data[0x58]; + for ( i = 0; i < 2; i++) { + // ADC x y + *ts_cal_data_area++ = user_settings->touch_cal[i].adc_x & 0xff; + *ts_cal_data_area++ = (user_settings->touch_cal[i].adc_x >> 8) & 0xff; + *ts_cal_data_area++ = user_settings->touch_cal[i].adc_y & 0xff; + *ts_cal_data_area++ = (user_settings->touch_cal[i].adc_y >> 8) & 0xff; + + //screen x y + *ts_cal_data_area++ = user_settings->touch_cal[i].screen_x; + *ts_cal_data_area++ = user_settings->touch_cal[i].screen_y; + } + + //language and flags + data[0x64] = user_settings->language; + data[0x65] = 0xfc; + + //update count and crc + data[0x70] = count & 0xff; + data[0x71] = (count >> 8) & 0xff; + + crc = calc_CRC16( 0xffff, data, 0x70); + data[0x72] = crc & 0xff; + data[0x73] = (crc >> 8) & 0xff; + + memset( &data[0x74], 0xff, 0x100 - 0x74); +} + +// creates an firmware flash image, which contains all needed info to initiate a wifi connection +int NDS_CreateDummyFirmware( struct NDS_fw_config_data *user_settings) +{ + //Create the firmware header + + memset( MMU.fw.data, 0, 0x40000); + + //firmware identifier + MMU.fw.data[0x8] = 'M'; + MMU.fw.data[0x8 + 1] = 'A'; + MMU.fw.data[0x8 + 2] = 'C'; + MMU.fw.data[0x8 + 3] = 'P'; + + // DS type + if ( user_settings->ds_type == NDS_CONSOLE_TYPE_LITE) + MMU.fw.data[0x1d] = 0x20; + else + MMU.fw.data[0x1d] = 0xff; + + //User Settings offset 0x3fe00 / 8 + MMU.fw.data[0x20] = 0xc0; + MMU.fw.data[0x21] = 0x7f; + + + //User settings (at 0x3FE00 and 0x3FF00) + + fill_user_data_area( user_settings, &MMU.fw.data[ 0x3FE00], 0); + fill_user_data_area( user_settings, &MMU.fw.data[ 0x3FF00], 1); + + // Wifi config length + MMU.fw.data[0x2C] = 0x38; + MMU.fw.data[0x2D] = 0x01; + + MMU.fw.data[0x2E] = 0x00; + + //Wifi version + MMU.fw.data[0x2F] = 0x00; + + //MAC address + memcpy((MMU.fw.data + 0x36), FW_Mac, sizeof(FW_Mac)); + + //Enabled channels + MMU.fw.data[0x3C] = 0xFE; + MMU.fw.data[0x3D] = 0x3F; + + MMU.fw.data[0x3E] = 0xFF; + MMU.fw.data[0x3F] = 0xFF; + + //RF related + MMU.fw.data[0x40] = 0x02; + MMU.fw.data[0x41] = 0x18; + MMU.fw.data[0x42] = 0x0C; + + MMU.fw.data[0x43] = 0x01; + + //Wifi I/O init values + memcpy((MMU.fw.data + 0x44), FW_WIFIInit, sizeof(FW_WIFIInit)); + + //Wifi BB init values + memcpy((MMU.fw.data + 0x64), FW_BBInit, sizeof(FW_BBInit)); + + //Wifi RF init values + memcpy((MMU.fw.data + 0xCE), FW_RFInit, sizeof(FW_RFInit)); + + //Wifi channel-related init values + memcpy((MMU.fw.data + 0xF2), FW_RFChannel, sizeof(FW_RFChannel)); + memcpy((MMU.fw.data + 0x146), FW_BBChannel, sizeof(FW_BBChannel)); + memset((MMU.fw.data + 0x154), 0x10, 0xE); + + //WFC profiles + memcpy((MMU.fw.data + 0x3FA40), &FW_WFCProfile1, sizeof(FW_WFCProfile)); + memcpy((MMU.fw.data + 0x3FB40), &FW_WFCProfile2, sizeof(FW_WFCProfile)); + memcpy((MMU.fw.data + 0x3FC40), &FW_WFCProfile3, sizeof(FW_WFCProfile)); + (*(u16*)(MMU.fw.data + 0x3FAFE)) = (u16)calc_CRC16(0, (MMU.fw.data + 0x3FA00), 0xFE); + (*(u16*)(MMU.fw.data + 0x3FBFE)) = (u16)calc_CRC16(0, (MMU.fw.data + 0x3FB00), 0xFE); + (*(u16*)(MMU.fw.data + 0x3FCFE)) = (u16)calc_CRC16(0, (MMU.fw.data + 0x3FC00), 0xFE); + + + MMU.fw.data[0x162] = 0x19; + memset((MMU.fw.data + 0x163), 0xFF, 0x9D); + + //Wifi settings CRC16 + (*(u16*)(MMU.fw.data + 0x2A)) = calc_CRC16(0, (MMU.fw.data + 0x2C), 0x138); + + if (&CommonSettings.InternalFirmConf != user_settings) + memcpy(&CommonSettings.InternalFirmConf, user_settings, sizeof(struct NDS_fw_config_data)); + + return TRUE ; +} + +void NDS_FillDefaultFirmwareConfigData( struct NDS_fw_config_data *fw_config) { + const char *default_nickname = "DeSmuME"; + const char *default_message = "DeSmuME makes you happy!"; + int i; + int str_length; + + memset( fw_config, 0, sizeof( struct NDS_fw_config_data)); + fw_config->ds_type = NDS_CONSOLE_TYPE_FAT; + + fw_config->fav_colour = 7; + + fw_config->birth_day = 23; + fw_config->birth_month = 6; + + str_length = strlen( default_nickname); + for ( i = 0; i < str_length; i++) { + fw_config->nickname[i] = default_nickname[i]; + } + fw_config->nickname_len = str_length; + + str_length = strlen( default_message); + for ( i = 0; i < str_length; i++) { + fw_config->message[i] = default_message[i]; + } + fw_config->message_len = str_length; + + //default to English + fw_config->language = 1; + + // default touchscreen calibration + + //ANCIENT DESMUME VALUES + fw_config->touch_cal[0].adc_x = 0x200; + fw_config->touch_cal[0].adc_y = 0x200; + fw_config->touch_cal[0].screen_x = 0x20 + 1; // calibration screen coords are 1-based, + fw_config->touch_cal[0].screen_y = 0x20 + 1; // either that or NDS_getADCTouchPosX/Y are wrong. + //VALUES FROM NOCASH + //fw_config->touch_cal[0].adc_x = 0x02DF; + //fw_config->touch_cal[0].adc_y = 0x032C; + //fw_config->touch_cal[0].screen_x = 0x20; + //fw_config->touch_cal[0].screen_y = 0x20; + + //ANCIENT DESMUME VALUES + fw_config->touch_cal[1].adc_x = 0xe00; + fw_config->touch_cal[1].adc_y = 0x800; + fw_config->touch_cal[1].screen_x = 0xe0 + 1; + fw_config->touch_cal[1].screen_y = 0x80 + 1; + //VALUES FROM NOCASH + //fw_config->touch_cal[1].adc_x = 0x0D3B; + //fw_config->touch_cal[1].adc_y = 0x0CE7; + //fw_config->touch_cal[1].screen_x = 0xE0; + //fw_config->touch_cal[1].screen_y = 0xA0; +} + +void NDS_PatchFirmwareMAC() +{ + memcpy((MMU.fw.data + 0x36), FW_Mac, sizeof(FW_Mac)); + (*(u16*)(MMU.fw.data + 0x2A)) = calc_CRC16(0, (MMU.fw.data + 0x2C), 0x138); +} diff --git a/jni/desmume/src/firmware.h b/jni/desmume/src/firmware.h new file mode 100755 index 0000000..e007521 --- /dev/null +++ b/jni/desmume/src/firmware.h @@ -0,0 +1,88 @@ +/* + Copyright (C) 2009-2011 DeSmuME Team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _FIRMWARE_H_ +#define _FIRMWARE_H_ +#include "common.h" + +// the count of bytes copied from the firmware into memory +#define NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT 0x70 + +#define FW_CONFIG_FILE_EXT "dfc" + +class CFIRMWARE +{ +private: + u8 *tmp_data9; + u8 *tmp_data7; + u32 size9, size7; + + u32 keyBuf[0x412]; + u32 keyCode[3]; + + bool getKeyBuf(); + void crypt64BitUp(u32 *ptr); + void crypt64BitDown(u32 *ptr); + void applyKeycode(u32 modulo); + bool initKeycode(u32 idCode, int level, u32 modulo); + u16 getBootCodeCRC16(); + u32 decrypt(const u8 *in, u8* &out); + u32 decompress(const u8 *in, u8* &out); + +public: + CFIRMWARE(): size9(0), size7(0), ARM9bootAddr(0), ARM7bootAddr(0), patched(0) {}; + + bool load(); + + static std::string GetExternalFilePath(); + + struct HEADER + { + u16 part3_rom_gui9_addr; // 000h + u16 part4_rom_wifi7_addr; // 002h + u16 part34_gui_wifi_crc16; // 004h + u16 part12_boot_crc16; // 006h + u8 fw_identifier[4]; // 008h + u16 part1_rom_boot9_addr; // 00Ch + u16 part1_ram_boot9_addr; // 00Eh + u16 part2_rom_boot7_addr; // 010h + u16 part2_ram_boot7_addr; // 012h + u16 shift_amounts; // 014h + u16 part5_data_gfx_addr; // 016h + + u8 fw_timestamp[5]; // 018h + u8 console_type; // 01Dh + u16 unused1; // 01Eh + u16 user_settings_offset; // 020h + u16 unknown1; // 022h + u16 unknown2; // 024h + u16 part5_crc16; // 026h + u16 unused2; // 028h - FFh filled + } header; + + u32 ARM9bootAddr; + u32 ARM7bootAddr; + bool patched; +}; + +int copy_firmware_user_data( u8 *dest_buffer, const u8 *fw_data); +int NDS_CreateDummyFirmware( struct NDS_fw_config_data *user_settings); +void NDS_FillDefaultFirmwareConfigData( struct NDS_fw_config_data *fw_config); +void NDS_PatchFirmwareMAC(); + +#endif + diff --git a/jni/desmume/src/fs-linux.cpp b/jni/desmume/src/fs-linux.cpp new file mode 100755 index 0000000..27039d9 --- /dev/null +++ b/jni/desmume/src/fs-linux.cpp @@ -0,0 +1,118 @@ +/* Copyright (C) 2006 Guillaume Duhamel + + This file is part of DeSmuME + + DeSmuME 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. + + DeSmuME 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 DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "fs.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <dirent.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +typedef struct { + DIR * dir; + char * path; +} FsLinuxDir; + +const char FS_SEPARATOR = '/'; + +void * FsReadFirst(const char * path, FsEntry * entry) { + FsLinuxDir * dir; + struct dirent * e; + struct stat s; + char buffer[512+1]; /* DirSpec[256] + '/' + dirent.d_name[256] */ + DIR * tmp; + + dir = (FsLinuxDir*)malloc(sizeof(FsLinuxDir)); + if (!dir) + return NULL; + + tmp = opendir(path); + if (!tmp) { + free(dir); + return NULL; + } + dir->dir = tmp; + + e = readdir(tmp); + if (!e) { + closedir(tmp); + free(dir); + return NULL; + } + strcpy(entry->cFileName, e->d_name); + // there's no 8.3 file names support on linux :) + strcpy(entry->cAlternateFileName, ""); + entry->flags = 0; + + dir->path = strdup(path); + sprintf(buffer, "%s/%s", dir->path, e->d_name); + + stat(buffer, &s); + if (S_ISDIR(s.st_mode)) { + entry->flags = FS_IS_DIR; + entry->fileSize = 0; + } else { + entry->fileSize = s.st_size; + } + + return dir; +} + +int FsReadNext(void * search, FsEntry * entry) { + FsLinuxDir * dir = (FsLinuxDir*)search; + struct dirent * e; + struct stat s; + char buffer[1024]; + + e = readdir(dir->dir); + if (!e) + return 0; + + strcpy(entry->cFileName, e->d_name); + // there's no 8.3 file names support on linux :) + strcpy(entry->cAlternateFileName, ""); + entry->flags = 0; + + sprintf(buffer, "%s/%s", dir->path, e->d_name); + + stat(buffer, &s); + if (S_ISDIR(s.st_mode)) { + entry->flags = FS_IS_DIR; + entry->fileSize = 0; + } else { + entry->fileSize = s.st_size; + } + + return 1; +} + +void FsClose(void * search) { + FsLinuxDir *linuxdir = (FsLinuxDir *) search; + DIR * dir = linuxdir->dir; + + closedir(dir); + free(linuxdir->path); + free(search); +} + +int FsError(void) { + return 0; +} diff --git a/jni/desmume/src/fs-windows.cpp b/jni/desmume/src/fs-windows.cpp new file mode 100755 index 0000000..0be1ad5 --- /dev/null +++ b/jni/desmume/src/fs-windows.cpp @@ -0,0 +1,89 @@ +/* + Copyright (C) 2006 Guillaume Duhamel + Copyright (C) 2006-2009 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "fs.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <windows.h> + +const char FS_SEPARATOR = '\\'; + +void * FsReadFirst(const char * p, FsEntry * entry) { + WIN32_FIND_DATA FindFileData; + HANDLE hFind; + HANDLE * ret; + char path[1024]; + if (strlen(p)+3 >sizeof(path)) return NULL ; + + sprintf(path, "%s\\*", p); + + hFind = FindFirstFile(path, &FindFileData); + if (hFind == INVALID_HANDLE_VALUE) + return NULL; + + strncpy(entry->cFileName, FindFileData.cFileName,256); + entry->cFileName[255] = 0 ; + strncpy(entry->cAlternateFileName, FindFileData.cAlternateFileName,14); + entry->cAlternateFileName[13] = 0 ; + entry->flags = 0; + if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + entry->flags = FS_IS_DIR; + entry->fileSize = 0; + } else { + entry->fileSize = FindFileData.nFileSizeLow; + } + + ret = (void**)malloc(sizeof(HANDLE)); + *ret = hFind; + return ret; +} + +int FsReadNext(void * search, FsEntry * entry) { + WIN32_FIND_DATA FindFileData; + HANDLE * h = (HANDLE *) search; + int ret; + + ret = FindNextFile(*h, &FindFileData); + + strncpy(entry->cFileName, FindFileData.cFileName,256); + entry->cFileName[255] = 0 ; + strncpy(entry->cAlternateFileName, FindFileData.cAlternateFileName,14); + entry->cAlternateFileName[13] = 0 ; + entry->flags = 0; + if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + entry->flags = FS_IS_DIR; + entry->fileSize = 0; + } else { + entry->fileSize = FindFileData.nFileSizeLow; + } + + return ret; +} + +void FsClose(void * search) { + FindClose(*((HANDLE *) search)); +} + +int FsError(void) { + if (GetLastError() == ERROR_NO_MORE_FILES) + return FS_ERR_NO_MORE_FILES; + + return FS_ERR_UNKNOWN; +} diff --git a/jni/desmume/src/fs.h b/jni/desmume/src/fs.h new file mode 100755 index 0000000..bfa8c5b --- /dev/null +++ b/jni/desmume/src/fs.h @@ -0,0 +1,43 @@ +/* + Copyright (C) 2006 Guillaume Duhamel + Copyright (C) 2007-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef FS_H +#define FS_H + +#include "types.h" + +#define FS_IS_DIR 1 + +#define FS_ERR_UNKNOWN -1 +#define FS_ERR_NO_MORE_FILES 1 + +extern const char FS_SEPARATOR; + +typedef struct { + char cFileName[256]; + char cAlternateFileName[14]; + u32 flags; + u32 fileSize; +} FsEntry; + +void * FsReadFirst(const char * path, FsEntry * entry); +int FsReadNext(void * search, FsEntry * entry); +void FsClose(void * search); +int FsError(void); + +#endif diff --git a/jni/desmume/src/gdbstub.h b/jni/desmume/src/gdbstub.h new file mode 100755 index 0000000..9ec5b9a --- /dev/null +++ b/jni/desmume/src/gdbstub.h @@ -0,0 +1,54 @@ +/* + Copyright (C) 2006 Ben Jaques + Copyright (C) 2008-2009 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _GDBSTUB_H_ +#define _GDBSTUB_H_ 1 + +#include "types.h" + +typedef void *gdbstub_handle_t; + +/* + * The function interface + */ + +gdbstub_handle_t +createStub_gdb( u16 port, + struct armcpu_memory_iface **cpu_memio, + struct armcpu_memory_iface *direct_memio); + +void +destroyStub_gdb( gdbstub_handle_t stub); + +void +activateStub_gdb( gdbstub_handle_t stub, + struct armcpu_ctrl_iface *cpu_ctrl); + + /* + * An implementation of the following functions is required + * for the GDB stub to function. + */ +void * +createThread_gdb( void (WINAPI *thread_function)( void *data), + void *thread_data); + +void +joinThread_gdb( void *thread_handle); + +#endif /* End of _GDBSTUB_H_ */ + diff --git a/jni/desmume/src/gfx3d.cpp b/jni/desmume/src/gfx3d.cpp new file mode 100755 index 0000000..b9953c0 --- /dev/null +++ b/jni/desmume/src/gfx3d.cpp @@ -0,0 +1,2905 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2008-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +//This file implements the geometry engine hardware component. +//This handles almost all of the work of 3d rendering, leaving the renderer +//plugin responsible only for drawing primitives. + +//#define FLUSHMODE_HACK + +//--------------- +//TODO TODO TODO TODO +//make up mind once and for all whether fog, toon, etc. should reside in memory buffers (for easier handling in MMU) +//if they do, then we need to copy them out in doFlush!!! +//--------------- + +#include <algorithm> +#include <assert.h> +#include <math.h> +#include <string.h> +#include "armcpu.h" +#include "debug.h" +#include "gfx3d.h" +#include "matrix.h" +#include "bits.h" +#include "MMU.h" +#include "render3D.h" +#include "mem.h" +#include "types.h" +#include "saves.h" +#include "NDSSystem.h" +#include "readwrite.h" +#include "FIFO.h" +#include "movie.h" //only for currframecounter which really ought to be moved into the core emu.... +#include <queue> + +//#define _SHOW_VTX_COUNTERS // show polygon/vertex counters on screen +#ifdef _SHOW_VTX_COUNTERS +u32 max_polys, max_verts; +#include "GPU_OSD.h" +#endif + + +/* +thoughts on flush timing: +I think a flush is supposed to queue up and wait to happen during vblank sometime. +But, we have some games that continue to do work after a flush but before a vblank. +Since our timing is bad anyway, and we're not sure when the flush is really supposed to happen, +then this leaves us in a bad situation. +What makes it worse is that if flush is supposed to be deferred, then we have to queue these +errant geometry commands. That would require a better gxfifo we have now, and some mechanism to block +while the geometry engine is stalled (which doesnt exist). +Since these errant games are nevertheless using flush command to represent the end of a frame, we deem this +a good time to execute an actual flush. +I think we originally didnt do this because we found some game that it glitched, but that may have been +resolved since then by deferring actual rendering to the next vcount=0 (giving textures enough time to upload). +But since we're not sure how we'll eventually want this, I am leaving it sort of reconfigurable, doing all the work +in this function: */ +static void gfx3d_doFlush(); + +#define GFX_NOARG_COMMAND 0x00 +#define GFX_INVALID_COMMAND 0xFF +#define GFX_UNDEFINED_COMMAND 0xCC +static const u8 gfx3d_commandTypes[] = { + /* 00 */ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, //invalid commands; no parameters + /* 10 */ 0x01,0x00,0x01,0x01,0x01,0x00,0x10,0x0C, 0x10,0x0C,0x09,0x03,0x03,0xCC,0xCC,0xCC, //matrix commands + /* 20 */ 0x01,0x01,0x01,0x02,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0xCC,0xCC,0xCC,0xCC, //vertex and per-vertex material commands + /* 30 */ 0x01,0x01,0x01,0x01,0x20,0xCC,0xCC,0xCC, 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, //lighting engine material commands + /* 40 */ 0x01,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, //begin and end + /* 50 */ 0x01,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, //swapbuffers + /* 60 */ 0x01,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, //viewport + /* 70 */ 0x03,0x02,0x01,0xCC,0xCC,0xCC,0xCC,0xCC, 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, //tests + //0x80: + /* 80 */ 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, + /* 90 */ 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, + /* A0 */ 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, + /* B0 */ 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, + /* C0 */ 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, + /* D0 */ 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, + /* E0 */ 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, + /* F0 */ 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC +}; + +class GXF_Hardware +{ +public: + GXF_Hardware() + { + reset(); + } + void reset() { + countdown = 0; + commandCursor = 4; + for(int i=0;i<4;i++) { + commandsPending[i].command = 0; + commandsPending[i].countdown = 0; + } + size = 0; + } + + void receive(u32 val) + { + if (size > 0) + { + GFX_FIFOsend(front().command, val); + front().countdown--; + if (front().countdown == 0) + { + size--; + if (size == 0) return; + dequeue(); + + while (gfx3d_commandTypes[front().command] == GFX_NOARG_COMMAND) + { + GFX_FIFOsend(front().command, 0); + size--; + if (size == 0) break; + dequeue(); + } + } + } + else + { + if (val == 0) return; // nop + + const u8 commands[] = { val&0xFF, (val>>8)&0xFF, (val>>16)&0xFF, (val>>24)&0xFF }; + const u8 commandTypes[] = { gfx3d_commandTypes[commands[0]], gfx3d_commandTypes[commands[1]], gfx3d_commandTypes[commands[2]], gfx3d_commandTypes[commands[3]] }; + + commandCursor = 0; + size = 0; + + // A “command without parameters” is one of the four following commands: + // - PushMatrix + // - LoadIdentity + // - End + // - Commands undefined within the region between 0x10 and 0xFF + + for (u8 i = 0; i < 4; i++) + { + if (commandTypes[i] == GFX_INVALID_COMMAND) + { + //printf("gfx3D: invalid command (%02X)\n", commands[i]); + continue; + } + + if (commandTypes[i] == GFX_UNDEFINED_COMMAND) + { + //printf("gfx3D: undefined command (%02X)\n", commands[i]); + continue; + } + commandsPending[size].command = commands[i]; + commandsPending[size].countdown = commandTypes[i]; + //printf("%i: CMD %02X size %i\n", i, commands[i], commandsPending[size].countdown); + if ((commandsPending[size].countdown == 0) && (size == 0)) // cmd 0x11, 0x15, 0x41 - no params + { + GFX_FIFOsend(commands[i], 0); + + while ((i < 4) && commands[i+1] != 0 && gfx3d_commandTypes[commands[i+1]] == GFX_NOARG_COMMAND) + GFX_FIFOsend(commands[++i], 0); + } + else + size++; + } + } + } + + struct CommandItem { + u8 command, countdown; + } commandsPending[4]; + + u32 commandCursor; + u8 countdown; + +private: + void dequeue() { commandCursor++; } + CommandItem& front() { return commandsPending[commandCursor]; } + u32 size; +public: + + void savestate(EMUFILE *f) + { + //TODO - next time we invalidate savestates, simplify this format. + write32le(1,f); //version + write32le(size,f); + write32le(commandCursor,f); + for(u32 i=0;i<4;i++) write8le(commandsPending[i].command,f); + for(u32 i=0;i<4;i++) write8le(commandsPending[i].countdown,f); + write8le(countdown,f); + } + + bool loadstate(EMUFILE *f) + { + u32 version; + if(read32le(&version,f) != 1) return false; + if(version > 1) return false; + + if (version == 0) + { + read32le(&size,f); + commandCursor = 4-size; + for(u32 i=commandCursor;i<4;i++) read8le(&commandsPending[i-commandCursor].command,f); + read32le(&size,f); + size = 4-commandCursor; + for(u32 i=commandCursor;i<4;i++) read8le(&commandsPending[i-commandCursor].countdown,f); + } + else + if (version == 1) + { + read32le(&size,f); + read32le(&commandCursor,f); + for(u32 i=0;i<4;i++) read8le(&commandsPending[i].command,f); + for(u32 i=0;i<4;i++) read8le(&commandsPending[i].countdown,f); + } + + read8le(&countdown,f); + + return true; + } + +} gxf_hardware; + +//these were 4 for the longest time (this is MUCH, MUCH less than their theoretical values) +//but it was changed to 1 for strawberry shortcake, which was issuing direct commands +//while the fifo was full, apparently expecting the fifo not to be full by that time. +//in general we are finding that 3d takes less time than we think.... +//although maybe the true culprit was charging the cpu less time for the dma. +#define GFX_DELAY(x) NDS_RescheduleGXFIFO(1); +#define GFX_DELAY_M2(x) NDS_RescheduleGXFIFO(1); + +using std::max; +using std::min; + +GFX3D gfx3d; +Viewer3d_State* viewer3d_state = NULL; +static GFX3D_Clipper boxtestClipper; + +//tables that are provided to anyone +CACHE_ALIGN u32 color_15bit_to_24bit_reverse[32768]; +CACHE_ALIGN u32 color_15bit_to_24bit[32768]; +CACHE_ALIGN u16 color_15bit_to_16bit_reverse[32768]; +CACHE_ALIGN u8 mixTable555[32][32][32]; + +//is this a crazy idea? this table spreads 5 bits evenly over 31 from exactly 0 to INT_MAX +CACHE_ALIGN const int material_5bit_to_31bit[] = { + 0x00000000, 0x04210842, 0x08421084, 0x0C6318C6, + 0x10842108, 0x14A5294A, 0x18C6318C, 0x1CE739CE, + 0x21084210, 0x25294A52, 0x294A5294, 0x2D6B5AD6, + 0x318C6318, 0x35AD6B5A, 0x39CE739C, 0x3DEF7BDE, + 0x42108421, 0x46318C63, 0x4A5294A5, 0x4E739CE7, + 0x5294A529, 0x56B5AD6B, 0x5AD6B5AD, 0x5EF7BDEF, + 0x6318C631, 0x6739CE73, 0x6B5AD6B5, 0x6F7BDEF7, + 0x739CE739, 0x77BDEF7B, 0x7BDEF7BD, 0x7FFFFFFF +}; + +CACHE_ALIGN const u8 material_5bit_to_6bit[] = { + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, + 0x10, 0x12, 0x14, 0x16, 0x19, 0x1A, 0x1C, 0x1E, + 0x21, 0x23, 0x25, 0x27, 0x29, 0x2B, 0x2D, 0x2F, + 0x31, 0x33, 0x35, 0x37, 0x39, 0x3B, 0x3D, 0x3F +}; + +CACHE_ALIGN const u8 material_5bit_to_8bit[] = { + 0x00, 0x08, 0x10, 0x18, 0x21, 0x29, 0x31, 0x39, + 0x42, 0x4A, 0x52, 0x5A, 0x63, 0x6B, 0x73, 0x7B, + 0x84, 0x8C, 0x94, 0x9C, 0xA5, 0xAD, 0xB5, 0xBD, + 0xC6, 0xCE, 0xD6, 0xDE, 0xE7, 0xEF, 0xF7, 0xFF +}; + +CACHE_ALIGN const u8 material_3bit_to_8bit[] = { + 0x00, 0x24, 0x49, 0x6D, 0x92, 0xB6, 0xDB, 0xFF +}; + +//maybe not very precise +CACHE_ALIGN const u8 material_3bit_to_5bit[] = { + 0, 4, 8, 13, 17, 22, 26, 31 +}; + +//TODO - generate this in the static init method more accurately +CACHE_ALIGN const u8 material_3bit_to_6bit[] = { + 0, 8, 16, 26, 34, 44, 52, 63 +}; + +//private acceleration tables +static float float16table[65536]; +static float float10Table[1024]; +static float float10RelTable[1024]; +static float normalTable[1024]; + +#define fix2float(v) (((float)((s32)(v))) / (float)(1<<12)) +#define fix10_2float(v) (((float)((s32)(v))) / (float)(1<<9)) + +CACHE_ALIGN u8 gfx3d_convertedScreen[256*192*4]; + +// Matrix stack handling +CACHE_ALIGN MatrixStack mtxStack[4] = { + MatrixStack(1, 0), // Projection stack + MatrixStack(31, 1), // Coordinate stack + MatrixStack(31, 2), // Directional stack + MatrixStack(1, 3), // Texture stack +}; + +int _hack_getMatrixStackLevel(int which) { return mtxStack[which].position; } + +static CACHE_ALIGN s32 mtxCurrent [4][16]; +static CACHE_ALIGN s32 mtxTemporal[16]; +static u32 mode = 0; + +// Indexes for matrix loading/multiplication +static u8 ML4x4ind = 0; +static u8 ML4x3ind = 0; +static u8 MM4x4ind = 0; +static u8 MM4x3ind = 0; +static u8 MM3x3ind = 0; + +// Data for vertex submission +static CACHE_ALIGN s16 s16coord[4] = {0, 0, 0, 0}; +static char coordind = 0; +static u32 vtxFormat = 0; +static BOOL inBegin = FALSE; + +// Data for basic transforms +static CACHE_ALIGN s32 trans[4] = {0, 0, 0, 0}; +static int transind = 0; +static CACHE_ALIGN s32 scale[4] = {0, 0, 0, 0}; +static int scaleind = 0; +static u32 viewport = 0; + +//various other registers +static s32 _t=0, _s=0; +static s32 last_t, last_s; +static u32 clCmd = 0; +static u32 clInd = 0; + +static u32 clInd2 = 0; +BOOL isSwapBuffers = FALSE; + +static u32 BTind = 0; +static u32 PTind = 0; +static CACHE_ALIGN u16 BTcoords[6] = {0, 0, 0, 0, 0, 0}; +static CACHE_ALIGN float PTcoords[4] = {0.0, 0.0, 0.0, 1.0}; + +//raw ds format poly attributes +static u32 polyAttr=0,textureFormat=0, texturePalette=0, polyAttrPending=0; + +//the current vertex color, 5bit values +static u8 colorRGB[4] = { 31,31,31,31 }; + +u32 control = 0; + +//light state: +static u32 lightColor[4] = {0,0,0,0}; +static s32 lightDirection[4] = {0,0,0,0}; +//material state: +static u16 dsDiffuse, dsAmbient, dsSpecular, dsEmission; +//used for indexing the shininess table during parameters to shininess command +static int shininessInd = 0; + + +//-----------cached things: +//these dont need to go into the savestate. they can be regenerated from HW registers +//from polygonattr: +static unsigned int cullingMask=0; +static u32 envMode=0; +static u32 lightMask=0; +//other things: +static int texCoordinateTransform = 0; +static CACHE_ALIGN s32 cacheLightDirection[4][4]; +static CACHE_ALIGN s32 cacheHalfVector[4][4]; +//------------------ + +#define RENDER_FRONT_SURFACE 0x80 +#define RENDER_BACK_SURFACE 0X40 + + +//-------------poly and vertex lists and such things +POLYLIST* polylists = NULL; +POLYLIST* polylist = NULL; +VERTLIST* vertlists = NULL; +VERTLIST* vertlist = NULL; +int polygonListCompleted = 0; + +int listTwiddle = 1; +int triStripToggle; + +//list-building state +struct tmpVertInfo { + //the number of verts registered in this list + int count; + //indices to the main vert list + int map[4]; + //indicates that the first poly in a list has been completed + BOOL first; +} tempVertInfo; + + +static void twiddleLists() { + listTwiddle++; + listTwiddle &= 1; + polylist = &polylists[listTwiddle]; + vertlist = &vertlists[listTwiddle]; + polylist->count = 0; + vertlist->count = 0; +} + +static BOOL flushPending = FALSE; +static BOOL drawPending = FALSE; +//------------------------------------------------------------ + +static void makeTables() { + + //produce the color bits of a 24bpp color from a DS RGB15 using bit logic (internal use only) + #define RGB15TO24_BITLOGIC(col) ( (material_5bit_to_8bit[((col)>>10)&0x1F]<<16) | (material_5bit_to_8bit[((col)>>5)&0x1F]<<8) | material_5bit_to_8bit[(col)&0x1F] ) + + for(int i=0;i<32768;i++) + color_15bit_to_24bit[i] = RGB15TO24_BITLOGIC((u16)i); + + //produce the color bits of a 24bpp color from a DS RGB15 using bit logic (internal use only). RGB are reverse of usual + #define RGB15TO24_BITLOGIC_REVERSE(col) ( (material_5bit_to_8bit[(col)&0x1F]<<16) | (material_5bit_to_8bit[((col)>>5)&0x1F]<<8) | material_5bit_to_8bit[((col)>>10)&0x1F] ) + + for(int i=0;i<32768;i++) + { + color_15bit_to_24bit_reverse[i] = RGB15TO24_BITLOGIC_REVERSE((u16)i); + color_15bit_to_16bit_reverse[i] = (((i & 0x001F) << 11) | (material_5bit_to_6bit[(i & 0x03E0) >> 5] << 5) | ((i & 0x7C00) >> 10)); + } + + for (int i = 0; i < 65536; i++) + float16table[i] = fix2float((signed short)i); + + for (int i = 0; i < 1024; i++) + float10Table[i] = ((signed short)(i<<6)) / (float)(1<<12); + + for (int i = 0; i < 1024; i++) + float10RelTable[i] = ((signed short)(i<<6)) / (float)(1<<18); + + for (int i = 0; i < 1024; i++) + normalTable[i] = ((signed short)(i<<6)) / (float)(1<<15); + + for(int r=0;r<=31;r++) + for(int oldr=0;oldr<=31;oldr++) + for(int a=0;a<=31;a++) { + int temp = (r*a + oldr*(31-a)) / 31; + mixTable555[a][r][oldr] = temp; + } +} + +void gfx3d_init() +{ + gxf_hardware.reset(); + //gxf_hardware.test(); + int zzz=9; + + //DWORD start = timeGetTime(); + //for(int i=0;i<1000000000;i++) + // MatrixMultVec4x4(mtxCurrent[0],mtxCurrent[1]); + //DWORD end = timeGetTime(); + //DWORD diff = end-start; + + //start = timeGetTime(); + //for(int i=0;i<1000000000;i++) + // MatrixMultVec4x4_b(mtxCurrent[0],mtxCurrent[1]); + //end = timeGetTime(); + //DWORD diff2 = end-start; + + //printf("SPEED TEST %d %d\n",diff,diff2); + + if(polylists == NULL) { polylists = new POLYLIST[2]; polylist = &polylists[0]; } + if(vertlists == NULL) { vertlists = new VERTLIST[2]; vertlist = &vertlists[0]; } + makeTables(); + gfx3d_reset(); +} + +void gfx3d_reset() +{ +#ifdef _SHOW_VTX_COUNTERS + max_polys = max_verts = 0; +#endif + + reconstruct(&gfx3d); + delete viewer3d_state; + viewer3d_state = new Viewer3d_State(); + + gxf_hardware.reset(); + + control = 0; + drawPending = FALSE; + flushPending = FALSE; + memset(polylists, 0, sizeof(POLYLIST)*2); + memset(vertlists, 0, sizeof(VERTLIST)*2); + gfx3d.state.invalidateToon = true; + listTwiddle = 1; + twiddleLists(); + gfx3d.polylist = polylist; + gfx3d.vertlist = vertlist; + + polyAttr = 0; + textureFormat = 0; + texturePalette = 0; + polyAttrPending = 0; + mode = 0; + s16coord[0] = s16coord[1] = s16coord[2] = s16coord[3] = 0; + coordind = 0; + vtxFormat = 0; + memset(trans, 0, sizeof(trans)); + transind = 0; + memset(scale, 0, sizeof(scale)); + scaleind = 0; + viewport = 0; + memset(gxPIPE.cmd, 0, sizeof(gxPIPE.cmd)); + memset(gxPIPE.param, 0, sizeof(gxPIPE.param)); + memset(colorRGB, 0, sizeof(colorRGB)); + memset(&tempVertInfo, 0, sizeof(tempVertInfo)); + + MatrixInit (mtxCurrent[0]); + MatrixInit (mtxCurrent[1]); + MatrixInit (mtxCurrent[2]); + MatrixInit (mtxCurrent[3]); + MatrixInit (mtxTemporal); + + MatrixStackInit(&mtxStack[0]); + MatrixStackInit(&mtxStack[1]); + MatrixStackInit(&mtxStack[2]); + MatrixStackInit(&mtxStack[3]); + + clCmd = 0; + clInd = 0; + + ML4x4ind = 0; + ML4x3ind = 0; + MM4x4ind = 0; + MM4x3ind = 0; + MM3x3ind = 0; + + BTind = 0; + PTind = 0; + + _t=0; + _s=0; + last_t = 0; + last_s = 0; + viewport = 0xBFFF0000; + + memset(gfx3d_convertedScreen,0,sizeof(gfx3d_convertedScreen)); + + gfx3d.state.clearDepth = gfx3d_extendDepth_15_to_24(0x7FFF); + + clInd2 = 0; + isSwapBuffers = FALSE; + + GFX_PIPEclear(); + GFX_FIFOclear(); +} + + +//================================================================================= Geometry Engine +//================================================================================= +//================================================================================= + +inline float vec3dot(float* a, float* b) { + return (((a[0]) * (b[0])) + ((a[1]) * (b[1])) + ((a[2]) * (b[2]))); +} + +FORCEINLINE s32 mul_fixed32(s32 a, s32 b) +{ + return fx32_shiftdown(fx32_mul(a,b)); +} + +FORCEINLINE s32 vec3dot_fixed32(const s32* a, const s32* b) { + return fx32_shiftdown(fx32_mul(a[0],b[0]) + fx32_mul(a[1],b[1]) + fx32_mul(a[2],b[2])); +} + +#define SUBMITVERTEX(ii, nn) polylist->list[polylist->count].vertIndexes[ii] = tempVertInfo.map[nn]; +//Submit a vertex to the GE +static void SetVertex() +{ + s32 coord[3] = { + s16coord[0], + s16coord[1], + s16coord[2] + }; + + DS_ALIGN(16) s32 coordTransformed[4] = { coord[0], coord[1], coord[2], (1<<12) }; + + if (texCoordinateTransform == 3) + { + //Tested by: Eledees The Adventures of Kai and Zero (E) [title screen and frontend menus] + last_s = (s32)(((s64)s16coord[0] * mtxCurrent[3][0] + + (s64)s16coord[1] * mtxCurrent[3][4] + + (s64)s16coord[2] * mtxCurrent[3][8] + + (((s64)(_s))<<24))>>24); + last_t = (s32)(((s64)s16coord[0] * mtxCurrent[3][1] + + (s64)s16coord[1] * mtxCurrent[3][5] + + (s64)s16coord[2] * mtxCurrent[3][9] + + (((s64)(_t))<<24))>>24); + } + + //refuse to do anything if we have too many verts or polys + polygonListCompleted = 0; + if(vertlist->count >= VERTLIST_SIZE) + return; + if(polylist->count >= POLYLIST_SIZE) + return; + + //TODO - think about keeping the clip matrix concatenated, + //so that we only have to multiply one matrix here + //(we could lazy cache the concatenated clip matrix and only generate it + //when we need to) + MatrixMultVec4x4_M2(mtxCurrent[0], coordTransformed); + + //printf("%f %f %f\n",s16coord[0]/4096.0f,s16coord[1]/4096.0f,s16coord[2]/4096.0f); + //printf("x %f %f %f %f\n",mtxCurrent[0][0]/4096.0f,mtxCurrent[0][1]/4096.0f,mtxCurrent[0][2]/4096.0f,mtxCurrent[0][3]/4096.0f); + //printf(" = %f %f %f %f\n",coordTransformed[0]/4096.0f,coordTransformed[1]/4096.0f,coordTransformed[2]/4096.0f,coordTransformed[3]/4096.0f); + + //TODO - culling should be done here. + //TODO - viewport transform? + + int continuation = 0; + if(vtxFormat==2 && !tempVertInfo.first) + continuation = 2; + else if(vtxFormat==3 && !tempVertInfo.first) + continuation = 2; + + //record the vertex + //VERT &vert = tempVertList.list[tempVertList.count]; + int vertIndex = vertlist->count + tempVertInfo.count - continuation; + if(vertIndex<0) { + printf("wtf\n"); + } + VERT &vert = vertlist->list[vertIndex]; + + //printf("%f %f %f\n",coordTransformed[0],coordTransformed[1],coordTransformed[2]); + //if(coordTransformed[1] > 20) + // coordTransformed[1] = 20; + + //printf("y-> %f\n",coord[1]); + + //if(mtxCurrent[1][14]>15) { + // printf("ACK!\n"); + // printf("----> modelview 1 state for that ack:\n"); + // //MatrixPrint(mtxCurrent[1]); + //} + + vert.texcoord[0] = last_s/16.0f; + vert.texcoord[1] = last_t/16.0f; + vert.coord[0] = coordTransformed[0]/4096.0f; + vert.coord[1] = coordTransformed[1]/4096.0f; + vert.coord[2] = coordTransformed[2]/4096.0f; + vert.coord[3] = coordTransformed[3]/4096.0f; + vert.color[0] = GFX3D_5TO6(colorRGB[0]); + vert.color[1] = GFX3D_5TO6(colorRGB[1]); + vert.color[2] = GFX3D_5TO6(colorRGB[2]); + tempVertInfo.map[tempVertInfo.count] = vertlist->count + tempVertInfo.count - continuation; + tempVertInfo.count++; + + //possibly complete a polygon + { + polygonListCompleted = 2; + switch(vtxFormat) { + case 0: //GL_TRIANGLES + if(tempVertInfo.count!=3) + break; + polygonListCompleted = 1; + //vertlist->list[polylist->list[polylist->count].vertIndexes[i] = vertlist->count++] = tempVertList.list[n]; + SUBMITVERTEX(0,0); + SUBMITVERTEX(1,1); + SUBMITVERTEX(2,2); + vertlist->count+=3; + polylist->list[polylist->count].type = 3; + tempVertInfo.count = 0; + break; + case 1: //GL_QUADS + if(tempVertInfo.count!=4) + break; + polygonListCompleted = 1; + SUBMITVERTEX(0,0); + SUBMITVERTEX(1,1); + SUBMITVERTEX(2,2); + SUBMITVERTEX(3,3); + vertlist->count+=4; + polylist->list[polylist->count].type = 4; + tempVertInfo.count = 0; + break; + case 2: //GL_TRIANGLE_STRIP + if(tempVertInfo.count!=3) + break; + polygonListCompleted = 1; + SUBMITVERTEX(0,0); + SUBMITVERTEX(1,1); + SUBMITVERTEX(2,2); + polylist->list[polylist->count].type = 3; + + if(triStripToggle) + tempVertInfo.map[1] = vertlist->count+2-continuation; + else + tempVertInfo.map[0] = vertlist->count+2-continuation; + + if(tempVertInfo.first) + vertlist->count+=3; + else + vertlist->count+=1; + + triStripToggle ^= 1; + tempVertInfo.first = false; + tempVertInfo.count = 2; + break; + case 3: //GL_QUAD_STRIP + if(tempVertInfo.count!=4) + break; + polygonListCompleted = 1; + SUBMITVERTEX(0,0); + SUBMITVERTEX(1,1); // TODO: + SUBMITVERTEX(2,3); // OpenGL Quad_Strip must be : 3,3 + SUBMITVERTEX(3,2); // : 2,2 + polylist->list[polylist->count].type = 4; + tempVertInfo.map[0] = vertlist->count+2-continuation; + tempVertInfo.map[1] = vertlist->count+3-continuation; + if(tempVertInfo.first) + vertlist->count+=4; + else vertlist->count+=2; + tempVertInfo.first = false; + tempVertInfo.count = 2; + break; + default: + return; + } + + if(polygonListCompleted == 1) + { + POLY &poly = polylist->list[polylist->count]; + + poly.vtxFormat = vtxFormat; + + // Line segment detect + // Tested" Castlevania POR - warp stone, trajectory of ricochet, "Eye of Decay" + if (!(textureFormat & (7 << 26))) // no texture + { + bool duplicated = false; + VERT &vert0 = vertlist->list[poly.vertIndexes[0]]; + VERT &vert1 = vertlist->list[poly.vertIndexes[1]]; + VERT &vert2 = vertlist->list[poly.vertIndexes[2]]; + if ( (vert0.x == vert1.x) && (vert0.y == vert1.y) ) duplicated = true; + else + if ( (vert1.x == vert2.x) && (vert1.y == vert2.y) ) duplicated = true; + else + if ( (vert0.y == vert1.y) && (vert1.y == vert2.y) ) duplicated = true; + else + if ( (vert0.x == vert1.x) && (vert1.x == vert2.x) ) duplicated = true; + if (duplicated) + { + //printf("Line Segmet detected (poly type %i, mode %i, texparam %08X)\n", poly.type, poly.vtxFormat, textureFormat); + poly.vtxFormat = vtxFormat + 4; + } + } + + poly.polyAttr = polyAttr; + poly.texParam = textureFormat; + poly.texPalette = texturePalette; + poly.viewport = viewport; + polylist->count++; + } + } +} + +static void gfx3d_glPolygonAttrib_cache() +{ + // Light enable/disable + lightMask = (polyAttr&0xF); + + // texture environment + envMode = (polyAttr&0x30)>>4; + + // back face culling + cullingMask = (polyAttr>>6)&3; +} + +static void gfx3d_glTexImage_cache() +{ + texCoordinateTransform = (textureFormat>>30); +} + +static void gfx3d_glLightDirection_cache(int index) +{ + s32 v = lightDirection[index]; + + s16 x = ((v<<22)>>22)<<3; + s16 y = ((v<<12)>>22)<<3; + s16 z = ((v<<2)>>22)<<3; + + cacheLightDirection[index][0] = x; + cacheLightDirection[index][1] = y; + cacheLightDirection[index][2] = z; + cacheLightDirection[index][3] = 0; + + //Multiply the vector by the directional matrix + MatrixMultVec3x3_fixed(mtxCurrent[2], cacheLightDirection[index]); + + //Calculate the half angle vector + s32 lineOfSight[4] = {0, 0, (-1)<<12, 0}; + for(int i = 0; i < 4; i++) + { + cacheHalfVector[index][i] = ((cacheLightDirection[index][i] + lineOfSight[i])); + } + + //normalize the half angle vector + //can't believe the hardware really does this... but yet it seems... + s32 halfLength = ((s32)(sqrt((double)vec3dot_fixed32(cacheHalfVector[index],cacheHalfVector[index]))))<<6; + + if(halfLength!=0) + { + halfLength = abs(halfLength); + halfLength >>= 6; + for(int i = 0; i < 4; i++) + { + s32 temp = cacheHalfVector[index][i]; + temp <<= 6; + temp /= halfLength; + cacheHalfVector[index][i] = temp; + } + } +} + + +//=============================================================================== +static void gfx3d_glMatrixMode(u32 v) +{ + mode = (v&3); + + GFX_DELAY(1); +} + +static void gfx3d_glPushMatrix() +{ + //this command always works on both pos and vector when either pos or pos-vector are the current mtx mode + short mymode = (mode==1?2:mode); + + MatrixStackPushMatrix(&mtxStack[mymode], mtxCurrent[mymode]); + + GFX_DELAY(17); + + if(mymode==2) + MatrixStackPushMatrix (&mtxStack[1], mtxCurrent[1]); +} + +static void gfx3d_glPopMatrix(s32 i) +{ + // The stack has only one level (at address 0) in projection mode, + // in that mode, the parameter value is ignored, the offset is always +1 in that mode. + if (mode == 0) i = 1; + + //this command always works on both pos and vector when either pos or pos-vector are the current mtx mode + short mymode = (mode==1?2:mode); + + //i = (i<<26)>>26; + //previously, we sign extended here. that isnt really necessary since the stacks are apparently modularly addressed. so i am somewhat doubtful that this is a real concept. + //example: + //suppose we had a -30 that would be %100010. + //which is the same as adding 34. if our stack was at 17 then one way is 17-30(+32)=19 and the other way is 17+34(-32)=19 + + //please note that our ability to skip treating this as signed is dependent on the modular addressing later. if that ever changes, we need to change this back. + + MatrixStackPopMatrix(mtxCurrent[mymode], &mtxStack[mymode], i); + + GFX_DELAY(36); + + if (mymode == 2) + MatrixStackPopMatrix(mtxCurrent[1], &mtxStack[1], i); +} + +static void gfx3d_glStoreMatrix(u32 v) +{ + //this command always works on both pos and vector when either pos or pos-vector are the current mtx mode + short mymode = (mode==1?2:mode); + + //limit height of these stacks. + //without the mymode==3 namco classics galaxian will try to use pos=1 and overrun the stack, corrupting emu + if(mymode==0 || mymode==3) + v = 0; + + v &= 31; + + //according to gbatek, 31 works but sets the stack overflow flag + //spider-man 2 tests this on the spiderman model (and elsewhere) + //i am somewhat skeptical of this, but we'll leave it this way for now. + //a test shouldnt be too hard + if(v==31) + MMU_new.gxstat.se = 1; + + MatrixStackLoadMatrix (&mtxStack[mymode], v, mtxCurrent[mymode]); + + GFX_DELAY(17); + + if(mymode==2) + MatrixStackLoadMatrix (&mtxStack[1], v, mtxCurrent[1]); +} + +static void gfx3d_glRestoreMatrix(u32 v) +{ + //this command always works on both pos and vector when either pos or pos-vector are the current mtx mode + short mymode = (mode==1?2:mode); + + //limit height of these stacks + //without the mymode==3 namco classics galaxian will try to use pos=1 and overrun the stack, corrupting emu + if(mymode==0 || mymode==3) + v = 0; + + v &= 31; + + //according to gbatek, 31 works but sets the stack overflow flag + //spider-man 2 tests this on the spiderman model (and elsewhere) + //i am somewhat skeptical of this, but we'll leave it this way for now. + //a test shouldnt be too hard + if(v==31) + MMU_new.gxstat.se = 1; + + + MatrixCopy (mtxCurrent[mymode], MatrixStackGetPos(&mtxStack[mymode], v)); + + GFX_DELAY(36); + + if (mymode == 2) + MatrixCopy (mtxCurrent[1], MatrixStackGetPos(&mtxStack[1], v)); +} + +static void gfx3d_glLoadIdentity() +{ + MatrixIdentity (mtxCurrent[mode]); + + GFX_DELAY(19); + + if (mode == 2) + MatrixIdentity (mtxCurrent[1]); + + //printf("identity: %d to: \n",mode); MatrixPrint(mtxCurrent[1]); +} + +static BOOL gfx3d_glLoadMatrix4x4(s32 v) +{ + mtxCurrent[mode][ML4x4ind] = v; + + ++ML4x4ind; + if(ML4x4ind<16) return FALSE; + ML4x4ind = 0; + + GFX_DELAY(19); + + //vector_fix2float<4>(mtxCurrent[mode], 4096.f); + + if (mode == 2) + MatrixCopy (mtxCurrent[1], mtxCurrent[2]); + + //printf("load4x4: matrix %d to: \n",mode); MatrixPrint(mtxCurrent[1]); + return TRUE; +} + +static BOOL gfx3d_glLoadMatrix4x3(s32 v) +{ + mtxCurrent[mode][ML4x3ind] = v; + + ML4x3ind++; + if((ML4x3ind & 0x03) == 3) ML4x3ind++; + if(ML4x3ind<16) return FALSE; + ML4x3ind = 0; + + //vector_fix2float<4>(mtxCurrent[mode], 4096.f); + + //fill in the unusued matrix values + mtxCurrent[mode][3] = mtxCurrent[mode][7] = mtxCurrent[mode][11] = 0; + mtxCurrent[mode][15] = (1<<12); + + GFX_DELAY(30); + + if (mode == 2) + MatrixCopy (mtxCurrent[1], mtxCurrent[2]); + //printf("load4x3: matrix %d to: \n",mode); MatrixPrint(mtxCurrent[1]); + return TRUE; +} + +static BOOL gfx3d_glMultMatrix4x4(s32 v) +{ + mtxTemporal[MM4x4ind] = v; + + MM4x4ind++; + if(MM4x4ind<16) return FALSE; + MM4x4ind = 0; + + GFX_DELAY(35); + + //vector_fix2float<4>(mtxTemporal, 4096.f); + + MatrixMultiply (mtxCurrent[mode], mtxTemporal); + + if (mode == 2) + { + MatrixMultiply (mtxCurrent[1], mtxTemporal); + GFX_DELAY_M2(30); + } + + //printf("mult4x4: matrix %d to: \n",mode); MatrixPrint(mtxCurrent[1]); + + MatrixIdentity (mtxTemporal); + return TRUE; +} + +static BOOL gfx3d_glMultMatrix4x3(s32 v) +{ + mtxTemporal[MM4x3ind] = v; + + MM4x3ind++; + if((MM4x3ind & 0x03) == 3) MM4x3ind++; + if(MM4x3ind<16) return FALSE; + MM4x3ind = 0; + + GFX_DELAY(31); + + //vector_fix2float<4>(mtxTemporal, 4096.f); + + //fill in the unusued matrix values + mtxTemporal[3] = mtxTemporal[7] = mtxTemporal[11] = 0; + mtxTemporal[15] = 1<<12; + + MatrixMultiply (mtxCurrent[mode], mtxTemporal); + + if (mode == 2) + { + MatrixMultiply (mtxCurrent[1], mtxTemporal); + GFX_DELAY_M2(30); + } + + //printf("mult4x3: matrix %d to: \n",mode); MatrixPrint(mtxCurrent[1]); + + //does this really need to be done? + MatrixIdentity (mtxTemporal); + return TRUE; +} + +static BOOL gfx3d_glMultMatrix3x3(s32 v) +{ + mtxTemporal[MM3x3ind] = v; + + + MM3x3ind++; + if((MM3x3ind & 0x03) == 3) MM3x3ind++; + if(MM3x3ind<12) return FALSE; + MM3x3ind = 0; + + GFX_DELAY(28); + + //vector_fix2float<3>(mtxTemporal, 4096.f); + + //fill in the unusued matrix values + mtxTemporal[3] = mtxTemporal[7] = mtxTemporal[11] = 0; + mtxTemporal[15] = 1<<12; + mtxTemporal[12] = mtxTemporal[13] = mtxTemporal[14] = 0; + + MatrixMultiply (mtxCurrent[mode], mtxTemporal); + + if (mode == 2) + { + MatrixMultiply (mtxCurrent[1], mtxTemporal); + GFX_DELAY_M2(30); + } + + //printf("mult3x3: matrix %d to: \n",mode); MatrixPrint(mtxCurrent[1]); + + + //does this really need to be done? + MatrixIdentity (mtxTemporal); + return TRUE; +} + +static BOOL gfx3d_glScale(s32 v) +{ + scale[scaleind] = v; + + ++scaleind; + + if(scaleind<3) return FALSE; + scaleind = 0; + + MatrixScale (mtxCurrent[(mode==2?1:mode)], scale); + //printf("scale: matrix %d to: \n",mode); MatrixPrint(mtxCurrent[1]); + + GFX_DELAY(22); + + //note: pos-vector mode should not cause both matrices to scale. + //the whole purpose is to keep the vector matrix orthogonal + //so, I am leaving this commented out as an example of what not to do. + //if (mode == 2) + // MatrixScale (mtxCurrent[1], scale); + return TRUE; +} + +static BOOL gfx3d_glTranslate(s32 v) +{ + trans[transind] = v; + + ++transind; + + if(transind<3) return FALSE; + transind = 0; + + MatrixTranslate (mtxCurrent[mode], trans); + + GFX_DELAY(22); + + if (mode == 2) + { + MatrixTranslate (mtxCurrent[1], trans); + GFX_DELAY_M2(30); + } + + //printf("translate: matrix %d to: \n",mode); MatrixPrint(mtxCurrent[1]); + + return TRUE; +} + +static void gfx3d_glColor3b(u32 v) +{ + colorRGB[0] = (v&0x1F); + colorRGB[1] = ((v>>5)&0x1F); + colorRGB[2] = ((v>>10)&0x1F); + GFX_DELAY(1); +} + +static void gfx3d_glNormal(s32 v) +{ + s16 nx = ((v<<22)>>22)<<3; + s16 ny = ((v<<12)>>22)<<3; + s16 nz = ((v<<2)>>22)<<3; + + CACHE_ALIGN s32 normal[4] = { nx,ny,nz,(1<<12) }; + + if (texCoordinateTransform == 2) + { + //SM64 highlight rendered star in main menu tests this + //also smackdown 2010 player textures tested this (needed cast on _s and _t) + last_s = (s32)(((s64)normal[0] * mtxCurrent[3][0] + (s64)normal[1] * mtxCurrent[3][4] + (s64)normal[2] * mtxCurrent[3][8] + (((s64)_s)<<24))>>24); + last_t = (s32)(((s64)normal[0] * mtxCurrent[3][1] + (s64)normal[1] * mtxCurrent[3][5] + (s64)normal[2] * mtxCurrent[3][9] + (((s64)_t)<<24))>>24); + } + + MatrixMultVec3x3_fixed(mtxCurrent[2],normal); + + //apply lighting model + u8 diffuse[3] = { + (dsDiffuse)&0x1F, + (dsDiffuse>>5)&0x1F, + (dsDiffuse>>10)&0x1F }; + + u8 ambient[3] = { + (dsAmbient)&0x1F, + (dsAmbient>>5)&0x1F, + (dsAmbient>>10)&0x1F }; + + u8 emission[3] = { + (dsEmission)&0x1F, + (dsEmission>>5)&0x1F, + (dsEmission>>10)&0x1F }; + + u8 specular[3] = { + (dsSpecular)&0x1F, + (dsSpecular>>5)&0x1F, + (dsSpecular>>10)&0x1F }; + + int vertexColor[3] = { emission[0], emission[1], emission[2] }; + + for(int i=0; i<4; i++) + { + if(!((lightMask>>i)&1)) continue; + + u8 _lightColor[3] = { + (lightColor[i])&0x1F, + (lightColor[i]>>5)&0x1F, + (lightColor[i]>>10)&0x1F }; + + //This formula is the one used by the DS + //Reference : http://nocash.emubase.de/gbatek.htm#ds3dpolygonlightparameters + s32 fixed_diffuse = std::max(0,-vec3dot_fixed32(cacheLightDirection[i],normal)); + + //todo - this could be cached in this form + s32 fixedTempNegativeHalf[] = {-cacheHalfVector[i][0],-cacheHalfVector[i][1],-cacheHalfVector[i][2],-cacheHalfVector[i][3]}; + s32 dot = vec3dot_fixed32(fixedTempNegativeHalf, normal); + + s32 fixedshininess = 0; + if(dot>0) //prevent shininess on opposite side + { + //we have cos(a). it seems that we need cos(2a). trig identity is a fast way to get it. + //cos^2(a)=(1/2)(1+cos(2a)) + //2*cos^2(a)-1=cos(2a) + fixedshininess = 2*mul_fixed32(dot,dot)-4096; + //gbatek is almost right but not quite! + } + + //this seems to need to be saturated, or else the table will overflow. + //even without a table, failure to saturate is bad news + fixedshininess = std::min(fixedshininess,4095); + fixedshininess = std::max(fixedshininess,0); + + if(dsSpecular & 0x8000) + { + //shininess is 20.12 fixed point, so >>5 gives us .7 which is 128 entries + //the entries are 8bits each so <<4 gives us .12 again, compatible with the lighting formulas below + //(according to other normal nds procedures, we might should fill the bottom bits with 1 or 0 according to rules...) + fixedshininess = gfx3d.state.shininessTable[fixedshininess>>5]<<4; + } + + for(int c = 0; c < 3; c++) + { + s32 specComp = ((specular[c] * _lightColor[c] * fixedshininess)>>17); //5 bits for color*color and 12 bits for the shininess + s32 diffComp = ((diffuse[c] * _lightColor[c] * fixed_diffuse)>>17); //5bits for the color*color and 12 its for the diffuse + s32 ambComp = ((ambient[c] * _lightColor[c])>>5); //5bits for color*color + vertexColor[c] += specComp + diffComp + ambComp; + } + } + + for(int c=0;c<3;c++) + { + colorRGB[c] = std::min(31,vertexColor[c]); + } + + GFX_DELAY(9); + GFX_DELAY_M2((lightMask) & 0x01); + GFX_DELAY_M2((lightMask>>1) & 0x01); + GFX_DELAY_M2((lightMask>>2) & 0x01); + GFX_DELAY_M2((lightMask>>3) & 0x01); +} + +static void gfx3d_glTexCoord(s32 val) +{ + _s = ((val<<16)>>16); + _t = (val>>16); + + if (texCoordinateTransform == 1) + { + //dragon quest 4 overworld will test this + last_s = (s32)(((s64)(_s<<12) * mtxCurrent[3][0] + (s64)(_t<<12) * mtxCurrent[3][4] + ((s64)mtxCurrent[3][8]<<12) + ((s64)mtxCurrent[3][12]<<12))>>24); + last_t = (s32)(((s64)(_s<<12) * mtxCurrent[3][1] + (s64)(_t<<12) * mtxCurrent[3][5] + ((s64)mtxCurrent[3][9]<<12) + ((s64)mtxCurrent[3][13]<<12))>>24); + } + else if(texCoordinateTransform == 0) + { + last_s=_s; + last_t=_t; + } + GFX_DELAY(1); +} + +static BOOL gfx3d_glVertex16b(s32 v) +{ + if(coordind==0) + { + s16coord[0] = (v<<16)>>16; + s16coord[1] = (v>>16)&0xFFFF; + + ++coordind; + return FALSE; + } + + s16coord[2] = (v<<16)>>16; + + coordind = 0; + SetVertex (); + + GFX_DELAY(9); + return TRUE; +} + +static void gfx3d_glVertex10b(s32 v) +{ + //TODO TODO TODO - contemplate the sign extension - shift in zeroes or ones? zeroes is certainly more normal.. + s16coord[0] = ((v<<22)>>22)<<6; + s16coord[1] = ((v<<12)>>22)<<6; + s16coord[2] = ((v<<2)>>22)<<6; + + GFX_DELAY(8); + SetVertex (); +} + +template<int ONE, int TWO> +static void gfx3d_glVertex3_cord(s32 v) +{ + s16coord[ONE] = (v<<16)>>16; + s16coord[TWO] = (v>>16); + + SetVertex (); + + GFX_DELAY(8); +} + +static void gfx3d_glVertex_rel(s32 v) +{ + s16 x = ((v<<22)>>22); + s16 y = ((v<<12)>>22); + s16 z = ((v<<2)>>22); + + s16coord[0] += x; + s16coord[1] += y; + s16coord[2] += z; + + + SetVertex (); + + GFX_DELAY(8); +} + +static void gfx3d_glPolygonAttrib (u32 val) +{ + if(inBegin) { + //PROGINFO("Set polyattr in the middle of a begin/end pair.\n (This won't be activated until the next begin)\n"); + //TODO - we need some some similar checking for teximageparam etc. + } + polyAttrPending = val; + GFX_DELAY(1); +} + +static void gfx3d_glTexImage(u32 val) +{ + textureFormat = val; + gfx3d_glTexImage_cache(); + GFX_DELAY(1); +} + +static void gfx3d_glTexPalette(u32 val) +{ + texturePalette = val; + GFX_DELAY(1); +} + +/* + 0-4 Diffuse Reflection Red + 5-9 Diffuse Reflection Green + 10-14 Diffuse Reflection Blue + 15 Set Vertex Color (0=No, 1=Set Diffuse Reflection Color as Vertex Color) + 16-20 Ambient Reflection Red + 21-25 Ambient Reflection Green + 26-30 Ambient Reflection Blue +*/ +static void gfx3d_glMaterial0(u32 val) +{ + dsDiffuse = val&0xFFFF; + dsAmbient = val>>16; + + if (BIT15(val)) + { + colorRGB[0] = (val)&0x1F; + colorRGB[1] = (val>>5)&0x1F; + colorRGB[2] = (val>>10)&0x1F; + } + GFX_DELAY(4); +} + +static void gfx3d_glMaterial1(u32 val) +{ + dsSpecular = val&0xFFFF; + dsEmission = val>>16; + GFX_DELAY(4); +} + +/* + 0-9 Directional Vector's X component (1bit sign + 9bit fractional part) + 10-19 Directional Vector's Y component (1bit sign + 9bit fractional part) + 20-29 Directional Vector's Z component (1bit sign + 9bit fractional part) + 30-31 Light Number (0..3) +*/ +static void gfx3d_glLightDirection (u32 v) +{ + int index = v>>30; + + lightDirection[index] = (s32)(v&0x3FFFFFFF); + gfx3d_glLightDirection_cache(index); + GFX_DELAY(6); +} + +static void gfx3d_glLightColor (u32 v) +{ + int index = v>>30; + lightColor[index] = v; + GFX_DELAY(1); +} + +static BOOL gfx3d_glShininess (u32 val) +{ + gfx3d.state.shininessTable[shininessInd++] = ((val & 0xFF)); + gfx3d.state.shininessTable[shininessInd++] = (((val >> 8) & 0xFF)); + gfx3d.state.shininessTable[shininessInd++] = (((val >> 16) & 0xFF)); + gfx3d.state.shininessTable[shininessInd++] = (((val >> 24) & 0xFF)); + + if (shininessInd < 128) return FALSE; + shininessInd = 0; + GFX_DELAY(32); + return TRUE; +} + +static void gfx3d_glBegin(u32 v) +{ + inBegin = TRUE; + vtxFormat = v&0x03; + triStripToggle = 0; + tempVertInfo.count = 0; + tempVertInfo.first = true; + polyAttr = polyAttrPending; + gfx3d_glPolygonAttrib_cache(); + GFX_DELAY(1); +} + +static void gfx3d_glEnd(void) +{ + tempVertInfo.count = 0; + inBegin = FALSE; + GFX_DELAY(1); +} + +// swap buffers - skipped + +static void gfx3d_glViewPort(u32 v) +{ + viewport = v; + GFX_DELAY(1); +} + +static BOOL gfx3d_glBoxTest(u32 v) +{ + //printf("boxtest\n"); + MMU_new.gxstat.tr = 0; // clear boxtest bit + MMU_new.gxstat.tb = 1; // busy + + BTcoords[BTind++] = v & 0xFFFF; + BTcoords[BTind++] = v >> 16; + + if (BTind < 5) return FALSE; + BTind = 0; + + MMU_new.gxstat.tb = 0; // clear busy + GFX_DELAY(103); + +#if 0 + INFO("BoxTEST: x %f y %f width %f height %f depth %f\n", + BTcoords[0], BTcoords[1], BTcoords[2], BTcoords[3], BTcoords[4], BTcoords[5]); + /*for (int i = 0; i < 16; i++) + { + INFO("mtx1[%i] = %f ", i, mtxCurrent[1][i]); + if ((i+1) % 4 == 0) INFO("\n"); + } + INFO("\n");*/ +#endif + + //(crafted to be clear, not fast.) + + //nanostray title, ff4, ice age 3 depend on this and work + //garfields nightmare and strawberry shortcake DO DEPEND on the overflow behavior. + + u16 ux = BTcoords[0]; + u16 uy = BTcoords[1]; + u16 uz = BTcoords[2]; + u16 uw = BTcoords[3]; + u16 uh = BTcoords[4]; + u16 ud = BTcoords[5]; + + //craft the coords by adding extents to startpoint + float x = float16table[ux]; + float y = float16table[uy]; + float z = float16table[uz]; + float xw = float16table[(ux+uw)&0xFFFF]; //&0xFFFF not necessary for u16+u16 addition but added for emphasis + float yh = float16table[(uy+uh)&0xFFFF]; + float zd = float16table[(uz+ud)&0xFFFF]; + + //eight corners of cube + VERT verts[8]; + verts[0].set_coord(x,y,z,1); + verts[1].set_coord(xw,y,z,1); + verts[2].set_coord(xw,yh,z,1); + verts[3].set_coord(x,yh,z,1); + verts[4].set_coord(x,y,zd,1); + verts[5].set_coord(xw,y,zd,1); + verts[6].set_coord(xw,yh,zd,1); + verts[7].set_coord(x,yh,zd,1); + + //craft the faces of the box (clockwise) + POLY polys[6]; + polys[0].setVertIndexes(7,6,5,4); //near + polys[1].setVertIndexes(0,1,2,3); //far + polys[2].setVertIndexes(0,3,7,4); //left + polys[3].setVertIndexes(6,2,1,5); //right + polys[4].setVertIndexes(3,2,6,7); //top + polys[5].setVertIndexes(0,4,5,1); //bottom + + //setup the clipper + GFX3D_Clipper::TClippedPoly tempClippedPoly; + boxtestClipper.clippedPolys = &tempClippedPoly; + boxtestClipper.reset(); + + ////----------------------------- + ////awesome hack: + ////emit the box as geometry for testing + //for(int i=0;i<6;i++) + //{ + // POLY* poly = &polys[i]; + // VERT* vertTable[4] = { + // &verts[poly->vertIndexes[0]], + // &verts[poly->vertIndexes[1]], + // &verts[poly->vertIndexes[2]], + // &verts[poly->vertIndexes[3]] + // }; + + // gfx3d_glBegin(1); + // for(int i=0;i<4;i++) { + // coord[0] = vertTable[i]->x; + // coord[1] = vertTable[i]->y; + // coord[2] = vertTable[i]->z; + // SetVertex(); + // } + // gfx3d_glEnd(); + //} + ////--------------------- + + //transform all coords + for(int i=0;i<8;i++) { + //MatrixMultVec4x4_M2(mtxCurrent[0], verts[i].coord); + + CACHE_ALIGN float temp1[16] = {mtxCurrent[1][0]/4096.0f,mtxCurrent[1][1]/4096.0f,mtxCurrent[1][2]/4096.0f,mtxCurrent[1][3]/4096.0f,mtxCurrent[1][4]/4096.0f,mtxCurrent[1][5]/4096.0f,mtxCurrent[1][6]/4096.0f,mtxCurrent[1][7]/4096.0f,mtxCurrent[1][8]/4096.0f,mtxCurrent[1][9]/4096.0f,mtxCurrent[1][10]/4096.0f,mtxCurrent[1][11]/4096.0f,mtxCurrent[1][12]/4096.0f,mtxCurrent[1][13]/4096.0f,mtxCurrent[1][14]/4096.0f,mtxCurrent[1][15]/4096.0f}; + CACHE_ALIGN float temp0[16] = {mtxCurrent[0][0]/4096.0f,mtxCurrent[0][1]/4096.0f,mtxCurrent[0][2]/4096.0f,mtxCurrent[0][3]/4096.0f,mtxCurrent[0][4]/4096.0f,mtxCurrent[0][5]/4096.0f,mtxCurrent[0][6]/4096.0f,mtxCurrent[0][7]/4096.0f,mtxCurrent[0][8]/4096.0f,mtxCurrent[0][9]/4096.0f,mtxCurrent[0][10]/4096.0f,mtxCurrent[0][11]/4096.0f,mtxCurrent[0][12]/4096.0f,mtxCurrent[0][13]/4096.0f,mtxCurrent[0][14]/4096.0f,mtxCurrent[0][15]/4096.0f}; + _NOSSE_MatrixMultVec4x4(temp1,verts[i].coord); + _NOSSE_MatrixMultVec4x4(temp0,verts[i].coord); + } + + //clip each poly + for(int i=0;i<6;i++) + { + POLY* poly = &polys[i]; + VERT* vertTable[4] = { + &verts[poly->vertIndexes[0]], + &verts[poly->vertIndexes[1]], + &verts[poly->vertIndexes[2]], + &verts[poly->vertIndexes[3]] + }; + + boxtestClipper.clipPoly<false>(poly,vertTable); + + //if any portion of this poly was retained, then the test passes. + if(boxtestClipper.clippedPolyCounter>0) { + //printf("%06d PASS %d\n",boxcounter,gxFIFO.size); + MMU_new.gxstat.tr = 1; + break; + } + } + + if(MMU_new.gxstat.tr == 0) + { + //printf("%06d FAIL %d\n",boxcounter,gxFIFO.size); + } + + return TRUE; +} + +static BOOL gfx3d_glPosTest(u32 v) +{ + //printf("postest\n"); + //this is apparently tested by transformers decepticons and ultimate spiderman + + //printf("POSTEST\n"); + MMU_new.gxstat.tb = 1; + + PTcoords[PTind++] = float16table[v & 0xFFFF]; + PTcoords[PTind++] = float16table[v >> 16]; + + if (PTind < 3) return FALSE; + PTind = 0; + + PTcoords[3] = 1.0f; + + CACHE_ALIGN float temp1[16] = {mtxCurrent[1][0]/4096.0f,mtxCurrent[1][1]/4096.0f,mtxCurrent[1][2]/4096.0f,mtxCurrent[1][3]/4096.0f,mtxCurrent[1][4]/4096.0f,mtxCurrent[1][5]/4096.0f,mtxCurrent[1][6]/4096.0f,mtxCurrent[1][7]/4096.0f,mtxCurrent[1][8]/4096.0f,mtxCurrent[1][9]/4096.0f,mtxCurrent[1][10]/4096.0f,mtxCurrent[1][11]/4096.0f,mtxCurrent[1][12]/4096.0f,mtxCurrent[1][13]/4096.0f,mtxCurrent[1][14]/4096.0f,mtxCurrent[1][15]/4096.0f}; + CACHE_ALIGN float temp0[16] = {mtxCurrent[0][0]/4096.0f,mtxCurrent[0][1]/4096.0f,mtxCurrent[0][2]/4096.0f,mtxCurrent[0][3]/4096.0f,mtxCurrent[0][4]/4096.0f,mtxCurrent[0][5]/4096.0f,mtxCurrent[0][6]/4096.0f,mtxCurrent[0][7]/4096.0f,mtxCurrent[0][8]/4096.0f,mtxCurrent[0][9]/4096.0f,mtxCurrent[0][10]/4096.0f,mtxCurrent[0][11]/4096.0f,mtxCurrent[0][12]/4096.0f,mtxCurrent[0][13]/4096.0f,mtxCurrent[0][14]/4096.0f,mtxCurrent[0][15]/4096.0f}; + + MatrixMultVec4x4(temp1, PTcoords); + MatrixMultVec4x4(temp0, PTcoords); + + MMU_new.gxstat.tb = 0; + + GFX_DELAY(9); + + return TRUE; +} + +static void gfx3d_glVecTest(u32 v) +{ + //printf("vectest\n"); + GFX_DELAY(5); + + //this is tested by phoenix wright in its evidence inspector modelviewer + //i am not sure exactly what it is doing, maybe it is testing to ensure + //that the normal vector for the point of interest is camera-facing. + + CACHE_ALIGN float normal[4] = { normalTable[v&1023], + normalTable[(v>>10)&1023], + normalTable[(v>>20)&1023], + 0}; + + CACHE_ALIGN float temp[16] = {mtxCurrent[2][0]/4096.0f,mtxCurrent[2][1]/4096.0f,mtxCurrent[2][2]/4096.0f,mtxCurrent[2][3]/4096.0f,mtxCurrent[2][4]/4096.0f,mtxCurrent[2][5]/4096.0f,mtxCurrent[2][6]/4096.0f,mtxCurrent[2][7]/4096.0f,mtxCurrent[2][8]/4096.0f,mtxCurrent[2][9]/4096.0f,mtxCurrent[2][10]/4096.0f,mtxCurrent[2][11]/4096.0f,mtxCurrent[2][12]/4096.0f,mtxCurrent[2][13]/4096.0f,mtxCurrent[2][14]/4096.0f,mtxCurrent[2][15]/4096.0f}; + MatrixMultVec4x4(temp, normal); + + s16 x = (s16)(normal[0]*4096); + s16 y = (s16)(normal[1]*4096); + s16 z = (s16)(normal[2]*4096); + + MMU_new.gxstat.tb = 0; // clear busy + T1WriteWord(MMU.MMU_MEM[0][0x40], 0x630, x); + T1WriteWord(MMU.MMU_MEM[0][0x40], 0x632, y); + T1WriteWord(MMU.MMU_MEM[0][0x40], 0x634, z); + +} +//================================================================================= Geometry Engine +//================================================================================= (end) +//================================================================================= + +void VIEWPORT::decode(u32 v) +{ + x = (v&0xFF); + y = std::min(191,(int)(((v>>8)&0xFF))); + width = (((v>>16)&0xFF)+1)-(v&0xFF); + height = ((v>>24)+1)-((v>>8)&0xFF); +} + +void gfx3d_glFogColor(u32 v) +{ + gfx3d.state.fogColor = v; +} + +void gfx3d_glFogOffset (u32 v) +{ + gfx3d.state.fogOffset = (v&0x7fff); +} + +void gfx3d_glClearDepth(u32 v) +{ + v &= 0x7FFF; + gfx3d.state.clearDepth = gfx3d_extendDepth_15_to_24(v); +} + +// Ignored for now +void gfx3d_glSwapScreen(unsigned int screen) +{ +} + +int gfx3d_GetNumPolys() +{ + //so is this in the currently-displayed or currently-built list? + return (polylists[listTwiddle].count); +} + +int gfx3d_GetNumVertex() +{ + //so is this in the currently-displayed or currently-built list? + return (vertlists[listTwiddle].count); +} + +void gfx3d_UpdateToonTable(u8 offset, u16 val) +{ + gfx3d.state.invalidateToon = true; + gfx3d.state.u16ToonTable[offset] = val; + //printf("toon %d set to %04X\n",offset,val); +} + +void gfx3d_UpdateToonTable(u8 offset, u32 val) +{ + //C.O.P. sets toon table via this method + gfx3d.state.invalidateToon = true; + gfx3d.state.u16ToonTable[offset] = val & 0xFFFF; + gfx3d.state.u16ToonTable[offset+1] = val >> 16; + //printf("toon %d set to %04X\n",offset,gfx3d.state.u16ToonTable[offset]); + //printf("toon %d set to %04X\n",offset+1,gfx3d.state.u16ToonTable[offset+1]); +} + +s32 gfx3d_GetClipMatrix (unsigned int index) +{ + s32 val = MatrixGetMultipliedIndex (index, mtxCurrent[0], mtxCurrent[1]); + + //printf("reading clip matrix: %d\n",index); + + return (s32)val; +} + +s32 gfx3d_GetDirectionalMatrix (unsigned int index) +{ + int _index = (((index / 3) * 4) + (index % 3)); + + //return (s32)(mtxCurrent[2][_index]*(1<<12)); + return mtxCurrent[2][_index]; +} + +void gfx3d_glAlphaFunc(u32 v) +{ + gfx3d.state.alphaTestRef = v&31; +} + +unsigned int gfx3d_glGetPosRes(unsigned int index) +{ + return (unsigned int)(PTcoords[index] * 4096.0f); +} + +//#define _3D_LOG_EXEC +#ifdef _3D_LOG_EXEC +static void log3D(u8 cmd, u32 param) +{ + INFO("3D command 0x%02X: ", cmd); + switch (cmd) + { + case 0x10: // MTX_MODE - Set Matrix Mode (W) + printf("MTX_MODE(%08X)", param); + break; + case 0x11: // MTX_PUSH - Push Current Matrix on Stack (W) + printf("MTX_PUSH()\t"); + break; + case 0x12: // MTX_POP - Pop Current Matrix from Stack (W) + printf("MTX_POP(%08X)", param); + break; + case 0x13: // MTX_STORE - Store Current Matrix on Stack (W) + printf("MTX_STORE(%08X)", param); + break; + case 0x14: // MTX_RESTORE - Restore Current Matrix from Stack (W) + printf("MTX_RESTORE(%08X)", param); + break; + case 0x15: // MTX_IDENTITY - Load Unit Matrix to Current Matrix (W) + printf("MTX_IDENTIFY()\t"); + break; + case 0x16: // MTX_LOAD_4x4 - Load 4x4 Matrix to Current Matrix (W) + printf("MTX_LOAD_4x4(%08X)", param); + break; + case 0x17: // MTX_LOAD_4x3 - Load 4x3 Matrix to Current Matrix (W) + printf("MTX_LOAD_4x3(%08X)", param); + break; + case 0x18: // MTX_MULT_4x4 - Multiply Current Matrix by 4x4 Matrix (W) + printf("MTX_MULT_4x4(%08X)", param); + break; + case 0x19: // MTX_MULT_4x3 - Multiply Current Matrix by 4x3 Matrix (W) + printf("MTX_MULT_4x3(%08X)", param); + break; + case 0x1A: // MTX_MULT_3x3 - Multiply Current Matrix by 3x3 Matrix (W) + printf("MTX_MULT_3x3(%08X)", param); + break; + case 0x1B: // MTX_SCALE - Multiply Current Matrix by Scale Matrix (W) + printf("MTX_SCALE(%08X)", param); + break; + case 0x1C: // MTX_TRANS - Mult. Curr. Matrix by Translation Matrix (W) + printf("MTX_TRANS(%08X)", param); + break; + case 0x20: // COLOR - Directly Set Vertex Color (W) + printf("COLOR(%08X)", param); + break; + case 0x21: // NORMAL - Set Normal Vector (W) + printf("NORMAL(%08X)", param); + break; + case 0x22: // TEXCOORD - Set Texture Coordinates (W) + printf("TEXCOORD(%08X)", param); + break; + case 0x23: // VTX_16 - Set Vertex XYZ Coordinates (W) + printf("VTX_16(%08X)", param); + break; + case 0x24: // VTX_10 - Set Vertex XYZ Coordinates (W) + printf("VTX_10(%08X)", param); + break; + case 0x25: // VTX_XY - Set Vertex XY Coordinates (W) + printf("VTX_XY(%08X)", param); + break; + case 0x26: // VTX_XZ - Set Vertex XZ Coordinates (W) + printf("VTX_XZ(%08X)", param); + break; + case 0x27: // VTX_YZ - Set Vertex YZ Coordinates (W) + printf("VTX_YZ(%08X)", param); + break; + case 0x28: // VTX_DIFF - Set Relative Vertex Coordinates (W) + printf("VTX_DIFF(%08X)", param); + break; + case 0x29: // POLYGON_ATTR - Set Polygon Attributes (W) + printf("POLYGON_ATTR(%08X)", param); + break; + case 0x2A: // TEXIMAGE_PARAM - Set Texture Parameters (W) + printf("TEXIMAGE_PARAM(%08X)", param); + break; + case 0x2B: // PLTT_BASE - Set Texture Palette Base Address (W) + printf("PLTT_BASE(%08X)", param); + break; + case 0x30: // DIF_AMB - MaterialColor0 - Diffuse/Ambient Reflect. (W) + printf("DIF_AMB(%08X)", param); + break; + case 0x31: // SPE_EMI - MaterialColor1 - Specular Ref. & Emission (W) + printf("SPE_EMI(%08X)", param); + break; + case 0x32: // LIGHT_VECTOR - Set Light's Directional Vector (W) + printf("LIGHT_VECTOR(%08X)", param); + break; + case 0x33: // LIGHT_COLOR - Set Light Color (W) + printf("LIGHT_COLOR(%08X)", param); + break; + case 0x34: // SHININESS - Specular Reflection Shininess Table (W) + printf("SHININESS(%08X)", param); + break; + case 0x40: // BEGIN_VTXS - Start of Vertex List (W) + printf("BEGIN_VTXS(%08X)", param); + break; + case 0x41: // END_VTXS - End of Vertex List (W) + printf("END_VTXS()\t"); + break; + case 0x50: // SWAP_BUFFERS - Swap Rendering Engine Buffer (W) + printf("SWAP_BUFFERS(%08X)", param); + break; + case 0x60: // VIEWPORT - Set Viewport (W) + printf("VIEWPORT(%08X)", param); + break; + case 0x70: // BOX_TEST - Test if Cuboid Sits inside View Volume (W) + printf("BOX_TEST(%08X)", param); + break; + case 0x71: // POS_TEST - Set Position Coordinates for Test (W) + printf("POS_TEST(%08X)", param); + break; + case 0x72: // VEC_TEST - Set Directional Vector for Test (W) + printf("VEC_TEST(%08X)", param); + break; + default: + INFO("!!! Unknown(%08X)", param); + break; + } + printf("\t\t(FIFO size %i)\n", gxFIFO.size); +} +#endif + +static void gfx3d_execute(u8 cmd, u32 param) +{ +#ifdef _3D_LOG_EXEC + log3D(cmd, param); +#endif + + switch (cmd) + { + case 0x10: // MTX_MODE - Set Matrix Mode (W) + gfx3d_glMatrixMode(param); + break; + case 0x11: // MTX_PUSH - Push Current Matrix on Stack (W) + gfx3d_glPushMatrix(); + break; + case 0x12: // MTX_POP - Pop Current Matrix from Stack (W) + gfx3d_glPopMatrix(param); + break; + case 0x13: // MTX_STORE - Store Current Matrix on Stack (W) + gfx3d_glStoreMatrix(param); + break; + case 0x14: // MTX_RESTORE - Restore Current Matrix from Stack (W) + gfx3d_glRestoreMatrix(param); + break; + case 0x15: // MTX_IDENTITY - Load Unit Matrix to Current Matrix (W) + gfx3d_glLoadIdentity(); + break; + case 0x16: // MTX_LOAD_4x4 - Load 4x4 Matrix to Current Matrix (W) + gfx3d_glLoadMatrix4x4(param); + break; + case 0x17: // MTX_LOAD_4x3 - Load 4x3 Matrix to Current Matrix (W) + gfx3d_glLoadMatrix4x3(param); + break; + case 0x18: // MTX_MULT_4x4 - Multiply Current Matrix by 4x4 Matrix (W) + gfx3d_glMultMatrix4x4(param); + break; + case 0x19: // MTX_MULT_4x3 - Multiply Current Matrix by 4x3 Matrix (W) + gfx3d_glMultMatrix4x3(param); + break; + case 0x1A: // MTX_MULT_3x3 - Multiply Current Matrix by 3x3 Matrix (W) + gfx3d_glMultMatrix3x3(param); + break; + case 0x1B: // MTX_SCALE - Multiply Current Matrix by Scale Matrix (W) + gfx3d_glScale(param); + break; + case 0x1C: // MTX_TRANS - Mult. Curr. Matrix by Translation Matrix (W) + gfx3d_glTranslate(param); + break; + case 0x20: // COLOR - Directly Set Vertex Color (W) + gfx3d_glColor3b(param); + break; + case 0x21: // NORMAL - Set Normal Vector (W) + gfx3d_glNormal(param); + break; + case 0x22: // TEXCOORD - Set Texture Coordinates (W) + gfx3d_glTexCoord(param); + break; + case 0x23: // VTX_16 - Set Vertex XYZ Coordinates (W) + gfx3d_glVertex16b(param); + break; + case 0x24: // VTX_10 - Set Vertex XYZ Coordinates (W) + gfx3d_glVertex10b(param); + break; + case 0x25: // VTX_XY - Set Vertex XY Coordinates (W) + gfx3d_glVertex3_cord<0,1>(param); + break; + case 0x26: // VTX_XZ - Set Vertex XZ Coordinates (W) + gfx3d_glVertex3_cord<0,2>(param); + break; + case 0x27: // VTX_YZ - Set Vertex YZ Coordinates (W) + gfx3d_glVertex3_cord<1,2>(param); + break; + case 0x28: // VTX_DIFF - Set Relative Vertex Coordinates (W) + gfx3d_glVertex_rel(param); + break; + case 0x29: // POLYGON_ATTR - Set Polygon Attributes (W) + gfx3d_glPolygonAttrib(param); + break; + case 0x2A: // TEXIMAGE_PARAM - Set Texture Parameters (W) + gfx3d_glTexImage(param); + break; + case 0x2B: // PLTT_BASE - Set Texture Palette Base Address (W) + gfx3d_glTexPalette(param); + break; + case 0x30: // DIF_AMB - MaterialColor0 - Diffuse/Ambient Reflect. (W) + gfx3d_glMaterial0(param); + break; + case 0x31: // SPE_EMI - MaterialColor1 - Specular Ref. & Emission (W) + gfx3d_glMaterial1(param); + break; + case 0x32: // LIGHT_VECTOR - Set Light's Directional Vector (W) + gfx3d_glLightDirection(param); + break; + case 0x33: // LIGHT_COLOR - Set Light Color (W) + gfx3d_glLightColor(param); + break; + case 0x34: // SHININESS - Specular Reflection Shininess Table (W) + gfx3d_glShininess(param); + break; + case 0x40: // BEGIN_VTXS - Start of Vertex List (W) + gfx3d_glBegin(param); + break; + case 0x41: // END_VTXS - End of Vertex List (W) + gfx3d_glEnd(); + break; + case 0x50: // SWAP_BUFFERS - Swap Rendering Engine Buffer (W) + gfx3d_glFlush(param); + break; + case 0x60: // VIEWPORT - Set Viewport (W) + gfx3d_glViewPort(param); + break; + case 0x70: // BOX_TEST - Test if Cuboid Sits inside View Volume (W) + gfx3d_glBoxTest(param); + break; + case 0x71: // POS_TEST - Set Position Coordinates for Test (W) + gfx3d_glPosTest(param); + break; + case 0x72: // VEC_TEST - Set Directional Vector for Test (W) + gfx3d_glVecTest(param); + break; + default: + INFO("Unknown execute FIFO 3D command 0x%02X with param 0x%08X\n", cmd, param); + break; + } +} + +void gfx3d_execute3D() +{ + u8 cmd = 0; + u32 param = 0; + +#ifndef FLUSHMODE_HACK + if (isSwapBuffers) return; +#endif + + //this is a SPEED HACK + //fifo is currently emulated more accurately than it probably needs to be. + //without this batch size the emuloop will escape way too often to run fast. + const int HACK_FIFO_BATCH_SIZE = 64; + + for(int i=0;i<HACK_FIFO_BATCH_SIZE;i++) { + if(GFX_PIPErecv(&cmd, ¶m)) + { + //if (isSwapBuffers) printf("Executing while swapbuffers is pending: %d:%08X\n",cmd,param); + + //since we did anything at all, incur a pipeline motion cost. + //also, we can't let gxfifo sequencer stall until the fifo is empty. + //see... + GFX_DELAY(1); + + //..these guys will ordinarily set a delay, but multi-param operations won't + //for the earlier params. + //printf("%05d:%03d:%12lld: executed 3d: %02X %08X\n",currFrameCounter, nds.VCount, nds_timer , cmd, param); + gfx3d_execute(cmd, param); + + //this is a COMPATIBILITY HACK. + //this causes 3d to take virtually no time whatsoever to execute. + //this was done for marvel nemesis, but a similar family of + //hacks for ridiculously fast 3d execution has proven necessary for a number of games. + //the true answer is probably dma bus blocking.. but lets go ahead and try this and + //check the compatibility, at the very least it will be nice to know if any games suffer from + //3d running too fast + MMU.gfx3dCycles = nds_timer+1; + } else break; + } + +} + +void gfx3d_glFlush(u32 v) +{ + //printf("-------------FLUSH------------- (vcount=%d\n",nds.VCount); + gfx3d.state.pendingFlushCommand = v; +#if 0 + if (isSwapBuffers) + { + INFO("Error: swapBuffers already use\n"); + } +#endif + + isSwapBuffers = TRUE; + + //printf("%05d:%03d:%12lld: FLUSH\n",currFrameCounter, nds.VCount, nds_timer); + + //well, the game wanted us to flush. + //it may be badly timed. lets just flush it. +#ifdef FLUSHMODE_HACK + gfx3d_doFlush(); +#endif + + GFX_DELAY(1); +} + +static bool gfx3d_ysort_compare(int num1, int num2) +{ + const POLY &poly1 = polylist->list[num1]; + const POLY &poly2 = polylist->list[num2]; + + //this may be verified by checking the game create menus in harvest moon island of happiness + //also the buttons in the knights in the nightmare frontend depend on this and the perspective division + if (poly1.maxy < poly2.maxy) return true; + if (poly1.maxy > poly2.maxy) return false; + if (poly1.miny < poly2.miny) return true; + if (poly1.miny > poly2.miny) return false; + //notably, the main shop interface in harvest moon will not have a correct RTN button + //i think this is due to a math error rounding its position to one pixel too high and it popping behind + //the bar that it sits on. + //everything else in all the other menus that I could find looks right.. + + //make sure we respect the game's ordering in cases of complete ties + //this makes it a stable sort. + //this must be a stable sort or else advance wars DOR will flicker in the main map mode + if (num1 < num2) return true; + else return false; +} + +static void gfx3d_doFlush() +{ + gfx3d.frameCtr++; + + //the renderer will get the lists we just built + gfx3d.polylist = polylist; + gfx3d.vertlist = vertlist; + + //and also our current render state + if(BIT1(control)) gfx3d.state.shading = GFX3D_State::HIGHLIGHT; + else gfx3d.state.shading = GFX3D_State::TOON; + gfx3d.state.enableTexturing = BIT0(control); + gfx3d.state.enableAlphaTest = BIT2(control); + gfx3d.state.enableAlphaBlending = BIT3(control); + gfx3d.state.enableAntialiasing = BIT4(control); + gfx3d.state.enableEdgeMarking = BIT5(control); + gfx3d.state.enableFogAlphaOnly = BIT6(control); + gfx3d.state.enableFog = BIT7(control); + gfx3d.state.enableClearImage = BIT14(control); + gfx3d.state.fogShift = (control>>8)&0xF; + gfx3d.state.sortmode = BIT0(gfx3d.state.activeFlushCommand); + gfx3d.state.wbuffer = BIT1(gfx3d.state.activeFlushCommand); + + gfx3d.renderState = gfx3d.state; + + if(!CommonSettings.GFX3D_Texture) + gfx3d.renderState.enableTexturing = false; + + gfx3d.state.activeFlushCommand = gfx3d.state.pendingFlushCommand; + + int polycount = polylist->count; +#ifdef _SHOW_VTX_COUNTERS + max_polys = max((u32)polycount, max_polys); + max_verts = max((u32)vertlist->count, max_verts); + osd->addFixed(180, 20, "%i/%i", polycount, vertlist->count); // current + osd->addFixed(180, 35, "%i/%i", max_polys, max_verts); // max +#endif + + //find the min and max y values for each poly. + //TODO - this could be a small waste of time if we are manual sorting the translucent polys + //TODO - this _MUST_ be moved later in the pipeline, after clipping. + //the w-division here is just an approximation to fix the shop in harvest moon island of happiness + //also the buttons in the knights in the nightmare frontend depend on this + for(int i=0; i<polycount; i++) + { + POLY &poly = polylist->list[i]; + float verty = vertlist->list[poly.vertIndexes[0]].y; + float vertw = vertlist->list[poly.vertIndexes[0]].w; + verty = 1.0f-(verty+vertw)/(2*vertw); + poly.miny = poly.maxy = verty; + + for(int j=1; j<poly.type; j++) + { + verty = vertlist->list[poly.vertIndexes[j]].y; + vertw = vertlist->list[poly.vertIndexes[j]].w; + verty = 1.0f-(verty+vertw)/(2*vertw); + poly.miny = min(poly.miny, verty); + poly.maxy = max(poly.maxy, verty); + } + + } + + //we need to sort the poly list with alpha polys last + //first, look for opaque polys + int ctr=0; + for(int i=0;i<polycount;i++) { + POLY &poly = polylist->list[i]; + if(!poly.isTranslucent()) + gfx3d.indexlist.list[ctr++] = i; + } + int opaqueCount = ctr; + //then look for translucent polys + for(int i=0;i<polycount;i++) { + POLY &poly = polylist->list[i]; + if(poly.isTranslucent()) + gfx3d.indexlist.list[ctr++] = i; + } + + //now we have to sort the opaque polys by y-value. + //(test case: harvest moon island of happiness character cretor UI) + //should this be done after clipping?? + std::sort(gfx3d.indexlist.list, gfx3d.indexlist.list + opaqueCount, gfx3d_ysort_compare); + + if(!gfx3d.state.sortmode) + { + //if we are autosorting translucent polys, we need to do this also + //TODO - this is unverified behavior. need a test case + std::sort(gfx3d.indexlist.list + opaqueCount, gfx3d.indexlist.list + polycount, gfx3d_ysort_compare); + } + + //switch to the new lists + twiddleLists(); + + if(driver->view3d->IsRunning()) + { + viewer3d_state->frameNumber = currFrameCounter; + viewer3d_state->state = gfx3d.state; + viewer3d_state->polylist = *gfx3d.polylist; + viewer3d_state->vertlist = *gfx3d.vertlist; + viewer3d_state->indexlist = gfx3d.indexlist; + driver->view3d->NewFrame(); + } + + drawPending = TRUE; +} + +void gfx3d_VBlankSignal() +{ + if (isSwapBuffers) + { +#ifndef FLUSHMODE_HACK + gfx3d_doFlush(); +#endif + GFX_DELAY(392); + isSwapBuffers = FALSE; + } +} + +void gfx3d_VBlankEndSignal(bool skipFrame) +{ + if (!drawPending) return; + if(skipFrame) return; + + drawPending = FALSE; + + bool isNull = gpu3D == &gpu3DNull; + bool noMain = !CommonSettings.showGpu.main; + //if the null 3d core is chosen, then we need to clear out the 3d buffers to keep old data from being rendered + if(isNull || noMain) + { + memset(gfx3d_convertedScreen,0,sizeof(gfx3d_convertedScreen)); + return; + } + + gpu3D->NDS_3D_Render(); +} + +//#define _3D_LOG + +void gfx3d_sendCommandToFIFO(u32 val) +{ + //printf("gxFIFO: send val=0x%08X, size=%03i (fifo)\n", val, gxFIFO.size); + + gxf_hardware.receive(val); +} + +void gfx3d_sendCommand(u32 cmd, u32 param) +{ + cmd = (cmd & 0x01FF) >> 2; + + //printf("gxFIFO: send 0x%02X: val=0x%08X, size=%03i (direct)\n", cmd, param, gxFIFO.size); + +#ifdef _3D_LOG + INFO("gxFIFO: send 0x%02X: val=0x%08X, pipe %02i, fifo %03i (direct)\n", cmd, param, gxPIPE.tail, gxFIFO.tail); +#endif + + switch (cmd) + { + case 0x10: // MTX_MODE - Set Matrix Mode (W) + case 0x11: // MTX_PUSH - Push Current Matrix on Stack (W) + case 0x12: // MTX_POP - Pop Current Matrix from Stack (W) + case 0x13: // MTX_STORE - Store Current Matrix on Stack (W) + case 0x14: // MTX_RESTORE - Restore Current Matrix from Stack (W) + case 0x15: // MTX_IDENTITY - Load Unit Matrix to Current Matrix (W) + case 0x16: // MTX_LOAD_4x4 - Load 4x4 Matrix to Current Matrix (W) + case 0x17: // MTX_LOAD_4x3 - Load 4x3 Matrix to Current Matrix (W) + case 0x18: // MTX_MULT_4x4 - Multiply Current Matrix by 4x4 Matrix (W) + case 0x19: // MTX_MULT_4x3 - Multiply Current Matrix by 4x3 Matrix (W) + case 0x1A: // MTX_MULT_3x3 - Multiply Current Matrix by 3x3 Matrix (W) + case 0x1B: // MTX_SCALE - Multiply Current Matrix by Scale Matrix (W) + case 0x1C: // MTX_TRANS - Mult. Curr. Matrix by Translation Matrix (W) + case 0x20: // COLOR - Directly Set Vertex Color (W) + case 0x21: // NORMAL - Set Normal Vector (W) + case 0x22: // TEXCOORD - Set Texture Coordinates (W) + case 0x23: // VTX_16 - Set Vertex XYZ Coordinates (W) + case 0x24: // VTX_10 - Set Vertex XYZ Coordinates (W) + case 0x25: // VTX_XY - Set Vertex XY Coordinates (W) + case 0x26: // VTX_XZ - Set Vertex XZ Coordinates (W) + case 0x27: // VTX_YZ - Set Vertex YZ Coordinates (W) + case 0x28: // VTX_DIFF - Set Relative Vertex Coordinates (W) + case 0x29: // POLYGON_ATTR - Set Polygon Attributes (W) + case 0x2A: // TEXIMAGE_PARAM - Set Texture Parameters (W) + case 0x2B: // PLTT_BASE - Set Texture Palette Base Address (W) + case 0x30: // DIF_AMB - MaterialColor0 - Diffuse/Ambient Reflect. (W) + case 0x31: // SPE_EMI - MaterialColor1 - Specular Ref. & Emission (W) + case 0x32: // LIGHT_VECTOR - Set Light's Directional Vector (W) + case 0x33: // LIGHT_COLOR - Set Light Color (W) + case 0x34: // SHININESS - Specular Reflection Shininess Table (W) + case 0x40: // BEGIN_VTXS - Start of Vertex List (W) + case 0x41: // END_VTXS - End of Vertex List (W) + case 0x60: // VIEWPORT - Set Viewport (W) + case 0x70: // BOX_TEST - Test if Cuboid Sits inside View Volume (W) + case 0x71: // POS_TEST - Set Position Coordinates for Test (W) + case 0x72: // VEC_TEST - Set Directional Vector for Test (W) + //printf("mmu: sending %02X: %08X\n", cmd,param); + GFX_FIFOsend(cmd, param); + break; + case 0x50: // SWAP_BUFFERS - Swap Rendering Engine Buffer (W) + //printf("mmu: sending %02X: %08X\n", cmd,param); + GFX_FIFOsend(cmd, param); + break; + default: + INFO("Unknown 3D command %03X with param 0x%08X (directport)\n", cmd, param); + break; + } +} + + + +void gfx3d_Control(u32 v) +{ + control = v; +} + +//-------------- +//other misc stuff +void gfx3d_glGetMatrix(unsigned int m_mode, int index, float* dest) +{ + //if(index == -1) + //{ + // MatrixCopy(dest, mtxCurrent[m_mode]); + // return; + //} + + //MatrixCopy(dest, MatrixStackGetPos(&mtxStack[m_mode], index)); + s32* src; + if(index==-1) + src = mtxCurrent[m_mode]; + else src=MatrixStackGetPos(&mtxStack[m_mode],index); + for(int i=0;i<16;i++) + dest[i] = src[i]/4096.0f; +} + +void gfx3d_glGetLightDirection(unsigned int index, unsigned int* dest) +{ + *dest = lightDirection[index]; +} + +void gfx3d_glGetLightColor(unsigned int index, unsigned int* dest) +{ + *dest = lightColor[index]; +} + +void gfx3d_GetLineData(int line, u8** dst) +{ + *dst = gfx3d_convertedScreen+((line)<<(8+2)); +} + +void gfx3d_GetLineData15bpp(int line, u16** dst) +{ + //TODO - this is not very thread safe!!! + static u16 buf[256]; + *dst = buf; + + u8* lineData; + gfx3d_GetLineData(line, &lineData); + for(int i=0;i<256;i++) + { + const u8 r = lineData[i*4+0]; + const u8 g = lineData[i*4+1]; + const u8 b = lineData[i*4+2]; + const u8 a = lineData[i*4+3]; + buf[i] = R6G6B6TORGB15(r,g,b) | (a==0?0:0x8000); + } +} + + +//http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node17.html +//talks about the state required to process verts in quadlists etc. helpful ideas. +//consider building a little state structure that looks exactly like this describes + +SFORMAT SF_GFX3D[]={ + { "GCTL", 4, 1, &control}, // no longer regenerated indirectly, see comment in loadstate() + { "GPAT", 4, 1, &polyAttr}, + { "GPAP", 4, 1, &polyAttrPending}, + { "GINB", 4, 1, &inBegin}, + { "GTFM", 4, 1, &textureFormat}, + { "GTPA", 4, 1, &texturePalette}, + { "GMOD", 4, 1, &mode}, + { "GMTM", 4,16, mtxTemporal}, + { "GMCU", 4,64, mtxCurrent}, + { "ML4I", 1, 1, &ML4x4ind}, + { "ML3I", 1, 1, &ML4x3ind}, + { "MM4I", 1, 1, &MM4x4ind}, + { "MM3I", 1, 1, &MM4x3ind}, + { "MMxI", 1, 1, &MM3x3ind}, + { "GSCO", 4, 1, s16coord}, + { "GCOI", 1, 1, &coordind}, + { "GVFM", 4, 1, &vtxFormat}, + { "GTRN", 4, 4, trans}, + { "GTRI", 1, 1, &transind}, + { "GSCA", 4, 4, scale}, + { "GSCI", 1, 1, &scaleind}, + { "G_T_", 4, 1, &_t}, + { "G_S_", 4, 1, &_s}, + { "GL_T", 4, 1, &last_t}, + { "GL_S", 4, 1, &last_s}, + { "GLCM", 4, 1, &clCmd}, + { "GLIN", 4, 1, &clInd}, + { "GLI2", 4, 1, &clInd2}, + { "GLSB", 4, 1, &isSwapBuffers}, + { "GLBT", 4, 1, &BTind}, + { "GLPT", 4, 1, &PTind}, + { "GLPC", 4, 4, PTcoords}, + { "GBTC", 2, 6, &BTcoords[0]}, + { "GFHE", 4, 1, &gxFIFO.head}, + { "GFTA", 4, 1, &gxFIFO.tail}, + { "GFSZ", 4, 1, &gxFIFO.size}, + { "GFMS", 4, 1, &gxFIFO.matrix_stack_op_size}, + { "GFCM", 1, HACK_GXIFO_SIZE, &gxFIFO.cmd[0]}, + { "GFPM", 4, HACK_GXIFO_SIZE, &gxFIFO.param[0]}, + { "GPHE", 1, 1, &gxPIPE.head}, + { "GPTA", 1, 1, &gxPIPE.tail}, + { "GPSZ", 1, 1, &gxPIPE.size}, + { "GPCM", 1, 4, &gxPIPE.cmd[0]}, + { "GPPM", 4, 4, &gxPIPE.param[0]}, + { "GCOL", 1, 4, &colorRGB[0]}, + { "GLCO", 4, 4, lightColor}, + { "GLDI", 4, 4, lightDirection}, + { "GMDI", 2, 1, &dsDiffuse}, + { "GMAM", 2, 1, &dsAmbient}, + { "GMSP", 2, 1, &dsSpecular}, + { "GMEM", 2, 1, &dsEmission}, + { "GFLP", 4, 1, &flushPending}, + { "GDRP", 4, 1, &drawPending}, + { "GSET", 4, 1, &gfx3d.state.enableTexturing}, + { "GSEA", 4, 1, &gfx3d.state.enableAlphaTest}, + { "GSEB", 4, 1, &gfx3d.state.enableAlphaBlending}, + { "GSEX", 4, 1, &gfx3d.state.enableAntialiasing}, + { "GSEE", 4, 1, &gfx3d.state.enableEdgeMarking}, + { "GSEC", 4, 1, &gfx3d.state.enableClearImage}, + { "GSEF", 4, 1, &gfx3d.state.enableFog}, + { "GSEO", 4, 1, &gfx3d.state.enableFogAlphaOnly}, + { "GFSH", 4, 1, &gfx3d.state.fogShift}, + { "GSSH", 4, 1, &gfx3d.state.shading}, + { "GSWB", 4, 1, &gfx3d.state.wbuffer}, + { "GSSM", 4, 1, &gfx3d.state.sortmode}, + { "GSAR", 1, 1, &gfx3d.state.alphaTestRef}, + { "GSVP", 4, 1, &viewport}, + { "GSCC", 4, 1, &gfx3d.state.clearColor}, + { "GSCD", 4, 1, &gfx3d.state.clearDepth}, + { "GSFC", 4, 4, &gfx3d.state.fogColor}, + { "GSFO", 4, 1, &gfx3d.state.fogOffset}, + { "GST4", 2, 32, gfx3d.state.u16ToonTable}, + { "GSSU", 1, 128, &gfx3d.state.shininessTable[0]}, + { "GSSI", 4, 1, &shininessInd}, + { "GSAF", 4, 1, &gfx3d.state.activeFlushCommand}, + { "GSPF", 4, 1, &gfx3d.state.pendingFlushCommand}, + //------------------------ + { "GTST", 4, 1, &triStripToggle}, + { "GTVC", 4, 1, &tempVertInfo.count}, + { "GTVM", 4, 4, tempVertInfo.map}, + { "GTVF", 4, 1, &tempVertInfo.first}, + { "G3CX", 1, 4*256*192, gfx3d_convertedScreen}, + { 0 } +}; + +//-------------savestate +void gfx3d_savestate(EMUFILE* os) +{ + //version + write32le(4,os); + + //dump the render lists + OSWRITE(vertlist->count); + for(int i=0;i<vertlist->count;i++) + vertlist->list[i].save(os); + OSWRITE(polylist->count); + for(int i=0;i<polylist->count;i++) + polylist->list[i].save(os); + + for(int i=0;i<4;i++) + { + OSWRITE(mtxStack[i].position); + for(int j=0;j<mtxStack[i].size*16;j++) + OSWRITE(mtxStack[i].matrix[j]); + } + + gxf_hardware.savestate(os); + + // evidently these need to be saved because we don't cache the matrix that would need to be used to properly regenerate them + OSWRITE(cacheLightDirection); + OSWRITE(cacheHalfVector); +} + +bool gfx3d_loadstate(EMUFILE* is, int size) +{ + int version; + if(read32le(&version,is) != 1) return false; + if(size==8) version = 0; + + + gfx3d_glPolygonAttrib_cache(); + gfx3d_glTexImage_cache(); + gfx3d_glLightDirection_cache(0); + gfx3d_glLightDirection_cache(1); + gfx3d_glLightDirection_cache(2); + gfx3d_glLightDirection_cache(3); + + //jiggle the lists. and also wipe them. this is clearly not the best thing to be doing. + listTwiddle = 0; + polylist = &polylists[listTwiddle]; + vertlist = &vertlists[listTwiddle]; + + if(version>=1) + { + OSREAD(vertlist->count); + for(int i=0;i<vertlist->count;i++) + vertlist->list[i].load(is); + OSREAD(polylist->count); + for(int i=0;i<polylist->count;i++) + polylist->list[i].load(is); + } + + if(version>=2) + { + for(int i=0;i<4;i++) + { + OSREAD(mtxStack[i].position); + for(int j=0;j<mtxStack[i].size*16;j++) + OSREAD(mtxStack[i].matrix[j]); + } + } + + if(version>=3) { + gxf_hardware.loadstate(is); + } + + gfx3d.polylist = &polylists[listTwiddle^1]; + gfx3d.vertlist = &vertlists[listTwiddle^1]; + gfx3d.polylist->count=0; + gfx3d.vertlist->count=0; + + if(version >= 4) + { + OSREAD(cacheLightDirection); + OSREAD(cacheHalfVector); + } + + return true; +} + +//------------------- +//clipping +//------------------- + +// this is optional for now in case someone has trouble with the new method +// or wants to toggle it to compare +#define OPTIMIZED_CLIPPING_METHOD + +//#define CLIPLOG(X) printf(X); +//#define CLIPLOG2(X,Y,Z) printf(X,Y,Z); +#define CLIPLOG(X) +#define CLIPLOG2(X,Y,Z) + +template<typename T> +static T interpolate(const float ratio, const T& x0, const T& x1) { + return (T)(x0 + (float)(x1-x0) * (ratio)); +} + + +//http://www.cs.berkeley.edu/~ug/slide/pipeline/assignments/as6/discussion.shtml +#ifdef OPTIMIZED_CLIPPING_METHOD +template<int coord, int which> static FORCEINLINE VERT clipPoint(bool hirez, VERT* inside, VERT* outside) +#else +static FORCEINLINE VERT clipPoint(VERT* inside, VERT* outside, int coord, int which) +#endif +{ + VERT ret; + + float coord_inside = inside->coord[coord]; + float coord_outside = outside->coord[coord]; + float w_inside = inside->coord[3]; + float w_outside = outside->coord[3]; + + float t; + + if(which==-1) { + w_outside = -w_outside; + w_inside = -w_inside; + } + + t = (coord_inside - w_inside)/ ((w_outside-w_inside) - (coord_outside-coord_inside)); + + +#define INTERP(X) ret . X = interpolate(t, inside-> X ,outside-> X ) + + INTERP(coord[0]); INTERP(coord[1]); INTERP(coord[2]); INTERP(coord[3]); + INTERP(texcoord[0]); INTERP(texcoord[1]); + + //if(CommonSettings.GFX3D_HighResolutionInterpolateColor) + if(hirez) + { + INTERP(fcolor[0]); INTERP(fcolor[1]); INTERP(fcolor[2]); + } + else + { + INTERP(color[0]); INTERP(color[1]); INTERP(color[2]); + ret.color_to_float(); + } + + //this seems like a prudent measure to make sure that math doesnt make a point pop back out + //of the clip volume through interpolation + if(which==-1) + ret.coord[coord] = -ret.coord[3]; + else + ret.coord[coord] = ret.coord[3]; + + return ret; +} + +#ifdef OPTIMIZED_CLIPPING_METHOD + +#define MAX_SCRATCH_CLIP_VERTS (4*6 + 40) +static VERT scratchClipVerts [MAX_SCRATCH_CLIP_VERTS]; +static int numScratchClipVerts = 0; + +template <int coord, int which, class Next> +class ClipperPlane +{ +public: + ClipperPlane(Next& next) : m_next(next) {} + + void init(VERT* verts) + { + m_prevVert = NULL; + m_firstVert = NULL; + m_next.init(verts); + } + + void clipVert(bool hirez, VERT* vert) + { + if(m_prevVert) + this->clipSegmentVsPlane(hirez, m_prevVert, vert); + else + m_firstVert = vert; + m_prevVert = vert; + } + + // closes the loop and returns the number of clipped output verts + int finish(bool hirez) + { + this->clipVert(hirez, m_firstVert); + return m_next.finish(hirez); + } + +private: + + VERT* m_prevVert; + VERT* m_firstVert; + Next& m_next; + + FORCEINLINE void clipSegmentVsPlane(bool hirez, VERT* vert0, VERT* vert1) + { + float* vert0coord = vert0->coord; + float* vert1coord = vert1->coord; + bool out0, out1; + if(which==-1) + out0 = vert0coord[coord] < -vert0coord[3]; + else + out0 = vert0coord[coord] > vert0coord[3]; + if(which==-1) + out1 = vert1coord[coord] < -vert1coord[3]; + else + out1 = vert1coord[coord] > vert1coord[3]; + + //CONSIDER: should we try and clip things behind the eye? does this code even successfully do it? not sure. + //if(coord==2 && which==1) { + // out0 = vert0coord[2] < 0; + // out1 = vert1coord[2] < 0; + //} + + //both outside: insert no points + if(out0 && out1) { + CLIPLOG(" both outside\n"); + } + + //both inside: insert the next point + if(!out0 && !out1) + { + CLIPLOG(" both inside\n"); + m_next.clipVert(hirez,vert1); + } + + //exiting volume: insert the clipped point + if(!out0 && out1) + { + CLIPLOG(" exiting\n"); + assert((u32)numScratchClipVerts < MAX_SCRATCH_CLIP_VERTS); + scratchClipVerts[numScratchClipVerts] = clipPoint<coord, which>(hirez,vert0,vert1); + m_next.clipVert(hirez,&scratchClipVerts[numScratchClipVerts++]); + } + + //entering volume: insert clipped point and the next (interior) point + if(out0 && !out1) { + CLIPLOG(" entering\n"); + assert((u32)numScratchClipVerts < MAX_SCRATCH_CLIP_VERTS); + scratchClipVerts[numScratchClipVerts] = clipPoint<coord, which>(hirez,vert1,vert0); + m_next.clipVert(hirez,&scratchClipVerts[numScratchClipVerts++]); + m_next.clipVert(hirez,vert1); + } + } +}; + +class ClipperOutput +{ +public: + void init(VERT* verts) + { + m_nextDestVert = verts; + m_numVerts = 0; + } + void clipVert(bool hirez, VERT* vert) + { + assert((u32)m_numVerts < MAX_CLIPPED_VERTS); + *m_nextDestVert++ = *vert; + m_numVerts++; + } + int finish(bool hirez) + { + return m_numVerts; + } +private: + VERT* m_nextDestVert; + int m_numVerts; +}; + +// see "Template juggling with Sutherland-Hodgman" http://www.codeguru.com/cpp/misc/misc/graphics/article.php/c8965__2/ +// for the idea behind setting things up like this. +static ClipperOutput clipperOut; +typedef ClipperPlane<2, 1,ClipperOutput> Stage6; static Stage6 clipper6 (clipperOut); // back plane //TODO - we need to parameterize back plane clipping +typedef ClipperPlane<2,-1,Stage6> Stage5; static Stage5 clipper5 (clipper6); // front plane +typedef ClipperPlane<1, 1,Stage5> Stage4; static Stage4 clipper4 (clipper5); // top plane +typedef ClipperPlane<1,-1,Stage4> Stage3; static Stage3 clipper3 (clipper4); // bottom plane +typedef ClipperPlane<0, 1,Stage3> Stage2; static Stage2 clipper2 (clipper3); // right plane +typedef ClipperPlane<0,-1,Stage2> Stage1; static Stage1 clipper (clipper2); // left plane + +template<bool hirez> void GFX3D_Clipper::clipPoly(POLY* poly, VERT** verts) +{ + CLIPLOG("==Begin poly==\n"); + + int type = poly->type; + numScratchClipVerts = 0; + + clipper.init(clippedPolys[clippedPolyCounter].clipVerts); + for(int i=0;i<type;i++) + clipper.clipVert(hirez,verts[i]); + int outType = clipper.finish(hirez); + + assert((u32)outType < MAX_CLIPPED_VERTS); + if(outType < 3) + { + //a totally clipped poly. discard it. + //or, a degenerate poly. we're not handling these right now + } + else + { + clippedPolys[clippedPolyCounter].type = outType; + clippedPolys[clippedPolyCounter].poly = poly; + clippedPolyCounter++; + } +} +//these templates needed to be instantiated manually +template void GFX3D_Clipper::clipPoly<true>(POLY* poly, VERT** verts); +template void GFX3D_Clipper::clipPoly<false>(POLY* poly, VERT** verts); + +void GFX3D_Clipper::clipSegmentVsPlane(VERT** verts, const int coord, int which) +{ + // not used (it's probably ok to delete this function) + assert(0); +} + +void GFX3D_Clipper::clipPolyVsPlane(const int coord, int which) +{ + // not used (it's probably ok to delete this function) + assert(0); +} + +#else // if not OPTIMIZED_CLIPPING_METHOD: + +FORCEINLINE void GFX3D_Clipper::clipSegmentVsPlane(VERT** verts, const int coord, int which) +{ + bool out0, out1; + if(which==-1) + out0 = verts[0]->coord[coord] < -verts[0]->coord[3]; + else + out0 = verts[0]->coord[coord] > verts[0]->coord[3]; + if(which==-1) + out1 = verts[1]->coord[coord] < -verts[1]->coord[3]; + else + out1 = verts[1]->coord[coord] > verts[1]->coord[3]; + + //CONSIDER: should we try and clip things behind the eye? does this code even successfully do it? not sure. + //if(coord==2 && which==1) { + // out0 = verts[0]->coord[2] < 0; + // out1 = verts[1]->coord[2] < 0; + //} + + //both outside: insert no points + if(out0 && out1) { + CLIPLOG(" both outside\n"); + } + + //both inside: insert the first point + if(!out0 && !out1) + { + CLIPLOG(" both inside\n"); + outClippedPoly.clipVerts[outClippedPoly.type++] = *verts[1]; + } + + //exiting volume: insert the clipped point and the first (interior) point + if(!out0 && out1) + { + CLIPLOG(" exiting\n"); + outClippedPoly.clipVerts[outClippedPoly.type++] = clipPoint(verts[0],verts[1], coord, which); + } + + //entering volume: insert clipped point + if(out0 && !out1) { + CLIPLOG(" entering\n"); + outClippedPoly.clipVerts[outClippedPoly.type++] = clipPoint(verts[1],verts[0], coord, which); + outClippedPoly.clipVerts[outClippedPoly.type++] = *verts[1]; + + } +} + +FORCEINLINE void GFX3D_Clipper::clipPolyVsPlane(const int coord, int which) +{ + outClippedPoly.type = 0; + CLIPLOG2("Clipping coord %d against %f\n",coord,x); + for(int i=0;i<tempClippedPoly.type;i++) + { + VERT* testverts[2] = {&tempClippedPoly.clipVerts[i],&tempClippedPoly.clipVerts[(i+1)%tempClippedPoly.type]}; + clipSegmentVsPlane(testverts, coord, which); + } + + //this doesnt seem to help any. leaving it until i decide to get rid of it + //int j = index_start_table[tempClippedPoly.type-3]; + //for(int i=0;i<tempClippedPoly.type;i++,j+=2) + //{ + // VERT* testverts[2] = {&tempClippedPoly.clipVerts[index_lookup_table[j]],&tempClippedPoly.clipVerts[index_lookup_table[j+1]]}; + // clipSegmentVsPlane(testverts, coord, which); + //} + + tempClippedPoly = outClippedPoly; +} + + +void GFX3D_Clipper::clipPoly(POLY* poly, VERT** verts) +{ + int type = poly->type; + + CLIPLOG("==Begin poly==\n"); + + tempClippedPoly.clipVerts[0] = *verts[0]; + tempClippedPoly.clipVerts[1] = *verts[1]; + tempClippedPoly.clipVerts[2] = *verts[2]; + if(type==4) + tempClippedPoly.clipVerts[3] = *verts[3]; + + + tempClippedPoly.type = type; + + clipPolyVsPlane(0, -1); + clipPolyVsPlane(0, 1); + clipPolyVsPlane(1, -1); + clipPolyVsPlane(1, 1); + clipPolyVsPlane(2, -1); + clipPolyVsPlane(2, 1); + //TODO - we need to parameterize back plane clipping + + + if(tempClippedPoly.type < 3) + { + //a totally clipped poly. discard it. + //or, a degenerate poly. we're not handling these right now + } + else + { + //TODO - build right in this list instead of copying + clippedPolys[clippedPolyCounter] = tempClippedPoly; + clippedPolys[clippedPolyCounter].poly = poly; + clippedPolyCounter++; + } + +} +#endif + +// "Workaround" for line poly +bool gfx3d_IsLinePoly(POLY *poly) +{ + if(!CommonSettings.GFX3D_LineHack) return false; + + int type = poly->type; + VERT *vert1, *vert2; + + if (type <= 2) + return true; + else if (type > 10) + return false; + + // Method 1: + // Castlevania Portrait of Ruin - trajectory of ricochet + bool duplicatedVert[10]; + for(int i = 0; i < type; i++) + duplicatedVert[i] = false; + for(int i = 0; i < type - 1; i++) + { + vert1 = &gfx3d.vertlist->list[poly->vertIndexes[i]]; + for(int j = i + 1; j < type; j++) + { + vert2 = &gfx3d.vertlist->list[poly->vertIndexes[j]]; + if (vert1->x == vert2->x && vert1->y == vert2->y + //&& vert1->z == vert2->z + ) + { + duplicatedVert[j] = true; + } + } + } + int vertCount = type; + for(int i = 0; i < type; i++) + { + if (duplicatedVert[i]) + vertCount--; + } + if (vertCount <= 2) + return true; + + // Method 2: + // Castlevania Portrait of Ruin - warp stone + bool horizontalLine = true; + bool verticalLine = true; + vert1 = &gfx3d.vertlist->list[poly->vertIndexes[0]]; + for(int i = 1; i < type && (horizontalLine || verticalLine); i++) + { + vert2 = &gfx3d.vertlist->list[poly->vertIndexes[i]]; + if (vert1->coord[0] != vert2->coord[0]) + { + verticalLine = false; + } + if (vert1->coord[1] != vert2->coord[1]) + { + horizontalLine = false; + } + + //the Z is different, and this method isn't even meant to catch that + //if (vert1->coord[2] != vert2->coord[2]) + // return false; + } + if (horizontalLine || verticalLine) + return true; + + return false; +} diff --git a/jni/desmume/src/gfx3d.h b/jni/desmume/src/gfx3d.h new file mode 100755 index 0000000..731f8a0 --- /dev/null +++ b/jni/desmume/src/gfx3d.h @@ -0,0 +1,452 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2008-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _GFX3D_H_ +#define _GFX3D_H_ + +#include <iosfwd> +#include <ostream> +#include <istream> +#include "types.h" +#include "emufile.h" + + +//geometry engine command numbers +#define GFX3D_NOP 0x00 +#define GFX3D_MTX_MODE 0x10 +#define GFX3D_MTX_PUSH 0x11 +#define GFX3D_MTX_POP 0x12 +#define GFX3D_MTX_STORE 0x13 +#define GFX3D_MTX_RESTORE 0x14 +#define GFX3D_MTX_IDENTITY 0x15 +#define GFX3D_MTX_LOAD_4x4 0x16 +#define GFX3D_MTX_LOAD_4x3 0x17 +#define GFX3D_MTX_MULT_4x4 0x18 +#define GFX3D_MTX_MULT_4x3 0x19 +#define GFX3D_MTX_MULT_3x3 0x1A +#define GFX3D_MTX_SCALE 0x1B +#define GFX3D_MTX_TRANS 0x1C +#define GFX3D_COLOR 0x20 +#define GFX3D_NORMAL 0x21 +#define GFX3D_TEXCOORD 0x22 +#define GFX3D_VTX_16 0x23 +#define GFX3D_VTX_10 0x24 +#define GFX3D_XY 0x25 +#define GFX3D_XZ 0x26 +#define GFX3D_YZ 0x27 +#define GFX3D_DIFF 0x28 +#define GFX3D_POLYGON_ATTR 0x29 +#define GFX3D_TEXIMAGE_PARAM 0x2A +#define GFX3D_PLTT_BASE 0x2B +#define GFX3D_DIF_AMB 0x30 +#define GFX3D_SPE_EMI 0x31 +#define GFX3D_LIGHT_VECTOR 0x32 +#define GFX3D_LIGHT_COLOR 0x33 +#define GFX3D_SHININESS 0x34 +#define GFX3D_BEGIN_VTXS 0x40 +#define GFX3D_END_VTXS 0x41 +#define GFX3D_SWAP_BUFFERS 0x50 +#define GFX3D_VIEWPORT 0x60 +#define GFX3D_BOX_TEST 0x70 +#define GFX3D_POS_TEST 0x71 +#define GFX3D_VEC_TEST 0x72 +#define GFX3D_NOP_NOARG_HACK 0xDD + +//produce a 32bpp color from a DS RGB16 +#define RGB16TO32(col,alpha) (((alpha)<<24) | ((((col) & 0x7C00)>>7)<<16) | ((((col) & 0x3E0)>>2)<<8) | (((col) & 0x1F)<<3)) + +//produce a 32bpp color from a ds RGB15, using a table +#define RGB15TO32_NOALPHA(col) ( color_15bit_to_24bit[col&0x7FFF] ) + +//produce a 32bpp color from a ds RGB15 plus an 8bit alpha, using a table +#define RGB15TO32(col,alpha8) ( ((alpha8)<<24) | color_15bit_to_24bit[col&0x7FFF] ) + +//produce a 5555 32bit color from a ds RGB15 plus an 5bit alpha +#define RGB15TO5555(col,alpha5) (((alpha5)<<24) | ((((col) & 0x7C00)>>10)<<16) | ((((col) & 0x3E0)>>5)<<8) | (((col) & 0x1F))) + +//produce a 6665 32bit color from a ds RGB15 plus an 5bit alpha +inline u32 RGB15TO6665(u16 col, u8 alpha5) +{ + u32 ret = alpha5<<24; + u16 r = (col&0x1F)>>0; + u16 g = (col&0x3E0)>>5; + u16 b = (col&0x7C00)>>10; + if(r) ret |= ((r<<1)+1); + if(g) ret |= ((g<<1)+1)<<8; + if(b) ret |= ((b<<1)+1)<<16; + return ret; +} + +//produce a 24bpp color from a ds RGB15, using a table +#define RGB15TO24_REVERSE(col) ( color_15bit_to_24bit_reverse[col&0x7FFF] ) + +//produce a 16bpp color from a ds RGB15, using a table +#define RGB15TO16_REVERSE(col) ( color_15bit_to_16bit_reverse[col&0x7FFF] ) + +//produce a 32bpp color from a ds RGB15 plus an 8bit alpha, not using a table (but using other tables) +#define RGB15TO32_DIRECT(col,alpha8) ( ((alpha8)<<24) | (material_5bit_to_8bit[((col)>>10)&0x1F]<<16) | (material_5bit_to_8bit[((col)>>5)&0x1F]<<8) | material_5bit_to_8bit[(col)&0x1F] ) + +//produce a 15bpp color from individual 5bit components +#define R5G5B5TORGB15(r,g,b) ((r)|((g)<<5)|((b)<<10)) +#define RGB15TO32_NOALPHA(col) ( color_15bit_to_24bit[col&0x7FFF] ) + +//produce a 16bpp color from individual 5bit components +#define R6G6B6TORGB15(r,g,b) ((r>>1)|((g&0x3E)<<4)|((b&0x3E)<<9)) + +#define GFX3D_5TO6(x) ((x)?(((x)<<1)+1):0) + +inline u32 gfx3d_extendDepth_15_to_24(u32 depth) +{ + //formula from http://nocash.emubase.de/gbatek.htm#ds3drearplane + //return (depth*0x200)+((depth+1)>>15)*0x01FF; + //I think this might be slightly faster + if(depth==0x7FFF) return 0x00FFFFFF; + else return depth<<9; +} + +#define TEXMODE_NONE 0 +#define TEXMODE_A3I5 1 +#define TEXMODE_I2 2 +#define TEXMODE_I4 3 +#define TEXMODE_I8 4 +#define TEXMODE_4X4 5 +#define TEXMODE_A5I3 6 +#define TEXMODE_16BPP 7 + +void gfx3d_init(); +void gfx3d_reset(); + +#define OSWRITE(x) os->fwrite((char*)&(x),sizeof((x))); +#define OSREAD(x) is->fread((char*)&(x),sizeof((x))); + +struct POLY { + int type; //tri or quad + u8 vtxFormat; + u16 vertIndexes[4]; //up to four verts can be referenced by this poly + u32 polyAttr, texParam, texPalette; //the hardware rendering params + u32 viewport; + float miny, maxy; + + void setVertIndexes(int a, int b, int c, int d=-1) + { + vertIndexes[0] = a; + vertIndexes[1] = b; + vertIndexes[2] = c; + if(d != -1) { vertIndexes[3] = d; type = 4; } + else type = 3; + } + + bool isTranslucent() + { + //alpha != 31 -> translucent + //except for alpha 0 which is wireframe (unless it has a translucent tex) + if((polyAttr&0x001F0000) != 0x001F0000 && (polyAttr&0x001F0000) != 0) + return true; + int texFormat = (texParam>>26)&7; + + //a5i3 or a3i5 -> translucent + if(texFormat==1 || texFormat==6) + return true; + + return false; + } + + int getAlpha() { return (polyAttr>>16)&0x1F; } + + void save(EMUFILE* os) + { + OSWRITE(type); + OSWRITE(vertIndexes[0]); OSWRITE(vertIndexes[1]); OSWRITE(vertIndexes[2]); OSWRITE(vertIndexes[3]); + OSWRITE(polyAttr); OSWRITE(texParam); OSWRITE(texPalette); + OSWRITE(viewport); + OSWRITE(miny); + OSWRITE(maxy); + } + + void load(EMUFILE* is) + { + OSREAD(type); + OSREAD(vertIndexes[0]); OSREAD(vertIndexes[1]); OSREAD(vertIndexes[2]); OSREAD(vertIndexes[3]); + OSREAD(polyAttr); OSREAD(texParam); OSREAD(texPalette); + OSREAD(viewport); + OSREAD(miny); + OSREAD(maxy); + } +}; + +#define POLYLIST_SIZE 100000 +struct POLYLIST { + POLY list[POLYLIST_SIZE]; + int count; +}; + +struct VERT { + union { + float coord[4]; + struct { + float x,y,z,w; + }; + }; + union { + float texcoord[2]; + struct { + float u,v; + }; + }; + void set_coord(float x, float y, float z, float w) { + this->x = x; + this->y = y; + this->z = z; + this->w = w; + } + void set_coord(float* coords) { + x = coords[0]; + y = coords[1]; + z = coords[2]; + w = coords[3]; + } + u8 color[3]; + float fcolor[3]; + void color_to_float() { + fcolor[0] = color[0]; + fcolor[1] = color[1]; + fcolor[2] = color[2]; + } + void save(EMUFILE* os) + { + OSWRITE(x); OSWRITE(y); OSWRITE(z); OSWRITE(w); + OSWRITE(u); OSWRITE(v); + OSWRITE(color[0]); OSWRITE(color[1]); OSWRITE(color[2]); + OSWRITE(fcolor[0]); OSWRITE(fcolor[1]); OSWRITE(fcolor[2]); + } + void load(EMUFILE* is) + { + OSREAD(x); OSREAD(y); OSREAD(z); OSREAD(w); + OSREAD(u); OSREAD(v); + OSREAD(color[0]); OSREAD(color[1]); OSREAD(color[2]); + OSREAD(fcolor[0]); OSREAD(fcolor[1]); OSREAD(fcolor[2]); + } +}; + +#define VERTLIST_SIZE 400000 +//#define VERTLIST_SIZE 10000 +struct VERTLIST { + VERT list[VERTLIST_SIZE]; + int count; +}; + +struct INDEXLIST { + int list[POLYLIST_SIZE]; +}; + + +struct VIEWPORT { + int x, y, width, height; + void decode(u32 v); +}; + +//ok, imagine the plane that cuts diagonally across a cube such that it clips +//out to be a hexagon. within that plane, draw a quad such that it cuts off +//four corners of the hexagon, and you will observe a decagon +#define MAX_CLIPPED_VERTS 10 + +class GFX3D_Clipper +{ +public: + + struct TClippedPoly + { + int type; //otherwise known as "count" of verts + POLY* poly; + VERT clipVerts[MAX_CLIPPED_VERTS]; + }; + + //the entry point for poly clipping + template<bool hirez> void clipPoly(POLY* poly, VERT** verts); + + //the output of clipping operations goes into here. + //be sure you init it before clipping! + TClippedPoly *clippedPolys; + int clippedPolyCounter; + void reset() { clippedPolyCounter=0; } + +private: + TClippedPoly tempClippedPoly; + TClippedPoly outClippedPoly; + FORCEINLINE void clipSegmentVsPlane(VERT** verts, const int coord, int which); + FORCEINLINE void clipPolyVsPlane(const int coord, int which); +}; + +//used to communicate state to the renderer +struct GFX3D_State +{ + GFX3D_State() + : enableTexturing(true) + , enableAlphaTest(true) + , enableAlphaBlending(true) + , enableAntialiasing(false) + , enableEdgeMarking(false) + , enableClearImage(false) + , enableFog(false) + , enableFogAlphaOnly(false) + , shading(TOON) + , alphaTestRef(0) + , activeFlushCommand(0) + , pendingFlushCommand(0) + , clearDepth(1) + , clearColor(0) + , fogColor(0) + , fogOffset(0) + , fogShift(0) + , invalidateToon(true) + { + for(u32 i=0;i<ARRAY_SIZE(shininessTable);i++) + shininessTable[i] = 0; + + for(u32 i=0;i<ARRAY_SIZE(u16ToonTable);i++) + u16ToonTable[i] = 0; + } + + BOOL enableTexturing, enableAlphaTest, enableAlphaBlending, + enableAntialiasing, enableEdgeMarking, enableClearImage, enableFog, enableFogAlphaOnly; + + static const u32 TOON = 0; + static const u32 HIGHLIGHT = 1; + u32 shading; + + BOOL wbuffer, sortmode; + u8 alphaTestRef; + u32 activeFlushCommand; + u32 pendingFlushCommand; + + u32 clearDepth; + u32 clearColor; + #include "PACKED.h" + struct { + u32 fogColor; + u32 pad[3]; //for savestate compatibility as of 26-jul-09 + }; + #include "PACKED_END.h" + u32 fogOffset; + u32 fogShift; + + bool invalidateToon; + u16 u16ToonTable[32]; + u8 shininessTable[128]; +}; + +struct Viewer3d_State +{ + int frameNumber; + GFX3D_State state; + VERTLIST vertlist; + POLYLIST polylist; + INDEXLIST indexlist; +}; + +extern Viewer3d_State* viewer3d_state; + +struct GFX3D +{ + GFX3D() + : polylist(0) + , vertlist(0) + , frameCtr(0) + , frameCtrRaw(0) { + } + + //currently set values + GFX3D_State state; + + //values used for the currently-rendered frame (committed with each flush) + GFX3D_State renderState; + + POLYLIST* polylist; + VERTLIST* vertlist; + INDEXLIST indexlist; + + //ticks every time flush() is called + int frameCtr; + + //you can use this to track how many real frames passed, for comparing to frameCtr; + int frameCtrRaw; +}; +extern GFX3D gfx3d; + +//--------------------- + +extern CACHE_ALIGN u32 color_15bit_to_24bit[32768]; +extern CACHE_ALIGN u32 color_15bit_to_24bit_reverse[32768]; +extern CACHE_ALIGN u16 color_15bit_to_16bit_reverse[32768]; +extern CACHE_ALIGN u8 mixTable555[32][32][32]; +extern CACHE_ALIGN const int material_5bit_to_31bit[32]; +extern CACHE_ALIGN const u8 material_5bit_to_8bit[32]; +extern CACHE_ALIGN const u8 material_3bit_to_5bit[8]; +extern CACHE_ALIGN const u8 material_3bit_to_6bit[8]; +extern CACHE_ALIGN const u8 material_3bit_to_8bit[8]; + +//these contain the 3d framebuffer converted into the most useful format +//they are stored here instead of in the renderers in order to consolidate the buffers +extern CACHE_ALIGN u8 gfx3d_convertedScreen[256*192*4]; +extern CACHE_ALIGN u8 gfx3d_convertedAlpha[256*192*2]; //see cpp for explanation of illogical *2 + +extern BOOL isSwapBuffers; + +int _hack_getMatrixStackLevel(int); + +void gfx3d_glFlush(u32 v); +// end GE commands + +void gfx3d_glFogColor(u32 v); +void gfx3d_glFogOffset (u32 v); +void gfx3d_glClearDepth(u32 v); +void gfx3d_glSwapScreen(u32 screen); +int gfx3d_GetNumPolys(); +int gfx3d_GetNumVertex(); +void gfx3d_UpdateToonTable(u8 offset, u16 val); +void gfx3d_UpdateToonTable(u8 offset, u32 val); +s32 gfx3d_GetClipMatrix (u32 index); +s32 gfx3d_GetDirectionalMatrix (u32 index); +void gfx3d_glAlphaFunc(u32 v); +u32 gfx3d_glGetPosRes(u32 index); +u16 gfx3d_glGetVecRes(u32 index); +void gfx3d_VBlankSignal(); +void gfx3d_VBlankEndSignal(bool skipFrame); +void gfx3d_Control(u32 v); +void gfx3d_execute3D(); +void gfx3d_sendCommandToFIFO(u32 val); +void gfx3d_sendCommand(u32 cmd, u32 param); + +//other misc stuff +void gfx3d_glGetMatrix(u32 mode, int index, float* dest); +void gfx3d_glGetLightDirection(u32 index, u32* dest); +void gfx3d_glGetLightColor(u32 index, u32* dest); + +void gfx3d_GetLineData(int line, u8** dst); +void gfx3d_GetLineData15bpp(int line, u16** dst); + +struct SFORMAT; +extern SFORMAT SF_GFX3D[]; +void gfx3d_savestate(EMUFILE* os); +bool gfx3d_loadstate(EMUFILE* is, int size); + +void gfx3d_ClearStack(); + +bool gfx3d_IsLinePoly(POLY *poly); + +#endif //_GFX3D_H_ diff --git a/jni/desmume/src/instruction_tabdef.inc b/jni/desmume/src/instruction_tabdef.inc new file mode 100755 index 0000000..5515e68 --- /dev/null +++ b/jni/desmume/src/instruction_tabdef.inc @@ -0,0 +1,4118 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2007-2012 DeSmuME team + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* 0XX000X0 */ + +/* 0000 0000 0000 */ TABDECL( OP_AND_LSL_IMM), +/* 0000 0000 0001 */ TABDECL( OP_AND_LSL_REG), +/* 0000 0000 0010 */ TABDECL( OP_AND_LSR_IMM), +/* 0000 0000 0011 */ TABDECL( OP_AND_LSR_REG), +/* 0000 0000 0100 */ TABDECL( OP_AND_ASR_IMM), +/* 0000 0000 0101 */ TABDECL( OP_AND_ASR_REG), +/* 0000 0000 0110 */ TABDECL( OP_AND_ROR_IMM), +/* 0000 0000 0111 */ TABDECL( OP_AND_ROR_REG), +/* 0000 0000 1000 */ TABDECL( OP_AND_LSL_IMM), +/* 0000 0000 1001 */ TABDECL( OP_MUL), +/* 0000 0000 1010 */ TABDECL( OP_AND_LSR_IMM), +/* 0000 0000 1011 */ TABDECL( OP_STRH_POS_INDE_M_REG_OFF), +/* 0000 0000 1100 */ TABDECL( OP_AND_ASR_IMM), +/* 0000 0000 1101 */ TABDECL( OP_LDRD_STRD_POST_INDEX), +/* 0000 0000 1110 */ TABDECL( OP_AND_ROR_IMM), +/* 0000 0000 1111 */ TABDECL( OP_LDRD_STRD_POST_INDEX), +/* 0000 0001 0000 */ TABDECL( OP_AND_S_LSL_IMM), +/* 0000 0001 0001 */ TABDECL( OP_AND_S_LSL_REG), +/* 0000 0001 0010 */ TABDECL( OP_AND_S_LSR_IMM), +/* 0000 0001 0011 */ TABDECL( OP_AND_S_LSR_REG), +/* 0000 0001 0100 */ TABDECL( OP_AND_S_ASR_IMM), +/* 0000 0001 0101 */ TABDECL( OP_AND_S_ASR_REG), +/* 0000 0001 0110 */ TABDECL( OP_AND_S_ROR_IMM), +/* 0000 0001 0111 */ TABDECL( OP_AND_S_ROR_REG), +/* 0000 0001 1000 */ TABDECL( OP_AND_S_LSL_IMM), +/* 0000 0001 1001 */ TABDECL( OP_MUL_S), +/* 0000 0001 1010 */ TABDECL( OP_AND_S_LSR_IMM), +/* 0000 0001 1011 */ TABDECL( OP_LDRH_POS_INDE_M_REG_OFF), +/* 0000 0001 1100 */ TABDECL( OP_AND_S_ASR_IMM), +/* 0000 0001 1101 */ TABDECL( OP_LDRSB_POS_INDE_M_REG_OFF), +/* 0000 0001 1110 */ TABDECL( OP_AND_S_ROR_IMM), +/* 0000 0001 1111 */ TABDECL( OP_LDRSH_POS_INDE_M_REG_OFF), +/* 0000 0010 0000 */ TABDECL( OP_EOR_LSL_IMM), +/* 0000 0010 0001 */ TABDECL( OP_EOR_LSL_REG), +/* 0000 0010 0010 */ TABDECL( OP_EOR_LSR_IMM), +/* 0000 0010 0011 */ TABDECL( OP_EOR_LSR_REG), +/* 0000 0010 0100 */ TABDECL( OP_EOR_ASR_IMM), +/* 0000 0010 0101 */ TABDECL( OP_EOR_ASR_REG), +/* 0000 0010 0110 */ TABDECL( OP_EOR_ROR_IMM), +/* 0000 0010 0111 */ TABDECL( OP_EOR_ROR_REG), +/* 0000 0010 1000 */ TABDECL( OP_EOR_LSL_IMM), +/* 0000 0010 1001 */ TABDECL( OP_MLA), +/* 0000 0010 1010 */ TABDECL( OP_EOR_LSR_IMM), // OOO OOO1 O 1010 +/* 0000 0010 1011 */ TABDECL( OP_UND), +/* 0000 0010 1100 */ TABDECL( OP_EOR_ASR_IMM), +/* 0000 0010 1101 */ TABDECL( OP_UND), +/* 0000 0010 1110 */ TABDECL( OP_EOR_ROR_IMM), +/* 0000 0010 1111 */ TABDECL( OP_UND), +/* 0000 0011 0000 */ TABDECL( OP_EOR_S_LSL_IMM), +/* 0000 0011 0001 */ TABDECL( OP_EOR_S_LSL_REG), +/* 0000 0011 0010 */ TABDECL( OP_EOR_S_LSR_IMM), +/* 0000 0011 0011 */ TABDECL( OP_EOR_S_LSR_REG), +/* 0000 0011 0100 */ TABDECL( OP_EOR_S_ASR_IMM), +/* 0000 0011 0101 */ TABDECL( OP_EOR_S_ASR_REG), +/* 0000 0011 0110 */ TABDECL( OP_EOR_S_ROR_IMM), +/* 0000 0011 0111 */ TABDECL( OP_EOR_S_ROR_REG), +/* 0000 0011 1000 */ TABDECL( OP_EOR_S_LSL_IMM), +/* 0000 0011 1001 */ TABDECL( OP_MLA_S), +/* 0000 0011 1010 */ TABDECL( OP_EOR_S_LSR_IMM), +/* 0000 0011 1011 */ TABDECL( OP_UND), +/* 0000 0011 1100 */ TABDECL( OP_EOR_S_ASR_IMM), +/* 0000 0011 1101 */ TABDECL( OP_UND), +/* 0000 0011 1110 */ TABDECL( OP_EOR_S_ROR_IMM), +/* 0000 0011 1111 */ TABDECL( OP_UND), +/* 0000 0100 0000 */ TABDECL( OP_SUB_LSL_IMM), +/* 0000 0100 0001 */ TABDECL( OP_SUB_LSL_REG), +/* 0000 0100 0010 */ TABDECL( OP_SUB_LSR_IMM), +/* 0000 0100 0011 */ TABDECL( OP_SUB_LSR_REG), +/* 0000 0100 0100 */ TABDECL( OP_SUB_ASR_IMM), +/* 0000 0100 0101 */ TABDECL( OP_SUB_ASR_REG), +/* 0000 0100 0110 */ TABDECL( OP_SUB_ROR_IMM), +/* 0000 0100 0111 */ TABDECL( OP_SUB_ROR_REG), +/* 0000 0100 1000 */ TABDECL( OP_SUB_LSL_IMM), +/* 0000 0100 1001 */ TABDECL( OP_UND), +/* 0000 0100 1010 */ TABDECL( OP_SUB_LSR_IMM), // OOO OO1O O 1010 +/* 0000 0100 1011 */ TABDECL( OP_STRH_POS_INDE_M_IMM_OFF), +/* 0000 0100 1100 */ TABDECL( OP_SUB_ASR_IMM), +/* 0000 0100 1101 */ TABDECL( OP_LDRD_STRD_POST_INDEX), +/* 0000 0100 1110 */ TABDECL( OP_SUB_ROR_IMM), +/* 0000 0100 1111 */ TABDECL( OP_LDRD_STRD_POST_INDEX), +/* 0000 0101 0000 */ TABDECL( OP_SUB_S_LSL_IMM), +/* 0000 0101 0001 */ TABDECL( OP_SUB_S_LSL_REG), +/* 0000 0101 0010 */ TABDECL( OP_SUB_S_LSR_IMM), +/* 0000 0101 0011 */ TABDECL( OP_SUB_S_LSR_REG), +/* 0000 0101 0100 */ TABDECL( OP_SUB_S_ASR_IMM), +/* 0000 0101 0101 */ TABDECL( OP_SUB_S_ASR_REG), +/* 0000 0101 0110 */ TABDECL( OP_SUB_S_ROR_IMM), +/* 0000 0101 0111 */ TABDECL( OP_SUB_S_ROR_REG), +/* 0000 0101 1000 */ TABDECL( OP_SUB_S_LSL_IMM), +/* 0000 0101 1001 */ TABDECL( OP_UND), +/* 0000 0101 1010 */ TABDECL( OP_SUB_S_LSR_IMM), +/* 0000 0101 1011 */ TABDECL( OP_LDRH_POS_INDE_M_IMM_OFF), +/* 0000 0101 1100 */ TABDECL( OP_SUB_S_ASR_IMM), +/* 0000 0101 1101 */ TABDECL( OP_LDRSB_POS_INDE_M_IMM_OFF), +/* 0000 0101 1110 */ TABDECL( OP_SUB_S_ROR_IMM), +/* 0000 0101 1111 */ TABDECL( OP_LDRSH_POS_INDE_M_IMM_OFF), +/* 0000 0110 0000 */ TABDECL( OP_RSB_LSL_IMM), +/* 0000 0110 0001 */ TABDECL( OP_RSB_LSL_REG), +/* 0000 0110 0010 */ TABDECL( OP_RSB_LSR_IMM), +/* 0000 0110 0011 */ TABDECL( OP_RSB_LSR_REG), +/* 0000 0110 0100 */ TABDECL( OP_RSB_ASR_IMM), +/* 0000 0110 0101 */ TABDECL( OP_RSB_ASR_REG), +/* 0000 0110 0110 */ TABDECL( OP_RSB_ROR_IMM), +/* 0000 0110 0111 */ TABDECL( OP_RSB_ROR_REG), +/* 0000 0110 1000 */ TABDECL( OP_RSB_LSL_IMM), +/* 0000 0110 1001 */ TABDECL( OP_UND), +/* 0000 0110 1010 */ TABDECL( OP_RSB_LSR_IMM), // OOO OO11 O 1010 +/* 0000 0110 1011 */ TABDECL( OP_UND), +/* 0000 0110 1100 */ TABDECL( OP_RSB_ASR_IMM), +/* 0000 0110 1101 */ TABDECL( OP_UND), +/* 0000 0110 1110 */ TABDECL( OP_RSB_ROR_IMM), +/* 0000 0110 1111 */ TABDECL( OP_UND), +/* 0000 0111 0000 */ TABDECL( OP_RSB_S_LSL_IMM), +/* 0000 0111 0001 */ TABDECL( OP_RSB_S_LSL_REG), +/* 0000 0111 0010 */ TABDECL( OP_RSB_S_LSR_IMM), +/* 0000 0111 0011 */ TABDECL( OP_RSB_S_LSR_REG), +/* 0000 0111 0100 */ TABDECL( OP_RSB_S_ASR_IMM), +/* 0000 0111 0101 */ TABDECL( OP_RSB_S_ASR_REG), +/* 0000 0111 0110 */ TABDECL( OP_RSB_S_ROR_IMM), +/* 0000 0111 0111 */ TABDECL( OP_RSB_S_ROR_REG), +/* 0000 0111 1000 */ TABDECL( OP_RSB_S_LSL_IMM), +/* 0000 0111 1001 */ TABDECL( OP_UND), +/* 0000 0111 1010 */ TABDECL( OP_RSB_S_LSR_IMM), +/* 0000 0111 1011 */ TABDECL( OP_UND), +/* 0000 0111 1100 */ TABDECL( OP_RSB_S_ASR_IMM), +/* 0000 0111 1101 */ TABDECL( OP_UND), +/* 0000 0111 1110 */ TABDECL( OP_RSB_S_ROR_IMM), +/* 0000 0111 1111 */ TABDECL( OP_UND), +/* 0000 1000 0000 */ TABDECL( OP_ADD_LSL_IMM), +/* 0000 1000 0001 */ TABDECL( OP_ADD_LSL_REG), +/* 0000 1000 0010 */ TABDECL( OP_ADD_LSR_IMM), +/* 0000 1000 0011 */ TABDECL( OP_ADD_LSR_REG), +/* 0000 1000 0100 */ TABDECL( OP_ADD_ASR_IMM), +/* 0000 1000 0101 */ TABDECL( OP_ADD_ASR_REG), +/* 0000 1000 0110 */ TABDECL( OP_ADD_ROR_IMM), +/* 0000 1000 0111 */ TABDECL( OP_ADD_ROR_REG), +/* 0000 1000 1000 */ TABDECL( OP_ADD_LSL_IMM), +/* 0000 1000 1001 */ TABDECL( OP_UMULL), +/* 0000 1000 1010 */ TABDECL( OP_ADD_LSR_IMM), // OOO O10O O 1010 +/* 0000 1000 1011 */ TABDECL( OP_STRH_POS_INDE_P_REG_OFF), +/* 0000 1000 1100 */ TABDECL( OP_ADD_ASR_IMM), +/* 0000 1000 1101 */ TABDECL( OP_LDRD_STRD_POST_INDEX), +/* 0000 1000 1110 */ TABDECL( OP_ADD_ROR_IMM), +/* 0000 1000 1111 */ TABDECL( OP_LDRD_STRD_POST_INDEX), +/* 0000 1001 0000 */ TABDECL( OP_ADD_S_LSL_IMM), +/* 0000 1001 0001 */ TABDECL( OP_ADD_S_LSL_REG), +/* 0000 1001 0010 */ TABDECL( OP_ADD_S_LSR_IMM), +/* 0000 1001 0011 */ TABDECL( OP_ADD_S_LSR_REG), +/* 0000 1001 0100 */ TABDECL( OP_ADD_S_ASR_IMM), +/* 0000 1001 0101 */ TABDECL( OP_ADD_S_ASR_REG), +/* 0000 1001 0110 */ TABDECL( OP_ADD_S_ROR_IMM), +/* 0000 1001 0111 */ TABDECL( OP_ADD_S_ROR_REG), +/* 0000 1001 1000 */ TABDECL( OP_ADD_S_LSL_IMM), +/* 0000 1001 1001 */ TABDECL( OP_UMULL_S), +/* 0000 1001 1010 */ TABDECL( OP_ADD_S_LSR_IMM), +/* 0000 1001 1011 */ TABDECL( OP_LDRH_POS_INDE_P_REG_OFF), +/* 0000 1001 1100 */ TABDECL( OP_ADD_S_ASR_IMM), +/* 0000 1001 1101 */ TABDECL( OP_LDRSB_POS_INDE_P_REG_OFF), +/* 0000 1001 1110 */ TABDECL( OP_ADD_S_ROR_IMM), +/* 0000 1001 1111 */ TABDECL( OP_LDRSH_POS_INDE_P_REG_OFF), +/* 0000 1010 0000 */ TABDECL( OP_ADC_LSL_IMM), +/* 0000 1010 0001 */ TABDECL( OP_ADC_LSL_REG), +/* 0000 1010 0010 */ TABDECL( OP_ADC_LSR_IMM), +/* 0000 1010 0011 */ TABDECL( OP_ADC_LSR_REG), +/* 0000 1010 0100 */ TABDECL( OP_ADC_ASR_IMM), +/* 0000 1010 0101 */ TABDECL( OP_ADC_ASR_REG), +/* 0000 1010 0110 */ TABDECL( OP_ADC_ROR_IMM), +/* 0000 1010 0111 */ TABDECL( OP_ADC_ROR_REG), +/* 0000 1010 1000 */ TABDECL( OP_ADC_LSL_IMM), +/* 0000 1010 1001 */ TABDECL( OP_UMLAL), +/* 0000 1010 1010 */ TABDECL( OP_ADC_LSR_IMM), // OOO O101 O 1010 +/* 0000 1010 1011 */ TABDECL( OP_UND), +/* 0000 1010 1100 */ TABDECL( OP_ADC_ASR_IMM), +/* 0000 1010 1101 */ TABDECL( OP_UND), +/* 0000 1010 1110 */ TABDECL( OP_ADC_ROR_IMM), +/* 0000 1010 1111 */ TABDECL( OP_UND), +/* 0000 1011 0000 */ TABDECL( OP_ADC_S_LSL_IMM), +/* 0000 1011 0001 */ TABDECL( OP_ADC_S_LSL_REG), +/* 0000 1011 0010 */ TABDECL( OP_ADC_S_LSR_IMM), +/* 0000 1011 0011 */ TABDECL( OP_ADC_S_LSR_REG), +/* 0000 1011 0100 */ TABDECL( OP_ADC_S_ASR_IMM), +/* 0000 1011 0101 */ TABDECL( OP_ADC_S_ASR_REG), +/* 0000 1011 0110 */ TABDECL( OP_ADC_S_ROR_IMM), +/* 0000 1011 0111 */ TABDECL( OP_ADC_S_ROR_REG), +/* 0000 1011 1000 */ TABDECL( OP_ADC_S_LSL_IMM), +/* 0000 1011 1001 */ TABDECL( OP_UMLAL_S), +/* 0000 1011 1010 */ TABDECL( OP_ADC_S_LSR_IMM), +/* 0000 1011 1011 */ TABDECL( OP_UND), +/* 0000 1011 1100 */ TABDECL( OP_ADC_S_ASR_IMM), +/* 0000 1011 1101 */ TABDECL( OP_UND), +/* 0000 1011 1110 */ TABDECL( OP_ADC_S_ROR_IMM), +/* 0000 1011 1111 */ TABDECL( OP_UND), +/* 0000 1100 0000 */ TABDECL( OP_SBC_LSL_IMM), +/* 0000 1100 0001 */ TABDECL( OP_SBC_LSL_REG), +/* 0000 1100 0010 */ TABDECL( OP_SBC_LSR_IMM), +/* 0000 1100 0011 */ TABDECL( OP_SBC_LSR_REG), +/* 0000 1100 0100 */ TABDECL( OP_SBC_ASR_IMM), +/* 0000 1100 0101 */ TABDECL( OP_SBC_ASR_REG), +/* 0000 1100 0110 */ TABDECL( OP_SBC_ROR_IMM), +/* 0000 1100 0111 */ TABDECL( OP_SBC_ROR_REG), +/* 0000 1100 1000 */ TABDECL( OP_SBC_LSL_IMM), +/* 0000 1100 1001 */ TABDECL( OP_SMULL), +/* 0000 1100 1010 */ TABDECL( OP_SBC_LSR_IMM), // OOO O11O O 1010 +/* 0000 1100 1011 */ TABDECL( OP_STRH_POS_INDE_P_IMM_OFF), +/* 0000 1100 1100 */ TABDECL( OP_SBC_ASR_IMM), +/* 0000 1100 1101 */ TABDECL( OP_LDRD_STRD_POST_INDEX), +/* 0000 1100 1110 */ TABDECL( OP_SBC_ROR_IMM), +/* 0000 1100 1111 */ TABDECL( OP_LDRD_STRD_POST_INDEX), +/* 0000 1101 0000 */ TABDECL( OP_SBC_S_LSL_IMM), +/* 0000 1101 0001 */ TABDECL( OP_SBC_S_LSL_REG), +/* 0000 1101 0010 */ TABDECL( OP_SBC_S_LSR_IMM), +/* 0000 1101 0011 */ TABDECL( OP_SBC_S_LSR_REG), +/* 0000 1101 0100 */ TABDECL( OP_SBC_S_ASR_IMM), +/* 0000 1101 0101 */ TABDECL( OP_SBC_S_ASR_REG), +/* 0000 1101 0110 */ TABDECL( OP_SBC_S_ROR_IMM), +/* 0000 1101 0111 */ TABDECL( OP_SBC_S_ROR_REG), +/* 0000 1101 1000 */ TABDECL( OP_SBC_S_LSL_IMM), +/* 0000 1101 1001 */ TABDECL( OP_SMULL_S), +/* 0000 1101 1010 */ TABDECL( OP_SBC_S_LSR_IMM), +/* 0000 1101 1011 */ TABDECL( OP_LDRH_POS_INDE_P_IMM_OFF), +/* 0000 1101 1100 */ TABDECL( OP_SBC_S_ASR_IMM), +/* 0000 1101 1101 */ TABDECL( OP_LDRSB_POS_INDE_P_IMM_OFF), +/* 0000 1101 1110 */ TABDECL( OP_SBC_S_ROR_IMM), +/* 0000 1101 1111 */ TABDECL( OP_LDRSH_POS_INDE_P_IMM_OFF), +/* 0000 1110 0000 */ TABDECL( OP_RSC_LSL_IMM), +/* 0000 1110 0001 */ TABDECL( OP_RSC_LSL_REG), +/* 0000 1110 0010 */ TABDECL( OP_RSC_LSR_IMM), +/* 0000 1110 0011 */ TABDECL( OP_RSC_LSR_REG), +/* 0000 1110 0100 */ TABDECL( OP_RSC_ASR_IMM), +/* 0000 1110 0101 */ TABDECL( OP_RSC_ASR_REG), +/* 0000 1110 0110 */ TABDECL( OP_RSC_ROR_IMM), +/* 0000 1110 0111 */ TABDECL( OP_RSC_ROR_REG), +/* 0000 1110 1000 */ TABDECL( OP_RSC_LSL_IMM), +/* 0000 1110 1001 */ TABDECL( OP_SMLAL), +/* 0000 1110 1010 */ TABDECL( OP_RSC_LSR_IMM), // OOO O111 O 1010 +/* 0000 1110 1011 */ TABDECL( OP_UND), +/* 0000 1110 1100 */ TABDECL( OP_RSC_ASR_IMM), +/* 0000 1110 1101 */ TABDECL( OP_UND), +/* 0000 1110 1110 */ TABDECL( OP_RSC_ROR_IMM), +/* 0000 1110 1111 */ TABDECL( OP_UND), +/* 0000 1111 0000 */ TABDECL( OP_RSC_S_LSL_IMM), +/* 0000 1111 0001 */ TABDECL( OP_RSC_S_LSL_REG), +/* 0000 1111 0010 */ TABDECL( OP_RSC_S_LSR_IMM), +/* 0000 1111 0011 */ TABDECL( OP_RSC_S_LSR_REG), +/* 0000 1111 0100 */ TABDECL( OP_RSC_S_ASR_IMM), +/* 0000 1111 0101 */ TABDECL( OP_RSC_S_ASR_REG), +/* 0000 1111 0110 */ TABDECL( OP_RSC_S_ROR_IMM), +/* 0000 1111 0111 */ TABDECL( OP_RSC_S_ROR_REG), +/* 0000 1111 1000 */ TABDECL( OP_RSC_S_LSL_IMM), +/* 0000 1111 1001 */ TABDECL( OP_SMLAL_S), +/* 0000 1111 1010 */ TABDECL( OP_RSC_S_LSR_IMM), +/* 0000 1111 1011 */ TABDECL( OP_UND), +/* 0000 1111 1100 */ TABDECL( OP_RSC_S_ASR_IMM), +/* 0000 1111 1101 */ TABDECL( OP_UND), +/* 0000 1111 1110 */ TABDECL( OP_RSC_S_ROR_IMM), +/* 0000 1111 1111 */ TABDECL( OP_UND), +/* 0001 0000 0000 */ TABDECL( OP_MRS_CPSR), +/* 0001 0000 0001 */ TABDECL( OP_UND), +/* 0001 0000 0010 */ TABDECL( OP_UND), +/* 0001 0000 0011 */ TABDECL( OP_UND), +/* 0001 0000 0100 */ TABDECL( OP_UND), +/* 0001 0000 0101 */ TABDECL( OP_QADD), +/* 0001 0000 0110 */ TABDECL( OP_UND), +/* 0001 0000 0111 */ TABDECL( OP_UND), +/* 0001 0000 1000 */ TABDECL( OP_SMLA_B_B), +/* 0001 0000 1001 */ TABDECL( OP_SWP), +/* 0001 0000 1010 */ TABDECL( OP_SMLA_T_B), +/* 0001 0000 1011 */ TABDECL( OP_STRH_M_REG_OFF), +/* 0001 0000 1100 */ TABDECL( OP_SMLA_B_T), +/* 0001 0000 1101 */ TABDECL( OP_LDRD_STRD_OFFSET_PRE_INDEX), +/* 0001 0000 1110 */ TABDECL( OP_SMLA_T_T), +/* 0001 0000 1111 */ TABDECL( OP_LDRD_STRD_OFFSET_PRE_INDEX), +/* 0001 0001 0000 */ TABDECL( OP_TST_LSL_IMM), +/* 0001 0001 0001 */ TABDECL( OP_TST_LSL_REG), +/* 0001 0001 0010 */ TABDECL( OP_TST_LSR_IMM), +/* 0001 0001 0011 */ TABDECL( OP_TST_LSR_REG), +/* 0001 0001 0100 */ TABDECL( OP_TST_ASR_IMM), +/* 0001 0001 0101 */ TABDECL( OP_TST_ASR_REG), +/* 0001 0001 0110 */ TABDECL( OP_TST_ROR_IMM), +/* 0001 0001 0111 */ TABDECL( OP_TST_ROR_REG), +/* 0001 0001 1000 */ TABDECL( OP_TST_LSL_IMM), +/* 0001 0001 1001 */ TABDECL( OP_UND), +/* 0001 0001 1010 */ TABDECL( OP_TST_LSR_IMM), // OOO 100O 1 1010 +/* 0001 0001 1011 */ TABDECL( OP_LDRH_M_REG_OFF), +/* 0001 0001 1100 */ TABDECL( OP_TST_ASR_IMM), +/* 0001 0001 1101 */ TABDECL( OP_LDRSB_M_REG_OFF), +/* 0001 0001 1110 */ TABDECL( OP_TST_ROR_IMM), +/* 0001 0001 1111 */ TABDECL( OP_LDRSH_M_REG_OFF), +/* 0001 0010 0000 */ TABDECL( OP_MSR_CPSR), +/* 0001 0010 0001 */ TABDECL( OP_BX), +/* 0001 0010 0010 */ TABDECL( OP_UND), +/* 0001 0010 0011 */ TABDECL( OP_BLX_REG), +/* 0001 0010 0100 */ TABDECL( OP_UND), +/* 0001 0010 0101 */ TABDECL( OP_QSUB), +/* 0001 0010 0110 */ TABDECL( OP_UND), +/* 0001 0010 0111 */ TABDECL( OP_BKPT), +/* 0001 0010 1000 */ TABDECL( OP_SMLAW_B), +/* 0001 0010 1001 */ TABDECL( OP_UND), +/* 0001 0010 1010 */ TABDECL( OP_SMULW_B), +/* 0001 0010 1011 */ TABDECL( OP_STRH_PRE_INDE_M_REG_OFF), +/* 0001 0010 1100 */ TABDECL( OP_SMLAW_T), +/* 0001 0010 1101 */ TABDECL( OP_LDRD_STRD_OFFSET_PRE_INDEX), +/* 0001 0010 1110 */ TABDECL( OP_SMULW_T), +/* 0001 0010 1111 */ TABDECL( OP_LDRD_STRD_OFFSET_PRE_INDEX), +/* 0001 0011 0000 */ TABDECL( OP_TEQ_LSL_IMM), +/* 0001 0011 0001 */ TABDECL( OP_TEQ_LSL_REG), +/* 0001 0011 0010 */ TABDECL( OP_TEQ_LSR_IMM), +/* 0001 0011 0011 */ TABDECL( OP_TEQ_LSR_REG), +/* 0001 0011 0100 */ TABDECL( OP_TEQ_ASR_IMM), +/* 0001 0011 0101 */ TABDECL( OP_TEQ_ASR_REG), +/* 0001 0011 0110 */ TABDECL( OP_TEQ_ROR_IMM), +/* 0001 0011 0111 */ TABDECL( OP_TEQ_ROR_REG), +/* 0001 0011 1000 */ TABDECL( OP_TEQ_LSL_IMM), +/* 0001 0011 1001 */ TABDECL( OP_UND), +/* 0001 0011 1010 */ TABDECL( OP_TEQ_LSR_IMM), // OOO 1001 1 1010 +/* 0001 0011 1011 */ TABDECL( OP_LDRH_PRE_INDE_M_REG_OFF), +/* 0001 0011 1100 */ TABDECL( OP_TEQ_ASR_IMM), +/* 0001 0011 1101 */ TABDECL( OP_LDRSB_PRE_INDE_M_REG_OFF), +/* 0001 0011 1110 */ TABDECL( OP_TEQ_ROR_IMM), +/* 0001 0011 1111 */ TABDECL( OP_LDRSH_PRE_INDE_M_REG_OFF), +/* 0001 0100 0000 */ TABDECL( OP_MRS_SPSR), +/* 0001 0100 0001 */ TABDECL( OP_UND), +/* 0001 0100 0010 */ TABDECL( OP_UND), +/* 0001 0100 0011 */ TABDECL( OP_UND), +/* 0001 0100 0100 */ TABDECL( OP_UND), +/* 0001 0100 0101 */ TABDECL( OP_QDADD), +/* 0001 0100 0110 */ TABDECL( OP_UND), +/* 0001 0100 0111 */ TABDECL( OP_UND), +/* 0001 0100 1000 */ TABDECL( OP_SMLAL_B_B), +/* 0001 0100 1001 */ TABDECL( OP_SWPB), +/* 0001 0100 1010 */ TABDECL( OP_SMLAL_T_B), +/* 0001 0100 1011 */ TABDECL( OP_STRH_M_IMM_OFF), +/* 0001 0100 1100 */ TABDECL( OP_SMLAL_B_T), +/* 0001 0100 1101 */ TABDECL( OP_LDRD_STRD_OFFSET_PRE_INDEX), +/* 0001 0100 1110 */ TABDECL( OP_SMLAL_T_T), +/* 0001 0100 1111 */ TABDECL( OP_LDRD_STRD_OFFSET_PRE_INDEX), +/* 0001 0101 0000 */ TABDECL( OP_CMP_LSL_IMM), +/* 0001 0101 0001 */ TABDECL( OP_CMP_LSL_REG), +/* 0001 0101 0010 */ TABDECL( OP_CMP_LSR_IMM), +/* 0001 0101 0011 */ TABDECL( OP_CMP_LSR_REG), +/* 0001 0101 0100 */ TABDECL( OP_CMP_ASR_IMM), +/* 0001 0101 0101 */ TABDECL( OP_CMP_ASR_REG), +/* 0001 0101 0110 */ TABDECL( OP_CMP_ROR_IMM), +/* 0001 0101 0111 */ TABDECL( OP_CMP_ROR_REG), +/* 0001 0101 1000 */ TABDECL( OP_CMP_LSL_IMM), +/* 0001 0101 1001 */ TABDECL( OP_UND), +/* 0001 0101 1010 */ TABDECL( OP_CMP_LSR_IMM), // OOO 1O1O 1 1010 +/* 0001 0101 1011 */ TABDECL( OP_LDRH_M_IMM_OFF), +/* 0001 0101 1100 */ TABDECL( OP_CMP_ASR_IMM), +/* 0001 0101 1101 */ TABDECL( OP_LDRSB_M_IMM_OFF), +/* 0001 0101 1110 */ TABDECL( OP_CMP_ROR_IMM), +/* 0001 0101 1111 */ TABDECL( OP_LDRSH_M_IMM_OFF), +/* 0001 0110 0000 */ TABDECL( OP_MSR_SPSR), +/* 0001 0110 0001 */ TABDECL( OP_CLZ), +/* 0001 0110 0010 */ TABDECL( OP_UND), +/* 0001 0110 0011 */ TABDECL( OP_UND), +/* 0001 0110 0100 */ TABDECL( OP_UND), +/* 0001 0110 0101 */ TABDECL( OP_QDSUB), +/* 0001 0110 0110 */ TABDECL( OP_UND), +/* 0001 0110 0111 */ TABDECL( OP_UND), +/* 0001 0110 1000 */ TABDECL( OP_SMUL_B_B), +/* 0001 0110 1001 */ TABDECL( OP_UND), +/* 0001 0110 1010 */ TABDECL( OP_SMUL_T_B), +/* 0001 0110 1011 */ TABDECL( OP_STRH_PRE_INDE_M_IMM_OFF), +/* 0001 0110 1100 */ TABDECL( OP_SMUL_B_T), +/* 0001 0110 1101 */ TABDECL( OP_LDRD_STRD_OFFSET_PRE_INDEX), +/* 0001 0110 1110 */ TABDECL( OP_SMUL_T_T), +/* 0001 0110 1111 */ TABDECL( OP_LDRD_STRD_OFFSET_PRE_INDEX), +/* 0001 0111 0000 */ TABDECL( OP_CMN_LSL_IMM), +/* 0001 0111 0001 */ TABDECL( OP_CMN_LSL_REG), +/* 0001 0111 0010 */ TABDECL( OP_CMN_LSR_IMM), +/* 0001 0111 0011 */ TABDECL( OP_CMN_LSR_REG), +/* 0001 0111 0100 */ TABDECL( OP_CMN_ASR_IMM), +/* 0001 0111 0101 */ TABDECL( OP_CMN_ASR_REG), +/* 0001 0111 0110 */ TABDECL( OP_CMN_ROR_IMM), +/* 0001 0111 0111 */ TABDECL( OP_CMN_ROR_REG), +/* 0001 0111 1000 */ TABDECL( OP_CMN_LSL_IMM), +/* 0001 0111 1001 */ TABDECL( OP_UND), +/* 0001 0111 1010 */ TABDECL( OP_CMN_LSR_IMM), // OOO 1O11 1 1010 +/* 0001 0111 1011 */ TABDECL( OP_LDRH_PRE_INDE_M_IMM_OFF), +/* 0001 0111 1100 */ TABDECL( OP_CMN_ASR_IMM), +/* 0001 0111 1101 */ TABDECL( OP_LDRSB_PRE_INDE_M_IMM_OFF), +/* 0001 0111 1110 */ TABDECL( OP_CMN_ROR_IMM), +/* 0001 0111 1111 */ TABDECL( OP_LDRSH_PRE_INDE_M_IMM_OFF), +/* 0001 1000 0000 */ TABDECL( OP_ORR_LSL_IMM), +/* 0001 1000 0001 */ TABDECL( OP_ORR_LSL_REG), +/* 0001 1000 0010 */ TABDECL( OP_ORR_LSR_IMM), +/* 0001 1000 0011 */ TABDECL( OP_ORR_LSR_REG), +/* 0001 1000 0100 */ TABDECL( OP_ORR_ASR_IMM), +/* 0001 1000 0101 */ TABDECL( OP_ORR_ASR_REG), +/* 0001 1000 0110 */ TABDECL( OP_ORR_ROR_IMM), +/* 0001 1000 0111 */ TABDECL( OP_ORR_ROR_REG), +/* 0001 1000 1000 */ TABDECL( OP_ORR_LSL_IMM), +/* 0001 1000 1001 */ TABDECL( OP_STREX), +/* 0001 1000 1010 */ TABDECL( OP_ORR_LSR_IMM), // OOO 110O O 1010 +/* 0001 1000 1011 */ TABDECL( OP_STRH_P_REG_OFF), +/* 0001 1000 1100 */ TABDECL( OP_ORR_ASR_IMM), +/* 0001 1000 1101 */ TABDECL( OP_LDRD_STRD_OFFSET_PRE_INDEX), +/* 0001 1000 1110 */ TABDECL( OP_ORR_ROR_IMM), +/* 0001 1000 1111 */ TABDECL( OP_LDRD_STRD_OFFSET_PRE_INDEX), +/* 0001 1001 0000 */ TABDECL( OP_ORR_S_LSL_IMM), +/* 0001 1001 0001 */ TABDECL( OP_ORR_S_LSL_REG), +/* 0001 1001 0010 */ TABDECL( OP_ORR_S_LSR_IMM), +/* 0001 1001 0011 */ TABDECL( OP_ORR_S_LSR_REG), +/* 0001 1001 0100 */ TABDECL( OP_ORR_S_ASR_IMM), +/* 0001 1001 0101 */ TABDECL( OP_ORR_S_ASR_REG), +/* 0001 1001 0110 */ TABDECL( OP_ORR_S_ROR_IMM), +/* 0001 1001 0111 */ TABDECL( OP_ORR_S_ROR_REG), +/* 0001 1001 1000 */ TABDECL( OP_ORR_S_LSL_IMM), +/* 0001 1001 1001 */ TABDECL( OP_LDREX), +/* 0001 1001 1010 */ TABDECL( OP_ORR_S_LSR_IMM), +/* 0001 1001 1011 */ TABDECL( OP_LDRH_P_REG_OFF), +/* 0001 1001 1100 */ TABDECL( OP_ORR_S_ASR_IMM), +/* 0001 1001 1101 */ TABDECL( OP_LDRSB_P_REG_OFF), +/* 0001 1001 1110 */ TABDECL( OP_ORR_S_ROR_IMM), +/* 0001 1001 1111 */ TABDECL( OP_LDRSH_P_REG_OFF), +/* 0001 1010 0000 */ TABDECL( OP_MOV_LSL_IMM), +/* 0001 1010 0001 */ TABDECL( OP_MOV_LSL_REG), +/* 0001 1010 0010 */ TABDECL( OP_MOV_LSR_IMM), +/* 0001 1010 0011 */ TABDECL( OP_MOV_LSR_REG), +/* 0001 1010 0100 */ TABDECL( OP_MOV_ASR_IMM), +/* 0001 1010 0101 */ TABDECL( OP_MOV_ASR_REG), +/* 0001 1010 0110 */ TABDECL( OP_MOV_ROR_IMM), +/* 0001 1010 0111 */ TABDECL( OP_MOV_ROR_REG), +/* 0001 1010 1000 */ TABDECL( OP_MOV_LSL_IMM), +/* 0001 1010 1001 */ TABDECL( OP_UND), +/* 0001 1010 1010 */ TABDECL( OP_MOV_LSR_IMM), // OOO 1101 O 1010 +/* 0001 1010 1011 */ TABDECL( OP_STRH_PRE_INDE_P_REG_OFF), +/* 0001 1010 1100 */ TABDECL( OP_MOV_ASR_IMM), +/* 0001 1010 1101 */ TABDECL( OP_LDRD_STRD_OFFSET_PRE_INDEX), +/* 0001 1010 1110 */ TABDECL( OP_MOV_ROR_IMM), +/* 0001 1010 1111 */ TABDECL( OP_LDRD_STRD_OFFSET_PRE_INDEX), +/* 0001 1011 0000 */ TABDECL( OP_MOV_S_LSL_IMM), +/* 0001 1011 0001 */ TABDECL( OP_MOV_S_LSL_REG), +/* 0001 1011 0010 */ TABDECL( OP_MOV_S_LSR_IMM), +/* 0001 1011 0011 */ TABDECL( OP_MOV_S_LSR_REG), +/* 0001 1011 0100 */ TABDECL( OP_MOV_S_ASR_IMM), +/* 0001 1011 0101 */ TABDECL( OP_MOV_S_ASR_REG), +/* 0001 1011 0110 */ TABDECL( OP_MOV_S_ROR_IMM), +/* 0001 1011 0111 */ TABDECL( OP_MOV_S_ROR_REG), +/* 0001 1011 1000 */ TABDECL( OP_MOV_S_LSL_IMM), +/* 0001 1011 1001 */ TABDECL( OP_UND), +/* 0001 1011 1010 */ TABDECL( OP_MOV_S_LSR_IMM), +/* 0001 1011 1011 */ TABDECL( OP_LDRH_PRE_INDE_P_REG_OFF), +/* 0001 1011 1100 */ TABDECL( OP_MOV_S_ASR_IMM), +/* 0001 1011 1101 */ TABDECL( OP_LDRSB_PRE_INDE_P_REG_OFF), +/* 0001 1011 1110 */ TABDECL( OP_MOV_S_ROR_IMM), +/* 0001 1011 1111 */ TABDECL( OP_LDRSH_PRE_INDE_P_REG_OFF), +/* 0001 1100 0000 */ TABDECL( OP_BIC_LSL_IMM), +/* 0001 1100 0001 */ TABDECL( OP_BIC_LSL_REG), +/* 0001 1100 0010 */ TABDECL( OP_BIC_LSR_IMM), +/* 0001 1100 0011 */ TABDECL( OP_BIC_LSR_REG), +/* 0001 1100 0100 */ TABDECL( OP_BIC_ASR_IMM), +/* 0001 1100 0101 */ TABDECL( OP_BIC_ASR_REG), +/* 0001 1100 0110 */ TABDECL( OP_BIC_ROR_IMM), +/* 0001 1100 0111 */ TABDECL( OP_BIC_ROR_REG), +/* 0001 1100 1000 */ TABDECL( OP_BIC_LSL_IMM), +/* 0001 1100 1001 */ TABDECL( OP_UND), +/* 0001 1100 1010 */ TABDECL( OP_BIC_LSR_IMM), // OOO 111O O 1010 +/* 0001 1100 1011 */ TABDECL( OP_STRH_P_IMM_OFF), +/* 0001 1100 1100 */ TABDECL( OP_BIC_ASR_IMM), +/* 0001 1100 1101 */ TABDECL( OP_LDRD_STRD_OFFSET_PRE_INDEX), +/* 0001 1100 1110 */ TABDECL( OP_BIC_ROR_IMM), +/* 0001 1100 1111 */ TABDECL( OP_LDRD_STRD_OFFSET_PRE_INDEX), +/* 0001 1101 0000 */ TABDECL( OP_BIC_S_LSL_IMM), +/* 0001 1101 0001 */ TABDECL( OP_BIC_S_LSL_REG), +/* 0001 1101 0010 */ TABDECL( OP_BIC_S_LSR_IMM), +/* 0001 1101 0011 */ TABDECL( OP_BIC_S_LSR_REG), +/* 0001 1101 0100 */ TABDECL( OP_BIC_S_ASR_IMM), +/* 0001 1101 0101 */ TABDECL( OP_BIC_S_ASR_REG), +/* 0001 1101 0110 */ TABDECL( OP_BIC_S_ROR_IMM), +/* 0001 1101 0111 */ TABDECL( OP_BIC_S_ROR_REG), +/* 0001 1101 1000 */ TABDECL( OP_BIC_S_LSL_IMM), +/* 0001 1101 1001 */ TABDECL( OP_UND), +/* 0001 1101 1010 */ TABDECL( OP_BIC_S_LSR_IMM), +/* 0001 1101 1011 */ TABDECL( OP_LDRH_P_IMM_OFF), +/* 0001 1101 1100 */ TABDECL( OP_BIC_S_ASR_IMM), +/* 0001 1101 1101 */ TABDECL( OP_LDRSB_P_IMM_OFF), +/* 0001 1101 1110 */ TABDECL( OP_BIC_S_ROR_IMM), +/* 0001 1101 1111 */ TABDECL( OP_LDRSH_P_IMM_OFF), +/* 0001 1110 0000 */ TABDECL( OP_MVN_LSL_IMM), +/* 0001 1110 0001 */ TABDECL( OP_MVN_LSL_REG), +/* 0001 1110 0010 */ TABDECL( OP_MVN_LSR_IMM), +/* 0001 1110 0011 */ TABDECL( OP_MVN_LSR_REG), +/* 0001 1110 0100 */ TABDECL( OP_MVN_ASR_IMM), +/* 0001 1110 0101 */ TABDECL( OP_MVN_ASR_REG), +/* 0001 1110 0110 */ TABDECL( OP_MVN_ROR_IMM), +/* 0001 1110 0111 */ TABDECL( OP_MVN_ROR_REG), +/* 0001 1110 1000 */ TABDECL( OP_MVN_LSL_IMM), +/* 0001 1110 1001 */ TABDECL( OP_UND), +/* 0001 1110 1010 */ TABDECL( OP_MVN_LSR_IMM), // OOO 1111 O 1010 +/* 0001 1110 1011 */ TABDECL( OP_STRH_PRE_INDE_P_IMM_OFF), +/* 0001 1110 1100 */ TABDECL( OP_MVN_ASR_IMM), +/* 0001 1110 1101 */ TABDECL( OP_LDRD_STRD_OFFSET_PRE_INDEX), +/* 0001 1110 1110 */ TABDECL( OP_MVN_ROR_IMM), +/* 0001 1110 1111 */ TABDECL( OP_LDRD_STRD_OFFSET_PRE_INDEX), +/* 0001 1111 0000 */ TABDECL( OP_MVN_S_LSL_IMM), +/* 0001 1111 0001 */ TABDECL( OP_MVN_S_LSL_REG), +/* 0001 1111 0010 */ TABDECL( OP_MVN_S_LSR_IMM), +/* 0001 1111 0011 */ TABDECL( OP_MVN_S_LSR_REG), +/* 0001 1111 0100 */ TABDECL( OP_MVN_S_ASR_IMM), +/* 0001 1111 0101 */ TABDECL( OP_MVN_S_ASR_REG), +/* 0001 1111 0110 */ TABDECL( OP_MVN_S_ROR_IMM), +/* 0001 1111 0111 */ TABDECL( OP_MVN_S_ROR_REG), +/* 0001 1111 1000 */ TABDECL( OP_MVN_S_LSL_IMM), +/* 0001 1111 1001 */ TABDECL( OP_UND), +/* 0001 1111 1010 */ TABDECL( OP_MVN_S_LSR_IMM), +/* 0001 1111 1011 */ TABDECL( OP_LDRH_PRE_INDE_P_IMM_OFF), +/* 0001 1111 1100 */ TABDECL( OP_MVN_S_ASR_IMM), +/* 0001 1111 1101 */ TABDECL( OP_LDRSB_PRE_INDE_P_IMM_OFF), +/* 0001 1111 1110 */ TABDECL( OP_MVN_S_ROR_IMM), +/* 0001 1111 1111 */ TABDECL( OP_LDRSH_PRE_INDE_P_IMM_OFF), +/* 0010 0000 0000 */ TABDECL( OP_AND_IMM_VAL), +/* 0010 0000 0001 */ TABDECL( OP_AND_IMM_VAL), +/* 0010 0000 0010 */ TABDECL( OP_AND_IMM_VAL), +/* 0010 0000 0011 */ TABDECL( OP_AND_IMM_VAL), +/* 0010 0000 0100 */ TABDECL( OP_AND_IMM_VAL), +/* 0010 0000 0101 */ TABDECL( OP_AND_IMM_VAL), +/* 0010 0000 0110 */ TABDECL( OP_AND_IMM_VAL), +/* 0010 0000 0111 */ TABDECL( OP_AND_IMM_VAL), +/* 0010 0000 1000 */ TABDECL( OP_AND_IMM_VAL), +/* 0010 0000 1001 */ TABDECL( OP_AND_IMM_VAL), +/* 0010 0000 1010 */ TABDECL( OP_AND_IMM_VAL), +/* 0010 0000 1011 */ TABDECL( OP_AND_IMM_VAL), +/* 0010 0000 1100 */ TABDECL( OP_AND_IMM_VAL), +/* 0010 0000 1101 */ TABDECL( OP_AND_IMM_VAL), +/* 0010 0000 1110 */ TABDECL( OP_AND_IMM_VAL), +/* 0010 0000 1111 */ TABDECL( OP_AND_IMM_VAL), +/* 0010 0001 0000 */ TABDECL( OP_AND_S_IMM_VAL), +/* 0010 0001 0001 */ TABDECL( OP_AND_S_IMM_VAL), +/* 0010 0001 0010 */ TABDECL( OP_AND_S_IMM_VAL), +/* 0010 0001 0011 */ TABDECL( OP_AND_S_IMM_VAL), +/* 0010 0001 0100 */ TABDECL( OP_AND_S_IMM_VAL), +/* 0010 0001 0101 */ TABDECL( OP_AND_S_IMM_VAL), +/* 0010 0001 0110 */ TABDECL( OP_AND_S_IMM_VAL), +/* 0010 0001 0111 */ TABDECL( OP_AND_S_IMM_VAL), +/* 0010 0001 1000 */ TABDECL( OP_AND_S_IMM_VAL), +/* 0010 0001 1001 */ TABDECL( OP_AND_S_IMM_VAL), +/* 0010 0001 1010 */ TABDECL( OP_AND_S_IMM_VAL), +/* 0010 0001 1011 */ TABDECL( OP_AND_S_IMM_VAL), +/* 0010 0001 1100 */ TABDECL( OP_AND_S_IMM_VAL), +/* 0010 0001 1101 */ TABDECL( OP_AND_S_IMM_VAL), +/* 0010 0001 1110 */ TABDECL( OP_AND_S_IMM_VAL), +/* 0010 0001 1111 */ TABDECL( OP_AND_S_IMM_VAL), +/* 0010 0010 0000 */ TABDECL( OP_EOR_IMM_VAL), +/* 0010 0010 0001 */ TABDECL( OP_EOR_IMM_VAL), +/* 0010 0010 0010 */ TABDECL( OP_EOR_IMM_VAL), +/* 0010 0010 0011 */ TABDECL( OP_EOR_IMM_VAL), +/* 0010 0010 0100 */ TABDECL( OP_EOR_IMM_VAL), +/* 0010 0010 0101 */ TABDECL( OP_EOR_IMM_VAL), +/* 0010 0010 0110 */ TABDECL( OP_EOR_IMM_VAL), +/* 0010 0010 0111 */ TABDECL( OP_EOR_IMM_VAL), +/* 0010 0010 1000 */ TABDECL( OP_EOR_IMM_VAL), +/* 0010 0010 1001 */ TABDECL( OP_EOR_IMM_VAL), +/* 0010 0010 1010 */ TABDECL( OP_EOR_IMM_VAL), +/* 0010 0010 1011 */ TABDECL( OP_EOR_IMM_VAL), +/* 0010 0010 1100 */ TABDECL( OP_EOR_IMM_VAL), +/* 0010 0010 1101 */ TABDECL( OP_EOR_IMM_VAL), +/* 0010 0010 1110 */ TABDECL( OP_EOR_IMM_VAL), +/* 0010 0010 1111 */ TABDECL( OP_EOR_IMM_VAL), +/* 0010 0011 0000 */ TABDECL( OP_EOR_S_IMM_VAL), +/* 0010 0011 0001 */ TABDECL( OP_EOR_S_IMM_VAL), +/* 0010 0011 0010 */ TABDECL( OP_EOR_S_IMM_VAL), +/* 0010 0011 0011 */ TABDECL( OP_EOR_S_IMM_VAL), +/* 0010 0011 0100 */ TABDECL( OP_EOR_S_IMM_VAL), +/* 0010 0011 0101 */ TABDECL( OP_EOR_S_IMM_VAL), +/* 0010 0011 0110 */ TABDECL( OP_EOR_S_IMM_VAL), +/* 0010 0011 0111 */ TABDECL( OP_EOR_S_IMM_VAL), +/* 0010 0011 1000 */ TABDECL( OP_EOR_S_IMM_VAL), +/* 0010 0011 1001 */ TABDECL( OP_EOR_S_IMM_VAL), +/* 0010 0011 1010 */ TABDECL( OP_EOR_S_IMM_VAL), +/* 0010 0011 1011 */ TABDECL( OP_EOR_S_IMM_VAL), +/* 0010 0011 1100 */ TABDECL( OP_EOR_S_IMM_VAL), +/* 0010 0011 1101 */ TABDECL( OP_EOR_S_IMM_VAL), +/* 0010 0011 1110 */ TABDECL( OP_EOR_S_IMM_VAL), +/* 0010 0011 1111 */ TABDECL( OP_EOR_S_IMM_VAL), +/* 0010 0100 0000 */ TABDECL( OP_SUB_IMM_VAL), +/* 0010 0100 0001 */ TABDECL( OP_SUB_IMM_VAL), +/* 0010 0100 0010 */ TABDECL( OP_SUB_IMM_VAL), +/* 0010 0100 0011 */ TABDECL( OP_SUB_IMM_VAL), +/* 0010 0100 0100 */ TABDECL( OP_SUB_IMM_VAL), +/* 0010 0100 0101 */ TABDECL( OP_SUB_IMM_VAL), +/* 0010 0100 0110 */ TABDECL( OP_SUB_IMM_VAL), +/* 0010 0100 0111 */ TABDECL( OP_SUB_IMM_VAL), +/* 0010 0100 1000 */ TABDECL( OP_SUB_IMM_VAL), +/* 0010 0100 1001 */ TABDECL( OP_SUB_IMM_VAL), +/* 0010 0100 1010 */ TABDECL( OP_SUB_IMM_VAL), +/* 0010 0100 1011 */ TABDECL( OP_SUB_IMM_VAL), +/* 0010 0100 1100 */ TABDECL( OP_SUB_IMM_VAL), +/* 0010 0100 1101 */ TABDECL( OP_SUB_IMM_VAL), +/* 0010 0100 1110 */ TABDECL( OP_SUB_IMM_VAL), +/* 0010 0100 1111 */ TABDECL( OP_SUB_IMM_VAL), +/* 0010 0101 0000 */ TABDECL( OP_SUB_S_IMM_VAL), +/* 0010 0101 0001 */ TABDECL( OP_SUB_S_IMM_VAL), +/* 0010 0101 0010 */ TABDECL( OP_SUB_S_IMM_VAL), +/* 0010 0101 0011 */ TABDECL( OP_SUB_S_IMM_VAL), +/* 0010 0101 0100 */ TABDECL( OP_SUB_S_IMM_VAL), +/* 0010 0101 0101 */ TABDECL( OP_SUB_S_IMM_VAL), +/* 0010 0101 0110 */ TABDECL( OP_SUB_S_IMM_VAL), +/* 0010 0101 0111 */ TABDECL( OP_SUB_S_IMM_VAL), +/* 0010 0101 1000 */ TABDECL( OP_SUB_S_IMM_VAL), +/* 0010 0101 1001 */ TABDECL( OP_SUB_S_IMM_VAL), +/* 0010 0101 1010 */ TABDECL( OP_SUB_S_IMM_VAL), +/* 0010 0101 1011 */ TABDECL( OP_SUB_S_IMM_VAL), +/* 0010 0101 1100 */ TABDECL( OP_SUB_S_IMM_VAL), +/* 0010 0101 1101 */ TABDECL( OP_SUB_S_IMM_VAL), +/* 0010 0101 1110 */ TABDECL( OP_SUB_S_IMM_VAL), +/* 0010 0101 1111 */ TABDECL( OP_SUB_S_IMM_VAL), +/* 0010 0110 0000 */ TABDECL( OP_RSB_IMM_VAL), +/* 0010 0110 0001 */ TABDECL( OP_RSB_IMM_VAL), +/* 0010 0110 0010 */ TABDECL( OP_RSB_IMM_VAL), +/* 0010 0110 0011 */ TABDECL( OP_RSB_IMM_VAL), +/* 0010 0110 0100 */ TABDECL( OP_RSB_IMM_VAL), +/* 0010 0110 0101 */ TABDECL( OP_RSB_IMM_VAL), +/* 0010 0110 0110 */ TABDECL( OP_RSB_IMM_VAL), +/* 0010 0110 0111 */ TABDECL( OP_RSB_IMM_VAL), +/* 0010 0110 1000 */ TABDECL( OP_RSB_IMM_VAL), +/* 0010 0110 1001 */ TABDECL( OP_RSB_IMM_VAL), +/* 0010 0110 1010 */ TABDECL( OP_RSB_IMM_VAL), +/* 0010 0110 1011 */ TABDECL( OP_RSB_IMM_VAL), +/* 0010 0110 1100 */ TABDECL( OP_RSB_IMM_VAL), +/* 0010 0110 1101 */ TABDECL( OP_RSB_IMM_VAL), +/* 0010 0110 1110 */ TABDECL( OP_RSB_IMM_VAL), +/* 0010 0110 1111 */ TABDECL( OP_RSB_IMM_VAL), +/* 0010 0111 0000 */ TABDECL( OP_RSB_S_IMM_VAL), +/* 0010 0111 0001 */ TABDECL( OP_RSB_S_IMM_VAL), +/* 0010 0111 0010 */ TABDECL( OP_RSB_S_IMM_VAL), +/* 0010 0111 0011 */ TABDECL( OP_RSB_S_IMM_VAL), +/* 0010 0111 0100 */ TABDECL( OP_RSB_S_IMM_VAL), +/* 0010 0111 0101 */ TABDECL( OP_RSB_S_IMM_VAL), +/* 0010 0111 0110 */ TABDECL( OP_RSB_S_IMM_VAL), +/* 0010 0111 0111 */ TABDECL( OP_RSB_S_IMM_VAL), +/* 0010 0111 1000 */ TABDECL( OP_RSB_S_IMM_VAL), +/* 0010 0111 1001 */ TABDECL( OP_RSB_S_IMM_VAL), +/* 0010 0111 1010 */ TABDECL( OP_RSB_S_IMM_VAL), +/* 0010 0111 1011 */ TABDECL( OP_RSB_S_IMM_VAL), +/* 0010 0111 1100 */ TABDECL( OP_RSB_S_IMM_VAL), +/* 0010 0111 1101 */ TABDECL( OP_RSB_S_IMM_VAL), +/* 0010 0111 1110 */ TABDECL( OP_RSB_S_IMM_VAL), +/* 0010 0111 1111 */ TABDECL( OP_RSB_S_IMM_VAL), +/* 0010 1000 0000 */ TABDECL( OP_ADD_IMM_VAL), +/* 0010 1000 0001 */ TABDECL( OP_ADD_IMM_VAL), +/* 0010 1000 0010 */ TABDECL( OP_ADD_IMM_VAL), +/* 0010 1000 0011 */ TABDECL( OP_ADD_IMM_VAL), +/* 0010 1000 0100 */ TABDECL( OP_ADD_IMM_VAL), +/* 0010 1000 0101 */ TABDECL( OP_ADD_IMM_VAL), +/* 0010 1000 0110 */ TABDECL( OP_ADD_IMM_VAL), +/* 0010 1000 0111 */ TABDECL( OP_ADD_IMM_VAL), +/* 0010 1000 1000 */ TABDECL( OP_ADD_IMM_VAL), +/* 0010 1000 1001 */ TABDECL( OP_ADD_IMM_VAL), +/* 0010 1000 1010 */ TABDECL( OP_ADD_IMM_VAL), +/* 0010 1000 1011 */ TABDECL( OP_ADD_IMM_VAL), +/* 0010 1000 1100 */ TABDECL( OP_ADD_IMM_VAL), +/* 0010 1000 1101 */ TABDECL( OP_ADD_IMM_VAL), +/* 0010 1000 1110 */ TABDECL( OP_ADD_IMM_VAL), +/* 0010 1000 1111 */ TABDECL( OP_ADD_IMM_VAL), +/* 0010 1001 0000 */ TABDECL( OP_ADD_S_IMM_VAL), +/* 0010 1001 0001 */ TABDECL( OP_ADD_S_IMM_VAL), +/* 0010 1001 0010 */ TABDECL( OP_ADD_S_IMM_VAL), +/* 0010 1001 0011 */ TABDECL( OP_ADD_S_IMM_VAL), +/* 0010 1001 0100 */ TABDECL( OP_ADD_S_IMM_VAL), +/* 0010 1001 0101 */ TABDECL( OP_ADD_S_IMM_VAL), +/* 0010 1001 0110 */ TABDECL( OP_ADD_S_IMM_VAL), +/* 0010 1001 0111 */ TABDECL( OP_ADD_S_IMM_VAL), +/* 0010 1001 1000 */ TABDECL( OP_ADD_S_IMM_VAL), +/* 0010 1001 1001 */ TABDECL( OP_ADD_S_IMM_VAL), +/* 0010 1001 1010 */ TABDECL( OP_ADD_S_IMM_VAL), +/* 0010 1001 1011 */ TABDECL( OP_ADD_S_IMM_VAL), +/* 0010 1001 1100 */ TABDECL( OP_ADD_S_IMM_VAL), +/* 0010 1001 1101 */ TABDECL( OP_ADD_S_IMM_VAL), +/* 0010 1001 1110 */ TABDECL( OP_ADD_S_IMM_VAL), +/* 0010 1001 1111 */ TABDECL( OP_ADD_S_IMM_VAL), +/* 0010 1010 0000 */ TABDECL( OP_ADC_IMM_VAL), +/* 0010 1010 0001 */ TABDECL( OP_ADC_IMM_VAL), +/* 0010 1010 0010 */ TABDECL( OP_ADC_IMM_VAL), +/* 0010 1010 0011 */ TABDECL( OP_ADC_IMM_VAL), +/* 0010 1010 0100 */ TABDECL( OP_ADC_IMM_VAL), +/* 0010 1010 0101 */ TABDECL( OP_ADC_IMM_VAL), +/* 0010 1010 0110 */ TABDECL( OP_ADC_IMM_VAL), +/* 0010 1010 0111 */ TABDECL( OP_ADC_IMM_VAL), +/* 0010 1010 1000 */ TABDECL( OP_ADC_IMM_VAL), +/* 0010 1010 1001 */ TABDECL( OP_ADC_IMM_VAL), +/* 0010 1010 1010 */ TABDECL( OP_ADC_IMM_VAL), +/* 0010 1010 1011 */ TABDECL( OP_ADC_IMM_VAL), +/* 0010 1010 1100 */ TABDECL( OP_ADC_IMM_VAL), +/* 0010 1010 1101 */ TABDECL( OP_ADC_IMM_VAL), +/* 0010 1010 1110 */ TABDECL( OP_ADC_IMM_VAL), +/* 0010 1010 1111 */ TABDECL( OP_ADC_IMM_VAL), +/* 0010 1011 0000 */ TABDECL( OP_ADC_S_IMM_VAL), +/* 0010 1011 0001 */ TABDECL( OP_ADC_S_IMM_VAL), +/* 0010 1011 0010 */ TABDECL( OP_ADC_S_IMM_VAL), +/* 0010 1011 0011 */ TABDECL( OP_ADC_S_IMM_VAL), +/* 0010 1011 0100 */ TABDECL( OP_ADC_S_IMM_VAL), +/* 0010 1011 0101 */ TABDECL( OP_ADC_S_IMM_VAL), +/* 0010 1011 0110 */ TABDECL( OP_ADC_S_IMM_VAL), +/* 0010 1011 0111 */ TABDECL( OP_ADC_S_IMM_VAL), +/* 0010 1011 1000 */ TABDECL( OP_ADC_S_IMM_VAL), +/* 0010 1011 1001 */ TABDECL( OP_ADC_S_IMM_VAL), +/* 0010 1011 1010 */ TABDECL( OP_ADC_S_IMM_VAL), +/* 0010 1011 1011 */ TABDECL( OP_ADC_S_IMM_VAL), +/* 0010 1011 1100 */ TABDECL( OP_ADC_S_IMM_VAL), +/* 0010 1011 1101 */ TABDECL( OP_ADC_S_IMM_VAL), +/* 0010 1011 1110 */ TABDECL( OP_ADC_S_IMM_VAL), +/* 0010 1011 1111 */ TABDECL( OP_ADC_S_IMM_VAL), +/* 0010 1100 0000 */ TABDECL( OP_SBC_IMM_VAL), +/* 0010 1100 0001 */ TABDECL( OP_SBC_IMM_VAL), +/* 0010 1100 0010 */ TABDECL( OP_SBC_IMM_VAL), +/* 0010 1100 0011 */ TABDECL( OP_SBC_IMM_VAL), +/* 0010 1100 0100 */ TABDECL( OP_SBC_IMM_VAL), +/* 0010 1100 0101 */ TABDECL( OP_SBC_IMM_VAL), +/* 0010 1100 0110 */ TABDECL( OP_SBC_IMM_VAL), +/* 0010 1100 0111 */ TABDECL( OP_SBC_IMM_VAL), +/* 0010 1100 1000 */ TABDECL( OP_SBC_IMM_VAL), +/* 0010 1100 1001 */ TABDECL( OP_SBC_IMM_VAL), +/* 0010 1100 1010 */ TABDECL( OP_SBC_IMM_VAL), +/* 0010 1100 1011 */ TABDECL( OP_SBC_IMM_VAL), +/* 0010 1100 1100 */ TABDECL( OP_SBC_IMM_VAL), +/* 0010 1100 1101 */ TABDECL( OP_SBC_IMM_VAL), +/* 0010 1100 1110 */ TABDECL( OP_SBC_IMM_VAL), +/* 0010 1100 1111 */ TABDECL( OP_SBC_IMM_VAL), +/* 0010 1101 0000 */ TABDECL( OP_SBC_S_IMM_VAL), +/* 0010 1101 0001 */ TABDECL( OP_SBC_S_IMM_VAL), +/* 0010 1101 0010 */ TABDECL( OP_SBC_S_IMM_VAL), +/* 0010 1101 0011 */ TABDECL( OP_SBC_S_IMM_VAL), +/* 0010 1101 0100 */ TABDECL( OP_SBC_S_IMM_VAL), +/* 0010 1101 0101 */ TABDECL( OP_SBC_S_IMM_VAL), +/* 0010 1101 0110 */ TABDECL( OP_SBC_S_IMM_VAL), +/* 0010 1101 0111 */ TABDECL( OP_SBC_S_IMM_VAL), +/* 0010 1101 1000 */ TABDECL( OP_SBC_S_IMM_VAL), +/* 0010 1101 1001 */ TABDECL( OP_SBC_S_IMM_VAL), +/* 0010 1101 1010 */ TABDECL( OP_SBC_S_IMM_VAL), +/* 0010 1101 1011 */ TABDECL( OP_SBC_S_IMM_VAL), +/* 0010 1101 1100 */ TABDECL( OP_SBC_S_IMM_VAL), +/* 0010 1101 1101 */ TABDECL( OP_SBC_S_IMM_VAL), +/* 0010 1101 1110 */ TABDECL( OP_SBC_S_IMM_VAL), +/* 0010 1101 1111 */ TABDECL( OP_SBC_S_IMM_VAL), +/* 0010 1110 0000 */ TABDECL( OP_RSC_IMM_VAL), +/* 0010 1110 0001 */ TABDECL( OP_RSC_IMM_VAL), +/* 0010 1110 0010 */ TABDECL( OP_RSC_IMM_VAL), +/* 0010 1110 0011 */ TABDECL( OP_RSC_IMM_VAL), +/* 0010 1110 0100 */ TABDECL( OP_RSC_IMM_VAL), +/* 0010 1110 0101 */ TABDECL( OP_RSC_IMM_VAL), +/* 0010 1110 0110 */ TABDECL( OP_RSC_IMM_VAL), +/* 0010 1110 0111 */ TABDECL( OP_RSC_IMM_VAL), +/* 0010 1110 1000 */ TABDECL( OP_RSC_IMM_VAL), +/* 0010 1110 1001 */ TABDECL( OP_RSC_IMM_VAL), +/* 0010 1110 1010 */ TABDECL( OP_RSC_IMM_VAL), +/* 0010 1110 1011 */ TABDECL( OP_RSC_IMM_VAL), +/* 0010 1110 1100 */ TABDECL( OP_RSC_IMM_VAL), +/* 0010 1110 1101 */ TABDECL( OP_RSC_IMM_VAL), +/* 0010 1110 1110 */ TABDECL( OP_RSC_IMM_VAL), +/* 0010 1110 1111 */ TABDECL( OP_RSC_IMM_VAL), +/* 0010 1111 0000 */ TABDECL( OP_RSC_S_IMM_VAL), +/* 0010 1111 0001 */ TABDECL( OP_RSC_S_IMM_VAL), +/* 0010 1111 0010 */ TABDECL( OP_RSC_S_IMM_VAL), +/* 0010 1111 0011 */ TABDECL( OP_RSC_S_IMM_VAL), +/* 0010 1111 0100 */ TABDECL( OP_RSC_S_IMM_VAL), +/* 0010 1111 0101 */ TABDECL( OP_RSC_S_IMM_VAL), +/* 0010 1111 0110 */ TABDECL( OP_RSC_S_IMM_VAL), +/* 0010 1111 0111 */ TABDECL( OP_RSC_S_IMM_VAL), +/* 0010 1111 1000 */ TABDECL( OP_RSC_S_IMM_VAL), +/* 0010 1111 1001 */ TABDECL( OP_RSC_S_IMM_VAL), +/* 0010 1111 1010 */ TABDECL( OP_RSC_S_IMM_VAL), +/* 0010 1111 1011 */ TABDECL( OP_RSC_S_IMM_VAL), +/* 0010 1111 1100 */ TABDECL( OP_RSC_S_IMM_VAL), +/* 0010 1111 1101 */ TABDECL( OP_RSC_S_IMM_VAL), +/* 0010 1111 1110 */ TABDECL( OP_RSC_S_IMM_VAL), +/* 0010 1111 1111 */ TABDECL( OP_RSC_S_IMM_VAL), +/* 0011 0000 0000 */ TABDECL( OP_UND), +/* 0011 0000 0001 */ TABDECL( OP_UND), +/* 0011 0000 0010 */ TABDECL( OP_UND), +/* 0011 0000 0011 */ TABDECL( OP_UND), +/* 0011 0000 0100 */ TABDECL( OP_UND), +/* 0011 0000 0101 */ TABDECL( OP_UND), +/* 0011 0000 0110 */ TABDECL( OP_UND), +/* 0011 0000 0111 */ TABDECL( OP_UND), +/* 0011 0000 1000 */ TABDECL( OP_UND), +/* 0011 0000 1001 */ TABDECL( OP_UND), +/* 0011 0000 1010 */ TABDECL( OP_UND), +/* 0011 0000 1011 */ TABDECL( OP_UND), +/* 0011 0000 1100 */ TABDECL( OP_UND), +/* 0011 0000 1101 */ TABDECL( OP_UND), +/* 0011 0000 1110 */ TABDECL( OP_UND), +/* 0011 0000 1111 */ TABDECL( OP_UND), +/* 0011 0001 0000 */ TABDECL( OP_TST_IMM_VAL), +/* 0011 0001 0001 */ TABDECL( OP_TST_IMM_VAL), +/* 0011 0001 0010 */ TABDECL( OP_TST_IMM_VAL), +/* 0011 0001 0011 */ TABDECL( OP_TST_IMM_VAL), +/* 0011 0001 0100 */ TABDECL( OP_TST_IMM_VAL), +/* 0011 0001 0101 */ TABDECL( OP_TST_IMM_VAL), +/* 0011 0001 0110 */ TABDECL( OP_TST_IMM_VAL), +/* 0011 0001 0111 */ TABDECL( OP_TST_IMM_VAL), +/* 0011 0001 1000 */ TABDECL( OP_TST_IMM_VAL), +/* 0011 0001 1001 */ TABDECL( OP_TST_IMM_VAL), +/* 0011 0001 1010 */ TABDECL( OP_TST_IMM_VAL), +/* 0011 0001 1011 */ TABDECL( OP_TST_IMM_VAL), +/* 0011 0001 1100 */ TABDECL( OP_TST_IMM_VAL), +/* 0011 0001 1101 */ TABDECL( OP_TST_IMM_VAL), +/* 0011 0001 1110 */ TABDECL( OP_TST_IMM_VAL), +/* 0011 0001 1111 */ TABDECL( OP_TST_IMM_VAL), +/* 0011 0010 0000 */ TABDECL( OP_MSR_CPSR_IMM_VAL), +/* 0011 0010 0001 */ TABDECL( OP_MSR_CPSR_IMM_VAL), +/* 0011 0010 0010 */ TABDECL( OP_MSR_CPSR_IMM_VAL), +/* 0011 0010 0011 */ TABDECL( OP_MSR_CPSR_IMM_VAL), +/* 0011 0010 0100 */ TABDECL( OP_MSR_CPSR_IMM_VAL), +/* 0011 0010 0101 */ TABDECL( OP_MSR_CPSR_IMM_VAL), +/* 0011 0010 0110 */ TABDECL( OP_MSR_CPSR_IMM_VAL), +/* 0011 0010 0111 */ TABDECL( OP_MSR_CPSR_IMM_VAL), +/* 0011 0010 1000 */ TABDECL( OP_MSR_CPSR_IMM_VAL), +/* 0011 0010 1001 */ TABDECL( OP_MSR_CPSR_IMM_VAL), +/* 0011 0010 1010 */ TABDECL( OP_MSR_CPSR_IMM_VAL), +/* 0011 0010 1011 */ TABDECL( OP_MSR_CPSR_IMM_VAL), +/* 0011 0010 1100 */ TABDECL( OP_MSR_CPSR_IMM_VAL), +/* 0011 0010 1101 */ TABDECL( OP_MSR_CPSR_IMM_VAL), +/* 0011 0010 1110 */ TABDECL( OP_MSR_CPSR_IMM_VAL), +/* 0011 0010 1111 */ TABDECL( OP_MSR_CPSR_IMM_VAL), +/* 0011 0011 0000 */ TABDECL( OP_TEQ_IMM_VAL), +/* 0011 0011 0001 */ TABDECL( OP_TEQ_IMM_VAL), +/* 0011 0011 0010 */ TABDECL( OP_TEQ_IMM_VAL), +/* 0011 0011 0011 */ TABDECL( OP_TEQ_IMM_VAL), +/* 0011 0011 0100 */ TABDECL( OP_TEQ_IMM_VAL), +/* 0011 0011 0101 */ TABDECL( OP_TEQ_IMM_VAL), +/* 0011 0011 0110 */ TABDECL( OP_TEQ_IMM_VAL), +/* 0011 0011 0111 */ TABDECL( OP_TEQ_IMM_VAL), +/* 0011 0011 1000 */ TABDECL( OP_TEQ_IMM_VAL), +/* 0011 0011 1001 */ TABDECL( OP_TEQ_IMM_VAL), +/* 0011 0011 1010 */ TABDECL( OP_TEQ_IMM_VAL), +/* 0011 0011 1011 */ TABDECL( OP_TEQ_IMM_VAL), +/* 0011 0011 1100 */ TABDECL( OP_TEQ_IMM_VAL), +/* 0011 0011 1101 */ TABDECL( OP_TEQ_IMM_VAL), +/* 0011 0011 1110 */ TABDECL( OP_TEQ_IMM_VAL), +/* 0011 0011 1111 */ TABDECL( OP_TEQ_IMM_VAL), +/* 0011 0100 0000 */ TABDECL( OP_UND), +/* 0011 0100 0001 */ TABDECL( OP_UND), +/* 0011 0100 0010 */ TABDECL( OP_UND), +/* 0011 0100 0011 */ TABDECL( OP_UND), +/* 0011 0100 0100 */ TABDECL( OP_UND), +/* 0011 0100 0101 */ TABDECL( OP_UND), +/* 0011 0100 0110 */ TABDECL( OP_UND), +/* 0011 0100 0111 */ TABDECL( OP_UND), +/* 0011 0100 1000 */ TABDECL( OP_UND), +/* 0011 0100 1001 */ TABDECL( OP_UND), +/* 0011 0100 1010 */ TABDECL( OP_UND), +/* 0011 0100 1011 */ TABDECL( OP_UND), +/* 0011 0100 1100 */ TABDECL( OP_UND), +/* 0011 0100 1101 */ TABDECL( OP_UND), +/* 0011 0100 1110 */ TABDECL( OP_UND), +/* 0011 0100 1111 */ TABDECL( OP_UND), +/* 0011 0101 0000 */ TABDECL( OP_CMP_IMM_VAL), +/* 0011 0101 0001 */ TABDECL( OP_CMP_IMM_VAL), +/* 0011 0101 0010 */ TABDECL( OP_CMP_IMM_VAL), +/* 0011 0101 0011 */ TABDECL( OP_CMP_IMM_VAL), +/* 0011 0101 0100 */ TABDECL( OP_CMP_IMM_VAL), +/* 0011 0101 0101 */ TABDECL( OP_CMP_IMM_VAL), +/* 0011 0101 0110 */ TABDECL( OP_CMP_IMM_VAL), +/* 0011 0101 0111 */ TABDECL( OP_CMP_IMM_VAL), +/* 0011 0101 1000 */ TABDECL( OP_CMP_IMM_VAL), +/* 0011 0101 1001 */ TABDECL( OP_CMP_IMM_VAL), +/* 0011 0101 1010 */ TABDECL( OP_CMP_IMM_VAL), +/* 0011 0101 1011 */ TABDECL( OP_CMP_IMM_VAL), +/* 0011 0101 1100 */ TABDECL( OP_CMP_IMM_VAL), +/* 0011 0101 1101 */ TABDECL( OP_CMP_IMM_VAL), +/* 0011 0101 1110 */ TABDECL( OP_CMP_IMM_VAL), +/* 0011 0101 1111 */ TABDECL( OP_CMP_IMM_VAL), +/* 0011 0110 0000 */ TABDECL( OP_MSR_SPSR_IMM_VAL), +/* 0011 0110 0001 */ TABDECL( OP_MSR_SPSR_IMM_VAL), +/* 0011 0110 0010 */ TABDECL( OP_MSR_SPSR_IMM_VAL), +/* 0011 0110 0011 */ TABDECL( OP_MSR_SPSR_IMM_VAL), +/* 0011 0110 0100 */ TABDECL( OP_MSR_SPSR_IMM_VAL), +/* 0011 0110 0101 */ TABDECL( OP_MSR_SPSR_IMM_VAL), +/* 0011 0110 0110 */ TABDECL( OP_MSR_SPSR_IMM_VAL), +/* 0011 0110 0111 */ TABDECL( OP_MSR_SPSR_IMM_VAL), +/* 0011 0110 1000 */ TABDECL( OP_MSR_SPSR_IMM_VAL), +/* 0011 0110 1001 */ TABDECL( OP_MSR_SPSR_IMM_VAL), +/* 0011 0110 1010 */ TABDECL( OP_MSR_SPSR_IMM_VAL), +/* 0011 0110 1011 */ TABDECL( OP_MSR_SPSR_IMM_VAL), +/* 0011 0110 1100 */ TABDECL( OP_MSR_SPSR_IMM_VAL), +/* 0011 0110 1101 */ TABDECL( OP_MSR_SPSR_IMM_VAL), +/* 0011 0110 1110 */ TABDECL( OP_MSR_SPSR_IMM_VAL), +/* 0011 0110 1111 */ TABDECL( OP_MSR_SPSR_IMM_VAL), +/* 0011 0111 0000 */ TABDECL( OP_CMN_IMM_VAL), +/* 0011 0111 0001 */ TABDECL( OP_CMN_IMM_VAL), +/* 0011 0111 0010 */ TABDECL( OP_CMN_IMM_VAL), +/* 0011 0111 0011 */ TABDECL( OP_CMN_IMM_VAL), +/* 0011 0111 0100 */ TABDECL( OP_CMN_IMM_VAL), +/* 0011 0111 0101 */ TABDECL( OP_CMN_IMM_VAL), +/* 0011 0111 0110 */ TABDECL( OP_CMN_IMM_VAL), +/* 0011 0111 0111 */ TABDECL( OP_CMN_IMM_VAL), +/* 0011 0111 1000 */ TABDECL( OP_CMN_IMM_VAL), +/* 0011 0111 1001 */ TABDECL( OP_CMN_IMM_VAL), +/* 0011 0111 1010 */ TABDECL( OP_CMN_IMM_VAL), +/* 0011 0111 1011 */ TABDECL( OP_CMN_IMM_VAL), +/* 0011 0111 1100 */ TABDECL( OP_CMN_IMM_VAL), +/* 0011 0111 1101 */ TABDECL( OP_CMN_IMM_VAL), +/* 0011 0111 1110 */ TABDECL( OP_CMN_IMM_VAL), +/* 0011 0111 1111 */ TABDECL( OP_CMN_IMM_VAL), +/* 0011 1000 0000 */ TABDECL( OP_ORR_IMM_VAL), +/* 0011 1000 0001 */ TABDECL( OP_ORR_IMM_VAL), +/* 0011 1000 0010 */ TABDECL( OP_ORR_IMM_VAL), +/* 0011 1000 0011 */ TABDECL( OP_ORR_IMM_VAL), +/* 0011 1000 0100 */ TABDECL( OP_ORR_IMM_VAL), +/* 0011 1000 0101 */ TABDECL( OP_ORR_IMM_VAL), +/* 0011 1000 0110 */ TABDECL( OP_ORR_IMM_VAL), +/* 0011 1000 0111 */ TABDECL( OP_ORR_IMM_VAL), +/* 0011 1000 1000 */ TABDECL( OP_ORR_IMM_VAL), +/* 0011 1000 1001 */ TABDECL( OP_ORR_IMM_VAL), +/* 0011 1000 1010 */ TABDECL( OP_ORR_IMM_VAL), +/* 0011 1000 1011 */ TABDECL( OP_ORR_IMM_VAL), +/* 0011 1000 1100 */ TABDECL( OP_ORR_IMM_VAL), +/* 0011 1000 1101 */ TABDECL( OP_ORR_IMM_VAL), +/* 0011 1000 1110 */ TABDECL( OP_ORR_IMM_VAL), +/* 0011 1000 1111 */ TABDECL( OP_ORR_IMM_VAL), +/* 0011 1001 0000 */ TABDECL( OP_ORR_S_IMM_VAL), +/* 0011 1001 0001 */ TABDECL( OP_ORR_S_IMM_VAL), +/* 0011 1001 0010 */ TABDECL( OP_ORR_S_IMM_VAL), +/* 0011 1001 0011 */ TABDECL( OP_ORR_S_IMM_VAL), +/* 0011 1001 0100 */ TABDECL( OP_ORR_S_IMM_VAL), +/* 0011 1001 0101 */ TABDECL( OP_ORR_S_IMM_VAL), +/* 0011 1001 0110 */ TABDECL( OP_ORR_S_IMM_VAL), +/* 0011 1001 0111 */ TABDECL( OP_ORR_S_IMM_VAL), +/* 0011 1001 1000 */ TABDECL( OP_ORR_S_IMM_VAL), +/* 0011 1001 1001 */ TABDECL( OP_ORR_S_IMM_VAL), +/* 0011 1001 1010 */ TABDECL( OP_ORR_S_IMM_VAL), +/* 0011 1001 1011 */ TABDECL( OP_ORR_S_IMM_VAL), +/* 0011 1001 1100 */ TABDECL( OP_ORR_S_IMM_VAL), +/* 0011 1001 1101 */ TABDECL( OP_ORR_S_IMM_VAL), +/* 0011 1001 1110 */ TABDECL( OP_ORR_S_IMM_VAL), +/* 0011 1001 1111 */ TABDECL( OP_ORR_S_IMM_VAL), +/* 0011 1010 0000 */ TABDECL( OP_MOV_IMM_VAL), +/* 0011 1010 0001 */ TABDECL( OP_MOV_IMM_VAL), +/* 0011 1010 0010 */ TABDECL( OP_MOV_IMM_VAL), +/* 0011 1010 0011 */ TABDECL( OP_MOV_IMM_VAL), +/* 0011 1010 0100 */ TABDECL( OP_MOV_IMM_VAL), +/* 0011 1010 0101 */ TABDECL( OP_MOV_IMM_VAL), +/* 0011 1010 0110 */ TABDECL( OP_MOV_IMM_VAL), +/* 0011 1010 0111 */ TABDECL( OP_MOV_IMM_VAL), +/* 0011 1010 1000 */ TABDECL( OP_MOV_IMM_VAL), +/* 0011 1010 1001 */ TABDECL( OP_MOV_IMM_VAL), +/* 0011 1010 1010 */ TABDECL( OP_MOV_IMM_VAL), +/* 0011 1010 1011 */ TABDECL( OP_MOV_IMM_VAL), +/* 0011 1010 1100 */ TABDECL( OP_MOV_IMM_VAL), +/* 0011 1010 1101 */ TABDECL( OP_MOV_IMM_VAL), +/* 0011 1010 1110 */ TABDECL( OP_MOV_IMM_VAL), +/* 0011 1010 1111 */ TABDECL( OP_MOV_IMM_VAL), +/* 0011 1011 0000 */ TABDECL( OP_MOV_S_IMM_VAL), +/* 0011 1011 0001 */ TABDECL( OP_MOV_S_IMM_VAL), +/* 0011 1011 0010 */ TABDECL( OP_MOV_S_IMM_VAL), +/* 0011 1011 0011 */ TABDECL( OP_MOV_S_IMM_VAL), +/* 0011 1011 0100 */ TABDECL( OP_MOV_S_IMM_VAL), +/* 0011 1011 0101 */ TABDECL( OP_MOV_S_IMM_VAL), +/* 0011 1011 0110 */ TABDECL( OP_MOV_S_IMM_VAL), +/* 0011 1011 0111 */ TABDECL( OP_MOV_S_IMM_VAL), +/* 0011 1011 1000 */ TABDECL( OP_MOV_S_IMM_VAL), +/* 0011 1011 1001 */ TABDECL( OP_MOV_S_IMM_VAL), +/* 0011 1011 1010 */ TABDECL( OP_MOV_S_IMM_VAL), +/* 0011 1011 1011 */ TABDECL( OP_MOV_S_IMM_VAL), +/* 0011 1011 1100 */ TABDECL( OP_MOV_S_IMM_VAL), +/* 0011 1011 1101 */ TABDECL( OP_MOV_S_IMM_VAL), +/* 0011 1011 1110 */ TABDECL( OP_MOV_S_IMM_VAL), +/* 0011 1011 1111 */ TABDECL( OP_MOV_S_IMM_VAL), +/* 0011 1100 0000 */ TABDECL( OP_BIC_IMM_VAL), +/* 0011 1100 0001 */ TABDECL( OP_BIC_IMM_VAL), +/* 0011 1100 0010 */ TABDECL( OP_BIC_IMM_VAL), +/* 0011 1100 0011 */ TABDECL( OP_BIC_IMM_VAL), +/* 0011 1100 0100 */ TABDECL( OP_BIC_IMM_VAL), +/* 0011 1100 0101 */ TABDECL( OP_BIC_IMM_VAL), +/* 0011 1100 0110 */ TABDECL( OP_BIC_IMM_VAL), +/* 0011 1100 0111 */ TABDECL( OP_BIC_IMM_VAL), +/* 0011 1100 1000 */ TABDECL( OP_BIC_IMM_VAL), +/* 0011 1100 1001 */ TABDECL( OP_BIC_IMM_VAL), +/* 0011 1100 1010 */ TABDECL( OP_BIC_IMM_VAL), +/* 0011 1100 1011 */ TABDECL( OP_BIC_IMM_VAL), +/* 0011 1100 1100 */ TABDECL( OP_BIC_IMM_VAL), +/* 0011 1100 1101 */ TABDECL( OP_BIC_IMM_VAL), +/* 0011 1100 1110 */ TABDECL( OP_BIC_IMM_VAL), +/* 0011 1100 1111 */ TABDECL( OP_BIC_IMM_VAL), +/* 0011 1101 0000 */ TABDECL( OP_BIC_S_IMM_VAL), +/* 0011 1101 0001 */ TABDECL( OP_BIC_S_IMM_VAL), +/* 0011 1101 0010 */ TABDECL( OP_BIC_S_IMM_VAL), +/* 0011 1101 0011 */ TABDECL( OP_BIC_S_IMM_VAL), +/* 0011 1101 0100 */ TABDECL( OP_BIC_S_IMM_VAL), +/* 0011 1101 0101 */ TABDECL( OP_BIC_S_IMM_VAL), +/* 0011 1101 0110 */ TABDECL( OP_BIC_S_IMM_VAL), +/* 0011 1101 0111 */ TABDECL( OP_BIC_S_IMM_VAL), +/* 0011 1101 1000 */ TABDECL( OP_BIC_S_IMM_VAL), +/* 0011 1101 1001 */ TABDECL( OP_BIC_S_IMM_VAL), +/* 0011 1101 1010 */ TABDECL( OP_BIC_S_IMM_VAL), +/* 0011 1101 1011 */ TABDECL( OP_BIC_S_IMM_VAL), +/* 0011 1101 1100 */ TABDECL( OP_BIC_S_IMM_VAL), +/* 0011 1101 1101 */ TABDECL( OP_BIC_S_IMM_VAL), +/* 0011 1101 1110 */ TABDECL( OP_BIC_S_IMM_VAL), +/* 0011 1101 1111 */ TABDECL( OP_BIC_S_IMM_VAL), +/* 0011 1110 0000 */ TABDECL( OP_MVN_IMM_VAL), +/* 0011 1110 0001 */ TABDECL( OP_MVN_IMM_VAL), +/* 0011 1110 0010 */ TABDECL( OP_MVN_IMM_VAL), +/* 0011 1110 0011 */ TABDECL( OP_MVN_IMM_VAL), +/* 0011 1110 0100 */ TABDECL( OP_MVN_IMM_VAL), +/* 0011 1110 0101 */ TABDECL( OP_MVN_IMM_VAL), +/* 0011 1110 0110 */ TABDECL( OP_MVN_IMM_VAL), +/* 0011 1110 0111 */ TABDECL( OP_MVN_IMM_VAL), +/* 0011 1110 1000 */ TABDECL( OP_MVN_IMM_VAL), +/* 0011 1110 1001 */ TABDECL( OP_MVN_IMM_VAL), +/* 0011 1110 1010 */ TABDECL( OP_MVN_IMM_VAL), +/* 0011 1110 1011 */ TABDECL( OP_MVN_IMM_VAL), +/* 0011 1110 1100 */ TABDECL( OP_MVN_IMM_VAL), +/* 0011 1110 1101 */ TABDECL( OP_MVN_IMM_VAL), +/* 0011 1110 1110 */ TABDECL( OP_MVN_IMM_VAL), +/* 0011 1110 1111 */ TABDECL( OP_MVN_IMM_VAL), +/* 0011 1111 0000 */ TABDECL( OP_MVN_S_IMM_VAL), +/* 0011 1111 0001 */ TABDECL( OP_MVN_S_IMM_VAL), +/* 0011 1111 0010 */ TABDECL( OP_MVN_S_IMM_VAL), +/* 0011 1111 0011 */ TABDECL( OP_MVN_S_IMM_VAL), +/* 0011 1111 0100 */ TABDECL( OP_MVN_S_IMM_VAL), +/* 0011 1111 0101 */ TABDECL( OP_MVN_S_IMM_VAL), +/* 0011 1111 0110 */ TABDECL( OP_MVN_S_IMM_VAL), +/* 0011 1111 0111 */ TABDECL( OP_MVN_S_IMM_VAL), +/* 0011 1111 1000 */ TABDECL( OP_MVN_S_IMM_VAL), +/* 0011 1111 1001 */ TABDECL( OP_MVN_S_IMM_VAL), +/* 0011 1111 1010 */ TABDECL( OP_MVN_S_IMM_VAL), +/* 0011 1111 1011 */ TABDECL( OP_MVN_S_IMM_VAL), +/* 0011 1111 1100 */ TABDECL( OP_MVN_S_IMM_VAL), +/* 0011 1111 1101 */ TABDECL( OP_MVN_S_IMM_VAL), +/* 0011 1111 1110 */ TABDECL( OP_MVN_S_IMM_VAL), +/* 0011 1111 1111 */ TABDECL( OP_MVN_S_IMM_VAL), +/* 0100 0000 0000 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0000 0001 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0000 0010 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0000 0011 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0000 0100 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0000 0101 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0000 0110 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0000 0111 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0000 1000 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0000 1001 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0000 1010 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0000 1011 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0000 1100 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0000 1101 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0000 1110 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0000 1111 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0001 0000 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0001 0001 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0001 0010 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0001 0011 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0001 0100 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0001 0101 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0001 0110 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0001 0111 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0001 1000 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0001 1001 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0001 1010 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0001 1011 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0001 1100 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0001 1101 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0001 1110 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0001 1111 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0010 0000 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0010 0001 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0010 0010 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0010 0011 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0010 0100 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0010 0101 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0010 0110 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0010 0111 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0010 1000 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0010 1001 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0010 1010 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0010 1011 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0010 1100 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0010 1101 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0010 1110 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0010 1111 */ TABDECL( OP_STR_M_IMM_OFF_POSTIND), +/* 0100 0011 0000 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0011 0001 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0011 0010 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0011 0011 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0011 0100 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0011 0101 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0011 0110 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0011 0111 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0011 1000 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0011 1001 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0011 1010 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0011 1011 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0011 1100 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0011 1101 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0011 1110 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0011 1111 */ TABDECL( OP_LDR_M_IMM_OFF_POSTIND), +/* 0100 0100 0000 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0100 0001 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0100 0010 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0100 0011 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0100 0100 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0100 0101 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0100 0110 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0100 0111 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0100 1000 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0100 1001 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0100 1010 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0100 1011 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0100 1100 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0100 1101 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0100 1110 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0100 1111 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0101 0000 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0101 0001 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0101 0010 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0101 0011 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0101 0100 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0101 0101 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0101 0110 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0101 0111 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0101 1000 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0101 1001 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0101 1010 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0101 1011 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0101 1100 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0101 1101 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0101 1110 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0101 1111 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0110 0000 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0110 0001 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0110 0010 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0110 0011 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0110 0100 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0110 0101 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0110 0110 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0110 0111 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0110 1000 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0110 1001 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0110 1010 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0110 1011 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0110 1100 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0110 1101 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0110 1110 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0110 1111 */ TABDECL( OP_STRB_M_IMM_OFF_POSTIND), +/* 0100 0111 0000 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0111 0001 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0111 0010 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0111 0011 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0111 0100 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0111 0101 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0111 0110 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0111 0111 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0111 1000 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0111 1001 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0111 1010 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0111 1011 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0111 1100 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0111 1101 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0111 1110 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 0111 1111 */ TABDECL( OP_LDRB_M_IMM_OFF_POSTIND), +/* 0100 1000 0000 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1000 0001 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1000 0010 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1000 0011 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1000 0100 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1000 0101 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1000 0110 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1000 0111 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1000 1000 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1000 1001 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1000 1010 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1000 1011 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1000 1100 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1000 1101 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1000 1110 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1000 1111 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1001 0000 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1001 0001 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1001 0010 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1001 0011 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1001 0100 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1001 0101 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1001 0110 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1001 0111 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1001 1000 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1001 1001 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1001 1010 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1001 1011 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1001 1100 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1001 1101 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1001 1110 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1001 1111 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1010 0000 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1010 0001 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1010 0010 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1010 0011 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1010 0100 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1010 0101 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1010 0110 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1010 0111 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1010 1000 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1010 1001 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1010 1010 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1010 1011 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1010 1100 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1010 1101 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1010 1110 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1010 1111 */ TABDECL( OP_STR_P_IMM_OFF_POSTIND), +/* 0100 1011 0000 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1011 0001 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1011 0010 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1011 0011 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1011 0100 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1011 0101 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1011 0110 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1011 0111 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1011 1000 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1011 1001 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1011 1010 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1011 1011 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1011 1100 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1011 1101 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1011 1110 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1011 1111 */ TABDECL( OP_LDR_P_IMM_OFF_POSTIND), +/* 0100 1100 0000 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1100 0001 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1100 0010 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1100 0011 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1100 0100 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1100 0101 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1100 0110 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1100 0111 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1100 1000 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1100 1001 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1100 1010 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1100 1011 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1100 1100 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1100 1101 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1100 1110 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1100 1111 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1101 0000 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1101 0001 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1101 0010 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1101 0011 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1101 0100 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1101 0101 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1101 0110 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1101 0111 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1101 1000 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1101 1001 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1101 1010 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1101 1011 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1101 1100 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1101 1101 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1101 1110 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1101 1111 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1110 0000 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1110 0001 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1110 0010 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1110 0011 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1110 0100 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1110 0101 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1110 0110 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1110 0111 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1110 1000 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1110 1001 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1110 1010 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1110 1011 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1110 1100 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1110 1101 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1110 1110 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1110 1111 */ TABDECL( OP_STRB_P_IMM_OFF_POSTIND), +/* 0100 1111 0000 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1111 0001 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1111 0010 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1111 0011 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1111 0100 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1111 0101 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1111 0110 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1111 0111 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1111 1000 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1111 1001 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1111 1010 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1111 1011 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1111 1100 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1111 1101 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1111 1110 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0100 1111 1111 */ TABDECL( OP_LDRB_P_IMM_OFF_POSTIND), +/* 0101 0000 0000 */ TABDECL( OP_STR_M_IMM_OFF), +/* 0101 0000 0001 */ TABDECL( OP_STR_M_IMM_OFF), +/* 0101 0000 0010 */ TABDECL( OP_STR_M_IMM_OFF), +/* 0101 0000 0011 */ TABDECL( OP_STR_M_IMM_OFF), +/* 0101 0000 0100 */ TABDECL( OP_STR_M_IMM_OFF), +/* 0101 0000 0101 */ TABDECL( OP_STR_M_IMM_OFF), +/* 0101 0000 0110 */ TABDECL( OP_STR_M_IMM_OFF), +/* 0101 0000 0111 */ TABDECL( OP_STR_M_IMM_OFF), +/* 0101 0000 1000 */ TABDECL( OP_STR_M_IMM_OFF), +/* 0101 0000 1001 */ TABDECL( OP_STR_M_IMM_OFF), +/* 0101 0000 1010 */ TABDECL( OP_STR_M_IMM_OFF), +/* 0101 0000 1011 */ TABDECL( OP_STR_M_IMM_OFF), +/* 0101 0000 1100 */ TABDECL( OP_STR_M_IMM_OFF), +/* 0101 0000 1101 */ TABDECL( OP_STR_M_IMM_OFF), +/* 0101 0000 1110 */ TABDECL( OP_STR_M_IMM_OFF), +/* 0101 0000 1111 */ TABDECL( OP_STR_M_IMM_OFF), +/* 0101 0001 0000 */ TABDECL( OP_LDR_M_IMM_OFF), +/* 0101 0001 0001 */ TABDECL( OP_LDR_M_IMM_OFF), +/* 0101 0001 0010 */ TABDECL( OP_LDR_M_IMM_OFF), +/* 0101 0001 0011 */ TABDECL( OP_LDR_M_IMM_OFF), +/* 0101 0001 0100 */ TABDECL( OP_LDR_M_IMM_OFF), +/* 0101 0001 0101 */ TABDECL( OP_LDR_M_IMM_OFF), +/* 0101 0001 0110 */ TABDECL( OP_LDR_M_IMM_OFF), +/* 0101 0001 0111 */ TABDECL( OP_LDR_M_IMM_OFF), +/* 0101 0001 1000 */ TABDECL( OP_LDR_M_IMM_OFF), +/* 0101 0001 1001 */ TABDECL( OP_LDR_M_IMM_OFF), +/* 0101 0001 1010 */ TABDECL( OP_LDR_M_IMM_OFF), +/* 0101 0001 1011 */ TABDECL( OP_LDR_M_IMM_OFF), +/* 0101 0001 1100 */ TABDECL( OP_LDR_M_IMM_OFF), +/* 0101 0001 1101 */ TABDECL( OP_LDR_M_IMM_OFF), +/* 0101 0001 1110 */ TABDECL( OP_LDR_M_IMM_OFF), +/* 0101 0001 1111 */ TABDECL( OP_LDR_M_IMM_OFF), +/* 0101 0010 0000 */ TABDECL( OP_STR_M_IMM_OFF_PREIND), +/* 0101 0010 0001 */ TABDECL( OP_STR_M_IMM_OFF_PREIND), +/* 0101 0010 0010 */ TABDECL( OP_STR_M_IMM_OFF_PREIND), +/* 0101 0010 0011 */ TABDECL( OP_STR_M_IMM_OFF_PREIND), +/* 0101 0010 0100 */ TABDECL( OP_STR_M_IMM_OFF_PREIND), +/* 0101 0010 0101 */ TABDECL( OP_STR_M_IMM_OFF_PREIND), +/* 0101 0010 0110 */ TABDECL( OP_STR_M_IMM_OFF_PREIND), +/* 0101 0010 0111 */ TABDECL( OP_STR_M_IMM_OFF_PREIND), +/* 0101 0010 1000 */ TABDECL( OP_STR_M_IMM_OFF_PREIND), +/* 0101 0010 1001 */ TABDECL( OP_STR_M_IMM_OFF_PREIND), +/* 0101 0010 1010 */ TABDECL( OP_STR_M_IMM_OFF_PREIND), +/* 0101 0010 1011 */ TABDECL( OP_STR_M_IMM_OFF_PREIND), +/* 0101 0010 1100 */ TABDECL( OP_STR_M_IMM_OFF_PREIND), +/* 0101 0010 1101 */ TABDECL( OP_STR_M_IMM_OFF_PREIND), +/* 0101 0010 1110 */ TABDECL( OP_STR_M_IMM_OFF_PREIND), +/* 0101 0010 1111 */ TABDECL( OP_STR_M_IMM_OFF_PREIND), +/* 0101 0011 0000 */ TABDECL( OP_LDR_M_IMM_OFF_PREIND), +/* 0101 0011 0001 */ TABDECL( OP_LDR_M_IMM_OFF_PREIND), +/* 0101 0011 0010 */ TABDECL( OP_LDR_M_IMM_OFF_PREIND), +/* 0101 0011 0011 */ TABDECL( OP_LDR_M_IMM_OFF_PREIND), +/* 0101 0011 0100 */ TABDECL( OP_LDR_M_IMM_OFF_PREIND), +/* 0101 0011 0101 */ TABDECL( OP_LDR_M_IMM_OFF_PREIND), +/* 0101 0011 0110 */ TABDECL( OP_LDR_M_IMM_OFF_PREIND), +/* 0101 0011 0111 */ TABDECL( OP_LDR_M_IMM_OFF_PREIND), +/* 0101 0011 1000 */ TABDECL( OP_LDR_M_IMM_OFF_PREIND), +/* 0101 0011 1001 */ TABDECL( OP_LDR_M_IMM_OFF_PREIND), +/* 0101 0011 1010 */ TABDECL( OP_LDR_M_IMM_OFF_PREIND), +/* 0101 0011 1011 */ TABDECL( OP_LDR_M_IMM_OFF_PREIND), +/* 0101 0011 1100 */ TABDECL( OP_LDR_M_IMM_OFF_PREIND), +/* 0101 0011 1101 */ TABDECL( OP_LDR_M_IMM_OFF_PREIND), +/* 0101 0011 1110 */ TABDECL( OP_LDR_M_IMM_OFF_PREIND), +/* 0101 0011 1111 */ TABDECL( OP_LDR_M_IMM_OFF_PREIND), +/* 0101 0100 0000 */ TABDECL( OP_STRB_M_IMM_OFF), +/* 0101 0100 0001 */ TABDECL( OP_STRB_M_IMM_OFF), +/* 0101 0100 0010 */ TABDECL( OP_STRB_M_IMM_OFF), +/* 0101 0100 0011 */ TABDECL( OP_STRB_M_IMM_OFF), +/* 0101 0100 0100 */ TABDECL( OP_STRB_M_IMM_OFF), +/* 0101 0100 0101 */ TABDECL( OP_STRB_M_IMM_OFF), +/* 0101 0100 0110 */ TABDECL( OP_STRB_M_IMM_OFF), +/* 0101 0100 0111 */ TABDECL( OP_STRB_M_IMM_OFF), +/* 0101 0100 1000 */ TABDECL( OP_STRB_M_IMM_OFF), +/* 0101 0100 1001 */ TABDECL( OP_STRB_M_IMM_OFF), +/* 0101 0100 1010 */ TABDECL( OP_STRB_M_IMM_OFF), +/* 0101 0100 1011 */ TABDECL( OP_STRB_M_IMM_OFF), +/* 0101 0100 1100 */ TABDECL( OP_STRB_M_IMM_OFF), +/* 0101 0100 1101 */ TABDECL( OP_STRB_M_IMM_OFF), +/* 0101 0100 1110 */ TABDECL( OP_STRB_M_IMM_OFF), +/* 0101 0100 1111 */ TABDECL( OP_STRB_M_IMM_OFF), +/* 0101 0101 0000 */ TABDECL( OP_LDRB_M_IMM_OFF), +/* 0101 0101 0001 */ TABDECL( OP_LDRB_M_IMM_OFF), +/* 0101 0101 0010 */ TABDECL( OP_LDRB_M_IMM_OFF), +/* 0101 0101 0011 */ TABDECL( OP_LDRB_M_IMM_OFF), +/* 0101 0101 0100 */ TABDECL( OP_LDRB_M_IMM_OFF), +/* 0101 0101 0101 */ TABDECL( OP_LDRB_M_IMM_OFF), +/* 0101 0101 0110 */ TABDECL( OP_LDRB_M_IMM_OFF), +/* 0101 0101 0111 */ TABDECL( OP_LDRB_M_IMM_OFF), +/* 0101 0101 1000 */ TABDECL( OP_LDRB_M_IMM_OFF), +/* 0101 0101 1001 */ TABDECL( OP_LDRB_M_IMM_OFF), +/* 0101 0101 1010 */ TABDECL( OP_LDRB_M_IMM_OFF), +/* 0101 0101 1011 */ TABDECL( OP_LDRB_M_IMM_OFF), +/* 0101 0101 1100 */ TABDECL( OP_LDRB_M_IMM_OFF), +/* 0101 0101 1101 */ TABDECL( OP_LDRB_M_IMM_OFF), +/* 0101 0101 1110 */ TABDECL( OP_LDRB_M_IMM_OFF), +/* 0101 0101 1111 */ TABDECL( OP_LDRB_M_IMM_OFF), +/* 0101 0110 0000 */ TABDECL( OP_STRB_M_IMM_OFF_PREIND), +/* 0101 0110 0001 */ TABDECL( OP_STRB_M_IMM_OFF_PREIND), +/* 0101 0110 0010 */ TABDECL( OP_STRB_M_IMM_OFF_PREIND), +/* 0101 0110 0011 */ TABDECL( OP_STRB_M_IMM_OFF_PREIND), +/* 0101 0110 0100 */ TABDECL( OP_STRB_M_IMM_OFF_PREIND), +/* 0101 0110 0101 */ TABDECL( OP_STRB_M_IMM_OFF_PREIND), +/* 0101 0110 0110 */ TABDECL( OP_STRB_M_IMM_OFF_PREIND), +/* 0101 0110 0111 */ TABDECL( OP_STRB_M_IMM_OFF_PREIND), +/* 0101 0110 1000 */ TABDECL( OP_STRB_M_IMM_OFF_PREIND), +/* 0101 0110 1001 */ TABDECL( OP_STRB_M_IMM_OFF_PREIND), +/* 0101 0110 1010 */ TABDECL( OP_STRB_M_IMM_OFF_PREIND), +/* 0101 0110 1011 */ TABDECL( OP_STRB_M_IMM_OFF_PREIND), +/* 0101 0110 1100 */ TABDECL( OP_STRB_M_IMM_OFF_PREIND), +/* 0101 0110 1101 */ TABDECL( OP_STRB_M_IMM_OFF_PREIND), +/* 0101 0110 1110 */ TABDECL( OP_STRB_M_IMM_OFF_PREIND), +/* 0101 0110 1111 */ TABDECL( OP_STRB_M_IMM_OFF_PREIND), +/* 0101 0111 0000 */ TABDECL( OP_LDRB_M_IMM_OFF_PREIND), +/* 0101 0111 0001 */ TABDECL( OP_LDRB_M_IMM_OFF_PREIND), +/* 0101 0111 0010 */ TABDECL( OP_LDRB_M_IMM_OFF_PREIND), +/* 0101 0111 0011 */ TABDECL( OP_LDRB_M_IMM_OFF_PREIND), +/* 0101 0111 0100 */ TABDECL( OP_LDRB_M_IMM_OFF_PREIND), +/* 0101 0111 0101 */ TABDECL( OP_LDRB_M_IMM_OFF_PREIND), +/* 0101 0111 0110 */ TABDECL( OP_LDRB_M_IMM_OFF_PREIND), +/* 0101 0111 0111 */ TABDECL( OP_LDRB_M_IMM_OFF_PREIND), +/* 0101 0111 1000 */ TABDECL( OP_LDRB_M_IMM_OFF_PREIND), +/* 0101 0111 1001 */ TABDECL( OP_LDRB_M_IMM_OFF_PREIND), +/* 0101 0111 1010 */ TABDECL( OP_LDRB_M_IMM_OFF_PREIND), +/* 0101 0111 1011 */ TABDECL( OP_LDRB_M_IMM_OFF_PREIND), +/* 0101 0111 1100 */ TABDECL( OP_LDRB_M_IMM_OFF_PREIND), +/* 0101 0111 1101 */ TABDECL( OP_LDRB_M_IMM_OFF_PREIND), +/* 0101 0111 1110 */ TABDECL( OP_LDRB_M_IMM_OFF_PREIND), +/* 0101 0111 1111 */ TABDECL( OP_LDRB_M_IMM_OFF_PREIND), +/* 0101 1000 0000 */ TABDECL( OP_STR_P_IMM_OFF), +/* 0101 1000 0001 */ TABDECL( OP_STR_P_IMM_OFF), +/* 0101 1000 0010 */ TABDECL( OP_STR_P_IMM_OFF), +/* 0101 1000 0011 */ TABDECL( OP_STR_P_IMM_OFF), +/* 0101 1000 0100 */ TABDECL( OP_STR_P_IMM_OFF), +/* 0101 1000 0101 */ TABDECL( OP_STR_P_IMM_OFF), +/* 0101 1000 0110 */ TABDECL( OP_STR_P_IMM_OFF), +/* 0101 1000 0111 */ TABDECL( OP_STR_P_IMM_OFF), +/* 0101 1000 1000 */ TABDECL( OP_STR_P_IMM_OFF), +/* 0101 1000 1001 */ TABDECL( OP_STR_P_IMM_OFF), +/* 0101 1000 1010 */ TABDECL( OP_STR_P_IMM_OFF), +/* 0101 1000 1011 */ TABDECL( OP_STR_P_IMM_OFF), +/* 0101 1000 1100 */ TABDECL( OP_STR_P_IMM_OFF), +/* 0101 1000 1101 */ TABDECL( OP_STR_P_IMM_OFF), +/* 0101 1000 1110 */ TABDECL( OP_STR_P_IMM_OFF), +/* 0101 1000 1111 */ TABDECL( OP_STR_P_IMM_OFF), +/* 0101 1001 0000 */ TABDECL( OP_LDR_P_IMM_OFF), +/* 0101 1001 0001 */ TABDECL( OP_LDR_P_IMM_OFF), +/* 0101 1001 0010 */ TABDECL( OP_LDR_P_IMM_OFF), +/* 0101 1001 0011 */ TABDECL( OP_LDR_P_IMM_OFF), +/* 0101 1001 0100 */ TABDECL( OP_LDR_P_IMM_OFF), +/* 0101 1001 0101 */ TABDECL( OP_LDR_P_IMM_OFF), +/* 0101 1001 0110 */ TABDECL( OP_LDR_P_IMM_OFF), +/* 0101 1001 0111 */ TABDECL( OP_LDR_P_IMM_OFF), +/* 0101 1001 1000 */ TABDECL( OP_LDR_P_IMM_OFF), +/* 0101 1001 1001 */ TABDECL( OP_LDR_P_IMM_OFF), +/* 0101 1001 1010 */ TABDECL( OP_LDR_P_IMM_OFF), +/* 0101 1001 1011 */ TABDECL( OP_LDR_P_IMM_OFF), +/* 0101 1001 1100 */ TABDECL( OP_LDR_P_IMM_OFF), +/* 0101 1001 1101 */ TABDECL( OP_LDR_P_IMM_OFF), +/* 0101 1001 1110 */ TABDECL( OP_LDR_P_IMM_OFF), +/* 0101 1001 1111 */ TABDECL( OP_LDR_P_IMM_OFF), +/* 0101 1010 0000 */ TABDECL( OP_STR_P_IMM_OFF_PREIND), +/* 0101 1010 0001 */ TABDECL( OP_STR_P_IMM_OFF_PREIND), +/* 0101 1010 0010 */ TABDECL( OP_STR_P_IMM_OFF_PREIND), +/* 0101 1010 0011 */ TABDECL( OP_STR_P_IMM_OFF_PREIND), +/* 0101 1010 0100 */ TABDECL( OP_STR_P_IMM_OFF_PREIND), +/* 0101 1010 0101 */ TABDECL( OP_STR_P_IMM_OFF_PREIND), +/* 0101 1010 0110 */ TABDECL( OP_STR_P_IMM_OFF_PREIND), +/* 0101 1010 0111 */ TABDECL( OP_STR_P_IMM_OFF_PREIND), +/* 0101 1010 1000 */ TABDECL( OP_STR_P_IMM_OFF_PREIND), +/* 0101 1010 1001 */ TABDECL( OP_STR_P_IMM_OFF_PREIND), +/* 0101 1010 1010 */ TABDECL( OP_STR_P_IMM_OFF_PREIND), +/* 0101 1010 1011 */ TABDECL( OP_STR_P_IMM_OFF_PREIND), +/* 0101 1010 1100 */ TABDECL( OP_STR_P_IMM_OFF_PREIND), +/* 0101 1010 1101 */ TABDECL( OP_STR_P_IMM_OFF_PREIND), +/* 0101 1010 1110 */ TABDECL( OP_STR_P_IMM_OFF_PREIND), +/* 0101 1010 1111 */ TABDECL( OP_STR_P_IMM_OFF_PREIND), +/* 0101 1011 0000 */ TABDECL( OP_LDR_P_IMM_OFF_PREIND), +/* 0101 1011 0001 */ TABDECL( OP_LDR_P_IMM_OFF_PREIND), +/* 0101 1011 0010 */ TABDECL( OP_LDR_P_IMM_OFF_PREIND), +/* 0101 1011 0011 */ TABDECL( OP_LDR_P_IMM_OFF_PREIND), +/* 0101 1011 0100 */ TABDECL( OP_LDR_P_IMM_OFF_PREIND), +/* 0101 1011 0101 */ TABDECL( OP_LDR_P_IMM_OFF_PREIND), +/* 0101 1011 0110 */ TABDECL( OP_LDR_P_IMM_OFF_PREIND), +/* 0101 1011 0111 */ TABDECL( OP_LDR_P_IMM_OFF_PREIND), +/* 0101 1011 1000 */ TABDECL( OP_LDR_P_IMM_OFF_PREIND), +/* 0101 1011 1001 */ TABDECL( OP_LDR_P_IMM_OFF_PREIND), +/* 0101 1011 1010 */ TABDECL( OP_LDR_P_IMM_OFF_PREIND), +/* 0101 1011 1011 */ TABDECL( OP_LDR_P_IMM_OFF_PREIND), +/* 0101 1011 1100 */ TABDECL( OP_LDR_P_IMM_OFF_PREIND), +/* 0101 1011 1101 */ TABDECL( OP_LDR_P_IMM_OFF_PREIND), +/* 0101 1011 1110 */ TABDECL( OP_LDR_P_IMM_OFF_PREIND), +/* 0101 1011 1111 */ TABDECL( OP_LDR_P_IMM_OFF_PREIND), +/* 0101 1100 0000 */ TABDECL( OP_STRB_P_IMM_OFF), +/* 0101 1100 0001 */ TABDECL( OP_STRB_P_IMM_OFF), +/* 0101 1100 0010 */ TABDECL( OP_STRB_P_IMM_OFF), +/* 0101 1100 0011 */ TABDECL( OP_STRB_P_IMM_OFF), +/* 0101 1100 0100 */ TABDECL( OP_STRB_P_IMM_OFF), +/* 0101 1100 0101 */ TABDECL( OP_STRB_P_IMM_OFF), +/* 0101 1100 0110 */ TABDECL( OP_STRB_P_IMM_OFF), +/* 0101 1100 0111 */ TABDECL( OP_STRB_P_IMM_OFF), +/* 0101 1100 1000 */ TABDECL( OP_STRB_P_IMM_OFF), +/* 0101 1100 1001 */ TABDECL( OP_STRB_P_IMM_OFF), +/* 0101 1100 1010 */ TABDECL( OP_STRB_P_IMM_OFF), +/* 0101 1100 1011 */ TABDECL( OP_STRB_P_IMM_OFF), +/* 0101 1100 1100 */ TABDECL( OP_STRB_P_IMM_OFF), +/* 0101 1100 1101 */ TABDECL( OP_STRB_P_IMM_OFF), +/* 0101 1100 1110 */ TABDECL( OP_STRB_P_IMM_OFF), +/* 0101 1100 1111 */ TABDECL( OP_STRB_P_IMM_OFF), +/* 0101 1101 0000 */ TABDECL( OP_LDRB_P_IMM_OFF), +/* 0101 1101 0001 */ TABDECL( OP_LDRB_P_IMM_OFF), +/* 0101 1101 0010 */ TABDECL( OP_LDRB_P_IMM_OFF), +/* 0101 1101 0011 */ TABDECL( OP_LDRB_P_IMM_OFF), +/* 0101 1101 0100 */ TABDECL( OP_LDRB_P_IMM_OFF), +/* 0101 1101 0101 */ TABDECL( OP_LDRB_P_IMM_OFF), +/* 0101 1101 0110 */ TABDECL( OP_LDRB_P_IMM_OFF), +/* 0101 1101 0111 */ TABDECL( OP_LDRB_P_IMM_OFF), +/* 0101 1101 1000 */ TABDECL( OP_LDRB_P_IMM_OFF), +/* 0101 1101 1001 */ TABDECL( OP_LDRB_P_IMM_OFF), +/* 0101 1101 1010 */ TABDECL( OP_LDRB_P_IMM_OFF), +/* 0101 1101 1011 */ TABDECL( OP_LDRB_P_IMM_OFF), +/* 0101 1101 1100 */ TABDECL( OP_LDRB_P_IMM_OFF), +/* 0101 1101 1101 */ TABDECL( OP_LDRB_P_IMM_OFF), +/* 0101 1101 1110 */ TABDECL( OP_LDRB_P_IMM_OFF), +/* 0101 1101 1111 */ TABDECL( OP_LDRB_P_IMM_OFF), +/* 0101 1110 0000 */ TABDECL( OP_STRB_P_IMM_OFF_PREIND), +/* 0101 1110 0001 */ TABDECL( OP_STRB_P_IMM_OFF_PREIND), +/* 0101 1110 0010 */ TABDECL( OP_STRB_P_IMM_OFF_PREIND), +/* 0101 1110 0011 */ TABDECL( OP_STRB_P_IMM_OFF_PREIND), +/* 0101 1110 0100 */ TABDECL( OP_STRB_P_IMM_OFF_PREIND), +/* 0101 1110 0101 */ TABDECL( OP_STRB_P_IMM_OFF_PREIND), +/* 0101 1110 0110 */ TABDECL( OP_STRB_P_IMM_OFF_PREIND), +/* 0101 1110 0111 */ TABDECL( OP_STRB_P_IMM_OFF_PREIND), +/* 0101 1110 1000 */ TABDECL( OP_STRB_P_IMM_OFF_PREIND), +/* 0101 1110 1001 */ TABDECL( OP_STRB_P_IMM_OFF_PREIND), +/* 0101 1110 1010 */ TABDECL( OP_STRB_P_IMM_OFF_PREIND), +/* 0101 1110 1011 */ TABDECL( OP_STRB_P_IMM_OFF_PREIND), +/* 0101 1110 1100 */ TABDECL( OP_STRB_P_IMM_OFF_PREIND), +/* 0101 1110 1101 */ TABDECL( OP_STRB_P_IMM_OFF_PREIND), +/* 0101 1110 1110 */ TABDECL( OP_STRB_P_IMM_OFF_PREIND), +/* 0101 1110 1111 */ TABDECL( OP_STRB_P_IMM_OFF_PREIND), +/* 0101 1111 0000 */ TABDECL( OP_LDRB_P_IMM_OFF_PREIND), +/* 0101 1111 0001 */ TABDECL( OP_LDRB_P_IMM_OFF_PREIND), +/* 0101 1111 0010 */ TABDECL( OP_LDRB_P_IMM_OFF_PREIND), +/* 0101 1111 0011 */ TABDECL( OP_LDRB_P_IMM_OFF_PREIND), +/* 0101 1111 0100 */ TABDECL( OP_LDRB_P_IMM_OFF_PREIND), +/* 0101 1111 0101 */ TABDECL( OP_LDRB_P_IMM_OFF_PREIND), +/* 0101 1111 0110 */ TABDECL( OP_LDRB_P_IMM_OFF_PREIND), +/* 0101 1111 0111 */ TABDECL( OP_LDRB_P_IMM_OFF_PREIND), +/* 0101 1111 1000 */ TABDECL( OP_LDRB_P_IMM_OFF_PREIND), +/* 0101 1111 1001 */ TABDECL( OP_LDRB_P_IMM_OFF_PREIND), +/* 0101 1111 1010 */ TABDECL( OP_LDRB_P_IMM_OFF_PREIND), +/* 0101 1111 1011 */ TABDECL( OP_LDRB_P_IMM_OFF_PREIND), +/* 0101 1111 1100 */ TABDECL( OP_LDRB_P_IMM_OFF_PREIND), +/* 0101 1111 1101 */ TABDECL( OP_LDRB_P_IMM_OFF_PREIND), +/* 0101 1111 1110 */ TABDECL( OP_LDRB_P_IMM_OFF_PREIND), +/* 0101 1111 1111 */ TABDECL( OP_LDRB_P_IMM_OFF_PREIND), +/* 0110 0000 0000 */ TABDECL( OP_STR_M_LSL_IMM_OFF_POSTIND), +/* 0110 0000 0001 */ TABDECL( OP_UND), +/* 0110 0000 0010 */ TABDECL( OP_STR_M_LSR_IMM_OFF_POSTIND), +/* 0110 0000 0011 */ TABDECL( OP_UND), +/* 0110 0000 0100 */ TABDECL( OP_STR_M_ASR_IMM_OFF_POSTIND), +/* 0110 0000 0101 */ TABDECL( OP_UND), +/* 0110 0000 0110 */ TABDECL( OP_STR_M_ROR_IMM_OFF_POSTIND), +/* 0110 0000 0111 */ TABDECL( OP_UND), +/* 0110 0000 1000 */ TABDECL( OP_STR_M_LSL_IMM_OFF_POSTIND), +/* 0110 0000 1001 */ TABDECL( OP_UND), +/* 0110 0000 1010 */ TABDECL( OP_STR_M_LSR_IMM_OFF_POSTIND), +/* 0110 0000 1011 */ TABDECL( OP_UND), +/* 0110 0000 1100 */ TABDECL( OP_STR_M_ASR_IMM_OFF_POSTIND), +/* 0110 0000 1101 */ TABDECL( OP_UND), +/* 0110 0000 1110 */ TABDECL( OP_STR_M_ROR_IMM_OFF_POSTIND), +/* 0110 0000 1111 */ TABDECL( OP_UND), +/* 0110 0001 0000 */ TABDECL( OP_LDR_M_LSL_IMM_OFF_POSTIND), +/* 0110 0001 0001 */ TABDECL( OP_UND), +/* 0110 0001 0010 */ TABDECL( OP_LDR_M_LSR_IMM_OFF_POSTIND), +/* 0110 0001 0011 */ TABDECL( OP_UND), +/* 0110 0001 0100 */ TABDECL( OP_LDR_M_ASR_IMM_OFF_POSTIND), +/* 0110 0001 0101 */ TABDECL( OP_UND), +/* 0110 0001 0110 */ TABDECL( OP_LDR_M_ROR_IMM_OFF_POSTIND), +/* 0110 0001 0111 */ TABDECL( OP_UND), +/* 0110 0001 1000 */ TABDECL( OP_LDR_M_LSL_IMM_OFF_POSTIND), +/* 0110 0001 1001 */ TABDECL( OP_UND), +/* 0110 0001 1010 */ TABDECL( OP_LDR_M_LSR_IMM_OFF_POSTIND), +/* 0110 0001 1011 */ TABDECL( OP_UND), +/* 0110 0001 1100 */ TABDECL( OP_LDR_M_ASR_IMM_OFF_POSTIND), +/* 0110 0001 1101 */ TABDECL( OP_UND), +/* 0110 0001 1110 */ TABDECL( OP_LDR_M_ROR_IMM_OFF_POSTIND), +/* 0110 0001 1111 */ TABDECL( OP_UND), +/* 0110 0010 0000 */ TABDECL( OP_STR_M_LSL_IMM_OFF_POSTIND), +/* 0110 0010 0001 */ TABDECL( OP_UND), +/* 0110 0010 0010 */ TABDECL( OP_STR_M_LSR_IMM_OFF_POSTIND), +/* 0110 0010 0011 */ TABDECL( OP_UND), +/* 0110 0010 0100 */ TABDECL( OP_STR_M_ASR_IMM_OFF_POSTIND), +/* 0110 0010 0101 */ TABDECL( OP_UND), +/* 0110 0010 0110 */ TABDECL( OP_STR_M_ROR_IMM_OFF_POSTIND), +/* 0110 0010 0111 */ TABDECL( OP_UND), +/* 0110 0010 1000 */ TABDECL( OP_STR_M_LSL_IMM_OFF_POSTIND), +/* 0110 0010 1001 */ TABDECL( OP_UND), +/* 0110 0010 1010 */ TABDECL( OP_STR_M_LSR_IMM_OFF_POSTIND), +/* 0110 0010 1011 */ TABDECL( OP_UND), +/* 0110 0010 1100 */ TABDECL( OP_STR_M_ASR_IMM_OFF_POSTIND), +/* 0110 0010 1101 */ TABDECL( OP_UND), +/* 0110 0010 1110 */ TABDECL( OP_STR_M_ROR_IMM_OFF_POSTIND), +/* 0110 0010 1111 */ TABDECL( OP_UND), +/* 0110 0011 0000 */ TABDECL( OP_LDR_M_LSL_IMM_OFF_POSTIND), +/* 0110 0011 0001 */ TABDECL( OP_UND), +/* 0110 0011 0010 */ TABDECL( OP_LDR_M_LSR_IMM_OFF_POSTIND), +/* 0110 0011 0011 */ TABDECL( OP_UND), +/* 0110 0011 0100 */ TABDECL( OP_LDR_M_ASR_IMM_OFF_POSTIND), +/* 0110 0011 0101 */ TABDECL( OP_UND), +/* 0110 0011 0110 */ TABDECL( OP_LDR_M_ROR_IMM_OFF_POSTIND), +/* 0110 0011 0111 */ TABDECL( OP_UND), +/* 0110 0011 1000 */ TABDECL( OP_LDR_M_LSL_IMM_OFF_POSTIND), +/* 0110 0011 1001 */ TABDECL( OP_UND), +/* 0110 0011 1010 */ TABDECL( OP_LDR_M_LSR_IMM_OFF_POSTIND), +/* 0110 0011 1011 */ TABDECL( OP_UND), +/* 0110 0011 1100 */ TABDECL( OP_LDR_M_ASR_IMM_OFF_POSTIND), +/* 0110 0011 1101 */ TABDECL( OP_UND), +/* 0110 0011 1110 */ TABDECL( OP_LDR_M_ROR_IMM_OFF_POSTIND), +/* 0110 0011 1111 */ TABDECL( OP_UND), +/* 0110 0100 0000 */ TABDECL( OP_STRB_M_LSL_IMM_OFF_POSTIND), +/* 0110 0100 0001 */ TABDECL( OP_UND), +/* 0110 0100 0010 */ TABDECL( OP_STRB_M_LSR_IMM_OFF_POSTIND), +/* 0110 0100 0011 */ TABDECL( OP_UND), +/* 0110 0100 0100 */ TABDECL( OP_STRB_M_ASR_IMM_OFF_POSTIND), +/* 0110 0100 0101 */ TABDECL( OP_UND), +/* 0110 0100 0110 */ TABDECL( OP_STRB_M_ROR_IMM_OFF_POSTIND), +/* 0110 0100 0111 */ TABDECL( OP_UND), +/* 0110 0100 1000 */ TABDECL( OP_STRB_M_LSL_IMM_OFF_POSTIND), +/* 0110 0100 1001 */ TABDECL( OP_UND), +/* 0110 0100 1010 */ TABDECL( OP_STRB_M_LSR_IMM_OFF_POSTIND), +/* 0110 0100 1011 */ TABDECL( OP_UND), +/* 0110 0100 1100 */ TABDECL( OP_STRB_M_ASR_IMM_OFF_POSTIND), +/* 0110 0100 1101 */ TABDECL( OP_UND), +/* 0110 0100 1110 */ TABDECL( OP_STRB_M_ROR_IMM_OFF_POSTIND), +/* 0110 0100 1111 */ TABDECL( OP_UND), +/* 0110 0101 0000 */ TABDECL( OP_LDRB_M_LSL_IMM_OFF_POSTIND), +/* 0110 0101 0001 */ TABDECL( OP_UND), +/* 0110 0101 0010 */ TABDECL( OP_LDRB_M_LSR_IMM_OFF_POSTIND), +/* 0110 0101 0011 */ TABDECL( OP_UND), +/* 0110 0101 0100 */ TABDECL( OP_LDRB_M_ASR_IMM_OFF_POSTIND), +/* 0110 0101 0101 */ TABDECL( OP_UND), +/* 0110 0101 0110 */ TABDECL( OP_LDRB_M_ROR_IMM_OFF_POSTIND), +/* 0110 0101 0111 */ TABDECL( OP_UND), +/* 0110 0101 1000 */ TABDECL( OP_LDRB_M_LSL_IMM_OFF_POSTIND), +/* 0110 0101 1001 */ TABDECL( OP_UND), +/* 0110 0101 1010 */ TABDECL( OP_LDRB_M_LSR_IMM_OFF_POSTIND), +/* 0110 0101 1011 */ TABDECL( OP_UND), +/* 0110 0101 1100 */ TABDECL( OP_LDRB_M_ASR_IMM_OFF_POSTIND), +/* 0110 0101 1101 */ TABDECL( OP_UND), +/* 0110 0101 1110 */ TABDECL( OP_LDRB_M_ROR_IMM_OFF_POSTIND), +/* 0110 0101 1111 */ TABDECL( OP_UND), +/* 0110 0110 0000 */ TABDECL( OP_STRB_M_LSL_IMM_OFF_POSTIND), +/* 0110 0110 0001 */ TABDECL( OP_UND), +/* 0110 0110 0010 */ TABDECL( OP_STRB_M_LSR_IMM_OFF_POSTIND), +/* 0110 0110 0011 */ TABDECL( OP_UND), +/* 0110 0110 0100 */ TABDECL( OP_STRB_M_ASR_IMM_OFF_POSTIND), +/* 0110 0110 0101 */ TABDECL( OP_UND), +/* 0110 0110 0110 */ TABDECL( OP_STRB_M_ROR_IMM_OFF_POSTIND), +/* 0110 0110 0111 */ TABDECL( OP_UND), +/* 0110 0110 1000 */ TABDECL( OP_STRB_M_LSL_IMM_OFF_POSTIND), +/* 0110 0110 1001 */ TABDECL( OP_UND), +/* 0110 0110 1010 */ TABDECL( OP_STRB_M_LSR_IMM_OFF_POSTIND), +/* 0110 0110 1011 */ TABDECL( OP_UND), +/* 0110 0110 1100 */ TABDECL( OP_STRB_M_ASR_IMM_OFF_POSTIND), +/* 0110 0110 1101 */ TABDECL( OP_UND), +/* 0110 0110 1110 */ TABDECL( OP_STRB_M_ROR_IMM_OFF_POSTIND), +/* 0110 0110 1111 */ TABDECL( OP_UND), +/* 0110 0111 0000 */ TABDECL( OP_LDRB_M_LSL_IMM_OFF_POSTIND), +/* 0110 0111 0001 */ TABDECL( OP_UND), +/* 0110 0111 0010 */ TABDECL( OP_LDRB_M_LSR_IMM_OFF_POSTIND), +/* 0110 0111 0011 */ TABDECL( OP_UND), +/* 0110 0111 0100 */ TABDECL( OP_LDRB_M_ASR_IMM_OFF_POSTIND), +/* 0110 0111 0101 */ TABDECL( OP_UND), +/* 0110 0111 0110 */ TABDECL( OP_LDRB_M_ROR_IMM_OFF_POSTIND), +/* 0110 0111 0111 */ TABDECL( OP_UND), +/* 0110 0111 1000 */ TABDECL( OP_LDRB_M_LSL_IMM_OFF_POSTIND), +/* 0110 0111 1001 */ TABDECL( OP_UND), +/* 0110 0111 1010 */ TABDECL( OP_LDRB_M_LSR_IMM_OFF_POSTIND), +/* 0110 0111 1011 */ TABDECL( OP_UND), +/* 0110 0111 1100 */ TABDECL( OP_LDRB_M_ASR_IMM_OFF_POSTIND), +/* 0110 0111 1101 */ TABDECL( OP_UND), +/* 0110 0111 1110 */ TABDECL( OP_LDRB_M_ROR_IMM_OFF_POSTIND), +/* 0110 0111 1111 */ TABDECL( OP_UND), +/* 0110 1000 0000 */ TABDECL( OP_STR_P_LSL_IMM_OFF_POSTIND), +/* 0110 1000 0001 */ TABDECL( OP_UND), +/* 0110 1000 0010 */ TABDECL( OP_STR_P_LSR_IMM_OFF_POSTIND), +/* 0110 1000 0011 */ TABDECL( OP_UND), +/* 0110 1000 0100 */ TABDECL( OP_STR_P_ASR_IMM_OFF_POSTIND), +/* 0110 1000 0101 */ TABDECL( OP_UND), +/* 0110 1000 0110 */ TABDECL( OP_STR_P_ROR_IMM_OFF_POSTIND), +/* 0110 1000 0111 */ TABDECL( OP_UND), +/* 0110 1000 1000 */ TABDECL( OP_STR_P_LSL_IMM_OFF_POSTIND), +/* 0110 1000 1001 */ TABDECL( OP_UND), +/* 0110 1000 1010 */ TABDECL( OP_STR_P_LSR_IMM_OFF_POSTIND), +/* 0110 1000 1011 */ TABDECL( OP_UND), +/* 0110 1000 1100 */ TABDECL( OP_STR_P_ASR_IMM_OFF_POSTIND), +/* 0110 1000 1101 */ TABDECL( OP_UND), +/* 0110 1000 1110 */ TABDECL( OP_STR_P_ROR_IMM_OFF_POSTIND), +/* 0110 1000 1111 */ TABDECL( OP_UND), +/* 0110 1001 0000 */ TABDECL( OP_LDR_P_LSL_IMM_OFF_POSTIND), +/* 0110 1001 0001 */ TABDECL( OP_UND), +/* 0110 1001 0010 */ TABDECL( OP_LDR_P_LSR_IMM_OFF_POSTIND), +/* 0110 1001 0011 */ TABDECL( OP_UND), +/* 0110 1001 0100 */ TABDECL( OP_LDR_P_ASR_IMM_OFF_POSTIND), +/* 0110 1001 0101 */ TABDECL( OP_UND), +/* 0110 1001 0110 */ TABDECL( OP_LDR_P_ROR_IMM_OFF_POSTIND), +/* 0110 1001 0111 */ TABDECL( OP_UND), +/* 0110 1001 1000 */ TABDECL( OP_LDR_P_LSL_IMM_OFF_POSTIND), +/* 0110 1001 1001 */ TABDECL( OP_UND), +/* 0110 1001 1010 */ TABDECL( OP_LDR_P_LSR_IMM_OFF_POSTIND), +/* 0110 1001 1011 */ TABDECL( OP_UND), +/* 0110 1001 1100 */ TABDECL( OP_LDR_P_ASR_IMM_OFF_POSTIND), +/* 0110 1001 1101 */ TABDECL( OP_UND), +/* 0110 1001 1110 */ TABDECL( OP_LDR_P_ROR_IMM_OFF_POSTIND), +/* 0110 1001 1111 */ TABDECL( OP_UND), +/* 0110 1010 0000 */ TABDECL( OP_STR_P_LSL_IMM_OFF_POSTIND), +/* 0110 1010 0001 */ TABDECL( OP_UND), +/* 0110 1010 0010 */ TABDECL( OP_STR_P_LSR_IMM_OFF_POSTIND), +/* 0110 1010 0011 */ TABDECL( OP_UND), +/* 0110 1010 0100 */ TABDECL( OP_STR_P_ASR_IMM_OFF_POSTIND), +/* 0110 1010 0101 */ TABDECL( OP_UND), +/* 0110 1010 0110 */ TABDECL( OP_STR_P_ROR_IMM_OFF_POSTIND), +/* 0110 1010 0111 */ TABDECL( OP_UND), +/* 0110 1010 1000 */ TABDECL( OP_STR_P_LSL_IMM_OFF_POSTIND), +/* 0110 1010 1001 */ TABDECL( OP_UND), +/* 0110 1010 1010 */ TABDECL( OP_STR_P_LSR_IMM_OFF_POSTIND), +/* 0110 1010 1011 */ TABDECL( OP_UND), +/* 0110 1010 1100 */ TABDECL( OP_STR_P_ASR_IMM_OFF_POSTIND), +/* 0110 1010 1101 */ TABDECL( OP_UND), +/* 0110 1010 1110 */ TABDECL( OP_STR_P_ROR_IMM_OFF_POSTIND), +/* 0110 1010 1111 */ TABDECL( OP_UND), +/* 0110 1011 0000 */ TABDECL( OP_LDR_P_LSL_IMM_OFF_POSTIND), +/* 0110 1011 0001 */ TABDECL( OP_UND), +/* 0110 1011 0010 */ TABDECL( OP_LDR_P_LSL_IMM_OFF_POSTIND), +/* 0110 1011 0011 */ TABDECL( OP_UND), +/* 0110 1011 0100 */ TABDECL( OP_LDR_P_LSL_IMM_OFF_POSTIND), +/* 0110 1011 0101 */ TABDECL( OP_UND), +/* 0110 1011 0110 */ TABDECL( OP_LDR_P_LSL_IMM_OFF_POSTIND), +/* 0110 1011 0111 */ TABDECL( OP_UND), +/* 0110 1011 1000 */ TABDECL( OP_LDR_P_LSL_IMM_OFF_POSTIND), +/* 0110 1011 1001 */ TABDECL( OP_UND), +/* 0110 1011 1010 */ TABDECL( OP_LDR_P_LSL_IMM_OFF_POSTIND), +/* 0110 1011 1011 */ TABDECL( OP_UND), +/* 0110 1011 1100 */ TABDECL( OP_LDR_P_LSL_IMM_OFF_POSTIND), +/* 0110 1011 1101 */ TABDECL( OP_UND), +/* 0110 1011 1110 */ TABDECL( OP_LDR_P_LSL_IMM_OFF_POSTIND), +/* 0110 1011 1111 */ TABDECL( OP_UND), +/* 0110 1100 0000 */ TABDECL( OP_STRB_P_LSL_IMM_OFF_POSTIND), +/* 0110 1100 0001 */ TABDECL( OP_UND), +/* 0110 1100 0010 */ TABDECL( OP_STRB_P_LSR_IMM_OFF_POSTIND), +/* 0110 1100 0011 */ TABDECL( OP_UND), +/* 0110 1100 0100 */ TABDECL( OP_STRB_P_ASR_IMM_OFF_POSTIND), +/* 0110 1100 0101 */ TABDECL( OP_UND), +/* 0110 1100 0110 */ TABDECL( OP_STRB_P_ROR_IMM_OFF_POSTIND), +/* 0110 1100 0111 */ TABDECL( OP_UND), +/* 0110 1100 1000 */ TABDECL( OP_STRB_P_LSL_IMM_OFF_POSTIND), +/* 0110 1100 1001 */ TABDECL( OP_UND), +/* 0110 1100 1010 */ TABDECL( OP_STRB_P_LSR_IMM_OFF_POSTIND), +/* 0110 1100 1011 */ TABDECL( OP_UND), +/* 0110 1100 1100 */ TABDECL( OP_STRB_P_ASR_IMM_OFF_POSTIND), +/* 0110 1100 1101 */ TABDECL( OP_UND), +/* 0110 1100 1110 */ TABDECL( OP_STRB_P_ROR_IMM_OFF_POSTIND), +/* 0110 1100 1111 */ TABDECL( OP_UND), +/* 0110 1101 0000 */ TABDECL( OP_LDRB_P_LSL_IMM_OFF_POSTIND), +/* 0110 1101 0001 */ TABDECL( OP_UND), +/* 0110 1101 0010 */ TABDECL( OP_LDRB_P_LSR_IMM_OFF_POSTIND), +/* 0110 1101 0011 */ TABDECL( OP_UND), +/* 0110 1101 0100 */ TABDECL( OP_LDRB_P_ASR_IMM_OFF_POSTIND), +/* 0110 1101 0101 */ TABDECL( OP_UND), +/* 0110 1101 0110 */ TABDECL( OP_LDRB_P_ROR_IMM_OFF_POSTIND), +/* 0110 1101 0111 */ TABDECL( OP_UND), +/* 0110 1101 1000 */ TABDECL( OP_LDRB_P_LSL_IMM_OFF_POSTIND), +/* 0110 1101 1001 */ TABDECL( OP_UND), +/* 0110 1101 1010 */ TABDECL( OP_LDRB_P_LSR_IMM_OFF_POSTIND), +/* 0110 1101 1011 */ TABDECL( OP_UND), +/* 0110 1101 1100 */ TABDECL( OP_LDRB_P_ASR_IMM_OFF_POSTIND), +/* 0110 1101 1101 */ TABDECL( OP_UND), +/* 0110 1101 1110 */ TABDECL( OP_LDRB_P_ROR_IMM_OFF_POSTIND), +/* 0110 1101 1111 */ TABDECL( OP_UND), +/* 0110 1110 0000 */ TABDECL( OP_STRB_P_LSL_IMM_OFF_POSTIND), +/* 0110 1110 0001 */ TABDECL( OP_UND), +/* 0110 1110 0010 */ TABDECL( OP_STRB_P_LSR_IMM_OFF_POSTIND), +/* 0110 1110 0011 */ TABDECL( OP_UND), +/* 0110 1110 0100 */ TABDECL( OP_STRB_P_ASR_IMM_OFF_POSTIND), +/* 0110 1110 0101 */ TABDECL( OP_UND), +/* 0110 1110 0110 */ TABDECL( OP_STRB_P_ROR_IMM_OFF_POSTIND), +/* 0110 1110 0111 */ TABDECL( OP_UND), +/* 0110 1110 1000 */ TABDECL( OP_STRB_P_LSL_IMM_OFF_POSTIND), +/* 0110 1110 1001 */ TABDECL( OP_UND), +/* 0110 1110 1010 */ TABDECL( OP_STRB_P_LSR_IMM_OFF_POSTIND), +/* 0110 1110 1011 */ TABDECL( OP_UND), +/* 0110 1110 1100 */ TABDECL( OP_STRB_P_ASR_IMM_OFF_POSTIND), +/* 0110 1110 1101 */ TABDECL( OP_UND), +/* 0110 1110 1110 */ TABDECL( OP_STRB_P_ROR_IMM_OFF_POSTIND), +/* 0110 1110 1111 */ TABDECL( OP_UND), +/* 0110 1111 0000 */ TABDECL( OP_LDRB_P_LSL_IMM_OFF_POSTIND), +/* 0110 1111 0001 */ TABDECL( OP_UND), +/* 0110 1111 0010 */ TABDECL( OP_LDRB_P_LSR_IMM_OFF_POSTIND), +/* 0110 1111 0011 */ TABDECL( OP_UND), +/* 0110 1111 0100 */ TABDECL( OP_LDRB_P_ASR_IMM_OFF_POSTIND), +/* 0110 1111 0101 */ TABDECL( OP_UND), +/* 0110 1111 0110 */ TABDECL( OP_LDRB_P_ROR_IMM_OFF_POSTIND), +/* 0110 1111 0111 */ TABDECL( OP_UND), +/* 0110 1111 1000 */ TABDECL( OP_LDRB_P_LSL_IMM_OFF_POSTIND), +/* 0110 1111 1001 */ TABDECL( OP_UND), +/* 0110 1111 1010 */ TABDECL( OP_LDRB_P_LSR_IMM_OFF_POSTIND), +/* 0110 1111 1011 */ TABDECL( OP_UND), +/* 0110 1111 1100 */ TABDECL( OP_LDRB_P_ASR_IMM_OFF_POSTIND), +/* 0110 1111 1101 */ TABDECL( OP_UND), +/* 0110 1111 1110 */ TABDECL( OP_LDRB_P_ROR_IMM_OFF_POSTIND), +/* 0110 1111 1111 */ TABDECL( OP_UND), +/* 0111 0000 0000 */ TABDECL( OP_STR_M_LSL_IMM_OFF), +/* 0111 0000 0001 */ TABDECL( OP_UND), +/* 0111 0000 0010 */ TABDECL( OP_STR_M_LSR_IMM_OFF), +/* 0111 0000 0011 */ TABDECL( OP_UND), +/* 0111 0000 0100 */ TABDECL( OP_STR_M_ASR_IMM_OFF), +/* 0111 0000 0101 */ TABDECL( OP_UND), +/* 0111 0000 0110 */ TABDECL( OP_STR_M_ROR_IMM_OFF), +/* 0111 0000 0111 */ TABDECL( OP_UND), +/* 0111 0000 1000 */ TABDECL( OP_STR_M_LSL_IMM_OFF), +/* 0111 0000 1001 */ TABDECL( OP_UND), +/* 0111 0000 1010 */ TABDECL( OP_STR_M_LSR_IMM_OFF), +/* 0111 0000 1011 */ TABDECL( OP_UND), +/* 0111 0000 1100 */ TABDECL( OP_STR_M_ASR_IMM_OFF), +/* 0111 0000 1101 */ TABDECL( OP_UND), +/* 0111 0000 1110 */ TABDECL( OP_STR_M_ROR_IMM_OFF), +/* 0111 0000 1111 */ TABDECL( OP_UND), +/* 0111 0001 0000 */ TABDECL( OP_LDR_M_LSL_IMM_OFF), +/* 0111 0001 0001 */ TABDECL( OP_UND), +/* 0111 0001 0010 */ TABDECL( OP_LDR_M_LSR_IMM_OFF), +/* 0111 0001 0011 */ TABDECL( OP_UND), +/* 0111 0001 0100 */ TABDECL( OP_LDR_M_ASR_IMM_OFF), +/* 0111 0001 0101 */ TABDECL( OP_UND), +/* 0111 0001 0110 */ TABDECL( OP_LDR_M_ROR_IMM_OFF), +/* 0111 0001 0111 */ TABDECL( OP_UND), +/* 0111 0001 1000 */ TABDECL( OP_LDR_M_LSL_IMM_OFF), +/* 0111 0001 1001 */ TABDECL( OP_UND), +/* 0111 0001 1010 */ TABDECL( OP_LDR_M_LSR_IMM_OFF), +/* 0111 0001 1011 */ TABDECL( OP_UND), +/* 0111 0001 1100 */ TABDECL( OP_LDR_M_ASR_IMM_OFF), +/* 0111 0001 1101 */ TABDECL( OP_UND), +/* 0111 0001 1110 */ TABDECL( OP_LDR_M_ROR_IMM_OFF), +/* 0111 0001 1111 */ TABDECL( OP_UND), +/* 0111 0010 0000 */ TABDECL( OP_STR_M_LSL_IMM_OFF_PREIND), +/* 0111 0010 0001 */ TABDECL( OP_UND), +/* 0111 0010 0010 */ TABDECL( OP_STR_M_LSR_IMM_OFF_PREIND), +/* 0111 0010 0011 */ TABDECL( OP_UND), +/* 0111 0010 0100 */ TABDECL( OP_STR_M_ASR_IMM_OFF_PREIND), +/* 0111 0010 0101 */ TABDECL( OP_UND), +/* 0111 0010 0110 */ TABDECL( OP_STR_M_ROR_IMM_OFF_PREIND), +/* 0111 0010 0111 */ TABDECL( OP_UND), +/* 0111 0010 1000 */ TABDECL( OP_STR_M_LSL_IMM_OFF_PREIND), +/* 0111 0010 1001 */ TABDECL( OP_UND), +/* 0111 0010 1010 */ TABDECL( OP_STR_M_LSR_IMM_OFF_PREIND), +/* 0111 0010 1011 */ TABDECL( OP_UND), +/* 0111 0010 1100 */ TABDECL( OP_STR_M_ASR_IMM_OFF_PREIND), +/* 0111 0010 1101 */ TABDECL( OP_UND), +/* 0111 0010 1110 */ TABDECL( OP_STR_M_ROR_IMM_OFF_PREIND), +/* 0111 0010 1111 */ TABDECL( OP_UND), +/* 0111 0011 0000 */ TABDECL( OP_LDR_M_LSL_IMM_OFF_PREIND), +/* 0111 0011 0001 */ TABDECL( OP_UND), +/* 0111 0011 0010 */ TABDECL( OP_LDR_M_LSR_IMM_OFF_PREIND), +/* 0111 0011 0011 */ TABDECL( OP_UND), +/* 0111 0011 0100 */ TABDECL( OP_LDR_M_ASR_IMM_OFF_PREIND), +/* 0111 0011 0101 */ TABDECL( OP_UND), +/* 0111 0011 0110 */ TABDECL( OP_LDR_M_ROR_IMM_OFF_PREIND), +/* 0111 0011 0111 */ TABDECL( OP_UND), +/* 0111 0011 1000 */ TABDECL( OP_LDR_M_LSL_IMM_OFF_PREIND), +/* 0111 0011 1001 */ TABDECL( OP_UND), +/* 0111 0011 1010 */ TABDECL( OP_LDR_M_LSR_IMM_OFF_PREIND), +/* 0111 0011 1011 */ TABDECL( OP_UND), +/* 0111 0011 1100 */ TABDECL( OP_LDR_M_ASR_IMM_OFF_PREIND), +/* 0111 0011 1101 */ TABDECL( OP_UND), +/* 0111 0011 1110 */ TABDECL( OP_LDR_M_ROR_IMM_OFF_PREIND), +/* 0111 0011 1111 */ TABDECL( OP_UND), +/* 0111 0100 0000 */ TABDECL( OP_STRB_M_LSL_IMM_OFF), +/* 0111 0100 0001 */ TABDECL( OP_UND), +/* 0111 0100 0010 */ TABDECL( OP_STRB_M_LSR_IMM_OFF), +/* 0111 0100 0011 */ TABDECL( OP_UND), +/* 0111 0100 0100 */ TABDECL( OP_STRB_M_ASR_IMM_OFF), +/* 0111 0100 0101 */ TABDECL( OP_UND), +/* 0111 0100 0110 */ TABDECL( OP_STRB_M_ROR_IMM_OFF), +/* 0111 0100 0111 */ TABDECL( OP_UND), +/* 0111 0100 1000 */ TABDECL( OP_STRB_M_LSL_IMM_OFF), +/* 0111 0100 1001 */ TABDECL( OP_UND), +/* 0111 0100 1010 */ TABDECL( OP_STRB_M_LSR_IMM_OFF), +/* 0111 0100 1011 */ TABDECL( OP_UND), +/* 0111 0100 1100 */ TABDECL( OP_STRB_M_ASR_IMM_OFF), +/* 0111 0100 1101 */ TABDECL( OP_UND), +/* 0111 0100 1110 */ TABDECL( OP_STRB_M_ROR_IMM_OFF), +/* 0111 0100 1111 */ TABDECL( OP_UND), +/* 0111 0101 0000 */ TABDECL( OP_LDRB_M_LSL_IMM_OFF), +/* 0111 0101 0001 */ TABDECL( OP_UND), +/* 0111 0101 0010 */ TABDECL( OP_LDRB_M_LSR_IMM_OFF), +/* 0111 0101 0011 */ TABDECL( OP_UND), +/* 0111 0101 0100 */ TABDECL( OP_LDRB_M_ASR_IMM_OFF), +/* 0111 0101 0101 */ TABDECL( OP_UND), +/* 0111 0101 0110 */ TABDECL( OP_LDRB_M_ROR_IMM_OFF), +/* 0111 0101 0111 */ TABDECL( OP_UND), +/* 0111 0101 1000 */ TABDECL( OP_LDRB_M_LSL_IMM_OFF), +/* 0111 0101 1001 */ TABDECL( OP_UND), +/* 0111 0101 1010 */ TABDECL( OP_LDRB_M_LSR_IMM_OFF), +/* 0111 0101 1011 */ TABDECL( OP_UND), +/* 0111 0101 1100 */ TABDECL( OP_LDRB_M_ASR_IMM_OFF), +/* 0111 0101 1101 */ TABDECL( OP_UND), +/* 0111 0101 1110 */ TABDECL( OP_LDRB_M_ROR_IMM_OFF), +/* 0111 0101 1111 */ TABDECL( OP_UND), +/* 0111 0110 0000 */ TABDECL( OP_STRB_M_LSL_IMM_OFF_PREIND), +/* 0111 0110 0001 */ TABDECL( OP_UND), +/* 0111 0110 0010 */ TABDECL( OP_STRB_M_LSR_IMM_OFF_PREIND), +/* 0111 0110 0011 */ TABDECL( OP_UND), +/* 0111 0110 0100 */ TABDECL( OP_STRB_M_ASR_IMM_OFF_PREIND), +/* 0111 0110 0101 */ TABDECL( OP_UND), +/* 0111 0110 0110 */ TABDECL( OP_STRB_M_ROR_IMM_OFF_PREIND), +/* 0111 0110 0111 */ TABDECL( OP_UND), +/* 0111 0110 1000 */ TABDECL( OP_STRB_M_LSL_IMM_OFF_PREIND), +/* 0111 0110 1001 */ TABDECL( OP_UND), +/* 0111 0110 1010 */ TABDECL( OP_STRB_M_LSR_IMM_OFF_PREIND), +/* 0111 0110 1011 */ TABDECL( OP_UND), +/* 0111 0110 1100 */ TABDECL( OP_STRB_M_ASR_IMM_OFF_PREIND), +/* 0111 0110 1101 */ TABDECL( OP_UND), +/* 0111 0110 1110 */ TABDECL( OP_STRB_M_ROR_IMM_OFF_PREIND), +/* 0111 0110 1111 */ TABDECL( OP_UND), +/* 0111 0111 0000 */ TABDECL( OP_LDRB_M_LSL_IMM_OFF_PREIND), +/* 0111 0111 0001 */ TABDECL( OP_UND), +/* 0111 0111 0010 */ TABDECL( OP_LDRB_M_LSR_IMM_OFF_PREIND), +/* 0111 0111 0011 */ TABDECL( OP_UND), +/* 0111 0111 0100 */ TABDECL( OP_LDRB_M_ASR_IMM_OFF_PREIND), +/* 0111 0111 0101 */ TABDECL( OP_UND), +/* 0111 0111 0110 */ TABDECL( OP_LDRB_M_ROR_IMM_OFF_PREIND), +/* 0111 0111 0111 */ TABDECL( OP_UND), +/* 0111 0111 1000 */ TABDECL( OP_LDRB_M_LSL_IMM_OFF_PREIND), +/* 0111 0111 1001 */ TABDECL( OP_UND), +/* 0111 0111 1010 */ TABDECL( OP_LDRB_M_LSR_IMM_OFF_PREIND), +/* 0111 0111 1011 */ TABDECL( OP_UND), +/* 0111 0111 1100 */ TABDECL( OP_LDRB_M_ASR_IMM_OFF_PREIND), +/* 0111 0111 1101 */ TABDECL( OP_UND), +/* 0111 0111 1110 */ TABDECL( OP_LDRB_M_ROR_IMM_OFF_PREIND), +/* 0111 0111 1111 */ TABDECL( OP_UND), +/* 0111 1000 0000 */ TABDECL( OP_STR_P_LSL_IMM_OFF), +/* 0111 1000 0001 */ TABDECL( OP_UND), +/* 0111 1000 0010 */ TABDECL( OP_STR_P_LSR_IMM_OFF), +/* 0111 1000 0011 */ TABDECL( OP_UND), +/* 0111 1000 0100 */ TABDECL( OP_STR_P_ASR_IMM_OFF), +/* 0111 1000 0101 */ TABDECL( OP_UND), +/* 0111 1000 0110 */ TABDECL( OP_STR_P_ROR_IMM_OFF), +/* 0111 1000 0111 */ TABDECL( OP_UND), +/* 0111 1000 1000 */ TABDECL( OP_STR_P_LSL_IMM_OFF), +/* 0111 1000 1001 */ TABDECL( OP_UND), +/* 0111 1000 1010 */ TABDECL( OP_STR_P_LSR_IMM_OFF), +/* 0111 1000 1011 */ TABDECL( OP_UND), +/* 0111 1000 1100 */ TABDECL( OP_STR_P_ASR_IMM_OFF), +/* 0111 1000 1101 */ TABDECL( OP_UND), +/* 0111 1000 1110 */ TABDECL( OP_STR_P_ROR_IMM_OFF), +/* 0111 1000 1111 */ TABDECL( OP_UND), +/* 0111 1001 0000 */ TABDECL( OP_LDR_P_LSL_IMM_OFF), +/* 0111 1001 0001 */ TABDECL( OP_UND), +/* 0111 1001 0010 */ TABDECL( OP_LDR_P_LSR_IMM_OFF), +/* 0111 1001 0011 */ TABDECL( OP_UND), +/* 0111 1001 0100 */ TABDECL( OP_LDR_P_ASR_IMM_OFF), +/* 0111 1001 0101 */ TABDECL( OP_UND), +/* 0111 1001 0110 */ TABDECL( OP_LDR_P_ROR_IMM_OFF), +/* 0111 1001 0111 */ TABDECL( OP_UND), +/* 0111 1001 1000 */ TABDECL( OP_LDR_P_LSL_IMM_OFF), +/* 0111 1001 1001 */ TABDECL( OP_UND), +/* 0111 1001 1010 */ TABDECL( OP_LDR_P_LSR_IMM_OFF), +/* 0111 1001 1011 */ TABDECL( OP_UND), +/* 0111 1001 1100 */ TABDECL( OP_LDR_P_ASR_IMM_OFF), +/* 0111 1001 1101 */ TABDECL( OP_UND), +/* 0111 1001 1110 */ TABDECL( OP_LDR_P_ROR_IMM_OFF), +/* 0111 1001 1111 */ TABDECL( OP_UND), +/* 0111 1010 0000 */ TABDECL( OP_STR_P_LSL_IMM_OFF_PREIND), +/* 0111 1010 0001 */ TABDECL( OP_UND), +/* 0111 1010 0010 */ TABDECL( OP_STR_P_LSR_IMM_OFF_PREIND), +/* 0111 1010 0011 */ TABDECL( OP_UND), +/* 0111 1010 0100 */ TABDECL( OP_STR_P_ASR_IMM_OFF_PREIND), +/* 0111 1010 0101 */ TABDECL( OP_UND), +/* 0111 1010 0110 */ TABDECL( OP_STR_P_ROR_IMM_OFF_PREIND), +/* 0111 1010 0111 */ TABDECL( OP_UND), +/* 0111 1010 1000 */ TABDECL( OP_STR_P_LSL_IMM_OFF_PREIND), +/* 0111 1010 1001 */ TABDECL( OP_UND), +/* 0111 1010 1010 */ TABDECL( OP_STR_P_LSR_IMM_OFF_PREIND), +/* 0111 1010 1011 */ TABDECL( OP_UND), +/* 0111 1010 1100 */ TABDECL( OP_STR_P_ASR_IMM_OFF_PREIND), +/* 0111 1010 1101 */ TABDECL( OP_UND), +/* 0111 1010 1110 */ TABDECL( OP_STR_P_ROR_IMM_OFF_PREIND), +/* 0111 1010 1111 */ TABDECL( OP_UND), +/* 0111 1011 0000 */ TABDECL( OP_LDR_P_LSL_IMM_OFF_PREIND), +/* 0111 1011 0001 */ TABDECL( OP_UND), +/* 0111 1011 0010 */ TABDECL( OP_LDR_P_LSR_IMM_OFF_PREIND), +/* 0111 1011 0011 */ TABDECL( OP_UND), +/* 0111 1011 0100 */ TABDECL( OP_LDR_P_ASR_IMM_OFF_PREIND), +/* 0111 1011 0101 */ TABDECL( OP_UND), +/* 0111 1011 0110 */ TABDECL( OP_LDR_P_ROR_IMM_OFF_PREIND), +/* 0111 1011 0111 */ TABDECL( OP_UND), +/* 0111 1011 1000 */ TABDECL( OP_LDR_P_LSL_IMM_OFF_PREIND), +/* 0111 1011 1001 */ TABDECL( OP_UND), +/* 0111 1011 1010 */ TABDECL( OP_LDR_P_LSR_IMM_OFF_PREIND), +/* 0111 1011 1011 */ TABDECL( OP_UND), +/* 0111 1011 1100 */ TABDECL( OP_LDR_P_ASR_IMM_OFF_PREIND), +/* 0111 1011 1101 */ TABDECL( OP_UND), +/* 0111 1011 1110 */ TABDECL( OP_LDR_P_ROR_IMM_OFF_PREIND), +/* 0111 1011 1111 */ TABDECL( OP_UND), +/* 0111 1100 0000 */ TABDECL( OP_STRB_P_LSL_IMM_OFF), +/* 0111 1100 0001 */ TABDECL( OP_UND), +/* 0111 1100 0010 */ TABDECL( OP_STRB_P_LSR_IMM_OFF), +/* 0111 1100 0011 */ TABDECL( OP_UND), +/* 0111 1100 0100 */ TABDECL( OP_STRB_P_ASR_IMM_OFF), +/* 0111 1100 0101 */ TABDECL( OP_UND), +/* 0111 1100 0110 */ TABDECL( OP_STRB_P_ROR_IMM_OFF), +/* 0111 1100 0111 */ TABDECL( OP_UND), +/* 0111 1100 1000 */ TABDECL( OP_STRB_P_LSL_IMM_OFF), +/* 0111 1100 1001 */ TABDECL( OP_UND), +/* 0111 1100 1010 */ TABDECL( OP_STRB_P_LSR_IMM_OFF), +/* 0111 1100 1011 */ TABDECL( OP_UND), +/* 0111 1100 1100 */ TABDECL( OP_STRB_P_ASR_IMM_OFF), +/* 0111 1100 1101 */ TABDECL( OP_UND), +/* 0111 1100 1110 */ TABDECL( OP_STRB_P_ROR_IMM_OFF), +/* 0111 1100 1111 */ TABDECL( OP_UND), +/* 0111 1101 0000 */ TABDECL( OP_LDRB_P_LSL_IMM_OFF), +/* 0111 1101 0001 */ TABDECL( OP_UND), +/* 0111 1101 0010 */ TABDECL( OP_LDRB_P_LSR_IMM_OFF), +/* 0111 1101 0011 */ TABDECL( OP_UND), +/* 0111 1101 0100 */ TABDECL( OP_LDRB_P_ASR_IMM_OFF), +/* 0111 1101 0101 */ TABDECL( OP_UND), +/* 0111 1101 0110 */ TABDECL( OP_LDRB_P_ROR_IMM_OFF), +/* 0111 1101 0111 */ TABDECL( OP_UND), +/* 0111 1101 1000 */ TABDECL( OP_LDRB_P_LSL_IMM_OFF), +/* 0111 1101 1001 */ TABDECL( OP_UND), +/* 0111 1101 1010 */ TABDECL( OP_LDRB_P_LSR_IMM_OFF), +/* 0111 1101 1011 */ TABDECL( OP_UND), +/* 0111 1101 1100 */ TABDECL( OP_LDRB_P_ASR_IMM_OFF), +/* 0111 1101 1101 */ TABDECL( OP_UND), +/* 0111 1101 1110 */ TABDECL( OP_LDRB_P_ROR_IMM_OFF), +/* 0111 1101 1111 */ TABDECL( OP_UND), +/* 0111 1110 0000 */ TABDECL( OP_STRB_P_LSL_IMM_OFF_PREIND), +/* 0111 1110 0001 */ TABDECL( OP_UND), +/* 0111 1110 0010 */ TABDECL( OP_STRB_P_LSR_IMM_OFF_PREIND), +/* 0111 1110 0011 */ TABDECL( OP_UND), +/* 0111 1110 0100 */ TABDECL( OP_STRB_P_ASR_IMM_OFF_PREIND), +/* 0111 1110 0101 */ TABDECL( OP_UND), +/* 0111 1110 0110 */ TABDECL( OP_STRB_P_ROR_IMM_OFF_PREIND), +/* 0111 1110 0111 */ TABDECL( OP_UND), +/* 0111 1110 1000 */ TABDECL( OP_STRB_P_LSL_IMM_OFF_PREIND), +/* 0111 1110 1001 */ TABDECL( OP_UND), +/* 0111 1110 1010 */ TABDECL( OP_STRB_P_LSR_IMM_OFF_PREIND), +/* 0111 1110 1011 */ TABDECL( OP_UND), +/* 0111 1110 1100 */ TABDECL( OP_STRB_P_ASR_IMM_OFF_PREIND), +/* 0111 1110 1101 */ TABDECL( OP_UND), +/* 0111 1110 1110 */ TABDECL( OP_STRB_P_ROR_IMM_OFF_PREIND), +/* 0111 1110 1111 */ TABDECL( OP_UND), +/* 0111 1111 0000 */ TABDECL( OP_LDRB_P_LSL_IMM_OFF_PREIND), +/* 0111 1111 0001 */ TABDECL( OP_UND), +/* 0111 1111 0010 */ TABDECL( OP_LDRB_P_LSR_IMM_OFF_PREIND), +/* 0111 1111 0011 */ TABDECL( OP_UND), +/* 0111 1111 0100 */ TABDECL( OP_LDRB_P_ASR_IMM_OFF_PREIND), +/* 0111 1111 0101 */ TABDECL( OP_UND), +/* 0111 1111 0110 */ TABDECL( OP_LDRB_P_ROR_IMM_OFF_PREIND), +/* 0111 1111 0111 */ TABDECL( OP_UND), +/* 0111 1111 1000 */ TABDECL( OP_LDRB_P_LSL_IMM_OFF_PREIND), +/* 0111 1111 1001 */ TABDECL( OP_UND), +/* 0111 1111 1010 */ TABDECL( OP_LDRB_P_LSR_IMM_OFF_PREIND), +/* 0111 1111 1011 */ TABDECL( OP_UND), +/* 0111 1111 1100 */ TABDECL( OP_LDRB_P_ASR_IMM_OFF_PREIND), +/* 0111 1111 1101 */ TABDECL( OP_UND), +/* 0111 1111 1110 */ TABDECL( OP_LDRB_P_ROR_IMM_OFF_PREIND), +/* 0111 1111 1111 */ TABDECL( OP_UND), +/* 1000 0000 0000 */ TABDECL( OP_STMDA), +/* 1000 0000 0001 */ TABDECL( OP_STMDA), +/* 1000 0000 0010 */ TABDECL( OP_STMDA), +/* 1000 0000 0011 */ TABDECL( OP_STMDA), +/* 1000 0000 0100 */ TABDECL( OP_STMDA), +/* 1000 0000 0101 */ TABDECL( OP_STMDA), +/* 1000 0000 0110 */ TABDECL( OP_STMDA), +/* 1000 0000 0111 */ TABDECL( OP_STMDA), +/* 1000 0000 1000 */ TABDECL( OP_STMDA), +/* 1000 0000 1001 */ TABDECL( OP_STMDA), +/* 1000 0000 1010 */ TABDECL( OP_STMDA), +/* 1000 0000 1011 */ TABDECL( OP_STMDA), +/* 1000 0000 1100 */ TABDECL( OP_STMDA), +/* 1000 0000 1101 */ TABDECL( OP_STMDA), +/* 1000 0000 1110 */ TABDECL( OP_STMDA), +/* 1000 0000 1111 */ TABDECL( OP_STMDA), +/* 1000 0001 0000 */ TABDECL( OP_LDMDA), +/* 1000 0001 0001 */ TABDECL( OP_LDMDA), +/* 1000 0001 0010 */ TABDECL( OP_LDMDA), +/* 1000 0001 0011 */ TABDECL( OP_LDMDA), +/* 1000 0001 0100 */ TABDECL( OP_LDMDA), +/* 1000 0001 0101 */ TABDECL( OP_LDMDA), +/* 1000 0001 0110 */ TABDECL( OP_LDMDA), +/* 1000 0001 0111 */ TABDECL( OP_LDMDA), +/* 1000 0001 1000 */ TABDECL( OP_LDMDA), +/* 1000 0001 1001 */ TABDECL( OP_LDMDA), +/* 1000 0001 1010 */ TABDECL( OP_LDMDA), +/* 1000 0001 1011 */ TABDECL( OP_LDMDA), +/* 1000 0001 1100 */ TABDECL( OP_LDMDA), +/* 1000 0001 1101 */ TABDECL( OP_LDMDA), +/* 1000 0001 1110 */ TABDECL( OP_LDMDA), +/* 1000 0001 1111 */ TABDECL( OP_LDMDA), +/* 1000 0010 0000 */ TABDECL( OP_STMDA_W), +/* 1000 0010 0001 */ TABDECL( OP_STMDA_W), +/* 1000 0010 0010 */ TABDECL( OP_STMDA_W), +/* 1000 0010 0011 */ TABDECL( OP_STMDA_W), +/* 1000 0010 0100 */ TABDECL( OP_STMDA_W), +/* 1000 0010 0101 */ TABDECL( OP_STMDA_W), +/* 1000 0010 0110 */ TABDECL( OP_STMDA_W), +/* 1000 0010 0111 */ TABDECL( OP_STMDA_W), +/* 1000 0010 1000 */ TABDECL( OP_STMDA_W), +/* 1000 0010 1001 */ TABDECL( OP_STMDA_W), +/* 1000 0010 1010 */ TABDECL( OP_STMDA_W), +/* 1000 0010 1011 */ TABDECL( OP_STMDA_W), +/* 1000 0010 1100 */ TABDECL( OP_STMDA_W), +/* 1000 0010 1101 */ TABDECL( OP_STMDA_W), +/* 1000 0010 1110 */ TABDECL( OP_STMDA_W), +/* 1000 0010 1111 */ TABDECL( OP_STMDA_W), +/* 1000 0011 0000 */ TABDECL( OP_LDMDA_W), +/* 1000 0011 0001 */ TABDECL( OP_LDMDA_W), +/* 1000 0011 0010 */ TABDECL( OP_LDMDA_W), +/* 1000 0011 0011 */ TABDECL( OP_LDMDA_W), +/* 1000 0011 0100 */ TABDECL( OP_LDMDA_W), +/* 1000 0011 0101 */ TABDECL( OP_LDMDA_W), +/* 1000 0011 0110 */ TABDECL( OP_LDMDA_W), +/* 1000 0011 0111 */ TABDECL( OP_LDMDA_W), +/* 1000 0011 1000 */ TABDECL( OP_LDMDA_W), +/* 1000 0011 1001 */ TABDECL( OP_LDMDA_W), +/* 1000 0011 1010 */ TABDECL( OP_LDMDA_W), +/* 1000 0011 1011 */ TABDECL( OP_LDMDA_W), +/* 1000 0011 1100 */ TABDECL( OP_LDMDA_W), +/* 1000 0011 1101 */ TABDECL( OP_LDMDA_W), +/* 1000 0011 1110 */ TABDECL( OP_LDMDA_W), +/* 1000 0011 1111 */ TABDECL( OP_LDMDA_W), +/* 1000 0100 0000 */ TABDECL( OP_STMDA2), +/* 1000 0100 0001 */ TABDECL( OP_STMDA2), +/* 1000 0100 0010 */ TABDECL( OP_STMDA2), +/* 1000 0100 0011 */ TABDECL( OP_STMDA2), +/* 1000 0100 0100 */ TABDECL( OP_STMDA2), +/* 1000 0100 0101 */ TABDECL( OP_STMDA2), +/* 1000 0100 0110 */ TABDECL( OP_STMDA2), +/* 1000 0100 0111 */ TABDECL( OP_STMDA2), +/* 1000 0100 1000 */ TABDECL( OP_STMDA2), +/* 1000 0100 1001 */ TABDECL( OP_STMDA2), +/* 1000 0100 1010 */ TABDECL( OP_STMDA2), +/* 1000 0100 1011 */ TABDECL( OP_STMDA2), +/* 1000 0100 1100 */ TABDECL( OP_STMDA2), +/* 1000 0100 1101 */ TABDECL( OP_STMDA2), +/* 1000 0100 1110 */ TABDECL( OP_STMDA2), +/* 1000 0100 1111 */ TABDECL( OP_STMDA2), +/* 1000 0101 0000 */ TABDECL( OP_LDMDA2), +/* 1000 0101 0001 */ TABDECL( OP_LDMDA2), +/* 1000 0101 0010 */ TABDECL( OP_LDMDA2), +/* 1000 0101 0011 */ TABDECL( OP_LDMDA2), +/* 1000 0101 0100 */ TABDECL( OP_LDMDA2), +/* 1000 0101 0101 */ TABDECL( OP_LDMDA2), +/* 1000 0101 0110 */ TABDECL( OP_LDMDA2), +/* 1000 0101 0111 */ TABDECL( OP_LDMDA2), +/* 1000 0101 1000 */ TABDECL( OP_LDMDA2), +/* 1000 0101 1001 */ TABDECL( OP_LDMDA2), +/* 1000 0101 1010 */ TABDECL( OP_LDMDA2), +/* 1000 0101 1011 */ TABDECL( OP_LDMDA2), +/* 1000 0101 1100 */ TABDECL( OP_LDMDA2), +/* 1000 0101 1101 */ TABDECL( OP_LDMDA2), +/* 1000 0101 1110 */ TABDECL( OP_LDMDA2), +/* 1000 0101 1111 */ TABDECL( OP_LDMDA2), +/* 1000 0110 0000 */ TABDECL( OP_STMDA2_W), +/* 1000 0110 0001 */ TABDECL( OP_STMDA2_W), +/* 1000 0110 0010 */ TABDECL( OP_STMDA2_W), +/* 1000 0110 0011 */ TABDECL( OP_STMDA2_W), +/* 1000 0110 0100 */ TABDECL( OP_STMDA2_W), +/* 1000 0110 0101 */ TABDECL( OP_STMDA2_W), +/* 1000 0110 0110 */ TABDECL( OP_STMDA2_W), +/* 1000 0110 0111 */ TABDECL( OP_STMDA2_W), +/* 1000 0110 1000 */ TABDECL( OP_STMDA2_W), +/* 1000 0110 1001 */ TABDECL( OP_STMDA2_W), +/* 1000 0110 1010 */ TABDECL( OP_STMDA2_W), +/* 1000 0110 1011 */ TABDECL( OP_STMDA2_W), +/* 1000 0110 1100 */ TABDECL( OP_STMDA2_W), +/* 1000 0110 1101 */ TABDECL( OP_STMDA2_W), +/* 1000 0110 1110 */ TABDECL( OP_STMDA2_W), +/* 1000 0110 1111 */ TABDECL( OP_STMDA2_W), +/* 1000 0111 0000 */ TABDECL( OP_LDMDA2_W), +/* 1000 0111 0001 */ TABDECL( OP_LDMDA2_W), +/* 1000 0111 0010 */ TABDECL( OP_LDMDA2_W), +/* 1000 0111 0011 */ TABDECL( OP_LDMDA2_W), +/* 1000 0111 0100 */ TABDECL( OP_LDMDA2_W), +/* 1000 0111 0101 */ TABDECL( OP_LDMDA2_W), +/* 1000 0111 0110 */ TABDECL( OP_LDMDA2_W), +/* 1000 0111 0111 */ TABDECL( OP_LDMDA2_W), +/* 1000 0111 1000 */ TABDECL( OP_LDMDA2_W), +/* 1000 0111 1001 */ TABDECL( OP_LDMDA2_W), +/* 1000 0111 1010 */ TABDECL( OP_LDMDA2_W), +/* 1000 0111 1011 */ TABDECL( OP_LDMDA2_W), +/* 1000 0111 1100 */ TABDECL( OP_LDMDA2_W), +/* 1000 0111 1101 */ TABDECL( OP_LDMDA2_W), +/* 1000 0111 1110 */ TABDECL( OP_LDMDA2_W), +/* 1000 0111 1111 */ TABDECL( OP_LDMDA2_W), +/* 1000 1000 0000 */ TABDECL( OP_STMIA), +/* 1000 1000 0001 */ TABDECL( OP_STMIA), +/* 1000 1000 0010 */ TABDECL( OP_STMIA), +/* 1000 1000 0011 */ TABDECL( OP_STMIA), +/* 1000 1000 0100 */ TABDECL( OP_STMIA), +/* 1000 1000 0101 */ TABDECL( OP_STMIA), +/* 1000 1000 0110 */ TABDECL( OP_STMIA), +/* 1000 1000 0111 */ TABDECL( OP_STMIA), +/* 1000 1000 1000 */ TABDECL( OP_STMIA), +/* 1000 1000 1001 */ TABDECL( OP_STMIA), +/* 1000 1000 1010 */ TABDECL( OP_STMIA), +/* 1000 1000 1011 */ TABDECL( OP_STMIA), +/* 1000 1000 1100 */ TABDECL( OP_STMIA), +/* 1000 1000 1101 */ TABDECL( OP_STMIA), +/* 1000 1000 1110 */ TABDECL( OP_STMIA), +/* 1000 1000 1111 */ TABDECL( OP_STMIA), +/* 1000 1001 0000 */ TABDECL( OP_LDMIA), +/* 1000 1001 0001 */ TABDECL( OP_LDMIA), +/* 1000 1001 0010 */ TABDECL( OP_LDMIA), +/* 1000 1001 0011 */ TABDECL( OP_LDMIA), +/* 1000 1001 0100 */ TABDECL( OP_LDMIA), +/* 1000 1001 0101 */ TABDECL( OP_LDMIA), +/* 1000 1001 0110 */ TABDECL( OP_LDMIA), +/* 1000 1001 0111 */ TABDECL( OP_LDMIA), +/* 1000 1001 1000 */ TABDECL( OP_LDMIA), +/* 1000 1001 1001 */ TABDECL( OP_LDMIA), +/* 1000 1001 1010 */ TABDECL( OP_LDMIA), +/* 1000 1001 1011 */ TABDECL( OP_LDMIA), +/* 1000 1001 1100 */ TABDECL( OP_LDMIA), +/* 1000 1001 1101 */ TABDECL( OP_LDMIA), +/* 1000 1001 1110 */ TABDECL( OP_LDMIA), +/* 1000 1001 1111 */ TABDECL( OP_LDMIA), +/* 1000 1010 0000 */ TABDECL( OP_STMIA_W), +/* 1000 1010 0001 */ TABDECL( OP_STMIA_W), +/* 1000 1010 0010 */ TABDECL( OP_STMIA_W), +/* 1000 1010 0011 */ TABDECL( OP_STMIA_W), +/* 1000 1010 0100 */ TABDECL( OP_STMIA_W), +/* 1000 1010 0101 */ TABDECL( OP_STMIA_W), +/* 1000 1010 0110 */ TABDECL( OP_STMIA_W), +/* 1000 1010 0111 */ TABDECL( OP_STMIA_W), +/* 1000 1010 1000 */ TABDECL( OP_STMIA_W), +/* 1000 1010 1001 */ TABDECL( OP_STMIA_W), +/* 1000 1010 1010 */ TABDECL( OP_STMIA_W), +/* 1000 1010 1011 */ TABDECL( OP_STMIA_W), +/* 1000 1010 1100 */ TABDECL( OP_STMIA_W), +/* 1000 1010 1101 */ TABDECL( OP_STMIA_W), +/* 1000 1010 1110 */ TABDECL( OP_STMIA_W), +/* 1000 1010 1111 */ TABDECL( OP_STMIA_W), +/* 1000 1011 0000 */ TABDECL( OP_LDMIA_W), +/* 1000 1011 0001 */ TABDECL( OP_LDMIA_W), +/* 1000 1011 0010 */ TABDECL( OP_LDMIA_W), +/* 1000 1011 0011 */ TABDECL( OP_LDMIA_W), +/* 1000 1011 0100 */ TABDECL( OP_LDMIA_W), +/* 1000 1011 0101 */ TABDECL( OP_LDMIA_W), +/* 1000 1011 0110 */ TABDECL( OP_LDMIA_W), +/* 1000 1011 0111 */ TABDECL( OP_LDMIA_W), +/* 1000 1011 1000 */ TABDECL( OP_LDMIA_W), +/* 1000 1011 1001 */ TABDECL( OP_LDMIA_W), +/* 1000 1011 1010 */ TABDECL( OP_LDMIA_W), +/* 1000 1011 1011 */ TABDECL( OP_LDMIA_W), +/* 1000 1011 1100 */ TABDECL( OP_LDMIA_W), +/* 1000 1011 1101 */ TABDECL( OP_LDMIA_W), +/* 1000 1011 1110 */ TABDECL( OP_LDMIA_W), +/* 1000 1011 1111 */ TABDECL( OP_LDMIA_W), +/* 1000 1100 0000 */ TABDECL( OP_STMIA2), +/* 1000 1100 0001 */ TABDECL( OP_STMIA2), +/* 1000 1100 0010 */ TABDECL( OP_STMIA2), +/* 1000 1100 0011 */ TABDECL( OP_STMIA2), +/* 1000 1100 0100 */ TABDECL( OP_STMIA2), +/* 1000 1100 0101 */ TABDECL( OP_STMIA2), +/* 1000 1100 0110 */ TABDECL( OP_STMIA2), +/* 1000 1100 0111 */ TABDECL( OP_STMIA2), +/* 1000 1100 1000 */ TABDECL( OP_STMIA2), +/* 1000 1100 1001 */ TABDECL( OP_STMIA2), +/* 1000 1100 1010 */ TABDECL( OP_STMIA2), +/* 1000 1100 1011 */ TABDECL( OP_STMIA2), +/* 1000 1100 1100 */ TABDECL( OP_STMIA2), +/* 1000 1100 1101 */ TABDECL( OP_STMIA2), +/* 1000 1100 1110 */ TABDECL( OP_STMIA2), +/* 1000 1100 1111 */ TABDECL( OP_STMIA2), +/* 1000 1101 0000 */ TABDECL( OP_LDMIA2), +/* 1000 1101 0001 */ TABDECL( OP_LDMIA2), +/* 1000 1101 0010 */ TABDECL( OP_LDMIA2), +/* 1000 1101 0011 */ TABDECL( OP_LDMIA2), +/* 1000 1101 0100 */ TABDECL( OP_LDMIA2), +/* 1000 1101 0101 */ TABDECL( OP_LDMIA2), +/* 1000 1101 0110 */ TABDECL( OP_LDMIA2), +/* 1000 1101 0111 */ TABDECL( OP_LDMIA2), +/* 1000 1101 1000 */ TABDECL( OP_LDMIA2), +/* 1000 1101 1001 */ TABDECL( OP_LDMIA2), +/* 1000 1101 1010 */ TABDECL( OP_LDMIA2), +/* 1000 1101 1011 */ TABDECL( OP_LDMIA2), +/* 1000 1101 1100 */ TABDECL( OP_LDMIA2), +/* 1000 1101 1101 */ TABDECL( OP_LDMIA2), +/* 1000 1101 1110 */ TABDECL( OP_LDMIA2), +/* 1000 1101 1111 */ TABDECL( OP_LDMIA2), +/* 1000 1110 0000 */ TABDECL( OP_STMIA2_W), +/* 1000 1110 0001 */ TABDECL( OP_STMIA2_W), +/* 1000 1110 0010 */ TABDECL( OP_STMIA2_W), +/* 1000 1110 0011 */ TABDECL( OP_STMIA2_W), +/* 1000 1110 0100 */ TABDECL( OP_STMIA2_W), +/* 1000 1110 0101 */ TABDECL( OP_STMIA2_W), +/* 1000 1110 0110 */ TABDECL( OP_STMIA2_W), +/* 1000 1110 0111 */ TABDECL( OP_STMIA2_W), +/* 1000 1110 1000 */ TABDECL( OP_STMIA2_W), +/* 1000 1110 1001 */ TABDECL( OP_STMIA2_W), +/* 1000 1110 1010 */ TABDECL( OP_STMIA2_W), +/* 1000 1110 1011 */ TABDECL( OP_STMIA2_W), +/* 1000 1110 1100 */ TABDECL( OP_STMIA2_W), +/* 1000 1110 1101 */ TABDECL( OP_STMIA2_W), +/* 1000 1110 1110 */ TABDECL( OP_STMIA2_W), +/* 1000 1110 1111 */ TABDECL( OP_STMIA2_W), +/* 1000 1111 0000 */ TABDECL( OP_LDMIA2_W), +/* 1000 1111 0001 */ TABDECL( OP_LDMIA2_W), +/* 1000 1111 0010 */ TABDECL( OP_LDMIA2_W), +/* 1000 1111 0011 */ TABDECL( OP_LDMIA2_W), +/* 1000 1111 0100 */ TABDECL( OP_LDMIA2_W), +/* 1000 1111 0101 */ TABDECL( OP_LDMIA2_W), +/* 1000 1111 0110 */ TABDECL( OP_LDMIA2_W), +/* 1000 1111 0111 */ TABDECL( OP_LDMIA2_W), +/* 1000 1111 1000 */ TABDECL( OP_LDMIA2_W), +/* 1000 1111 1001 */ TABDECL( OP_LDMIA2_W), +/* 1000 1111 1010 */ TABDECL( OP_LDMIA2_W), +/* 1000 1111 1011 */ TABDECL( OP_LDMIA2_W), +/* 1000 1111 1100 */ TABDECL( OP_LDMIA2_W), +/* 1000 1111 1101 */ TABDECL( OP_LDMIA2_W), +/* 1000 1111 1110 */ TABDECL( OP_LDMIA2_W), +/* 1000 1111 1111 */ TABDECL( OP_LDMIA2_W), +/* 1001 0000 0000 */ TABDECL( OP_STMDB), +/* 1001 0000 0001 */ TABDECL( OP_STMDB), +/* 1001 0000 0010 */ TABDECL( OP_STMDB), +/* 1001 0000 0011 */ TABDECL( OP_STMDB), +/* 1001 0000 0100 */ TABDECL( OP_STMDB), +/* 1001 0000 0101 */ TABDECL( OP_STMDB), +/* 1001 0000 0110 */ TABDECL( OP_STMDB), +/* 1001 0000 0111 */ TABDECL( OP_STMDB), +/* 1001 0000 1000 */ TABDECL( OP_STMDB), +/* 1001 0000 1001 */ TABDECL( OP_STMDB), +/* 1001 0000 1010 */ TABDECL( OP_STMDB), +/* 1001 0000 1011 */ TABDECL( OP_STMDB), +/* 1001 0000 1100 */ TABDECL( OP_STMDB), +/* 1001 0000 1101 */ TABDECL( OP_STMDB), +/* 1001 0000 1110 */ TABDECL( OP_STMDB), +/* 1001 0000 1111 */ TABDECL( OP_STMDB), +/* 1001 0001 0000 */ TABDECL( OP_LDMDB), +/* 1001 0001 0001 */ TABDECL( OP_LDMDB), +/* 1001 0001 0010 */ TABDECL( OP_LDMDB), +/* 1001 0001 0011 */ TABDECL( OP_LDMDB), +/* 1001 0001 0100 */ TABDECL( OP_LDMDB), +/* 1001 0001 0101 */ TABDECL( OP_LDMDB), +/* 1001 0001 0110 */ TABDECL( OP_LDMDB), +/* 1001 0001 0111 */ TABDECL( OP_LDMDB), +/* 1001 0001 1000 */ TABDECL( OP_LDMDB), +/* 1001 0001 1001 */ TABDECL( OP_LDMDB), +/* 1001 0001 1010 */ TABDECL( OP_LDMDB), +/* 1001 0001 1011 */ TABDECL( OP_LDMDB), +/* 1001 0001 1100 */ TABDECL( OP_LDMDB), +/* 1001 0001 1101 */ TABDECL( OP_LDMDB), +/* 1001 0001 1110 */ TABDECL( OP_LDMDB), +/* 1001 0001 1111 */ TABDECL( OP_LDMDB), +/* 1001 0010 0000 */ TABDECL( OP_STMDB_W), +/* 1001 0010 0001 */ TABDECL( OP_STMDB_W), +/* 1001 0010 0010 */ TABDECL( OP_STMDB_W), +/* 1001 0010 0011 */ TABDECL( OP_STMDB_W), +/* 1001 0010 0100 */ TABDECL( OP_STMDB_W), +/* 1001 0010 0101 */ TABDECL( OP_STMDB_W), +/* 1001 0010 0110 */ TABDECL( OP_STMDB_W), +/* 1001 0010 0111 */ TABDECL( OP_STMDB_W), +/* 1001 0010 1000 */ TABDECL( OP_STMDB_W), +/* 1001 0010 1001 */ TABDECL( OP_STMDB_W), +/* 1001 0010 1010 */ TABDECL( OP_STMDB_W), +/* 1001 0010 1011 */ TABDECL( OP_STMDB_W), +/* 1001 0010 1100 */ TABDECL( OP_STMDB_W), +/* 1001 0010 1101 */ TABDECL( OP_STMDB_W), +/* 1001 0010 1110 */ TABDECL( OP_STMDB_W), +/* 1001 0010 1111 */ TABDECL( OP_STMDB_W), +/* 1001 0011 0000 */ TABDECL( OP_LDMDB_W), +/* 1001 0011 0001 */ TABDECL( OP_LDMDB_W), +/* 1001 0011 0010 */ TABDECL( OP_LDMDB_W), +/* 1001 0011 0011 */ TABDECL( OP_LDMDB_W), +/* 1001 0011 0100 */ TABDECL( OP_LDMDB_W), +/* 1001 0011 0101 */ TABDECL( OP_LDMDB_W), +/* 1001 0011 0110 */ TABDECL( OP_LDMDB_W), +/* 1001 0011 0111 */ TABDECL( OP_LDMDB_W), +/* 1001 0011 1000 */ TABDECL( OP_LDMDB_W), +/* 1001 0011 1001 */ TABDECL( OP_LDMDB_W), +/* 1001 0011 1010 */ TABDECL( OP_LDMDB_W), +/* 1001 0011 1011 */ TABDECL( OP_LDMDB_W), +/* 1001 0011 1100 */ TABDECL( OP_LDMDB_W), +/* 1001 0011 1101 */ TABDECL( OP_LDMDB_W), +/* 1001 0011 1110 */ TABDECL( OP_LDMDB_W), +/* 1001 0011 1111 */ TABDECL( OP_LDMDB_W), +/* 1001 0100 0000 */ TABDECL( OP_STMDB2), +/* 1001 0100 0001 */ TABDECL( OP_STMDB2), +/* 1001 0100 0010 */ TABDECL( OP_STMDB2), +/* 1001 0100 0011 */ TABDECL( OP_STMDB2), +/* 1001 0100 0100 */ TABDECL( OP_STMDB2), +/* 1001 0100 0101 */ TABDECL( OP_STMDB2), +/* 1001 0100 0110 */ TABDECL( OP_STMDB2), +/* 1001 0100 0111 */ TABDECL( OP_STMDB2), +/* 1001 0100 1000 */ TABDECL( OP_STMDB2), +/* 1001 0100 1001 */ TABDECL( OP_STMDB2), +/* 1001 0100 1010 */ TABDECL( OP_STMDB2), +/* 1001 0100 1011 */ TABDECL( OP_STMDB2), +/* 1001 0100 1100 */ TABDECL( OP_STMDB2), +/* 1001 0100 1101 */ TABDECL( OP_STMDB2), +/* 1001 0100 1110 */ TABDECL( OP_STMDB2), +/* 1001 0100 1111 */ TABDECL( OP_STMDB2), +/* 1001 0101 0000 */ TABDECL( OP_LDMDB2), +/* 1001 0101 0001 */ TABDECL( OP_LDMDB2), +/* 1001 0101 0010 */ TABDECL( OP_LDMDB2), +/* 1001 0101 0011 */ TABDECL( OP_LDMDB2), +/* 1001 0101 0100 */ TABDECL( OP_LDMDB2), +/* 1001 0101 0101 */ TABDECL( OP_LDMDB2), +/* 1001 0101 0110 */ TABDECL( OP_LDMDB2), +/* 1001 0101 0111 */ TABDECL( OP_LDMDB2), +/* 1001 0101 1000 */ TABDECL( OP_LDMDB2), +/* 1001 0101 1001 */ TABDECL( OP_LDMDB2), +/* 1001 0101 1010 */ TABDECL( OP_LDMDB2), +/* 1001 0101 1011 */ TABDECL( OP_LDMDB2), +/* 1001 0101 1100 */ TABDECL( OP_LDMDB2), +/* 1001 0101 1101 */ TABDECL( OP_LDMDB2), +/* 1001 0101 1110 */ TABDECL( OP_LDMDB2), +/* 1001 0101 1111 */ TABDECL( OP_LDMDB2), +/* 1001 0110 0000 */ TABDECL( OP_STMDB2_W), +/* 1001 0110 0001 */ TABDECL( OP_STMDB2_W), +/* 1001 0110 0010 */ TABDECL( OP_STMDB2_W), +/* 1001 0110 0011 */ TABDECL( OP_STMDB2_W), +/* 1001 0110 0100 */ TABDECL( OP_STMDB2_W), +/* 1001 0110 0101 */ TABDECL( OP_STMDB2_W), +/* 1001 0110 0110 */ TABDECL( OP_STMDB2_W), +/* 1001 0110 0111 */ TABDECL( OP_STMDB2_W), +/* 1001 0110 1000 */ TABDECL( OP_STMDB2_W), +/* 1001 0110 1001 */ TABDECL( OP_STMDB2_W), +/* 1001 0110 1010 */ TABDECL( OP_STMDB2_W), +/* 1001 0110 1011 */ TABDECL( OP_STMDB2_W), +/* 1001 0110 1100 */ TABDECL( OP_STMDB2_W), +/* 1001 0110 1101 */ TABDECL( OP_STMDB2_W), +/* 1001 0110 1110 */ TABDECL( OP_STMDB2_W), +/* 1001 0110 1111 */ TABDECL( OP_STMDB2_W), +/* 1001 0111 0000 */ TABDECL( OP_LDMDB2_W), +/* 1001 0111 0001 */ TABDECL( OP_LDMDB2_W), +/* 1001 0111 0010 */ TABDECL( OP_LDMDB2_W), +/* 1001 0111 0011 */ TABDECL( OP_LDMDB2_W), +/* 1001 0111 0100 */ TABDECL( OP_LDMDB2_W), +/* 1001 0111 0101 */ TABDECL( OP_LDMDB2_W), +/* 1001 0111 0110 */ TABDECL( OP_LDMDB2_W), +/* 1001 0111 0111 */ TABDECL( OP_LDMDB2_W), +/* 1001 0111 1000 */ TABDECL( OP_LDMDB2_W), +/* 1001 0111 1001 */ TABDECL( OP_LDMDB2_W), +/* 1001 0111 1010 */ TABDECL( OP_LDMDB2_W), +/* 1001 0111 1011 */ TABDECL( OP_LDMDB2_W), +/* 1001 0111 1100 */ TABDECL( OP_LDMDB2_W), +/* 1001 0111 1101 */ TABDECL( OP_LDMDB2_W), +/* 1001 0111 1110 */ TABDECL( OP_LDMDB2_W), +/* 1001 0111 1111 */ TABDECL( OP_LDMDB2_W), +/* 1001 1000 0000 */ TABDECL( OP_STMIB), +/* 1001 1000 0001 */ TABDECL( OP_STMIB), +/* 1001 1000 0010 */ TABDECL( OP_STMIB), +/* 1001 1000 0011 */ TABDECL( OP_STMIB), +/* 1001 1000 0100 */ TABDECL( OP_STMIB), +/* 1001 1000 0101 */ TABDECL( OP_STMIB), +/* 1001 1000 0110 */ TABDECL( OP_STMIB), +/* 1001 1000 0111 */ TABDECL( OP_STMIB), +/* 1001 1000 1000 */ TABDECL( OP_STMIB), +/* 1001 1000 1001 */ TABDECL( OP_STMIB), +/* 1001 1000 1010 */ TABDECL( OP_STMIB), +/* 1001 1000 1011 */ TABDECL( OP_STMIB), +/* 1001 1000 1100 */ TABDECL( OP_STMIB), +/* 1001 1000 1101 */ TABDECL( OP_STMIB), +/* 1001 1000 1110 */ TABDECL( OP_STMIB), +/* 1001 1000 1111 */ TABDECL( OP_STMIB), +/* 1001 1001 0000 */ TABDECL( OP_LDMIB), +/* 1001 1001 0001 */ TABDECL( OP_LDMIB), +/* 1001 1001 0010 */ TABDECL( OP_LDMIB), +/* 1001 1001 0011 */ TABDECL( OP_LDMIB), +/* 1001 1001 0100 */ TABDECL( OP_LDMIB), +/* 1001 1001 0101 */ TABDECL( OP_LDMIB), +/* 1001 1001 0110 */ TABDECL( OP_LDMIB), +/* 1001 1001 0111 */ TABDECL( OP_LDMIB), +/* 1001 1001 1000 */ TABDECL( OP_LDMIB), +/* 1001 1001 1001 */ TABDECL( OP_LDMIB), +/* 1001 1001 1010 */ TABDECL( OP_LDMIB), +/* 1001 1001 1011 */ TABDECL( OP_LDMIB), +/* 1001 1001 1100 */ TABDECL( OP_LDMIB), +/* 1001 1001 1101 */ TABDECL( OP_LDMIB), +/* 1001 1001 1110 */ TABDECL( OP_LDMIB), +/* 1001 1001 1111 */ TABDECL( OP_LDMIB), +/* 1001 1010 0000 */ TABDECL( OP_STMIB_W), +/* 1001 1010 0001 */ TABDECL( OP_STMIB_W), +/* 1001 1010 0010 */ TABDECL( OP_STMIB_W), +/* 1001 1010 0011 */ TABDECL( OP_STMIB_W), +/* 1001 1010 0100 */ TABDECL( OP_STMIB_W), +/* 1001 1010 0101 */ TABDECL( OP_STMIB_W), +/* 1001 1010 0110 */ TABDECL( OP_STMIB_W), +/* 1001 1010 0111 */ TABDECL( OP_STMIB_W), +/* 1001 1010 1000 */ TABDECL( OP_STMIB_W), +/* 1001 1010 1001 */ TABDECL( OP_STMIB_W), +/* 1001 1010 1010 */ TABDECL( OP_STMIB_W), +/* 1001 1010 1011 */ TABDECL( OP_STMIB_W), +/* 1001 1010 1100 */ TABDECL( OP_STMIB_W), +/* 1001 1010 1101 */ TABDECL( OP_STMIB_W), +/* 1001 1010 1110 */ TABDECL( OP_STMIB_W), +/* 1001 1010 1111 */ TABDECL( OP_STMIB_W), +/* 1001 1011 0000 */ TABDECL( OP_LDMIB_W), +/* 1001 1011 0001 */ TABDECL( OP_LDMIB_W), +/* 1001 1011 0010 */ TABDECL( OP_LDMIB_W), +/* 1001 1011 0011 */ TABDECL( OP_LDMIB_W), +/* 1001 1011 0100 */ TABDECL( OP_LDMIB_W), +/* 1001 1011 0101 */ TABDECL( OP_LDMIB_W), +/* 1001 1011 0110 */ TABDECL( OP_LDMIB_W), +/* 1001 1011 0111 */ TABDECL( OP_LDMIB_W), +/* 1001 1011 1000 */ TABDECL( OP_LDMIB_W), +/* 1001 1011 1001 */ TABDECL( OP_LDMIB_W), +/* 1001 1011 1010 */ TABDECL( OP_LDMIB_W), +/* 1001 1011 1011 */ TABDECL( OP_LDMIB_W), +/* 1001 1011 1100 */ TABDECL( OP_LDMIB_W), +/* 1001 1011 1101 */ TABDECL( OP_LDMIB_W), +/* 1001 1011 1110 */ TABDECL( OP_LDMIB_W), +/* 1001 1011 1111 */ TABDECL( OP_LDMIB_W), +/* 1001 1100 0000 */ TABDECL( OP_STMIB2), +/* 1001 1100 0001 */ TABDECL( OP_STMIB2), +/* 1001 1100 0010 */ TABDECL( OP_STMIB2), +/* 1001 1100 0011 */ TABDECL( OP_STMIB2), +/* 1001 1100 0100 */ TABDECL( OP_STMIB2), +/* 1001 1100 0101 */ TABDECL( OP_STMIB2), +/* 1001 1100 0110 */ TABDECL( OP_STMIB2), +/* 1001 1100 0111 */ TABDECL( OP_STMIB2), +/* 1001 1100 1000 */ TABDECL( OP_STMIB2), +/* 1001 1100 1001 */ TABDECL( OP_STMIB2), +/* 1001 1100 1010 */ TABDECL( OP_STMIB2), +/* 1001 1100 1011 */ TABDECL( OP_STMIB2), +/* 1001 1100 1100 */ TABDECL( OP_STMIB2), +/* 1001 1100 1101 */ TABDECL( OP_STMIB2), +/* 1001 1100 1110 */ TABDECL( OP_STMIB2), +/* 1001 1100 1111 */ TABDECL( OP_STMIB2), +/* 1001 1101 0000 */ TABDECL( OP_LDMIB2), +/* 1001 1101 0001 */ TABDECL( OP_LDMIB2), +/* 1001 1101 0010 */ TABDECL( OP_LDMIB2), +/* 1001 1101 0011 */ TABDECL( OP_LDMIB2), +/* 1001 1101 0100 */ TABDECL( OP_LDMIB2), +/* 1001 1101 0101 */ TABDECL( OP_LDMIB2), +/* 1001 1101 0110 */ TABDECL( OP_LDMIB2), +/* 1001 1101 0111 */ TABDECL( OP_LDMIB2), +/* 1001 1101 1000 */ TABDECL( OP_LDMIB2), +/* 1001 1101 1001 */ TABDECL( OP_LDMIB2), +/* 1001 1101 1010 */ TABDECL( OP_LDMIB2), +/* 1001 1101 1011 */ TABDECL( OP_LDMIB2), +/* 1001 1101 1100 */ TABDECL( OP_LDMIB2), +/* 1001 1101 1101 */ TABDECL( OP_LDMIB2), +/* 1001 1101 1110 */ TABDECL( OP_LDMIB2), +/* 1001 1101 1111 */ TABDECL( OP_LDMIB2), +/* 1001 1110 0000 */ TABDECL( OP_STMIB2_W), +/* 1001 1110 0001 */ TABDECL( OP_STMIB2_W), +/* 1001 1110 0010 */ TABDECL( OP_STMIB2_W), +/* 1001 1110 0011 */ TABDECL( OP_STMIB2_W), +/* 1001 1110 0100 */ TABDECL( OP_STMIB2_W), +/* 1001 1110 0101 */ TABDECL( OP_STMIB2_W), +/* 1001 1110 0110 */ TABDECL( OP_STMIB2_W), +/* 1001 1110 0111 */ TABDECL( OP_STMIB2_W), +/* 1001 1110 1000 */ TABDECL( OP_STMIB2_W), +/* 1001 1110 1001 */ TABDECL( OP_STMIB2_W), +/* 1001 1110 1010 */ TABDECL( OP_STMIB2_W), +/* 1001 1110 1011 */ TABDECL( OP_STMIB2_W), +/* 1001 1110 1100 */ TABDECL( OP_STMIB2_W), +/* 1001 1110 1101 */ TABDECL( OP_STMIB2_W), +/* 1001 1110 1110 */ TABDECL( OP_STMIB2_W), +/* 1001 1110 1111 */ TABDECL( OP_STMIB2_W), +/* 1001 1111 0000 */ TABDECL( OP_LDMIB2_W), +/* 1001 1111 0001 */ TABDECL( OP_LDMIB2_W), +/* 1001 1111 0010 */ TABDECL( OP_LDMIB2_W), +/* 1001 1111 0011 */ TABDECL( OP_LDMIB2_W), +/* 1001 1111 0100 */ TABDECL( OP_LDMIB2_W), +/* 1001 1111 0101 */ TABDECL( OP_LDMIB2_W), +/* 1001 1111 0110 */ TABDECL( OP_LDMIB2_W), +/* 1001 1111 0111 */ TABDECL( OP_LDMIB2_W), +/* 1001 1111 1000 */ TABDECL( OP_LDMIB2_W), +/* 1001 1111 1001 */ TABDECL( OP_LDMIB2_W), +/* 1001 1111 1010 */ TABDECL( OP_LDMIB2_W), +/* 1001 1111 1011 */ TABDECL( OP_LDMIB2_W), +/* 1001 1111 1100 */ TABDECL( OP_LDMIB2_W), +/* 1001 1111 1101 */ TABDECL( OP_LDMIB2_W), +/* 1001 1111 1110 */ TABDECL( OP_LDMIB2_W), +/* 1001 1111 1111 */ TABDECL( OP_LDMIB2_W), +/* 1010 0000 0000 */ TABDECL( OP_B), +/* 1010 0000 0001 */ TABDECL( OP_B), +/* 1010 0000 0010 */ TABDECL( OP_B), +/* 1010 0000 0011 */ TABDECL( OP_B), +/* 1010 0000 0100 */ TABDECL( OP_B), +/* 1010 0000 0101 */ TABDECL( OP_B), +/* 1010 0000 0110 */ TABDECL( OP_B), +/* 1010 0000 0111 */ TABDECL( OP_B), +/* 1010 0000 1000 */ TABDECL( OP_B), +/* 1010 0000 1001 */ TABDECL( OP_B), +/* 1010 0000 1010 */ TABDECL( OP_B), +/* 1010 0000 1011 */ TABDECL( OP_B), +/* 1010 0000 1100 */ TABDECL( OP_B), +/* 1010 0000 1101 */ TABDECL( OP_B), +/* 1010 0000 1110 */ TABDECL( OP_B), +/* 1010 0000 1111 */ TABDECL( OP_B), +/* 1010 0001 0000 */ TABDECL( OP_B), +/* 1010 0001 0001 */ TABDECL( OP_B), +/* 1010 0001 0010 */ TABDECL( OP_B), +/* 1010 0001 0011 */ TABDECL( OP_B), +/* 1010 0001 0100 */ TABDECL( OP_B), +/* 1010 0001 0101 */ TABDECL( OP_B), +/* 1010 0001 0110 */ TABDECL( OP_B), +/* 1010 0001 0111 */ TABDECL( OP_B), +/* 1010 0001 1000 */ TABDECL( OP_B), +/* 1010 0001 1001 */ TABDECL( OP_B), +/* 1010 0001 1010 */ TABDECL( OP_B), +/* 1010 0001 1011 */ TABDECL( OP_B), +/* 1010 0001 1100 */ TABDECL( OP_B), +/* 1010 0001 1101 */ TABDECL( OP_B), +/* 1010 0001 1110 */ TABDECL( OP_B), +/* 1010 0001 1111 */ TABDECL( OP_B), +/* 1010 0010 0000 */ TABDECL( OP_B), +/* 1010 0010 0001 */ TABDECL( OP_B), +/* 1010 0010 0010 */ TABDECL( OP_B), +/* 1010 0010 0011 */ TABDECL( OP_B), +/* 1010 0010 0100 */ TABDECL( OP_B), +/* 1010 0010 0101 */ TABDECL( OP_B), +/* 1010 0010 0110 */ TABDECL( OP_B), +/* 1010 0010 0111 */ TABDECL( OP_B), +/* 1010 0010 1000 */ TABDECL( OP_B), +/* 1010 0010 1001 */ TABDECL( OP_B), +/* 1010 0010 1010 */ TABDECL( OP_B), +/* 1010 0010 1011 */ TABDECL( OP_B), +/* 1010 0010 1100 */ TABDECL( OP_B), +/* 1010 0010 1101 */ TABDECL( OP_B), +/* 1010 0010 1110 */ TABDECL( OP_B), +/* 1010 0010 1111 */ TABDECL( OP_B), +/* 1010 0011 0000 */ TABDECL( OP_B), +/* 1010 0011 0001 */ TABDECL( OP_B), +/* 1010 0011 0010 */ TABDECL( OP_B), +/* 1010 0011 0011 */ TABDECL( OP_B), +/* 1010 0011 0100 */ TABDECL( OP_B), +/* 1010 0011 0101 */ TABDECL( OP_B), +/* 1010 0011 0110 */ TABDECL( OP_B), +/* 1010 0011 0111 */ TABDECL( OP_B), +/* 1010 0011 1000 */ TABDECL( OP_B), +/* 1010 0011 1001 */ TABDECL( OP_B), +/* 1010 0011 1010 */ TABDECL( OP_B), +/* 1010 0011 1011 */ TABDECL( OP_B), +/* 1010 0011 1100 */ TABDECL( OP_B), +/* 1010 0011 1101 */ TABDECL( OP_B), +/* 1010 0011 1110 */ TABDECL( OP_B), +/* 1010 0011 1111 */ TABDECL( OP_B), +/* 1010 0100 0000 */ TABDECL( OP_B), +/* 1010 0100 0001 */ TABDECL( OP_B), +/* 1010 0100 0010 */ TABDECL( OP_B), +/* 1010 0100 0011 */ TABDECL( OP_B), +/* 1010 0100 0100 */ TABDECL( OP_B), +/* 1010 0100 0101 */ TABDECL( OP_B), +/* 1010 0100 0110 */ TABDECL( OP_B), +/* 1010 0100 0111 */ TABDECL( OP_B), +/* 1010 0100 1000 */ TABDECL( OP_B), +/* 1010 0100 1001 */ TABDECL( OP_B), +/* 1010 0100 1010 */ TABDECL( OP_B), +/* 1010 0100 1011 */ TABDECL( OP_B), +/* 1010 0100 1100 */ TABDECL( OP_B), +/* 1010 0100 1101 */ TABDECL( OP_B), +/* 1010 0100 1110 */ TABDECL( OP_B), +/* 1010 0100 1111 */ TABDECL( OP_B), +/* 1010 0101 0000 */ TABDECL( OP_B), +/* 1010 0101 0001 */ TABDECL( OP_B), +/* 1010 0101 0010 */ TABDECL( OP_B), +/* 1010 0101 0011 */ TABDECL( OP_B), +/* 1010 0101 0100 */ TABDECL( OP_B), +/* 1010 0101 0101 */ TABDECL( OP_B), +/* 1010 0101 0110 */ TABDECL( OP_B), +/* 1010 0101 0111 */ TABDECL( OP_B), +/* 1010 0101 1000 */ TABDECL( OP_B), +/* 1010 0101 1001 */ TABDECL( OP_B), +/* 1010 0101 1010 */ TABDECL( OP_B), +/* 1010 0101 1011 */ TABDECL( OP_B), +/* 1010 0101 1100 */ TABDECL( OP_B), +/* 1010 0101 1101 */ TABDECL( OP_B), +/* 1010 0101 1110 */ TABDECL( OP_B), +/* 1010 0101 1111 */ TABDECL( OP_B), +/* 1010 0110 0000 */ TABDECL( OP_B), +/* 1010 0110 0001 */ TABDECL( OP_B), +/* 1010 0110 0010 */ TABDECL( OP_B), +/* 1010 0110 0011 */ TABDECL( OP_B), +/* 1010 0110 0100 */ TABDECL( OP_B), +/* 1010 0110 0101 */ TABDECL( OP_B), +/* 1010 0110 0110 */ TABDECL( OP_B), +/* 1010 0110 0111 */ TABDECL( OP_B), +/* 1010 0110 1000 */ TABDECL( OP_B), +/* 1010 0110 1001 */ TABDECL( OP_B), +/* 1010 0110 1010 */ TABDECL( OP_B), +/* 1010 0110 1011 */ TABDECL( OP_B), +/* 1010 0110 1100 */ TABDECL( OP_B), +/* 1010 0110 1101 */ TABDECL( OP_B), +/* 1010 0110 1110 */ TABDECL( OP_B), +/* 1010 0110 1111 */ TABDECL( OP_B), +/* 1010 0111 0000 */ TABDECL( OP_B), +/* 1010 0111 0001 */ TABDECL( OP_B), +/* 1010 0111 0010 */ TABDECL( OP_B), +/* 1010 0111 0011 */ TABDECL( OP_B), +/* 1010 0111 0100 */ TABDECL( OP_B), +/* 1010 0111 0101 */ TABDECL( OP_B), +/* 1010 0111 0110 */ TABDECL( OP_B), +/* 1010 0111 0111 */ TABDECL( OP_B), +/* 1010 0111 1000 */ TABDECL( OP_B), +/* 1010 0111 1001 */ TABDECL( OP_B), +/* 1010 0111 1010 */ TABDECL( OP_B), +/* 1010 0111 1011 */ TABDECL( OP_B), +/* 1010 0111 1100 */ TABDECL( OP_B), +/* 1010 0111 1101 */ TABDECL( OP_B), +/* 1010 0111 1110 */ TABDECL( OP_B), +/* 1010 0111 1111 */ TABDECL( OP_B), +/* 1010 1000 0000 */ TABDECL( OP_B), +/* 1010 1000 0001 */ TABDECL( OP_B), +/* 1010 1000 0010 */ TABDECL( OP_B), +/* 1010 1000 0011 */ TABDECL( OP_B), +/* 1010 1000 0100 */ TABDECL( OP_B), +/* 1010 1000 0101 */ TABDECL( OP_B), +/* 1010 1000 0110 */ TABDECL( OP_B), +/* 1010 1000 0111 */ TABDECL( OP_B), +/* 1010 1000 1000 */ TABDECL( OP_B), +/* 1010 1000 1001 */ TABDECL( OP_B), +/* 1010 1000 1010 */ TABDECL( OP_B), +/* 1010 1000 1011 */ TABDECL( OP_B), +/* 1010 1000 1100 */ TABDECL( OP_B), +/* 1010 1000 1101 */ TABDECL( OP_B), +/* 1010 1000 1110 */ TABDECL( OP_B), +/* 1010 1000 1111 */ TABDECL( OP_B), +/* 1010 1001 0000 */ TABDECL( OP_B), +/* 1010 1001 0001 */ TABDECL( OP_B), +/* 1010 1001 0010 */ TABDECL( OP_B), +/* 1010 1001 0011 */ TABDECL( OP_B), +/* 1010 1001 0100 */ TABDECL( OP_B), +/* 1010 1001 0101 */ TABDECL( OP_B), +/* 1010 1001 0110 */ TABDECL( OP_B), +/* 1010 1001 0111 */ TABDECL( OP_B), +/* 1010 1001 1000 */ TABDECL( OP_B), +/* 1010 1001 1001 */ TABDECL( OP_B), +/* 1010 1001 1010 */ TABDECL( OP_B), +/* 1010 1001 1011 */ TABDECL( OP_B), +/* 1010 1001 1100 */ TABDECL( OP_B), +/* 1010 1001 1101 */ TABDECL( OP_B), +/* 1010 1001 1110 */ TABDECL( OP_B), +/* 1010 1001 1111 */ TABDECL( OP_B), +/* 1010 1010 0000 */ TABDECL( OP_B), +/* 1010 1010 0001 */ TABDECL( OP_B), +/* 1010 1010 0010 */ TABDECL( OP_B), +/* 1010 1010 0011 */ TABDECL( OP_B), +/* 1010 1010 0100 */ TABDECL( OP_B), +/* 1010 1010 0101 */ TABDECL( OP_B), +/* 1010 1010 0110 */ TABDECL( OP_B), +/* 1010 1010 0111 */ TABDECL( OP_B), +/* 1010 1010 1000 */ TABDECL( OP_B), +/* 1010 1010 1001 */ TABDECL( OP_B), +/* 1010 1010 1010 */ TABDECL( OP_B), +/* 1010 1010 1011 */ TABDECL( OP_B), +/* 1010 1010 1100 */ TABDECL( OP_B), +/* 1010 1010 1101 */ TABDECL( OP_B), +/* 1010 1010 1110 */ TABDECL( OP_B), +/* 1010 1010 1111 */ TABDECL( OP_B), +/* 1010 1011 0000 */ TABDECL( OP_B), +/* 1010 1011 0001 */ TABDECL( OP_B), +/* 1010 1011 0010 */ TABDECL( OP_B), +/* 1010 1011 0011 */ TABDECL( OP_B), +/* 1010 1011 0100 */ TABDECL( OP_B), +/* 1010 1011 0101 */ TABDECL( OP_B), +/* 1010 1011 0110 */ TABDECL( OP_B), +/* 1010 1011 0111 */ TABDECL( OP_B), +/* 1010 1011 1000 */ TABDECL( OP_B), +/* 1010 1011 1001 */ TABDECL( OP_B), +/* 1010 1011 1010 */ TABDECL( OP_B), +/* 1010 1011 1011 */ TABDECL( OP_B), +/* 1010 1011 1100 */ TABDECL( OP_B), +/* 1010 1011 1101 */ TABDECL( OP_B), +/* 1010 1011 1110 */ TABDECL( OP_B), +/* 1010 1011 1111 */ TABDECL( OP_B), +/* 1010 1100 0000 */ TABDECL( OP_B), +/* 1010 1100 0001 */ TABDECL( OP_B), +/* 1010 1100 0010 */ TABDECL( OP_B), +/* 1010 1100 0011 */ TABDECL( OP_B), +/* 1010 1100 0100 */ TABDECL( OP_B), +/* 1010 1100 0101 */ TABDECL( OP_B), +/* 1010 1100 0110 */ TABDECL( OP_B), +/* 1010 1100 0111 */ TABDECL( OP_B), +/* 1010 1100 1000 */ TABDECL( OP_B), +/* 1010 1100 1001 */ TABDECL( OP_B), +/* 1010 1100 1010 */ TABDECL( OP_B), +/* 1010 1100 1011 */ TABDECL( OP_B), +/* 1010 1100 1100 */ TABDECL( OP_B), +/* 1010 1100 1101 */ TABDECL( OP_B), +/* 1010 1100 1110 */ TABDECL( OP_B), +/* 1010 1100 1111 */ TABDECL( OP_B), +/* 1010 1101 0000 */ TABDECL( OP_B), +/* 1010 1101 0001 */ TABDECL( OP_B), +/* 1010 1101 0010 */ TABDECL( OP_B), +/* 1010 1101 0011 */ TABDECL( OP_B), +/* 1010 1101 0100 */ TABDECL( OP_B), +/* 1010 1101 0101 */ TABDECL( OP_B), +/* 1010 1101 0110 */ TABDECL( OP_B), +/* 1010 1101 0111 */ TABDECL( OP_B), +/* 1010 1101 1000 */ TABDECL( OP_B), +/* 1010 1101 1001 */ TABDECL( OP_B), +/* 1010 1101 1010 */ TABDECL( OP_B), +/* 1010 1101 1011 */ TABDECL( OP_B), +/* 1010 1101 1100 */ TABDECL( OP_B), +/* 1010 1101 1101 */ TABDECL( OP_B), +/* 1010 1101 1110 */ TABDECL( OP_B), +/* 1010 1101 1111 */ TABDECL( OP_B), +/* 1010 1110 0000 */ TABDECL( OP_B), +/* 1010 1110 0001 */ TABDECL( OP_B), +/* 1010 1110 0010 */ TABDECL( OP_B), +/* 1010 1110 0011 */ TABDECL( OP_B), +/* 1010 1110 0100 */ TABDECL( OP_B), +/* 1010 1110 0101 */ TABDECL( OP_B), +/* 1010 1110 0110 */ TABDECL( OP_B), +/* 1010 1110 0111 */ TABDECL( OP_B), +/* 1010 1110 1000 */ TABDECL( OP_B), +/* 1010 1110 1001 */ TABDECL( OP_B), +/* 1010 1110 1010 */ TABDECL( OP_B), +/* 1010 1110 1011 */ TABDECL( OP_B), +/* 1010 1110 1100 */ TABDECL( OP_B), +/* 1010 1110 1101 */ TABDECL( OP_B), +/* 1010 1110 1110 */ TABDECL( OP_B), +/* 1010 1110 1111 */ TABDECL( OP_B), +/* 1010 1111 0000 */ TABDECL( OP_B), +/* 1010 1111 0001 */ TABDECL( OP_B), +/* 1010 1111 0010 */ TABDECL( OP_B), +/* 1010 1111 0011 */ TABDECL( OP_B), +/* 1010 1111 0100 */ TABDECL( OP_B), +/* 1010 1111 0101 */ TABDECL( OP_B), +/* 1010 1111 0110 */ TABDECL( OP_B), +/* 1010 1111 0111 */ TABDECL( OP_B), +/* 1010 1111 1000 */ TABDECL( OP_B), +/* 1010 1111 1001 */ TABDECL( OP_B), +/* 1010 1111 1010 */ TABDECL( OP_B), +/* 1010 1111 1011 */ TABDECL( OP_B), +/* 1010 1111 1100 */ TABDECL( OP_B), +/* 1010 1111 1101 */ TABDECL( OP_B), +/* 1010 1111 1110 */ TABDECL( OP_B), +/* 1010 1111 1111 */ TABDECL( OP_B), +/* 1011 0000 0000 */ TABDECL( OP_BL), +/* 1011 0000 0001 */ TABDECL( OP_BL), +/* 1011 0000 0010 */ TABDECL( OP_BL), +/* 1011 0000 0011 */ TABDECL( OP_BL), +/* 1011 0000 0100 */ TABDECL( OP_BL), +/* 1011 0000 0101 */ TABDECL( OP_BL), +/* 1011 0000 0110 */ TABDECL( OP_BL), +/* 1011 0000 0111 */ TABDECL( OP_BL), +/* 1011 0000 1000 */ TABDECL( OP_BL), +/* 1011 0000 1001 */ TABDECL( OP_BL), +/* 1011 0000 1010 */ TABDECL( OP_BL), +/* 1011 0000 1011 */ TABDECL( OP_BL), +/* 1011 0000 1100 */ TABDECL( OP_BL), +/* 1011 0000 1101 */ TABDECL( OP_BL), +/* 1011 0000 1110 */ TABDECL( OP_BL), +/* 1011 0000 1111 */ TABDECL( OP_BL), +/* 1011 0001 0000 */ TABDECL( OP_BL), +/* 1011 0001 0001 */ TABDECL( OP_BL), +/* 1011 0001 0010 */ TABDECL( OP_BL), +/* 1011 0001 0011 */ TABDECL( OP_BL), +/* 1011 0001 0100 */ TABDECL( OP_BL), +/* 1011 0001 0101 */ TABDECL( OP_BL), +/* 1011 0001 0110 */ TABDECL( OP_BL), +/* 1011 0001 0111 */ TABDECL( OP_BL), +/* 1011 0001 1000 */ TABDECL( OP_BL), +/* 1011 0001 1001 */ TABDECL( OP_BL), +/* 1011 0001 1010 */ TABDECL( OP_BL), +/* 1011 0001 1011 */ TABDECL( OP_BL), +/* 1011 0001 1100 */ TABDECL( OP_BL), +/* 1011 0001 1101 */ TABDECL( OP_BL), +/* 1011 0001 1110 */ TABDECL( OP_BL), +/* 1011 0001 1111 */ TABDECL( OP_BL), +/* 1011 0010 0000 */ TABDECL( OP_BL), +/* 1011 0010 0001 */ TABDECL( OP_BL), +/* 1011 0010 0010 */ TABDECL( OP_BL), +/* 1011 0010 0011 */ TABDECL( OP_BL), +/* 1011 0010 0100 */ TABDECL( OP_BL), +/* 1011 0010 0101 */ TABDECL( OP_BL), +/* 1011 0010 0110 */ TABDECL( OP_BL), +/* 1011 0010 0111 */ TABDECL( OP_BL), +/* 1011 0010 1000 */ TABDECL( OP_BL), +/* 1011 0010 1001 */ TABDECL( OP_BL), +/* 1011 0010 1010 */ TABDECL( OP_BL), +/* 1011 0010 1011 */ TABDECL( OP_BL), +/* 1011 0010 1100 */ TABDECL( OP_BL), +/* 1011 0010 1101 */ TABDECL( OP_BL), +/* 1011 0010 1110 */ TABDECL( OP_BL), +/* 1011 0010 1111 */ TABDECL( OP_BL), +/* 1011 0011 0000 */ TABDECL( OP_BL), +/* 1011 0011 0001 */ TABDECL( OP_BL), +/* 1011 0011 0010 */ TABDECL( OP_BL), +/* 1011 0011 0011 */ TABDECL( OP_BL), +/* 1011 0011 0100 */ TABDECL( OP_BL), +/* 1011 0011 0101 */ TABDECL( OP_BL), +/* 1011 0011 0110 */ TABDECL( OP_BL), +/* 1011 0011 0111 */ TABDECL( OP_BL), +/* 1011 0011 1000 */ TABDECL( OP_BL), +/* 1011 0011 1001 */ TABDECL( OP_BL), +/* 1011 0011 1010 */ TABDECL( OP_BL), +/* 1011 0011 1011 */ TABDECL( OP_BL), +/* 1011 0011 1100 */ TABDECL( OP_BL), +/* 1011 0011 1101 */ TABDECL( OP_BL), +/* 1011 0011 1110 */ TABDECL( OP_BL), +/* 1011 0011 1111 */ TABDECL( OP_BL), +/* 1011 0100 0000 */ TABDECL( OP_BL), +/* 1011 0100 0001 */ TABDECL( OP_BL), +/* 1011 0100 0010 */ TABDECL( OP_BL), +/* 1011 0100 0011 */ TABDECL( OP_BL), +/* 1011 0100 0100 */ TABDECL( OP_BL), +/* 1011 0100 0101 */ TABDECL( OP_BL), +/* 1011 0100 0110 */ TABDECL( OP_BL), +/* 1011 0100 0111 */ TABDECL( OP_BL), +/* 1011 0100 1000 */ TABDECL( OP_BL), +/* 1011 0100 1001 */ TABDECL( OP_BL), +/* 1011 0100 1010 */ TABDECL( OP_BL), +/* 1011 0100 1011 */ TABDECL( OP_BL), +/* 1011 0100 1100 */ TABDECL( OP_BL), +/* 1011 0100 1101 */ TABDECL( OP_BL), +/* 1011 0100 1110 */ TABDECL( OP_BL), +/* 1011 0100 1111 */ TABDECL( OP_BL), +/* 1011 0101 0000 */ TABDECL( OP_BL), +/* 1011 0101 0001 */ TABDECL( OP_BL), +/* 1011 0101 0010 */ TABDECL( OP_BL), +/* 1011 0101 0011 */ TABDECL( OP_BL), +/* 1011 0101 0100 */ TABDECL( OP_BL), +/* 1011 0101 0101 */ TABDECL( OP_BL), +/* 1011 0101 0110 */ TABDECL( OP_BL), +/* 1011 0101 0111 */ TABDECL( OP_BL), +/* 1011 0101 1000 */ TABDECL( OP_BL), +/* 1011 0101 1001 */ TABDECL( OP_BL), +/* 1011 0101 1010 */ TABDECL( OP_BL), +/* 1011 0101 1011 */ TABDECL( OP_BL), +/* 1011 0101 1100 */ TABDECL( OP_BL), +/* 1011 0101 1101 */ TABDECL( OP_BL), +/* 1011 0101 1110 */ TABDECL( OP_BL), +/* 1011 0101 1111 */ TABDECL( OP_BL), +/* 1011 0110 0000 */ TABDECL( OP_BL), +/* 1011 0110 0001 */ TABDECL( OP_BL), +/* 1011 0110 0010 */ TABDECL( OP_BL), +/* 1011 0110 0011 */ TABDECL( OP_BL), +/* 1011 0110 0100 */ TABDECL( OP_BL), +/* 1011 0110 0101 */ TABDECL( OP_BL), +/* 1011 0110 0110 */ TABDECL( OP_BL), +/* 1011 0110 0111 */ TABDECL( OP_BL), +/* 1011 0110 1000 */ TABDECL( OP_BL), +/* 1011 0110 1001 */ TABDECL( OP_BL), +/* 1011 0110 1010 */ TABDECL( OP_BL), +/* 1011 0110 1011 */ TABDECL( OP_BL), +/* 1011 0110 1100 */ TABDECL( OP_BL), +/* 1011 0110 1101 */ TABDECL( OP_BL), +/* 1011 0110 1110 */ TABDECL( OP_BL), +/* 1011 0110 1111 */ TABDECL( OP_BL), +/* 1011 0111 0000 */ TABDECL( OP_BL), +/* 1011 0111 0001 */ TABDECL( OP_BL), +/* 1011 0111 0010 */ TABDECL( OP_BL), +/* 1011 0111 0011 */ TABDECL( OP_BL), +/* 1011 0111 0100 */ TABDECL( OP_BL), +/* 1011 0111 0101 */ TABDECL( OP_BL), +/* 1011 0111 0110 */ TABDECL( OP_BL), +/* 1011 0111 0111 */ TABDECL( OP_BL), +/* 1011 0111 1000 */ TABDECL( OP_BL), +/* 1011 0111 1001 */ TABDECL( OP_BL), +/* 1011 0111 1010 */ TABDECL( OP_BL), +/* 1011 0111 1011 */ TABDECL( OP_BL), +/* 1011 0111 1100 */ TABDECL( OP_BL), +/* 1011 0111 1101 */ TABDECL( OP_BL), +/* 1011 0111 1110 */ TABDECL( OP_BL), +/* 1011 0111 1111 */ TABDECL( OP_BL), +/* 1011 1000 0000 */ TABDECL( OP_BL), +/* 1011 1000 0001 */ TABDECL( OP_BL), +/* 1011 1000 0010 */ TABDECL( OP_BL), +/* 1011 1000 0011 */ TABDECL( OP_BL), +/* 1011 1000 0100 */ TABDECL( OP_BL), +/* 1011 1000 0101 */ TABDECL( OP_BL), +/* 1011 1000 0110 */ TABDECL( OP_BL), +/* 1011 1000 0111 */ TABDECL( OP_BL), +/* 1011 1000 1000 */ TABDECL( OP_BL), +/* 1011 1000 1001 */ TABDECL( OP_BL), +/* 1011 1000 1010 */ TABDECL( OP_BL), +/* 1011 1000 1011 */ TABDECL( OP_BL), +/* 1011 1000 1100 */ TABDECL( OP_BL), +/* 1011 1000 1101 */ TABDECL( OP_BL), +/* 1011 1000 1110 */ TABDECL( OP_BL), +/* 1011 1000 1111 */ TABDECL( OP_BL), +/* 1011 1001 0000 */ TABDECL( OP_BL), +/* 1011 1001 0001 */ TABDECL( OP_BL), +/* 1011 1001 0010 */ TABDECL( OP_BL), +/* 1011 1001 0011 */ TABDECL( OP_BL), +/* 1011 1001 0100 */ TABDECL( OP_BL), +/* 1011 1001 0101 */ TABDECL( OP_BL), +/* 1011 1001 0110 */ TABDECL( OP_BL), +/* 1011 1001 0111 */ TABDECL( OP_BL), +/* 1011 1001 1000 */ TABDECL( OP_BL), +/* 1011 1001 1001 */ TABDECL( OP_BL), +/* 1011 1001 1010 */ TABDECL( OP_BL), +/* 1011 1001 1011 */ TABDECL( OP_BL), +/* 1011 1001 1100 */ TABDECL( OP_BL), +/* 1011 1001 1101 */ TABDECL( OP_BL), +/* 1011 1001 1110 */ TABDECL( OP_BL), +/* 1011 1001 1111 */ TABDECL( OP_BL), +/* 1011 1010 0000 */ TABDECL( OP_BL), +/* 1011 1010 0001 */ TABDECL( OP_BL), +/* 1011 1010 0010 */ TABDECL( OP_BL), +/* 1011 1010 0011 */ TABDECL( OP_BL), +/* 1011 1010 0100 */ TABDECL( OP_BL), +/* 1011 1010 0101 */ TABDECL( OP_BL), +/* 1011 1010 0110 */ TABDECL( OP_BL), +/* 1011 1010 0111 */ TABDECL( OP_BL), +/* 1011 1010 1000 */ TABDECL( OP_BL), +/* 1011 1010 1001 */ TABDECL( OP_BL), +/* 1011 1010 1010 */ TABDECL( OP_BL), +/* 1011 1010 1011 */ TABDECL( OP_BL), +/* 1011 1010 1100 */ TABDECL( OP_BL), +/* 1011 1010 1101 */ TABDECL( OP_BL), +/* 1011 1010 1110 */ TABDECL( OP_BL), +/* 1011 1010 1111 */ TABDECL( OP_BL), +/* 1011 1011 0000 */ TABDECL( OP_BL), +/* 1011 1011 0001 */ TABDECL( OP_BL), +/* 1011 1011 0010 */ TABDECL( OP_BL), +/* 1011 1011 0011 */ TABDECL( OP_BL), +/* 1011 1011 0100 */ TABDECL( OP_BL), +/* 1011 1011 0101 */ TABDECL( OP_BL), +/* 1011 1011 0110 */ TABDECL( OP_BL), +/* 1011 1011 0111 */ TABDECL( OP_BL), +/* 1011 1011 1000 */ TABDECL( OP_BL), +/* 1011 1011 1001 */ TABDECL( OP_BL), +/* 1011 1011 1010 */ TABDECL( OP_BL), +/* 1011 1011 1011 */ TABDECL( OP_BL), +/* 1011 1011 1100 */ TABDECL( OP_BL), +/* 1011 1011 1101 */ TABDECL( OP_BL), +/* 1011 1011 1110 */ TABDECL( OP_BL), +/* 1011 1011 1111 */ TABDECL( OP_BL), +/* 1011 1100 0000 */ TABDECL( OP_BL), +/* 1011 1100 0001 */ TABDECL( OP_BL), +/* 1011 1100 0010 */ TABDECL( OP_BL), +/* 1011 1100 0011 */ TABDECL( OP_BL), +/* 1011 1100 0100 */ TABDECL( OP_BL), +/* 1011 1100 0101 */ TABDECL( OP_BL), +/* 1011 1100 0110 */ TABDECL( OP_BL), +/* 1011 1100 0111 */ TABDECL( OP_BL), +/* 1011 1100 1000 */ TABDECL( OP_BL), +/* 1011 1100 1001 */ TABDECL( OP_BL), +/* 1011 1100 1010 */ TABDECL( OP_BL), +/* 1011 1100 1011 */ TABDECL( OP_BL), +/* 1011 1100 1100 */ TABDECL( OP_BL), +/* 1011 1100 1101 */ TABDECL( OP_BL), +/* 1011 1100 1110 */ TABDECL( OP_BL), +/* 1011 1100 1111 */ TABDECL( OP_BL), +/* 1011 1101 0000 */ TABDECL( OP_BL), +/* 1011 1101 0001 */ TABDECL( OP_BL), +/* 1011 1101 0010 */ TABDECL( OP_BL), +/* 1011 1101 0011 */ TABDECL( OP_BL), +/* 1011 1101 0100 */ TABDECL( OP_BL), +/* 1011 1101 0101 */ TABDECL( OP_BL), +/* 1011 1101 0110 */ TABDECL( OP_BL), +/* 1011 1101 0111 */ TABDECL( OP_BL), +/* 1011 1101 1000 */ TABDECL( OP_BL), +/* 1011 1101 1001 */ TABDECL( OP_BL), +/* 1011 1101 1010 */ TABDECL( OP_BL), +/* 1011 1101 1011 */ TABDECL( OP_BL), +/* 1011 1101 1100 */ TABDECL( OP_BL), +/* 1011 1101 1101 */ TABDECL( OP_BL), +/* 1011 1101 1110 */ TABDECL( OP_BL), +/* 1011 1101 1111 */ TABDECL( OP_BL), +/* 1011 1110 0000 */ TABDECL( OP_BL), +/* 1011 1110 0001 */ TABDECL( OP_BL), +/* 1011 1110 0010 */ TABDECL( OP_BL), +/* 1011 1110 0011 */ TABDECL( OP_BL), +/* 1011 1110 0100 */ TABDECL( OP_BL), +/* 1011 1110 0101 */ TABDECL( OP_BL), +/* 1011 1110 0110 */ TABDECL( OP_BL), +/* 1011 1110 0111 */ TABDECL( OP_BL), +/* 1011 1110 1000 */ TABDECL( OP_BL), +/* 1011 1110 1001 */ TABDECL( OP_BL), +/* 1011 1110 1010 */ TABDECL( OP_BL), +/* 1011 1110 1011 */ TABDECL( OP_BL), +/* 1011 1110 1100 */ TABDECL( OP_BL), +/* 1011 1110 1101 */ TABDECL( OP_BL), +/* 1011 1110 1110 */ TABDECL( OP_BL), +/* 1011 1110 1111 */ TABDECL( OP_BL), +/* 1011 1111 0000 */ TABDECL( OP_BL), +/* 1011 1111 0001 */ TABDECL( OP_BL), +/* 1011 1111 0010 */ TABDECL( OP_BL), +/* 1011 1111 0011 */ TABDECL( OP_BL), +/* 1011 1111 0100 */ TABDECL( OP_BL), +/* 1011 1111 0101 */ TABDECL( OP_BL), +/* 1011 1111 0110 */ TABDECL( OP_BL), +/* 1011 1111 0111 */ TABDECL( OP_BL), +/* 1011 1111 1000 */ TABDECL( OP_BL), +/* 1011 1111 1001 */ TABDECL( OP_BL), +/* 1011 1111 1010 */ TABDECL( OP_BL), +/* 1011 1111 1011 */ TABDECL( OP_BL), +/* 1011 1111 1100 */ TABDECL( OP_BL), +/* 1011 1111 1101 */ TABDECL( OP_BL), +/* 1011 1111 1110 */ TABDECL( OP_BL), +/* 1011 1111 1111 */ TABDECL( OP_BL), +/* 1100 0000 0000 */ TABDECL( OP_STC_OPTION), +/* 1100 0000 0001 */ TABDECL( OP_STC_OPTION), +/* 1100 0000 0010 */ TABDECL( OP_STC_OPTION), +/* 1100 0000 0011 */ TABDECL( OP_STC_OPTION), +/* 1100 0000 0100 */ TABDECL( OP_STC_OPTION), +/* 1100 0000 0101 */ TABDECL( OP_STC_OPTION), +/* 1100 0000 0110 */ TABDECL( OP_STC_OPTION), +/* 1100 0000 0111 */ TABDECL( OP_STC_OPTION), +/* 1100 0000 1000 */ TABDECL( OP_STC_OPTION), +/* 1100 0000 1001 */ TABDECL( OP_STC_OPTION), +/* 1100 0000 1010 */ TABDECL( OP_STC_OPTION), +/* 1100 0000 1011 */ TABDECL( OP_STC_OPTION), +/* 1100 0000 1100 */ TABDECL( OP_STC_OPTION), +/* 1100 0000 1101 */ TABDECL( OP_STC_OPTION), +/* 1100 0000 1110 */ TABDECL( OP_STC_OPTION), +/* 1100 0000 1111 */ TABDECL( OP_STC_OPTION), +/* 1100 0001 0000 */ TABDECL( OP_LDC_OPTION), +/* 1100 0001 0001 */ TABDECL( OP_LDC_OPTION), +/* 1100 0001 0010 */ TABDECL( OP_LDC_OPTION), +/* 1100 0001 0011 */ TABDECL( OP_LDC_OPTION), +/* 1100 0001 0100 */ TABDECL( OP_LDC_OPTION), +/* 1100 0001 0101 */ TABDECL( OP_LDC_OPTION), +/* 1100 0001 0110 */ TABDECL( OP_LDC_OPTION), +/* 1100 0001 0111 */ TABDECL( OP_LDC_OPTION), +/* 1100 0001 1000 */ TABDECL( OP_LDC_OPTION), +/* 1100 0001 1001 */ TABDECL( OP_LDC_OPTION), +/* 1100 0001 1010 */ TABDECL( OP_LDC_OPTION), +/* 1100 0001 1011 */ TABDECL( OP_LDC_OPTION), +/* 1100 0001 1100 */ TABDECL( OP_LDC_OPTION), +/* 1100 0001 1101 */ TABDECL( OP_LDC_OPTION), +/* 1100 0001 1110 */ TABDECL( OP_LDC_OPTION), +/* 1100 0001 1111 */ TABDECL( OP_LDC_OPTION), +/* 1100 0010 0000 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0010 0001 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0010 0010 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0010 0011 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0010 0100 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0010 0101 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0010 0110 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0010 0111 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0010 1000 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0010 1001 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0010 1010 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0010 1011 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0010 1100 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0010 1101 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0010 1110 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0010 1111 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0011 0000 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0011 0001 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0011 0010 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0011 0011 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0011 0100 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0011 0101 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0011 0110 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0011 0111 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0011 1000 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0011 1001 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0011 1010 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0011 1011 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0011 1100 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0011 1101 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0011 1110 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0011 1111 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0100 0000 */ TABDECL( OP_STC_OPTION), +/* 1100 0100 0001 */ TABDECL( OP_STC_OPTION), +/* 1100 0100 0010 */ TABDECL( OP_STC_OPTION), +/* 1100 0100 0011 */ TABDECL( OP_STC_OPTION), +/* 1100 0100 0100 */ TABDECL( OP_STC_OPTION), +/* 1100 0100 0101 */ TABDECL( OP_STC_OPTION), +/* 1100 0100 0110 */ TABDECL( OP_STC_OPTION), +/* 1100 0100 0111 */ TABDECL( OP_STC_OPTION), +/* 1100 0100 1000 */ TABDECL( OP_STC_OPTION), +/* 1100 0100 1001 */ TABDECL( OP_STC_OPTION), +/* 1100 0100 1010 */ TABDECL( OP_STC_OPTION), +/* 1100 0100 1011 */ TABDECL( OP_STC_OPTION), +/* 1100 0100 1100 */ TABDECL( OP_STC_OPTION), +/* 1100 0100 1101 */ TABDECL( OP_STC_OPTION), +/* 1100 0100 1110 */ TABDECL( OP_STC_OPTION), +/* 1100 0100 1111 */ TABDECL( OP_STC_OPTION), +/* 1100 0101 0000 */ TABDECL( OP_LDC_OPTION), +/* 1100 0101 0001 */ TABDECL( OP_LDC_OPTION), +/* 1100 0101 0010 */ TABDECL( OP_LDC_OPTION), +/* 1100 0101 0011 */ TABDECL( OP_LDC_OPTION), +/* 1100 0101 0100 */ TABDECL( OP_LDC_OPTION), +/* 1100 0101 0101 */ TABDECL( OP_LDC_OPTION), +/* 1100 0101 0110 */ TABDECL( OP_LDC_OPTION), +/* 1100 0101 0111 */ TABDECL( OP_LDC_OPTION), +/* 1100 0101 1000 */ TABDECL( OP_LDC_OPTION), +/* 1100 0101 1001 */ TABDECL( OP_LDC_OPTION), +/* 1100 0101 1010 */ TABDECL( OP_LDC_OPTION), +/* 1100 0101 1011 */ TABDECL( OP_LDC_OPTION), +/* 1100 0101 1100 */ TABDECL( OP_LDC_OPTION), +/* 1100 0101 1101 */ TABDECL( OP_LDC_OPTION), +/* 1100 0101 1110 */ TABDECL( OP_LDC_OPTION), +/* 1100 0101 1111 */ TABDECL( OP_LDC_OPTION), +/* 1100 0110 0000 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0110 0001 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0110 0010 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0110 0011 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0110 0100 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0110 0101 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0110 0110 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0110 0111 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0110 1000 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0110 1001 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0110 1010 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0110 1011 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0110 1100 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0110 1101 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0110 1110 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0110 1111 */ TABDECL( OP_STC_M_POSTIND), +/* 1100 0111 0000 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0111 0001 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0111 0010 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0111 0011 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0111 0100 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0111 0101 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0111 0110 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0111 0111 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0111 1000 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0111 1001 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0111 1010 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0111 1011 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0111 1100 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0111 1101 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0111 1110 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 0111 1111 */ TABDECL( OP_LDC_M_POSTIND), +/* 1100 1000 0000 */ TABDECL( OP_STC_OPTION), +/* 1100 1000 0001 */ TABDECL( OP_STC_OPTION), +/* 1100 1000 0010 */ TABDECL( OP_STC_OPTION), +/* 1100 1000 0011 */ TABDECL( OP_STC_OPTION), +/* 1100 1000 0100 */ TABDECL( OP_STC_OPTION), +/* 1100 1000 0101 */ TABDECL( OP_STC_OPTION), +/* 1100 1000 0110 */ TABDECL( OP_STC_OPTION), +/* 1100 1000 0111 */ TABDECL( OP_STC_OPTION), +/* 1100 1000 1000 */ TABDECL( OP_STC_OPTION), +/* 1100 1000 1001 */ TABDECL( OP_STC_OPTION), +/* 1100 1000 1010 */ TABDECL( OP_STC_OPTION), +/* 1100 1000 1011 */ TABDECL( OP_STC_OPTION), +/* 1100 1000 1100 */ TABDECL( OP_STC_OPTION), +/* 1100 1000 1101 */ TABDECL( OP_STC_OPTION), +/* 1100 1000 1110 */ TABDECL( OP_STC_OPTION), +/* 1100 1000 1111 */ TABDECL( OP_STC_OPTION), +/* 1100 1001 0000 */ TABDECL( OP_LDC_OPTION), +/* 1100 1001 0001 */ TABDECL( OP_LDC_OPTION), +/* 1100 1001 0010 */ TABDECL( OP_LDC_OPTION), +/* 1100 1001 0011 */ TABDECL( OP_LDC_OPTION), +/* 1100 1001 0100 */ TABDECL( OP_LDC_OPTION), +/* 1100 1001 0101 */ TABDECL( OP_LDC_OPTION), +/* 1100 1001 0110 */ TABDECL( OP_LDC_OPTION), +/* 1100 1001 0111 */ TABDECL( OP_LDC_OPTION), +/* 1100 1001 1000 */ TABDECL( OP_LDC_OPTION), +/* 1100 1001 1001 */ TABDECL( OP_LDC_OPTION), +/* 1100 1001 1010 */ TABDECL( OP_LDC_OPTION), +/* 1100 1001 1011 */ TABDECL( OP_LDC_OPTION), +/* 1100 1001 1100 */ TABDECL( OP_LDC_OPTION), +/* 1100 1001 1101 */ TABDECL( OP_LDC_OPTION), +/* 1100 1001 1110 */ TABDECL( OP_LDC_OPTION), +/* 1100 1001 1111 */ TABDECL( OP_LDC_OPTION), +/* 1100 1010 0000 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1010 0001 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1010 0010 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1010 0011 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1010 0100 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1010 0101 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1010 0110 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1010 0111 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1010 1000 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1010 1001 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1010 1010 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1010 1011 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1010 1100 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1010 1101 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1010 1110 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1010 1111 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1011 0000 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1011 0001 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1011 0010 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1011 0011 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1011 0100 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1011 0101 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1011 0110 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1011 0111 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1011 1000 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1011 1001 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1011 1010 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1011 1011 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1011 1100 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1011 1101 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1011 1110 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1011 1111 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1100 0000 */ TABDECL( OP_STC_OPTION), +/* 1100 1100 0001 */ TABDECL( OP_STC_OPTION), +/* 1100 1100 0010 */ TABDECL( OP_STC_OPTION), +/* 1100 1100 0011 */ TABDECL( OP_STC_OPTION), +/* 1100 1100 0100 */ TABDECL( OP_STC_OPTION), +/* 1100 1100 0101 */ TABDECL( OP_STC_OPTION), +/* 1100 1100 0110 */ TABDECL( OP_STC_OPTION), +/* 1100 1100 0111 */ TABDECL( OP_STC_OPTION), +/* 1100 1100 1000 */ TABDECL( OP_STC_OPTION), +/* 1100 1100 1001 */ TABDECL( OP_STC_OPTION), +/* 1100 1100 1010 */ TABDECL( OP_STC_OPTION), +/* 1100 1100 1011 */ TABDECL( OP_STC_OPTION), +/* 1100 1100 1100 */ TABDECL( OP_STC_OPTION), +/* 1100 1100 1101 */ TABDECL( OP_STC_OPTION), +/* 1100 1100 1110 */ TABDECL( OP_STC_OPTION), +/* 1100 1100 1111 */ TABDECL( OP_STC_OPTION), +/* 1100 1101 0000 */ TABDECL( OP_LDC_OPTION), +/* 1100 1101 0001 */ TABDECL( OP_LDC_OPTION), +/* 1100 1101 0010 */ TABDECL( OP_LDC_OPTION), +/* 1100 1101 0011 */ TABDECL( OP_LDC_OPTION), +/* 1100 1101 0100 */ TABDECL( OP_LDC_OPTION), +/* 1100 1101 0101 */ TABDECL( OP_LDC_OPTION), +/* 1100 1101 0110 */ TABDECL( OP_LDC_OPTION), +/* 1100 1101 0111 */ TABDECL( OP_LDC_OPTION), +/* 1100 1101 1000 */ TABDECL( OP_LDC_OPTION), +/* 1100 1101 1001 */ TABDECL( OP_LDC_OPTION), +/* 1100 1101 1010 */ TABDECL( OP_LDC_OPTION), +/* 1100 1101 1011 */ TABDECL( OP_LDC_OPTION), +/* 1100 1101 1100 */ TABDECL( OP_LDC_OPTION), +/* 1100 1101 1101 */ TABDECL( OP_LDC_OPTION), +/* 1100 1101 1110 */ TABDECL( OP_LDC_OPTION), +/* 1100 1101 1111 */ TABDECL( OP_LDC_OPTION), +/* 1100 1110 0000 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1110 0001 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1110 0010 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1110 0011 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1110 0100 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1110 0101 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1110 0110 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1110 0111 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1110 1000 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1110 1001 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1110 1010 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1110 1011 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1110 1100 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1110 1101 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1110 1110 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1110 1111 */ TABDECL( OP_STC_P_POSTIND), +/* 1100 1111 0000 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1111 0001 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1111 0010 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1111 0011 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1111 0100 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1111 0101 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1111 0110 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1111 0111 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1111 1000 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1111 1001 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1111 1010 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1111 1011 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1111 1100 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1111 1101 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1111 1110 */ TABDECL( OP_LDC_P_POSTIND), +/* 1100 1111 1111 */ TABDECL( OP_LDC_P_POSTIND), +/* 1101 0000 0000 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0000 0001 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0000 0010 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0000 0011 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0000 0100 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0000 0101 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0000 0110 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0000 0111 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0000 1000 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0000 1001 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0000 1010 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0000 1011 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0000 1100 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0000 1101 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0000 1110 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0000 1111 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0001 0000 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0001 0001 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0001 0010 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0001 0011 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0001 0100 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0001 0101 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0001 0110 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0001 0111 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0001 1000 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0001 1001 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0001 1010 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0001 1011 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0001 1100 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0001 1101 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0001 1110 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0001 1111 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0010 0000 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0010 0001 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0010 0010 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0010 0011 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0010 0100 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0010 0101 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0010 0110 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0010 0111 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0010 1000 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0010 1001 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0010 1010 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0010 1011 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0010 1100 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0010 1101 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0010 1110 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0010 1111 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0011 0000 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0011 0001 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0011 0010 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0011 0011 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0011 0100 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0011 0101 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0011 0110 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0011 0111 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0011 1000 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0011 1001 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0011 1010 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0011 1011 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0011 1100 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0011 1101 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0011 1110 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0011 1111 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0100 0000 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0100 0001 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0100 0010 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0100 0011 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0100 0100 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0100 0101 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0100 0110 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0100 0111 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0100 1000 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0100 1001 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0100 1010 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0100 1011 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0100 1100 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0100 1101 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0100 1110 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0100 1111 */ TABDECL( OP_STC_M_IMM_OFF), +/* 1101 0101 0000 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0101 0001 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0101 0010 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0101 0011 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0101 0100 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0101 0101 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0101 0110 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0101 0111 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0101 1000 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0101 1001 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0101 1010 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0101 1011 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0101 1100 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0101 1101 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0101 1110 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0101 1111 */ TABDECL( OP_LDC_M_IMM_OFF), +/* 1101 0110 0000 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0110 0001 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0110 0010 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0110 0011 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0110 0100 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0110 0101 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0110 0110 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0110 0111 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0110 1000 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0110 1001 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0110 1010 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0110 1011 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0110 1100 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0110 1101 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0110 1110 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0110 1111 */ TABDECL( OP_STC_M_PREIND), +/* 1101 0111 0000 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0111 0001 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0111 0010 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0111 0011 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0111 0100 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0111 0101 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0111 0110 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0111 0111 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0111 1000 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0111 1001 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0111 1010 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0111 1011 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0111 1100 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0111 1101 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0111 1110 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 0111 1111 */ TABDECL( OP_LDC_M_PREIND), +/* 1101 1000 0000 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1000 0001 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1000 0010 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1000 0011 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1000 0100 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1000 0101 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1000 0110 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1000 0111 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1000 1000 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1000 1001 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1000 1010 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1000 1011 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1000 1100 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1000 1101 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1000 1110 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1000 1111 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1001 0000 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1001 0001 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1001 0010 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1001 0011 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1001 0100 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1001 0101 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1001 0110 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1001 0111 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1001 1000 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1001 1001 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1001 1010 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1001 1011 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1001 1100 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1001 1101 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1001 1110 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1001 1111 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1010 0000 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1010 0001 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1010 0010 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1010 0011 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1010 0100 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1010 0101 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1010 0110 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1010 0111 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1010 1000 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1010 1001 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1010 1010 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1010 1011 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1010 1100 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1010 1101 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1010 1110 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1010 1111 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1011 0000 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1011 0001 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1011 0010 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1011 0011 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1011 0100 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1011 0101 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1011 0110 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1011 0111 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1011 1000 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1011 1001 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1011 1010 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1011 1011 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1011 1100 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1011 1101 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1011 1110 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1011 1111 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1100 0000 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1100 0001 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1100 0010 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1100 0011 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1100 0100 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1100 0101 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1100 0110 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1100 0111 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1100 1000 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1100 1001 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1100 1010 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1100 1011 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1100 1100 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1100 1101 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1100 1110 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1100 1111 */ TABDECL( OP_STC_P_IMM_OFF), +/* 1101 1101 0000 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1101 0001 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1101 0010 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1101 0011 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1101 0100 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1101 0101 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1101 0110 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1101 0111 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1101 1000 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1101 1001 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1101 1010 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1101 1011 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1101 1100 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1101 1101 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1101 1110 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1101 1111 */ TABDECL( OP_LDC_P_IMM_OFF), +/* 1101 1110 0000 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1110 0001 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1110 0010 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1110 0011 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1110 0100 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1110 0101 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1110 0110 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1110 0111 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1110 1000 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1110 1001 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1110 1010 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1110 1011 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1110 1100 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1110 1101 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1110 1110 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1110 1111 */ TABDECL( OP_STC_P_PREIND), +/* 1101 1111 0000 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1111 0001 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1111 0010 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1111 0011 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1111 0100 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1111 0101 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1111 0110 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1111 0111 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1111 1000 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1111 1001 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1111 1010 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1111 1011 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1111 1100 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1111 1101 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1111 1110 */ TABDECL( OP_LDC_P_PREIND), +/* 1101 1111 1111 */ TABDECL( OP_LDC_P_PREIND), +/* 1110 0000 0000 */ TABDECL( OP_CDP), +/* 1110 0000 0001 */ TABDECL( OP_MCR), +/* 1110 0000 0010 */ TABDECL( OP_CDP), +/* 1110 0000 0011 */ TABDECL( OP_MCR), +/* 1110 0000 0100 */ TABDECL( OP_CDP), +/* 1110 0000 0101 */ TABDECL( OP_MCR), +/* 1110 0000 0110 */ TABDECL( OP_CDP), +/* 1110 0000 0111 */ TABDECL( OP_MCR), +/* 1110 0000 1000 */ TABDECL( OP_CDP), +/* 1110 0000 1001 */ TABDECL( OP_MCR), +/* 1110 0000 1010 */ TABDECL( OP_CDP), +/* 1110 0000 1011 */ TABDECL( OP_MCR), +/* 1110 0000 1100 */ TABDECL( OP_CDP), +/* 1110 0000 1101 */ TABDECL( OP_MCR), +/* 1110 0000 1110 */ TABDECL( OP_CDP), +/* 1110 0000 1111 */ TABDECL( OP_MCR), +/* 1110 0001 0000 */ TABDECL( OP_CDP), +/* 1110 0001 0001 */ TABDECL( OP_MRC), +/* 1110 0001 0010 */ TABDECL( OP_CDP), +/* 1110 0001 0011 */ TABDECL( OP_MRC), +/* 1110 0001 0100 */ TABDECL( OP_CDP), +/* 1110 0001 0101 */ TABDECL( OP_MRC), +/* 1110 0001 0110 */ TABDECL( OP_CDP), +/* 1110 0001 0111 */ TABDECL( OP_MRC), +/* 1110 0001 1000 */ TABDECL( OP_CDP), +/* 1110 0001 1001 */ TABDECL( OP_MRC), +/* 1110 0001 1010 */ TABDECL( OP_CDP), +/* 1110 0001 1011 */ TABDECL( OP_MRC), +/* 1110 0001 1100 */ TABDECL( OP_CDP), +/* 1110 0001 1101 */ TABDECL( OP_MRC), +/* 1110 0001 1110 */ TABDECL( OP_CDP), +/* 1110 0001 1111 */ TABDECL( OP_MRC), +/* 1110 0010 0000 */ TABDECL( OP_CDP), +/* 1110 0010 0001 */ TABDECL( OP_MCR), +/* 1110 0010 0010 */ TABDECL( OP_CDP), +/* 1110 0010 0011 */ TABDECL( OP_MCR), +/* 1110 0010 0100 */ TABDECL( OP_CDP), +/* 1110 0010 0101 */ TABDECL( OP_MCR), +/* 1110 0010 0110 */ TABDECL( OP_CDP), +/* 1110 0010 0111 */ TABDECL( OP_MCR), +/* 1110 0010 1000 */ TABDECL( OP_CDP), +/* 1110 0010 1001 */ TABDECL( OP_MCR), +/* 1110 0010 1010 */ TABDECL( OP_CDP), +/* 1110 0010 1011 */ TABDECL( OP_MCR), +/* 1110 0010 1100 */ TABDECL( OP_CDP), +/* 1110 0010 1101 */ TABDECL( OP_MCR), +/* 1110 0010 1110 */ TABDECL( OP_CDP), +/* 1110 0010 1111 */ TABDECL( OP_MCR), +/* 1110 0011 0000 */ TABDECL( OP_CDP), +/* 1110 0011 0001 */ TABDECL( OP_MRC), +/* 1110 0011 0010 */ TABDECL( OP_CDP), +/* 1110 0011 0011 */ TABDECL( OP_MRC), +/* 1110 0011 0100 */ TABDECL( OP_CDP), +/* 1110 0011 0101 */ TABDECL( OP_MRC), +/* 1110 0011 0110 */ TABDECL( OP_CDP), +/* 1110 0011 0111 */ TABDECL( OP_MRC), +/* 1110 0011 1000 */ TABDECL( OP_CDP), +/* 1110 0011 1001 */ TABDECL( OP_MRC), +/* 1110 0011 1010 */ TABDECL( OP_CDP), +/* 1110 0011 1011 */ TABDECL( OP_MRC), +/* 1110 0011 1100 */ TABDECL( OP_CDP), +/* 1110 0011 1101 */ TABDECL( OP_MRC), +/* 1110 0011 1110 */ TABDECL( OP_CDP), +/* 1110 0011 1111 */ TABDECL( OP_MRC), +/* 1110 0100 0000 */ TABDECL( OP_CDP), +/* 1110 0100 0001 */ TABDECL( OP_MCR), +/* 1110 0100 0010 */ TABDECL( OP_CDP), +/* 1110 0100 0011 */ TABDECL( OP_MCR), +/* 1110 0100 0100 */ TABDECL( OP_CDP), +/* 1110 0100 0101 */ TABDECL( OP_MCR), +/* 1110 0100 0110 */ TABDECL( OP_CDP), +/* 1110 0100 0111 */ TABDECL( OP_MCR), +/* 1110 0100 1000 */ TABDECL( OP_CDP), +/* 1110 0100 1001 */ TABDECL( OP_MCR), +/* 1110 0100 1010 */ TABDECL( OP_CDP), +/* 1110 0100 1011 */ TABDECL( OP_MCR), +/* 1110 0100 1100 */ TABDECL( OP_CDP), +/* 1110 0100 1101 */ TABDECL( OP_MCR), +/* 1110 0100 1110 */ TABDECL( OP_CDP), +/* 1110 0100 1111 */ TABDECL( OP_MCR), +/* 1110 0101 0000 */ TABDECL( OP_CDP), +/* 1110 0101 0001 */ TABDECL( OP_MRC), +/* 1110 0101 0010 */ TABDECL( OP_CDP), +/* 1110 0101 0011 */ TABDECL( OP_MRC), +/* 1110 0101 0100 */ TABDECL( OP_CDP), +/* 1110 0101 0101 */ TABDECL( OP_MRC), +/* 1110 0101 0110 */ TABDECL( OP_CDP), +/* 1110 0101 0111 */ TABDECL( OP_MRC), +/* 1110 0101 1000 */ TABDECL( OP_CDP), +/* 1110 0101 1001 */ TABDECL( OP_MRC), +/* 1110 0101 1010 */ TABDECL( OP_CDP), +/* 1110 0101 1011 */ TABDECL( OP_MRC), +/* 1110 0101 1100 */ TABDECL( OP_CDP), +/* 1110 0101 1101 */ TABDECL( OP_MRC), +/* 1110 0101 1110 */ TABDECL( OP_CDP), +/* 1110 0101 1111 */ TABDECL( OP_MRC), +/* 1110 0110 0000 */ TABDECL( OP_CDP), +/* 1110 0110 0001 */ TABDECL( OP_MCR), +/* 1110 0110 0010 */ TABDECL( OP_CDP), +/* 1110 0110 0011 */ TABDECL( OP_MCR), +/* 1110 0110 0100 */ TABDECL( OP_CDP), +/* 1110 0110 0101 */ TABDECL( OP_MCR), +/* 1110 0110 0110 */ TABDECL( OP_CDP), +/* 1110 0110 0111 */ TABDECL( OP_MCR), +/* 1110 0110 1000 */ TABDECL( OP_CDP), +/* 1110 0110 1001 */ TABDECL( OP_MCR), +/* 1110 0110 1010 */ TABDECL( OP_CDP), +/* 1110 0110 1011 */ TABDECL( OP_MCR), +/* 1110 0110 1100 */ TABDECL( OP_CDP), +/* 1110 0110 1101 */ TABDECL( OP_MCR), +/* 1110 0110 1110 */ TABDECL( OP_CDP), +/* 1110 0110 1111 */ TABDECL( OP_MCR), +/* 1110 0111 0000 */ TABDECL( OP_CDP), +/* 1110 0111 0001 */ TABDECL( OP_MRC), +/* 1110 0111 0010 */ TABDECL( OP_CDP), +/* 1110 0111 0011 */ TABDECL( OP_MRC), +/* 1110 0111 0100 */ TABDECL( OP_CDP), +/* 1110 0111 0101 */ TABDECL( OP_MRC), +/* 1110 0111 0110 */ TABDECL( OP_CDP), +/* 1110 0111 0111 */ TABDECL( OP_MRC), +/* 1110 0111 1000 */ TABDECL( OP_CDP), +/* 1110 0111 1001 */ TABDECL( OP_MRC), +/* 1110 0111 1010 */ TABDECL( OP_CDP), +/* 1110 0111 1011 */ TABDECL( OP_MRC), +/* 1110 0111 1100 */ TABDECL( OP_CDP), +/* 1110 0111 1101 */ TABDECL( OP_MRC), +/* 1110 0111 1110 */ TABDECL( OP_CDP), +/* 1110 0111 1111 */ TABDECL( OP_MRC), +/* 1110 1000 0000 */ TABDECL( OP_CDP), +/* 1110 1000 0001 */ TABDECL( OP_MCR), +/* 1110 1000 0010 */ TABDECL( OP_CDP), +/* 1110 1000 0011 */ TABDECL( OP_MCR), +/* 1110 1000 0100 */ TABDECL( OP_CDP), +/* 1110 1000 0101 */ TABDECL( OP_MCR), +/* 1110 1000 0110 */ TABDECL( OP_CDP), +/* 1110 1000 0111 */ TABDECL( OP_MCR), +/* 1110 1000 1000 */ TABDECL( OP_CDP), +/* 1110 1000 1001 */ TABDECL( OP_MCR), +/* 1110 1000 1010 */ TABDECL( OP_CDP), +/* 1110 1000 1011 */ TABDECL( OP_MCR), +/* 1110 1000 1100 */ TABDECL( OP_CDP), +/* 1110 1000 1101 */ TABDECL( OP_MCR), +/* 1110 1000 1110 */ TABDECL( OP_CDP), +/* 1110 1000 1111 */ TABDECL( OP_MCR), +/* 1110 1001 0000 */ TABDECL( OP_CDP), +/* 1110 1001 0001 */ TABDECL( OP_MRC), +/* 1110 1001 0010 */ TABDECL( OP_CDP), +/* 1110 1001 0011 */ TABDECL( OP_MRC), +/* 1110 1001 0100 */ TABDECL( OP_CDP), +/* 1110 1001 0101 */ TABDECL( OP_MRC), +/* 1110 1001 0110 */ TABDECL( OP_CDP), +/* 1110 1001 0111 */ TABDECL( OP_MRC), +/* 1110 1001 1000 */ TABDECL( OP_CDP), +/* 1110 1001 1001 */ TABDECL( OP_MRC), +/* 1110 1001 1010 */ TABDECL( OP_CDP), +/* 1110 1001 1011 */ TABDECL( OP_MRC), +/* 1110 1001 1100 */ TABDECL( OP_CDP), +/* 1110 1001 1101 */ TABDECL( OP_MRC), +/* 1110 1001 1110 */ TABDECL( OP_CDP), +/* 1110 1001 1111 */ TABDECL( OP_MRC), +/* 1110 1010 0000 */ TABDECL( OP_CDP), +/* 1110 1010 0001 */ TABDECL( OP_MCR), +/* 1110 1010 0010 */ TABDECL( OP_CDP), +/* 1110 1010 0011 */ TABDECL( OP_MCR), +/* 1110 1010 0100 */ TABDECL( OP_CDP), +/* 1110 1010 0101 */ TABDECL( OP_MCR), +/* 1110 1010 0110 */ TABDECL( OP_CDP), +/* 1110 1010 0111 */ TABDECL( OP_MCR), +/* 1110 1010 1000 */ TABDECL( OP_CDP), +/* 1110 1010 1001 */ TABDECL( OP_MCR), +/* 1110 1010 1010 */ TABDECL( OP_CDP), +/* 1110 1010 1011 */ TABDECL( OP_MCR), +/* 1110 1010 1100 */ TABDECL( OP_CDP), +/* 1110 1010 1101 */ TABDECL( OP_MCR), +/* 1110 1010 1110 */ TABDECL( OP_CDP), +/* 1110 1010 1111 */ TABDECL( OP_MCR), +/* 1110 1011 0000 */ TABDECL( OP_CDP), +/* 1110 1011 0001 */ TABDECL( OP_MRC), +/* 1110 1011 0010 */ TABDECL( OP_CDP), +/* 1110 1011 0011 */ TABDECL( OP_MRC), +/* 1110 1011 0100 */ TABDECL( OP_CDP), +/* 1110 1011 0101 */ TABDECL( OP_MRC), +/* 1110 1011 0110 */ TABDECL( OP_CDP), +/* 1110 1011 0111 */ TABDECL( OP_MRC), +/* 1110 1011 1000 */ TABDECL( OP_CDP), +/* 1110 1011 1001 */ TABDECL( OP_MRC), +/* 1110 1011 1010 */ TABDECL( OP_CDP), +/* 1110 1011 1011 */ TABDECL( OP_MRC), +/* 1110 1011 1100 */ TABDECL( OP_CDP), +/* 1110 1011 1101 */ TABDECL( OP_MRC), +/* 1110 1011 1110 */ TABDECL( OP_CDP), +/* 1110 1011 1111 */ TABDECL( OP_MRC), +/* 1110 1100 0000 */ TABDECL( OP_CDP), +/* 1110 1100 0001 */ TABDECL( OP_MCR), +/* 1110 1100 0010 */ TABDECL( OP_CDP), +/* 1110 1100 0011 */ TABDECL( OP_MCR), +/* 1110 1100 0100 */ TABDECL( OP_CDP), +/* 1110 1100 0101 */ TABDECL( OP_MCR), +/* 1110 1100 0110 */ TABDECL( OP_CDP), +/* 1110 1100 0111 */ TABDECL( OP_MCR), +/* 1110 1100 1000 */ TABDECL( OP_CDP), +/* 1110 1100 1001 */ TABDECL( OP_MCR), +/* 1110 1100 1010 */ TABDECL( OP_CDP), +/* 1110 1100 1011 */ TABDECL( OP_MCR), +/* 1110 1100 1100 */ TABDECL( OP_CDP), +/* 1110 1100 1101 */ TABDECL( OP_MCR), +/* 1110 1100 1110 */ TABDECL( OP_CDP), +/* 1110 1100 1111 */ TABDECL( OP_MCR), +/* 1110 1101 0000 */ TABDECL( OP_CDP), +/* 1110 1101 0001 */ TABDECL( OP_MRC), +/* 1110 1101 0010 */ TABDECL( OP_CDP), +/* 1110 1101 0011 */ TABDECL( OP_MRC), +/* 1110 1101 0100 */ TABDECL( OP_CDP), +/* 1110 1101 0101 */ TABDECL( OP_MRC), +/* 1110 1101 0110 */ TABDECL( OP_CDP), +/* 1110 1101 0111 */ TABDECL( OP_MRC), +/* 1110 1101 1000 */ TABDECL( OP_CDP), +/* 1110 1101 1001 */ TABDECL( OP_MRC), +/* 1110 1101 1010 */ TABDECL( OP_CDP), +/* 1110 1101 1011 */ TABDECL( OP_MRC), +/* 1110 1101 1100 */ TABDECL( OP_CDP), +/* 1110 1101 1101 */ TABDECL( OP_MRC), +/* 1110 1101 1110 */ TABDECL( OP_CDP), +/* 1110 1101 1111 */ TABDECL( OP_MRC), +/* 1110 1110 0000 */ TABDECL( OP_CDP), +/* 1110 1110 0001 */ TABDECL( OP_MCR), +/* 1110 1110 0010 */ TABDECL( OP_CDP), +/* 1110 1110 0011 */ TABDECL( OP_MCR), +/* 1110 1110 0100 */ TABDECL( OP_CDP), +/* 1110 1110 0101 */ TABDECL( OP_MCR), +/* 1110 1110 0110 */ TABDECL( OP_CDP), +/* 1110 1110 0111 */ TABDECL( OP_MCR), +/* 1110 1110 1000 */ TABDECL( OP_CDP), +/* 1110 1110 1001 */ TABDECL( OP_MCR), +/* 1110 1110 1010 */ TABDECL( OP_CDP), +/* 1110 1110 1011 */ TABDECL( OP_MCR), +/* 1110 1110 1100 */ TABDECL( OP_CDP), +/* 1110 1110 1101 */ TABDECL( OP_MCR), +/* 1110 1110 1110 */ TABDECL( OP_CDP), +/* 1110 1110 1111 */ TABDECL( OP_MCR), +/* 1110 1111 0000 */ TABDECL( OP_CDP), +/* 1110 1111 0001 */ TABDECL( OP_MRC), +/* 1110 1111 0010 */ TABDECL( OP_CDP), +/* 1110 1111 0011 */ TABDECL( OP_MRC), +/* 1110 1111 0100 */ TABDECL( OP_CDP), +/* 1110 1111 0101 */ TABDECL( OP_MRC), +/* 1110 1111 0110 */ TABDECL( OP_CDP), +/* 1110 1111 0111 */ TABDECL( OP_MRC), +/* 1110 1111 1000 */ TABDECL( OP_CDP), +/* 1110 1111 1001 */ TABDECL( OP_MRC), +/* 1110 1111 1010 */ TABDECL( OP_CDP), +/* 1110 1111 1011 */ TABDECL( OP_MRC), +/* 1110 1111 1100 */ TABDECL( OP_CDP), +/* 1110 1111 1101 */ TABDECL( OP_MRC), +/* 1110 1111 1110 */ TABDECL( OP_CDP), +/* 1110 1111 1111 */ TABDECL( OP_MRC), +/* 1111 0000 0000 */ TABDECL( OP_SWI), +/* 1111 0000 0001 */ TABDECL( OP_SWI), +/* 1111 0000 0010 */ TABDECL( OP_SWI), +/* 1111 0000 0011 */ TABDECL( OP_SWI), +/* 1111 0000 0100 */ TABDECL( OP_SWI), +/* 1111 0000 0101 */ TABDECL( OP_SWI), +/* 1111 0000 0110 */ TABDECL( OP_SWI), +/* 1111 0000 0111 */ TABDECL( OP_SWI), +/* 1111 0000 1000 */ TABDECL( OP_SWI), +/* 1111 0000 1001 */ TABDECL( OP_SWI), +/* 1111 0000 1010 */ TABDECL( OP_SWI), +/* 1111 0000 1011 */ TABDECL( OP_SWI), +/* 1111 0000 1100 */ TABDECL( OP_SWI), +/* 1111 0000 1101 */ TABDECL( OP_SWI), +/* 1111 0000 1110 */ TABDECL( OP_SWI), +/* 1111 0000 1111 */ TABDECL( OP_SWI), +/* 1111 0001 0000 */ TABDECL( OP_SWI), +/* 1111 0001 0001 */ TABDECL( OP_SWI), +/* 1111 0001 0010 */ TABDECL( OP_SWI), +/* 1111 0001 0011 */ TABDECL( OP_SWI), +/* 1111 0001 0100 */ TABDECL( OP_SWI), +/* 1111 0001 0101 */ TABDECL( OP_SWI), +/* 1111 0001 0110 */ TABDECL( OP_SWI), +/* 1111 0001 0111 */ TABDECL( OP_SWI), +/* 1111 0001 1000 */ TABDECL( OP_SWI), +/* 1111 0001 1001 */ TABDECL( OP_SWI), +/* 1111 0001 1010 */ TABDECL( OP_SWI), +/* 1111 0001 1011 */ TABDECL( OP_SWI), +/* 1111 0001 1100 */ TABDECL( OP_SWI), +/* 1111 0001 1101 */ TABDECL( OP_SWI), +/* 1111 0001 1110 */ TABDECL( OP_SWI), +/* 1111 0001 1111 */ TABDECL( OP_SWI), +/* 1111 0010 0000 */ TABDECL( OP_SWI), +/* 1111 0010 0001 */ TABDECL( OP_SWI), +/* 1111 0010 0010 */ TABDECL( OP_SWI), +/* 1111 0010 0011 */ TABDECL( OP_SWI), +/* 1111 0010 0100 */ TABDECL( OP_SWI), +/* 1111 0010 0101 */ TABDECL( OP_SWI), +/* 1111 0010 0110 */ TABDECL( OP_SWI), +/* 1111 0010 0111 */ TABDECL( OP_SWI), +/* 1111 0010 1000 */ TABDECL( OP_SWI), +/* 1111 0010 1001 */ TABDECL( OP_SWI), +/* 1111 0010 1010 */ TABDECL( OP_SWI), +/* 1111 0010 1011 */ TABDECL( OP_SWI), +/* 1111 0010 1100 */ TABDECL( OP_SWI), +/* 1111 0010 1101 */ TABDECL( OP_SWI), +/* 1111 0010 1110 */ TABDECL( OP_SWI), +/* 1111 0010 1111 */ TABDECL( OP_SWI), +/* 1111 0011 0000 */ TABDECL( OP_SWI), +/* 1111 0011 0001 */ TABDECL( OP_SWI), +/* 1111 0011 0010 */ TABDECL( OP_SWI), +/* 1111 0011 0011 */ TABDECL( OP_SWI), +/* 1111 0011 0100 */ TABDECL( OP_SWI), +/* 1111 0011 0101 */ TABDECL( OP_SWI), +/* 1111 0011 0110 */ TABDECL( OP_SWI), +/* 1111 0011 0111 */ TABDECL( OP_SWI), +/* 1111 0011 1000 */ TABDECL( OP_SWI), +/* 1111 0011 1001 */ TABDECL( OP_SWI), +/* 1111 0011 1010 */ TABDECL( OP_SWI), +/* 1111 0011 1011 */ TABDECL( OP_SWI), +/* 1111 0011 1100 */ TABDECL( OP_SWI), +/* 1111 0011 1101 */ TABDECL( OP_SWI), +/* 1111 0011 1110 */ TABDECL( OP_SWI), +/* 1111 0011 1111 */ TABDECL( OP_SWI), +/* 1111 0100 0000 */ TABDECL( OP_SWI), +/* 1111 0100 0001 */ TABDECL( OP_SWI), +/* 1111 0100 0010 */ TABDECL( OP_SWI), +/* 1111 0100 0011 */ TABDECL( OP_SWI), +/* 1111 0100 0100 */ TABDECL( OP_SWI), +/* 1111 0100 0101 */ TABDECL( OP_SWI), +/* 1111 0100 0110 */ TABDECL( OP_SWI), +/* 1111 0100 0111 */ TABDECL( OP_SWI), +/* 1111 0100 1000 */ TABDECL( OP_SWI), +/* 1111 0100 1001 */ TABDECL( OP_SWI), +/* 1111 0100 1010 */ TABDECL( OP_SWI), +/* 1111 0100 1011 */ TABDECL( OP_SWI), +/* 1111 0100 1100 */ TABDECL( OP_SWI), +/* 1111 0100 1101 */ TABDECL( OP_SWI), +/* 1111 0100 1110 */ TABDECL( OP_SWI), +/* 1111 0100 1111 */ TABDECL( OP_SWI), +/* 1111 0101 0000 */ TABDECL( OP_SWI), +/* 1111 0101 0001 */ TABDECL( OP_SWI), +/* 1111 0101 0010 */ TABDECL( OP_SWI), +/* 1111 0101 0011 */ TABDECL( OP_SWI), +/* 1111 0101 0100 */ TABDECL( OP_SWI), +/* 1111 0101 0101 */ TABDECL( OP_SWI), +/* 1111 0101 0110 */ TABDECL( OP_SWI), +/* 1111 0101 0111 */ TABDECL( OP_SWI), +/* 1111 0101 1000 */ TABDECL( OP_SWI), +/* 1111 0101 1001 */ TABDECL( OP_SWI), +/* 1111 0101 1010 */ TABDECL( OP_SWI), +/* 1111 0101 1011 */ TABDECL( OP_SWI), +/* 1111 0101 1100 */ TABDECL( OP_SWI), +/* 1111 0101 1101 */ TABDECL( OP_SWI), +/* 1111 0101 1110 */ TABDECL( OP_SWI), +/* 1111 0101 1111 */ TABDECL( OP_SWI), +/* 1111 0110 0000 */ TABDECL( OP_SWI), +/* 1111 0110 0001 */ TABDECL( OP_SWI), +/* 1111 0110 0010 */ TABDECL( OP_SWI), +/* 1111 0110 0011 */ TABDECL( OP_SWI), +/* 1111 0110 0100 */ TABDECL( OP_SWI), +/* 1111 0110 0101 */ TABDECL( OP_SWI), +/* 1111 0110 0110 */ TABDECL( OP_SWI), +/* 1111 0110 0111 */ TABDECL( OP_SWI), +/* 1111 0110 1000 */ TABDECL( OP_SWI), +/* 1111 0110 1001 */ TABDECL( OP_SWI), +/* 1111 0110 1010 */ TABDECL( OP_SWI), +/* 1111 0110 1011 */ TABDECL( OP_SWI), +/* 1111 0110 1100 */ TABDECL( OP_SWI), +/* 1111 0110 1101 */ TABDECL( OP_SWI), +/* 1111 0110 1110 */ TABDECL( OP_SWI), +/* 1111 0110 1111 */ TABDECL( OP_SWI), +/* 1111 0111 0000 */ TABDECL( OP_SWI), +/* 1111 0111 0001 */ TABDECL( OP_SWI), +/* 1111 0111 0010 */ TABDECL( OP_SWI), +/* 1111 0111 0011 */ TABDECL( OP_SWI), +/* 1111 0111 0100 */ TABDECL( OP_SWI), +/* 1111 0111 0101 */ TABDECL( OP_SWI), +/* 1111 0111 0110 */ TABDECL( OP_SWI), +/* 1111 0111 0111 */ TABDECL( OP_SWI), +/* 1111 0111 1000 */ TABDECL( OP_SWI), +/* 1111 0111 1001 */ TABDECL( OP_SWI), +/* 1111 0111 1010 */ TABDECL( OP_SWI), +/* 1111 0111 1011 */ TABDECL( OP_SWI), +/* 1111 0111 1100 */ TABDECL( OP_SWI), +/* 1111 0111 1101 */ TABDECL( OP_SWI), +/* 1111 0111 1110 */ TABDECL( OP_SWI), +/* 1111 0111 1111 */ TABDECL( OP_SWI), +/* 1111 1000 0000 */ TABDECL( OP_SWI), +/* 1111 1000 0001 */ TABDECL( OP_SWI), +/* 1111 1000 0010 */ TABDECL( OP_SWI), +/* 1111 1000 0011 */ TABDECL( OP_SWI), +/* 1111 1000 0100 */ TABDECL( OP_SWI), +/* 1111 1000 0101 */ TABDECL( OP_SWI), +/* 1111 1000 0110 */ TABDECL( OP_SWI), +/* 1111 1000 0111 */ TABDECL( OP_SWI), +/* 1111 1000 1000 */ TABDECL( OP_SWI), +/* 1111 1000 1001 */ TABDECL( OP_SWI), +/* 1111 1000 1010 */ TABDECL( OP_SWI), +/* 1111 1000 1011 */ TABDECL( OP_SWI), +/* 1111 1000 1100 */ TABDECL( OP_SWI), +/* 1111 1000 1101 */ TABDECL( OP_SWI), +/* 1111 1000 1110 */ TABDECL( OP_SWI), +/* 1111 1000 1111 */ TABDECL( OP_SWI), +/* 1111 1001 0000 */ TABDECL( OP_SWI), +/* 1111 1001 0001 */ TABDECL( OP_SWI), +/* 1111 1001 0010 */ TABDECL( OP_SWI), +/* 1111 1001 0011 */ TABDECL( OP_SWI), +/* 1111 1001 0100 */ TABDECL( OP_SWI), +/* 1111 1001 0101 */ TABDECL( OP_SWI), +/* 1111 1001 0110 */ TABDECL( OP_SWI), +/* 1111 1001 0111 */ TABDECL( OP_SWI), +/* 1111 1001 1000 */ TABDECL( OP_SWI), +/* 1111 1001 1001 */ TABDECL( OP_SWI), +/* 1111 1001 1010 */ TABDECL( OP_SWI), +/* 1111 1001 1011 */ TABDECL( OP_SWI), +/* 1111 1001 1100 */ TABDECL( OP_SWI), +/* 1111 1001 1101 */ TABDECL( OP_SWI), +/* 1111 1001 1110 */ TABDECL( OP_SWI), +/* 1111 1001 1111 */ TABDECL( OP_SWI), +/* 1111 1010 0000 */ TABDECL( OP_SWI), +/* 1111 1010 0001 */ TABDECL( OP_SWI), +/* 1111 1010 0010 */ TABDECL( OP_SWI), +/* 1111 1010 0011 */ TABDECL( OP_SWI), +/* 1111 1010 0100 */ TABDECL( OP_SWI), +/* 1111 1010 0101 */ TABDECL( OP_SWI), +/* 1111 1010 0110 */ TABDECL( OP_SWI), +/* 1111 1010 0111 */ TABDECL( OP_SWI), +/* 1111 1010 1000 */ TABDECL( OP_SWI), +/* 1111 1010 1001 */ TABDECL( OP_SWI), +/* 1111 1010 1010 */ TABDECL( OP_SWI), +/* 1111 1010 1011 */ TABDECL( OP_SWI), +/* 1111 1010 1100 */ TABDECL( OP_SWI), +/* 1111 1010 1101 */ TABDECL( OP_SWI), +/* 1111 1010 1110 */ TABDECL( OP_SWI), +/* 1111 1010 1111 */ TABDECL( OP_SWI), +/* 1111 1011 0000 */ TABDECL( OP_SWI), +/* 1111 1011 0001 */ TABDECL( OP_SWI), +/* 1111 1011 0010 */ TABDECL( OP_SWI), +/* 1111 1011 0011 */ TABDECL( OP_SWI), +/* 1111 1011 0100 */ TABDECL( OP_SWI), +/* 1111 1011 0101 */ TABDECL( OP_SWI), +/* 1111 1011 0110 */ TABDECL( OP_SWI), +/* 1111 1011 0111 */ TABDECL( OP_SWI), +/* 1111 1011 1000 */ TABDECL( OP_SWI), +/* 1111 1011 1001 */ TABDECL( OP_SWI), +/* 1111 1011 1010 */ TABDECL( OP_SWI), +/* 1111 1011 1011 */ TABDECL( OP_SWI), +/* 1111 1011 1100 */ TABDECL( OP_SWI), +/* 1111 1011 1101 */ TABDECL( OP_SWI), +/* 1111 1011 1110 */ TABDECL( OP_SWI), +/* 1111 1011 1111 */ TABDECL( OP_SWI), +/* 1111 1100 0000 */ TABDECL( OP_SWI), +/* 1111 1100 0001 */ TABDECL( OP_SWI), +/* 1111 1100 0010 */ TABDECL( OP_SWI), +/* 1111 1100 0011 */ TABDECL( OP_SWI), +/* 1111 1100 0100 */ TABDECL( OP_SWI), +/* 1111 1100 0101 */ TABDECL( OP_SWI), +/* 1111 1100 0110 */ TABDECL( OP_SWI), +/* 1111 1100 0111 */ TABDECL( OP_SWI), +/* 1111 1100 1000 */ TABDECL( OP_SWI), +/* 1111 1100 1001 */ TABDECL( OP_SWI), +/* 1111 1100 1010 */ TABDECL( OP_SWI), +/* 1111 1100 1011 */ TABDECL( OP_SWI), +/* 1111 1100 1100 */ TABDECL( OP_SWI), +/* 1111 1100 1101 */ TABDECL( OP_SWI), +/* 1111 1100 1110 */ TABDECL( OP_SWI), +/* 1111 1100 1111 */ TABDECL( OP_SWI), +/* 1111 1101 0000 */ TABDECL( OP_SWI), +/* 1111 1101 0001 */ TABDECL( OP_SWI), +/* 1111 1101 0010 */ TABDECL( OP_SWI), +/* 1111 1101 0011 */ TABDECL( OP_SWI), +/* 1111 1101 0100 */ TABDECL( OP_SWI), +/* 1111 1101 0101 */ TABDECL( OP_SWI), +/* 1111 1101 0110 */ TABDECL( OP_SWI), +/* 1111 1101 0111 */ TABDECL( OP_SWI), +/* 1111 1101 1000 */ TABDECL( OP_SWI), +/* 1111 1101 1001 */ TABDECL( OP_SWI), +/* 1111 1101 1010 */ TABDECL( OP_SWI), +/* 1111 1101 1011 */ TABDECL( OP_SWI), +/* 1111 1101 1100 */ TABDECL( OP_SWI), +/* 1111 1101 1101 */ TABDECL( OP_SWI), +/* 1111 1101 1110 */ TABDECL( OP_SWI), +/* 1111 1101 1111 */ TABDECL( OP_SWI), +/* 1111 1110 0000 */ TABDECL( OP_SWI), +/* 1111 1110 0001 */ TABDECL( OP_SWI), +/* 1111 1110 0010 */ TABDECL( OP_SWI), +/* 1111 1110 0011 */ TABDECL( OP_SWI), +/* 1111 1110 0100 */ TABDECL( OP_SWI), +/* 1111 1110 0101 */ TABDECL( OP_SWI), +/* 1111 1110 0110 */ TABDECL( OP_SWI), +/* 1111 1110 0111 */ TABDECL( OP_SWI), +/* 1111 1110 1000 */ TABDECL( OP_SWI), +/* 1111 1110 1001 */ TABDECL( OP_SWI), +/* 1111 1110 1010 */ TABDECL( OP_SWI), +/* 1111 1110 1011 */ TABDECL( OP_SWI), +/* 1111 1110 1100 */ TABDECL( OP_SWI), +/* 1111 1110 1101 */ TABDECL( OP_SWI), +/* 1111 1110 1110 */ TABDECL( OP_SWI), +/* 1111 1110 1111 */ TABDECL( OP_SWI), +/* 1111 1111 0000 */ TABDECL( OP_SWI), +/* 1111 1111 0001 */ TABDECL( OP_SWI), +/* 1111 1111 0010 */ TABDECL( OP_SWI), +/* 1111 1111 0011 */ TABDECL( OP_SWI), +/* 1111 1111 0100 */ TABDECL( OP_SWI), +/* 1111 1111 0101 */ TABDECL( OP_SWI), +/* 1111 1111 0110 */ TABDECL( OP_SWI), +/* 1111 1111 0111 */ TABDECL( OP_SWI), +/* 1111 1111 1000 */ TABDECL( OP_SWI), +/* 1111 1111 1001 */ TABDECL( OP_SWI), +/* 1111 1111 1010 */ TABDECL( OP_SWI), +/* 1111 1111 1011 */ TABDECL( OP_SWI), +/* 1111 1111 1100 */ TABDECL( OP_SWI), +/* 1111 1111 1101 */ TABDECL( OP_SWI), +/* 1111 1111 1110 */ TABDECL( OP_SWI), +/* 1111 1111 1111 */ TABDECL( OP_SWI), + + + diff --git a/jni/desmume/src/lua-engine.cpp b/jni/desmume/src/lua-engine.cpp new file mode 100755 index 0000000..c7d72be --- /dev/null +++ b/jni/desmume/src/lua-engine.cpp @@ -0,0 +1,6403 @@ +/* + Copyright (C) 2009-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "types.h" +#include "lua-engine.h" +#include "movie.h" +#include <assert.h> +#include <vector> +#include <map> +#include <string> +#include <algorithm> +#include "zlib.h" +#include "NDSSystem.h" +#include "movie.h" +#include "GPU_osd.h" +#include "saves.h" +#include "emufile.h" +#if defined(WIN32) && !defined(WXPORT) +#include <windows.h> +#include "main.h" +#include "video.h" +#include "resource.h" +#endif +#ifdef WIN32 +#include <direct.h> +#else +#include <unistd.h> +#endif + +using namespace std; + + +// functions that maybe aren't part of the Lua engine +// but didn't make sense to add to BaseDriver (at least not yet) +static bool IsHardwareAddressValid(u32 address) { + // maybe TODO? let's say everything is valid. + return true; +} + + +// actual lua engine follows +// adapted from gens-rr, nitsuja + upthorn + +extern "C" { + #include "lua.h" + #include "lauxlib.h" + #include "lualib.h" + #include "lstate.h" +}; + +enum SpeedMode +{ + SPEEDMODE_NORMAL, + SPEEDMODE_NOTHROTTLE, + SPEEDMODE_TURBO, + SPEEDMODE_MAXIMUM, +}; + +struct LuaGUIData +{ + u32* data; + int stridePix; + int xOrigin, yOrigin; + int xMin, yMin, xMax, yMax; +}; + +struct LuaSubMenuData +{ + PlatformMenu menu; + PlatformMenu subMenu; + PlatformMenuItem menuItem; + LuaSubMenuData(PlatformMenu _menu, PlatformMenu _subMenu, PlatformMenuItem _menuItem) + { + menu = _menu; + subMenu = _subMenu; + menuItem = _menuItem; + } +}; + +struct LuaMenuData +{ + std::vector<LuaSubMenuData> subMenuData; + std::map<PlatformMenuItem, PlatformMenu> menuItemMap; +}; + +static const char* menuCallbackIDString = "menuhandlers"; + +struct LuaContextInfo { + lua_State* L; // the Lua state + bool started; // script has been started and hasn't yet been terminated, although it may not be currently running + bool running; // script is currently running code (either the main call to the script or the callbacks it registered) + bool returned; // main call to the script has returned (but it may still be active if it registered callbacks) + bool crashed; // true if script has errored out + bool restart; // if true, tells the script-running code to restart the script when the script stops + bool restartLater; // set to true when a still-running script is stopped so that RestartAllLuaScripts can know which scripts to restart + unsigned int worryCount; // counts up as the script executes, gets reset when the application is able to process messages, triggers a warning prompt if it gets too high + bool stopWorrying; // set to true if the user says to let the script run forever despite appearing to be frozen + bool panic; // if set to true, tells the script to terminate as soon as it can do so safely (used because directly calling lua_close() or luaL_error() is unsafe in some contexts) + bool ranExit; // used to prevent a registered exit callback from ever getting called more than once + bool guiFuncsNeedDeferring; // true whenever GUI drawing would be cleared by the next emulation update before it would be visible, and thus needs to be deferred until after the next emulation update + int numDeferredFuncs; // number of deferred function calls accumulated, used to impose an arbitrary limit to avoid running out of memory + bool ranFrameAdvance; // false if emu.frameadvance() hasn't been called yet + int transparencyModifier; // values less than 255 will scale down the opacity of whatever the GUI renders, values greater than 255 will increase the opacity of anything transparent the GUI renders + SpeedMode speedMode; // determines how emu.frameadvance() acts + char panicMessage [72]; // a message to print if the script terminates due to panic being set + std::string lastFilename; // path to where the script last ran from so that restart can work (note: storing the script in memory instead would not be useful because we always want the most up-to-date script from file) + std::string nextFilename; // path to where the script should run from next, mainly used in case the restart flag is true + unsigned int dataSaveKey; // crc32 of the save data key, used to decide which script should get which data... by default (if no key is specified) it's calculated from the script filename + unsigned int dataLoadKey; // same as dataSaveKey but set through registerload instead of registersave if the two differ + bool dataSaveLoadKeySet; // false if the data save keys are unset or set to their default value + bool rerecordCountingDisabled; // true if this script has disabled rerecord counting for the savestates it loads + std::vector<std::string> persistVars; // names of the global variables to persist, kept here so their associated values can be output when the script exits + LuaSaveData newDefaultData; // data about the default state of persisted global variables, which we save on script exit so we can detect when the default value has changed to make it easier to reset persisted variables + unsigned int numMemHooks; // number of registered memory functions (1 per hooked byte) + LuaGUIData guiData; + LuaMenuData menuData; + // callbacks into the lua window... these don't need to exist per context the way I'm using them, but whatever + void(*print)(int uid, const char* str); + void(*onstart)(int uid); + void(*onstop)(int uid, bool statusOK); +}; +std::map<int, LuaContextInfo*> luaContextInfo; +std::map<lua_State*, int> luaStateToUIDMap; +int g_numScriptsStarted = 0; +bool g_anyScriptsHighSpeed = false; +bool g_stopAllScriptsEnabled = true; + +#define USE_INFO_STACK +#ifdef USE_INFO_STACK + std::vector<LuaContextInfo*> infoStack; + #define GetCurrentInfo() (*infoStack.front()) // should be faster but relies on infoStack correctly being updated to always have the current info in the first element +#else + std::map<lua_State*, LuaContextInfo*> luaStateToContextMap; + #define GetCurrentInfo() (*luaStateToContextMap[L->l_G->mainthread]) // should always work but might be slower +#endif + +//#define ASK_USER_ON_FREEZE // dialog on freeze is disabled now because it seems to be unnecessary, but this can be re-defined to enable it + + +static std::map<lua_CFunction, const char*> s_cFuncInfoMap; + +// using this macro you can define a callable-from-Lua function +// while associating with it some information about its arguments. +// that information will show up if the user tries to print the function +// or otherwise convert it to a string. +// (for example, "writebyte=function(addr,value)" instead of "writebyte=function:0A403490") +// note that the user can always use addressof(func) if they want to retrieve the address. +#define DEFINE_LUA_FUNCTION(name, argstring) \ + static int name(lua_State* L); \ + static const char* name##_args = s_cFuncInfoMap[name] = argstring; \ + static int name(lua_State* L) + +#ifdef _MSC_VER + #define snprintf _snprintf + #define vscprintf _vscprintf +#else + #define stricmp strcasecmp + #define strnicmp strncasecmp + #define __forceinline __attribute__((always_inline)) +#endif + + +static const char* luaCallIDStrings [] = +{ + "CALL_BEFOREEMULATION", + "CALL_AFTEREMULATION", + "CALL_AFTEREMULATIONGUI", + "CALL_BEFOREEXIT", + "CALL_BEFORESAVE", + "CALL_AFTERLOAD", + "CALL_ONSTART", + "CALL_ONINITMENU", + + "CALL_HOTKEY_1", + "CALL_HOTKEY_2", + "CALL_HOTKEY_3", + "CALL_HOTKEY_4", + "CALL_HOTKEY_5", + "CALL_HOTKEY_6", + "CALL_HOTKEY_7", + "CALL_HOTKEY_8", + "CALL_HOTKEY_9", + "CALL_HOTKEY_10", + "CALL_HOTKEY_11", + "CALL_HOTKEY_12", + "CALL_HOTKEY_13", + "CALL_HOTKEY_14", + "CALL_HOTKEY_15", + "CALL_HOTKEY_16", +}; +static const int _makeSureWeHaveTheRightNumberOfStrings [sizeof(luaCallIDStrings)/sizeof(*luaCallIDStrings) == LUACALL_COUNT ? 1 : 0]; + +static const char* luaMemHookTypeStrings [] = +{ + "MEMHOOK_WRITE", + "MEMHOOK_READ", + "MEMHOOK_EXEC", + + "MEMHOOK_WRITE_SUB", + "MEMHOOK_READ_SUB", + "MEMHOOK_EXEC_SUB", +}; +static const int _makeSureWeHaveTheRightNumberOfStrings2 [sizeof(luaMemHookTypeStrings)/sizeof(*luaMemHookTypeStrings) == LUAMEMHOOK_COUNT ? 1 : 0]; + +void StopScriptIfFinished(int uid, bool justReturned = false); +void SetSaveKey(LuaContextInfo& info, const char* key); +void SetLoadKey(LuaContextInfo& info, const char* key); +void RefreshScriptStartedStatus(); +void RefreshScriptSpeedStatus(); + +static char* rawToCString(lua_State* L, int idx=0); +static const char* toCString(lua_State* L, int idx=0); + +static void CalculateMemHookRegions(LuaMemHookType hookType); + +static int memory_registerHook(lua_State* L, LuaMemHookType hookType, int defaultSize) +{ + // get first argument: address + unsigned int addr = luaL_checkinteger(L,1); + //if((addr & ~0xFFFFFF) == ~0xFFFFFF) + // addr &= 0xFFFFFF; + + // get optional second argument: size + int size = defaultSize; + int funcIdx = 2; + if(lua_isnumber(L,2)) + { + size = luaL_checkinteger(L,2); + if(size < 0) + { + size = -size; + addr -= size; + } + funcIdx++; + } + + // check last argument: callback function + bool clearing = lua_isnil(L,funcIdx); + if(!clearing) + luaL_checktype(L, funcIdx, LUA_TFUNCTION); + lua_settop(L,funcIdx); + + // get the address-to-callback table for this hook type of the current script + lua_getfield(L, LUA_REGISTRYINDEX, luaMemHookTypeStrings[hookType]); + + // count how many callback functions we'll be displacing + int numFuncsAfter = clearing ? 0 : size; + int numFuncsBefore = 0; + for(unsigned int i = addr; i != addr+size; i++) + { + lua_rawgeti(L, -1, i); + if(lua_isfunction(L, -1)) + numFuncsBefore++; + lua_pop(L,1); + } + + // put the callback function in the address slots + for(unsigned int i = addr; i != addr+size; i++) + { + lua_pushvalue(L, -2); + lua_rawseti(L, -2, i); + } + + // adjust the count of active hooks + LuaContextInfo& info = GetCurrentInfo(); + info.numMemHooks += numFuncsAfter - numFuncsBefore; + + // re-cache regions of hooked memory across all scripts + CalculateMemHookRegions(hookType); + + StopScriptIfFinished(luaStateToUIDMap[L->l_G->mainthread]); + return 0; +} + +LuaMemHookType MatchHookTypeToCPU(lua_State* L, LuaMemHookType hookType) +{ + int cpuID = 0; + + int cpunameIndex = 0; + if(lua_type(L,2) == LUA_TSTRING) + cpunameIndex = 2; + else if(lua_type(L,3) == LUA_TSTRING) + cpunameIndex = 3; + + if(cpunameIndex) + { + const char* cpuName = lua_tostring(L, cpunameIndex); +// if(!stricmp(cpuName, "sub") || !stricmp(cpuName, "s68k")) +// cpuID = 1; + lua_remove(L, cpunameIndex); + } + +// switch(cpuID) +// { +// case 0: // m68k: +// return hookType; +// +// case 1: // s68k: +// switch(hookType) +// { +// case LUAMEMHOOK_WRITE: return LUAMEMHOOK_WRITE_SUB; +// case LUAMEMHOOK_READ: return LUAMEMHOOK_READ_SUB; +// case LUAMEMHOOK_EXEC: return LUAMEMHOOK_EXEC_SUB; +// } +// } + return hookType; +} + +DEFINE_LUA_FUNCTION(memory_registerwrite, "address,[size=1,][cpuname=\"main\",]func") +{ +#ifndef HAVE_LUA + luaL_error(L, "memory.registerwrite failed: function is not available in this build."); +#endif + return memory_registerHook(L, MatchHookTypeToCPU(L,LUAMEMHOOK_WRITE), 1); +} +DEFINE_LUA_FUNCTION(memory_registerread, "address,[size=1,][cpuname=\"main\",]func") +{ +#ifndef HAVE_LUA + luaL_error(L, "memory.registerread failed: function is not available in this build."); +#endif + return memory_registerHook(L, MatchHookTypeToCPU(L,LUAMEMHOOK_READ), 1); +} +DEFINE_LUA_FUNCTION(memory_registerexec, "address,[size=2,][cpuname=\"main\",]func") +{ +#ifndef HAVE_LUA + luaL_error(L, "memory.registerexec failed: function is not available in this build."); +#endif + return memory_registerHook(L, MatchHookTypeToCPU(L,LUAMEMHOOK_EXEC), 2); +} + +DEFINE_LUA_FUNCTION(emu_registerbefore, "func") +{ + if (!lua_isnil(L,1)) + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L,1); + lua_getfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_BEFOREEMULATION]); + lua_insert(L,1); + lua_setfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_BEFOREEMULATION]); + StopScriptIfFinished(luaStateToUIDMap[L->l_G->mainthread]); + return 1; +} +DEFINE_LUA_FUNCTION(emu_registerafter, "func") +{ + if (!lua_isnil(L,1)) + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L,1); + lua_getfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_AFTEREMULATION]); + lua_insert(L,1); + lua_setfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_AFTEREMULATION]); + StopScriptIfFinished(luaStateToUIDMap[L->l_G->mainthread]); + return 1; +} +DEFINE_LUA_FUNCTION(emu_registerexit, "func") +{ + if (!lua_isnil(L,1)) + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L,1); + lua_getfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_BEFOREEXIT]); + lua_insert(L,1); + lua_setfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_BEFOREEXIT]); + StopScriptIfFinished(luaStateToUIDMap[L->l_G->mainthread]); + return 1; +} +DEFINE_LUA_FUNCTION(emu_registerstart, "func") // TODO: use call registered LUACALL_ONSTART functions on reset +{ + if (!lua_isnil(L,1)) + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L,1); + lua_getfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_ONSTART]); + lua_insert(L,1); + lua_pushvalue(L,-1); // copy the function so we can also call it + lua_setfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_ONSTART]); + if (!lua_isnil(L,-1) && driver->EMU_HasEmulationStarted()) + lua_call(L,0,0); // call the function now since the game has already started and this start function hasn't been called yet + StopScriptIfFinished(luaStateToUIDMap[L->l_G->mainthread]); + return 1; +} +DEFINE_LUA_FUNCTION(gui_register, "func") +{ + if (!lua_isnil(L,1)) + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L,1); + lua_getfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_AFTEREMULATIONGUI]); + lua_insert(L,1); + lua_setfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_AFTEREMULATIONGUI]); + StopScriptIfFinished(luaStateToUIDMap[L->l_G->mainthread]); + return 1; +} +DEFINE_LUA_FUNCTION(state_registersave, "func[,savekey]") +{ + if (!lua_isnil(L,1)) + luaL_checktype(L, 1, LUA_TFUNCTION); + if (!lua_isnoneornil(L,2)) + SetSaveKey(GetCurrentInfo(), rawToCString(L,2)); + lua_settop(L,1); + lua_getfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_BEFORESAVE]); + lua_insert(L,1); + lua_setfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_BEFORESAVE]); + StopScriptIfFinished(luaStateToUIDMap[L->l_G->mainthread]); + return 1; +} +DEFINE_LUA_FUNCTION(state_registerload, "func[,loadkey]") +{ + if (!lua_isnil(L,1)) + luaL_checktype(L, 1, LUA_TFUNCTION); + if (!lua_isnoneornil(L,2)) + SetLoadKey(GetCurrentInfo(), rawToCString(L,2)); + lua_settop(L,1); + lua_getfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_AFTERLOAD]); + lua_insert(L,1); + lua_setfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_AFTERLOAD]); + StopScriptIfFinished(luaStateToUIDMap[L->l_G->mainthread]); + return 1; +} + +DEFINE_LUA_FUNCTION(input_registerhotkey, "keynum,func") +{ + int hotkeyNumber = luaL_checkinteger(L,1); + if(hotkeyNumber < 1 || hotkeyNumber > 16) + { + luaL_error(L, "input.registerhotkey(n,func) requires 1 <= n <= 16, but got n = %d.", hotkeyNumber); + return 0; + } + else + { + const char* key = luaCallIDStrings[LUACALL_SCRIPT_HOTKEY_1 + hotkeyNumber-1]; + lua_getfield(L, LUA_REGISTRYINDEX, key); + lua_replace(L,1); + if (!lua_isnil(L,2)) + luaL_checktype(L, 2, LUA_TFUNCTION); + lua_settop(L,2); + lua_setfield(L, LUA_REGISTRYINDEX, key); + StopScriptIfFinished(luaStateToUIDMap[L->l_G->mainthread]); + return 1; + } +} + +static int doPopup(lua_State* L, const char* deftype, const char* deficon) +{ + const char* str = toCString(L,1); + const char* type = lua_type(L,2) == LUA_TSTRING ? lua_tostring(L,2) : deftype; + const char* icon = lua_type(L,3) == LUA_TSTRING ? lua_tostring(L,3) : deficon; + + int itype = -1, iters = 0; + while(itype == -1 && iters++ < 2) + { + if(!stricmp(type, "ok")) itype = 0; + else if(!stricmp(type, "yesno")) itype = 1; + else if(!stricmp(type, "yesnocancel")) itype = 2; + else if(!stricmp(type, "okcancel")) itype = 3; + else if(!stricmp(type, "abortretryignore")) itype = 4; + else type = deftype; + } + assert(itype >= 0 && itype <= 4); + if(!(itype >= 0 && itype <= 4)) itype = 0; + + int iicon = -1; iters = 0; + while(iicon == -1 && iters++ < 2) + { + if(!stricmp(icon, "message") || !stricmp(icon, "notice")) iicon = 0; + else if(!stricmp(icon, "question")) iicon = 1; + else if(!stricmp(icon, "warning")) iicon = 2; + else if(!stricmp(icon, "error")) iicon = 3; + else icon = deficon; + } + assert(iicon >= 0 && iicon <= 3); + if(!(iicon >= 0 && iicon <= 3)) iicon = 0; + + static const char * const titles [] = {"Notice", "Question", "Warning", "Error"}; + const char* answer = "ok"; +#if defined(_WIN32) && !defined(WXPORT) + static const int etypes [] = {MB_OK, MB_YESNO, MB_YESNOCANCEL, MB_OKCANCEL, MB_ABORTRETRYIGNORE}; + static const int eicons [] = {MB_ICONINFORMATION, MB_ICONQUESTION, MB_ICONWARNING, MB_ICONERROR}; +// DialogsOpen++; + int uid = luaStateToUIDMap[L->l_G->mainthread]; + EnableWindow(MainWindow->getHWnd(), false); +// if (Full_Screen) +// { +// while (ShowCursor(false) >= 0); +// while (ShowCursor(true) < 0); +// } + int ianswer = MessageBox((HWND)uid, str, titles[iicon], etypes[itype] | eicons[iicon]); + EnableWindow(MainWindow->getHWnd(), true); +// DialogsOpen--; + switch(ianswer) + { + case IDOK: answer = "ok"; break; + case IDCANCEL: answer = "cancel"; break; + case IDABORT: answer = "abort"; break; + case IDRETRY: answer = "retry"; break; + case IDIGNORE: answer = "ignore"; break; + case IDYES: answer = "yes"; break; + case IDNO: answer = "no"; break; + } +#else + // NYI (assume first answer for now) + switch(itype) + { + case 0: case 3: answer = "ok"; break; + case 1: case 2: answer = "yes"; break; + case 4: answer = "abort"; break; + } +#endif + + lua_pushstring(L, answer); + return 1; +} + +// string gui.popup(string message, string type = "ok", string icon = "message") +// string input.popup(string message, string type = "yesno", string icon = "question") +DEFINE_LUA_FUNCTION(gui_popup, "message[,type=\"ok\"[,icon=\"message\"]]") +{ + return doPopup(L, "ok", "message"); +} +DEFINE_LUA_FUNCTION(input_popup, "message[,type=\"yesno\"[,icon=\"question\"]]") +{ + return doPopup(L, "yesno", "question"); +} + +static const char* FilenameFromPath(const char* path) +{ + const char* slash1 = strrchr(path, '\\'); + const char* slash2 = strrchr(path, '/'); + if(slash1) slash1++; + if(slash2) slash2++; + const char* rv = path; + rv = std::max(rv, slash1); + rv = std::max(rv, slash2); + if(!rv) rv = ""; + return rv; +} + +void TrimFilenameFromPath(char* path) +{ + char* slash1 = strrchr(path, '\\'); + char* slash2 = strrchr(path, '/'); + char* slash = slash1; + if (slash == NULL || slash2 > slash) { + slash = slash2; + } + if (slash != NULL) { + *(slash + 1) = '\0'; + } +} + + +static void toCStringConverter(lua_State* L, int i, char*& ptr, int& remaining); + +// compare the contents of two items on the Lua stack to determine if they differ +// only works for relatively simple, saveable items (numbers, strings, bools, nil, and possibly-nested tables of those, up to a certain max length) +// not the best implementation, but good enough for what it's currently used for +static bool luaValueContentsDiffer(lua_State* L, int idx1, int idx2) +{ + static const int maxLen = 8192; + static char str1[maxLen]; + static char str2[maxLen]; + str1[0] = 0; + str2[0] = 0; + char* ptr1 = str1; + char* ptr2 = str2; + int remaining1 = maxLen; + int remaining2 = maxLen; + toCStringConverter(L, idx1, ptr1, remaining1); + toCStringConverter(L, idx2, ptr2, remaining2); + return (remaining1 != remaining2) || (strcmp(str1,str2) != 0); +} + + +// fills output with the path +// also returns a pointer to the first character in the filename (non-directory) part of the path +static char* ConstructScriptSaveDataPath(char* output, int bufferSize, LuaContextInfo& info) +{ +// Get_State_File_Name(output); TODO + char* slash1 = strrchr(output, '\\'); + char* slash2 = strrchr(output, '/'); + if(slash1) slash1[1] = '\0'; + if(slash2) slash2[1] = '\0'; + char* rv = output + strlen(output); + strncat(output, "u.", bufferSize-(strlen(output)+1)); + if(!info.dataSaveLoadKeySet) + strncat(output, FilenameFromPath(info.lastFilename.c_str()), bufferSize-(strlen(output)+1)); + else + snprintf(output+strlen(output), bufferSize-(strlen(output)+1), "%X", info.dataSaveKey); + strncat(output, ".luasav", bufferSize-(strlen(output)+1)); + return rv; +} + +// emu.persistglobalvariables({ +// variable1 = defaultvalue1, +// variable2 = defaultvalue2, +// etc +// }) +// takes a table with variable names as the keys and default values as the values, +// and defines each of those variables names as a global variable, +// setting them equal to the values they had the last time the script exited, +// or (if that isn't available) setting them equal to the provided default values. +// as a special case, if you want the default value for a variable to be nil, +// then put the variable name alone in quotes as an entry in the table without saying "= nil". +// this special case is because tables in lua don't store nil valued entries. +// also, if you change the default value that will reset the variable to the new default. +DEFINE_LUA_FUNCTION(emu_persistglobalvariables, "variabletable") +{ + int uid = luaStateToUIDMap[L->l_G->mainthread]; + LuaContextInfo& info = GetCurrentInfo(); + + // construct a path we can load the persistent variables from + char path [1024] = {0}; + char* pathTypeChrPtr = ConstructScriptSaveDataPath(path, 1024, info); + + // load the previously-saved final variable values from file + LuaSaveData exitData; + { + *pathTypeChrPtr = 'e'; + FILE* persistFile = fopen(path, "rb"); + if(persistFile) + { + exitData.ImportRecords(persistFile); + fclose(persistFile); + } + } + + // load the previously-saved default variable values from file + LuaSaveData defaultData; + { + *pathTypeChrPtr = 'd'; + FILE* defaultsFile = fopen(path, "rb"); + if(defaultsFile) + { + defaultData.ImportRecords(defaultsFile); + fclose(defaultsFile); + } + } + + // loop through the passed-in variables, + // exposing a global variable to the script for each one + // while also keeping a record of their names + // so we can save them (to the persistFile) later when the script exits + int numTables = lua_gettop(L); + for(int i = 1; i <= numTables; i++) + { + luaL_checktype(L, i, LUA_TTABLE); + + lua_pushnil(L); // before first key + int keyIndex = lua_gettop(L); + int valueIndex = keyIndex + 1; + while(lua_next(L, i)) + { + int keyType = lua_type(L, keyIndex); + int valueType = lua_type(L, valueIndex); + if(keyType == LUA_TSTRING && valueType <= LUA_TTABLE && valueType != LUA_TLIGHTUSERDATA) + { + // variablename = defaultvalue, + + // duplicate the key first because lua_next() needs to eat that + lua_pushvalue(L, keyIndex); + lua_insert(L, keyIndex); + } + else if(keyType == LUA_TNUMBER && valueType == LUA_TSTRING) + { + // "variablename", + // or [index] = "variablename", + + // defaultvalue is assumed to be nil + lua_pushnil(L); + } + else + { + luaL_error(L, "'%s' = '%s' entries are not allowed in the table passed to emu.persistglobalvariables()", lua_typename(L,keyType), lua_typename(L,valueType)); + } + + int varNameIndex = valueIndex; + int defaultIndex = valueIndex+1; + + // keep track of the variable name for later + const char* varName = lua_tostring(L, varNameIndex); + info.persistVars.push_back(varName); + unsigned int varNameCRC = crc32(0, (const unsigned char*)varName, strlen(varName)); + info.newDefaultData.SaveRecordPartial(uid, varNameCRC, defaultIndex); + + // load the previous default value for this variable if it exists. + // if the new default is different than the old one, + // assume the user wants to set the value to the new default value + // instead of the previously-saved exit value. + bool attemptPersist = true; + defaultData.LoadRecord(uid, varNameCRC, 1); + lua_pushnil(L); + if(luaValueContentsDiffer(L, defaultIndex, defaultIndex+1)) + attemptPersist = false; + lua_settop(L, defaultIndex); + + if(attemptPersist) + { + // load the previous saved value for this variable if it exists + exitData.LoadRecord(uid, varNameCRC, 1); + if(lua_gettop(L) > defaultIndex) + lua_remove(L, defaultIndex); // replace value with loaded record + lua_settop(L, defaultIndex); + } + + // set the global variable + lua_settable(L, LUA_GLOBALSINDEX); + + assert(lua_gettop(L) == keyIndex); + } + } + + return 0; +} + +static const char* deferredGUIIDString = "lazygui"; +static const char* deferredJoySetIDString = "lazyjoy"; +#define MAX_DEFERRED_COUNT 16384 + +// store the most recent C function call from Lua (and all its arguments) +// for later evaluation +void DeferFunctionCall(lua_State* L, const char* idstring) +{ + LuaContextInfo& info = GetCurrentInfo(); + if(info.numDeferredFuncs < MAX_DEFERRED_COUNT) + info.numDeferredFuncs++; + else + return; // too many deferred functions on the same frame, silently discard the rest + + // there might be a cleaner way of doing this using lua_pushcclosure and lua_getref + + int num = lua_gettop(L); + + // get the C function pointer + //lua_CFunction cf = lua_tocfunction(L, -(num+1)); + lua_CFunction cf = (L->ci->func)->value.gc->cl.c.f; + assert(cf); + lua_pushcfunction(L,cf); + + // make a list of the function and its arguments (and also pop those arguments from the stack) + lua_createtable(L, num+1, 0); + lua_insert(L, 1); + for(int n = num+1; n > 0; n--) + lua_rawseti(L, 1, n); + + // put the list into a global array + lua_getfield(L, LUA_REGISTRYINDEX, idstring); + lua_insert(L, 1); + int curSize = lua_objlen(L, 1); + lua_rawseti(L, 1, curSize+1); + + // clean the stack + lua_settop(L, 0); +} + +static const char* refStashString = "refstash"; + +void CallDeferredFunctions(lua_State* L, const char* idstring) +{ + lua_getfield(L, LUA_REGISTRYINDEX, idstring); + int numCalls = lua_objlen(L, -1); + if(numCalls > 0) + { + // save and pop any extra things that were on the stack + int top = lua_gettop(L); + int stashRef = -1; + if(top > 1) + { + lua_insert(L, 1); + lua_getfield(L, LUA_REGISTRYINDEX, refStashString); + lua_insert(L, 2); + lua_createtable(L, top-1, 0); + lua_insert(L, 3); + for(int remaining = top; remaining-- > 1;) + lua_rawseti(L, 3, remaining); + assert(lua_gettop(L) == 3); + stashRef = luaL_ref(L, 2); + lua_pop(L, 1); + } + + // loop through all the queued function calls + for(int i = 1; i <= numCalls; i++) + { + lua_rawgeti(L, 1, i); // get the function+arguments list + int listSize = lua_objlen(L, 2); + + // push the arguments and the function + for(int j = 1; j <= listSize; j++) + lua_rawgeti(L, 2, j); + + // get and pop the function + lua_CFunction cf = lua_tocfunction(L, -1); + lua_pop(L, 1); + + // shift first argument to slot 1 and call the function + lua_remove(L, 2); + lua_remove(L, 1); + cf(L); + + // prepare for next iteration + lua_settop(L, 0); + lua_getfield(L, LUA_REGISTRYINDEX, idstring); + } + + // clear the list of deferred functions + lua_newtable(L); + lua_setfield(L, LUA_REGISTRYINDEX, idstring); + LuaContextInfo& info = GetCurrentInfo(); + info.numDeferredFuncs -= numCalls; + if(info.numDeferredFuncs < 0) + info.numDeferredFuncs = 0; + + // restore the stack + lua_settop(L, 0); + if(top > 1) + { + lua_getfield(L, LUA_REGISTRYINDEX, refStashString); + lua_rawgeti(L, 1, stashRef); + for(int i = 1; i <= top-1; i++) + lua_rawgeti(L, 2, i); + luaL_unref(L, 1, stashRef); + lua_remove(L, 2); + lua_remove(L, 1); + } + assert(lua_gettop(L) == top - 1); + } + else + { + lua_pop(L, 1); + } +} + +bool DeferGUIFuncIfNeeded(lua_State* L) +{ + LuaContextInfo& info = GetCurrentInfo(); + if(info.speedMode == SPEEDMODE_MAXIMUM) + { + // if the mode is "maximum" then discard all GUI function calls + // and pretend it was because we deferred them + return true; + } + if(info.guiFuncsNeedDeferring) + { + // defer whatever function called this one until later + DeferFunctionCall(L, deferredGUIIDString); + return true; + } + + // ok to run the function right now + return false; +} + +void worry(lua_State* L, int intensity) +{ + LuaContextInfo& info = GetCurrentInfo(); + info.worryCount += intensity; +} + +static inline bool isalphaorunderscore(char c) +{ + return isalpha(c) || c == '_'; +} + +static std::vector<const void*> s_tableAddressStack; // prevents infinite recursion of a table within a table (when cycle is found, print something like table:parent) +static std::vector<const void*> s_metacallStack; // prevents infinite recursion if something's __tostring returns another table that contains that something (when cycle is found, print the inner result without using __tostring) + +#define APPENDPRINT { int _n = snprintf(ptr, remaining, +#define END ); if(_n >= 0) { ptr += _n; remaining -= _n; } else { remaining = 0; } } +static void toCStringConverter(lua_State* L, int i, char*& ptr, int& remaining) +{ + if(remaining <= 0) + return; + + const char* str = ptr; // for debugging + + // if there is a __tostring metamethod then call it + int usedMeta = luaL_callmeta(L, i, "__tostring"); + if(usedMeta) + { + std::vector<const void*>::const_iterator foundCycleIter = std::find(s_metacallStack.begin(), s_metacallStack.end(), lua_topointer(L,i)); + if(foundCycleIter != s_metacallStack.end()) + { + lua_pop(L, 1); + usedMeta = false; + } + else + { + s_metacallStack.push_back(lua_topointer(L,i)); + i = lua_gettop(L); + } + } + + switch(lua_type(L, i)) + { + case LUA_TNONE: break; + case LUA_TNIL: APPENDPRINT "nil" END break; + case LUA_TBOOLEAN: APPENDPRINT lua_toboolean(L,i) ? "true" : "false" END break; + case LUA_TSTRING: APPENDPRINT "%s",lua_tostring(L,i) END break; + case LUA_TNUMBER: APPENDPRINT "%.12Lg",lua_tonumber(L,i) END break; + case LUA_TFUNCTION: + if((L->base + i-1)->value.gc->cl.c.isC) + { + lua_CFunction func = lua_tocfunction(L, i); + std::map<lua_CFunction, const char*>::iterator iter = s_cFuncInfoMap.find(func); + if(iter == s_cFuncInfoMap.end()) + goto defcase; + APPENDPRINT "function(%s)", iter->second END + } + else + { + APPENDPRINT "function(" END + Proto* p = (L->base + i-1)->value.gc->cl.l.p; + int numParams = p->numparams + (p->is_vararg?1:0); + for (int n=0; n<p->numparams; n++) + { + APPENDPRINT "%s", getstr(p->locvars[n].varname) END + if(n != numParams-1) + APPENDPRINT "," END + } + if(p->is_vararg) + APPENDPRINT "..." END + APPENDPRINT ")" END + } + break; +defcase:default: APPENDPRINT "%s:%p",luaL_typename(L,i),lua_topointer(L,i) END break; + case LUA_TTABLE: + { + // first make sure there's enough stack space + if(!lua_checkstack(L, 4)) + { + // note that even if lua_checkstack never returns false, + // that doesn't mean we didn't need to call it, + // because calling it retrieves stack space past LUA_MINSTACK + goto defcase; + } + + std::vector<const void*>::const_iterator foundCycleIter = std::find(s_tableAddressStack.begin(), s_tableAddressStack.end(), lua_topointer(L,i)); + if(foundCycleIter != s_tableAddressStack.end()) + { + int parentNum = s_tableAddressStack.end() - foundCycleIter; + if(parentNum > 1) + APPENDPRINT "%s:parent^%d",luaL_typename(L,i),parentNum END + else + APPENDPRINT "%s:parent",luaL_typename(L,i) END + } + else + { + s_tableAddressStack.push_back(lua_topointer(L,i)); + struct Scope { ~Scope(){ s_tableAddressStack.pop_back(); } } scope; + + APPENDPRINT "{" END + + lua_pushnil(L); // first key + int keyIndex = lua_gettop(L); + int valueIndex = keyIndex + 1; + bool first = true; + bool skipKey = true; // true if we're still in the "array part" of the table + lua_Number arrayIndex = (lua_Number)0; + while(lua_next(L, i)) + { + if(first) + first = false; + else + APPENDPRINT ", " END + if(skipKey) + { + arrayIndex += (lua_Number)1; + bool keyIsNumber = (lua_type(L, keyIndex) == LUA_TNUMBER); + skipKey = keyIsNumber && (lua_tonumber(L, keyIndex) == arrayIndex); + } + if(!skipKey) + { + bool keyIsString = (lua_type(L, keyIndex) == LUA_TSTRING); + bool invalidLuaIdentifier = (!keyIsString || !isalphaorunderscore(*lua_tostring(L, keyIndex))); + if(invalidLuaIdentifier) + if(keyIsString) + APPENDPRINT "['" END + else + APPENDPRINT "[" END + + toCStringConverter(L, keyIndex, ptr, remaining); // key + + if(invalidLuaIdentifier) + if(keyIsString) + APPENDPRINT "']=" END + else + APPENDPRINT "]=" END + else + APPENDPRINT "=" END + } + + bool valueIsString = (lua_type(L, valueIndex) == LUA_TSTRING); + if(valueIsString) + APPENDPRINT "'" END + + toCStringConverter(L, valueIndex, ptr, remaining); // value + + if(valueIsString) + APPENDPRINT "'" END + + lua_pop(L, 1); + + if(remaining <= 0) + { + lua_settop(L, keyIndex-1); // stack might not be clean yet if we're breaking early + break; + } + } + APPENDPRINT "}" END + } + } break; + } + + if(usedMeta) + { + s_metacallStack.pop_back(); + lua_pop(L, 1); + } +} + +static const int s_tempStrMaxLen = 64 * 1024; +static char s_tempStr [s_tempStrMaxLen]; + +static char* rawToCString(lua_State* L, int idx) +{ + int a = idx>0 ? idx : 1; + int n = idx>0 ? idx : lua_gettop(L); + + char* ptr = s_tempStr; + *ptr = 0; + + int remaining = s_tempStrMaxLen; + for(int i = a; i <= n; i++) + { + toCStringConverter(L, i, ptr, remaining); + if(i != n) + APPENDPRINT " " END + } + + if(remaining < 3) + { + while(remaining < 6) + remaining++, ptr--; + APPENDPRINT "..." END + } + APPENDPRINT "\r\n" END + // the trailing newline is so print() can avoid having to do wasteful things to print its newline + // (string copying would be wasteful and calling info.print() twice can be extremely slow) + // at the cost of functions that don't want the newline needing to trim off the last two characters + // (which is a very fast operation and thus acceptable in this case) + + return s_tempStr; +} +#undef APPENDPRINT +#undef END + + +// replacement for luaB_tostring() that is able to show the contents of tables (and formats numbers better, and show function prototypes) +// can be called directly from lua via tostring(), assuming tostring hasn't been reassigned +DEFINE_LUA_FUNCTION(tostring, "...") +{ + char* str = rawToCString(L); + str[strlen(str)-2] = 0; // hack: trim off the \r\n (which is there to simplify the print function's task) + lua_pushstring(L, str); + return 1; +} + +// like rawToCString, but will check if the global Lua function tostring() +// has been replaced with a custom function, and call that instead if so +static const char* toCString(lua_State* L, int idx) +{ + int a = idx>0 ? idx : 1; + int n = idx>0 ? idx : lua_gettop(L); + lua_getglobal(L, "tostring"); + lua_CFunction cf = lua_tocfunction(L,-1); + if(cf == tostring) // optimization: if using our own C tostring function, we can bypass the call through Lua and all the string object allocation that would entail + { + lua_pop(L,1); + return rawToCString(L, idx); + } + else // if the user overrided the tostring function, we have to actually call it and store the temporarily allocated string it returns + { + lua_pushstring(L, ""); + for (int i=a; i<=n; i++) { + lua_pushvalue(L, -2); // function to be called + lua_pushvalue(L, i); // value to print + lua_call(L, 1, 1); + if(lua_tostring(L, -1) == NULL) + luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("print")); + lua_pushstring(L, (i<n) ? " " : "\r\n"); + lua_concat(L, 3); + } + const char* str = lua_tostring(L, -1); + strncpy(s_tempStr, str, s_tempStrMaxLen); + s_tempStr[s_tempStrMaxLen-1] = 0; + lua_pop(L, 2); + return s_tempStr; + } +} + +// replacement for luaB_print() that goes to the appropriate textbox instead of stdout +DEFINE_LUA_FUNCTION(print, "...") +{ + const char* str = toCString(L); + + int uid = luaStateToUIDMap[L->l_G->mainthread]; + LuaContextInfo& info = GetCurrentInfo(); + + if(info.print) + info.print(uid, str); + else + puts(str); + + worry(L, 100); + return 0; +} + + +DEFINE_LUA_FUNCTION(emu_message, "str") +{ + const char* str = toCString(L); + driver->USR_InfoMessage(str); + return 0; +} + +// provides an easy way to copy a table from Lua +// (simple assignment only makes an alias, but sometimes an independent table is desired) +// currently this function only performs a shallow copy, +// but I think it should be changed to do a deep copy (possibly of configurable depth?) +// that maintains the internal table reference structure +DEFINE_LUA_FUNCTION(copytable, "origtable") +{ + int origIndex = 1; // we only care about the first argument + int origType = lua_type(L, origIndex); + if(origType == LUA_TNIL) + { + lua_pushnil(L); + return 1; + } + if(origType != LUA_TTABLE) + { + luaL_typerror(L, 1, lua_typename(L, LUA_TTABLE)); + lua_pushnil(L); + return 1; + } + + lua_createtable(L, lua_objlen(L,1), 0); + int copyIndex = lua_gettop(L); + + lua_pushnil(L); // first key + int keyIndex = lua_gettop(L); + int valueIndex = keyIndex + 1; + + while(lua_next(L, origIndex)) + { + lua_pushvalue(L, keyIndex); + lua_pushvalue(L, valueIndex); + lua_rawset(L, copyIndex); // copytable[key] = value + lua_pop(L, 1); + } + + // copy the reference to the metatable as well, if any + if(lua_getmetatable(L, origIndex)) + lua_setmetatable(L, copyIndex); + + return 1; // return the new table +} + +// because print traditionally shows the address of tables, +// and the print function I provide instead shows the contents of tables, +// I also provide this function +// (otherwise there would be no way to see a table's address, AFAICT) +DEFINE_LUA_FUNCTION(addressof, "table_or_function") +{ + const void* ptr = lua_topointer(L,-1); + lua_pushinteger(L, (lua_Integer)ptr); + return 1; +} + +// the following bit operations are ported from LuaBitOp 1.0.1, +// because it can handle the sign bit (bit 31) correctly. + +/* +** Lua BitOp -- a bit operations library for Lua 5.1. +** http://bitop.luajit.org/ +** +** Copyright (C) 2008-2009 Mike Pall. All rights reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +** [ MIT license: http://www.opensource.org/licenses/mit-license.php ] +*/ + +#ifdef _MSC_VER +/* MSVC is stuck in the last century and doesn't have C99's stdint.h. */ +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +#else +#include <stdint.h> +#endif + +typedef int32_t SBits; +typedef uint32_t UBits; + +typedef union { + lua_Number n; +#ifdef LUA_NUMBER_DOUBLE + uint64_t b; +#else + UBits b; +#endif +} BitNum; + +/* Convert argument to bit type. */ +static UBits barg(lua_State *L, int idx) +{ + BitNum bn; + UBits b; + bn.n = lua_tonumber(L, idx); +#if defined(LUA_NUMBER_DOUBLE) + bn.n += 6755399441055744.0; /* 2^52+2^51 */ +#ifdef SWAPPED_DOUBLE + b = (UBits)(bn.b >> 32); +#else + b = (UBits)bn.b; +#endif +#elif defined(LUA_NUMBER_INT) || defined(LUA_NUMBER_LONG) || \ + defined(LUA_NUMBER_LONGLONG) || defined(LUA_NUMBER_LONG_LONG) || \ + defined(LUA_NUMBER_LLONG) + if (sizeof(UBits) == sizeof(lua_Number)) + b = bn.b; + else + b = (UBits)(SBits)bn.n; +#elif defined(LUA_NUMBER_FLOAT) +#error "A 'float' lua_Number type is incompatible with this library" +#else +#error "Unknown number type, check LUA_NUMBER_* in luaconf.h" +#endif + if (b == 0 && !lua_isnumber(L, idx)) + luaL_typerror(L, idx, "number"); + return b; +} + +/* Return bit type. */ +#define BRET(b) lua_pushnumber(L, (lua_Number)(SBits)(b)); return 1; + +DEFINE_LUA_FUNCTION(bit_tobit, "x") { BRET(barg(L, 1)) } +DEFINE_LUA_FUNCTION(bit_bnot, "x") { BRET(~barg(L, 1)) } + +#define BIT_OP(func, opr) \ + DEFINE_LUA_FUNCTION(func, "x1 [,x2...]") { int i; UBits b = barg(L, 1); \ + for (i = lua_gettop(L); i > 1; i--) b opr barg(L, i); BRET(b) } +BIT_OP(bit_band, &=) +BIT_OP(bit_bor, |=) +BIT_OP(bit_bxor, ^=) + +#define bshl(b, n) (b << n) +#define bshr(b, n) (b >> n) +#define bsar(b, n) ((SBits)b >> n) +#define brol(b, n) ((b << n) | (b >> (32-n))) +#define bror(b, n) ((b << (32-n)) | (b >> n)) +#define BIT_SH(func, fn) \ + DEFINE_LUA_FUNCTION(func, "x, n") { \ + UBits b = barg(L, 1); UBits n = barg(L, 2) & 31; BRET(fn(b, n)) } +BIT_SH(bit_lshift, bshl) +BIT_SH(bit_rshift, bshr) +BIT_SH(bit_arshift, bsar) +BIT_SH(bit_rol, brol) +BIT_SH(bit_ror, bror) + +DEFINE_LUA_FUNCTION(bit_bswap, "x") +{ + UBits b = barg(L, 1); + b = (b >> 24) | ((b >> 8) & 0xff00) | ((b & 0xff00) << 8) | (b << 24); + BRET(b) +} + +DEFINE_LUA_FUNCTION(bit_tohex, "x [,n]") +{ + UBits b = barg(L, 1); + SBits n = lua_isnone(L, 2) ? 8 : (SBits)barg(L, 2); + const char *hexdigits = "0123456789abcdef"; + char buf[8]; + int i; + if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; } + if (n > 8) n = 8; + for (i = (int)n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; } + lua_pushlstring(L, buf, (size_t)n); + return 1; +} + +static const struct luaL_Reg bit_funcs[] = { + { "tobit", bit_tobit }, + { "bnot", bit_bnot }, + { "band", bit_band }, + { "bor", bit_bor }, + { "bxor", bit_bxor }, + { "lshift", bit_lshift }, + { "rshift", bit_rshift }, + { "arshift", bit_arshift }, + { "rol", bit_rol }, + { "ror", bit_ror }, + { "bswap", bit_bswap }, + { "tohex", bit_tohex }, + { NULL, NULL } +}; + +/* Signed right-shifts are implementation-defined per C89/C99. +** But the de facto standard are arithmetic right-shifts on two's +** complement CPUs. This behaviour is required here, so test for it. +*/ +#define BAD_SAR (bsar(-8, 2) != (SBits)-2) + +bool luabitop_validate(lua_State *L) // originally named as luaopen_bit +{ + UBits b; + lua_pushnumber(L, (lua_Number)1437217655L); + b = barg(L, -1); + if (b != (UBits)1437217655L || BAD_SAR) { /* Perform a simple self-test. */ + const char *msg = "compiled with incompatible luaconf.h"; +#ifdef LUA_NUMBER_DOUBLE +#if defined(_WIN32) && !defined(WXPORT) + if (b == (UBits)1610612736L) + msg = "use D3DCREATE_FPU_PRESERVE with DirectX"; +#endif + if (b == (UBits)1127743488L) + msg = "not compiled with SWAPPED_DOUBLE"; +#endif + if (BAD_SAR) + msg = "arithmetic right-shift broken"; + luaL_error(L, "bit library self-test failed (%s)", msg); + return false; + } + return true; +} + +// LuaBitOp ends here + +DEFINE_LUA_FUNCTION(bitshift, "num,shift") +{ + int shift = luaL_checkinteger(L,2); + if (shift < 0) { + lua_pushinteger(L, -shift); + lua_replace(L, 2); + return bit_lshift(L); + } + else + return bit_rshift(L); +} + +DEFINE_LUA_FUNCTION(bitbit, "whichbit") +{ + int rv = 0; + int numArgs = lua_gettop(L); + for(int i = 1; i <= numArgs; i++) { + int where = luaL_checkinteger(L,i); + if (where >= 0 && where < 32) + rv |= (1 << where); + } + lua_settop(L,0); + BRET(rv); +} + +int emu_wait(lua_State* L); +int dontworry(LuaContextInfo& info); + +void indicateBusy(lua_State* L, bool busy) +{ + // disabled because there have been complaints about this message being useless spam. + // the script window's title changing should be sufficient, I guess. +/* if(busy) + { + const char* fmt = "script became busy (frozen?)"; + va_list argp; + va_start(argp, fmt); + luaL_where(L, 0); + lua_pushvfstring(L, fmt, argp); + va_end(argp); + lua_concat(L, 2); + LuaContextInfo& info = GetCurrentInfo(); + int uid = luaStateToUIDMap[L->l_G->mainthread]; + if(info.print) + { + info.print(uid, lua_tostring(L,-1)); + info.print(uid, "\r\n"); + } + else + { + fprintf(stderr, "%s\n", lua_tostring(L,-1)); + } + lua_pop(L, 1); + } +*/ +#if defined(_WIN32) && !defined(WXPORT) + int uid = luaStateToUIDMap[L->l_G->mainthread]; + HWND hDlg = (HWND)uid; + char str [1024]; + GetWindowText(hDlg, str, 1000); + char* extra = strchr(str, '<'); + if(busy) + { + if(!extra) + extra = str + strlen(str), *extra++ = ' '; + strcpy(extra, "<BUSY>"); + } + else + { + if(extra) + extra[-1] = 0; + } + SetWindowText(hDlg, str); +#endif +} + + +#define HOOKCOUNT 4096 +#define MAX_WORRY_COUNT 6000 +void LuaRescueHook(lua_State* L, lua_Debug *dbg) +{ + LuaContextInfo& info = GetCurrentInfo(); + + info.worryCount++; + + if(info.stopWorrying && !info.panic) + { + if(info.worryCount > (MAX_WORRY_COUNT >> 2)) + { + // the user already said they're OK with the script being frozen, + // but we don't trust their judgement completely, + // so periodically update the main loop so they have a chance to manually stop it + info.worryCount = 0; + emu_wait(L); + info.stopWorrying = true; + } + return; + } + + if(info.worryCount > MAX_WORRY_COUNT || info.panic) + { + info.worryCount = 0; + info.stopWorrying = false; + + bool stoprunning = true; + bool stopworrying = true; + if(!info.panic) + { + SPU_ClearOutputBuffer(); +#if defined(ASK_USER_ON_FREEZE) && defined(_WIN32) && !defined(WXPORT) + DialogsOpen++; + int answer = MessageBox(HWnd, "A Lua script has been running for quite a while. Maybe it is in an infinite loop.\n\nWould you like to stop the script?\n\n(Yes to stop it now,\n No to keep running and not ask again,\n Cancel to keep running but ask again later)", "Lua Alert", MB_YESNOCANCEL | MB_DEFBUTTON3 | MB_ICONASTERISK); + DialogsOpen--; + if(answer == IDNO) + stoprunning = false; + if(answer == IDCANCEL) + stopworrying = false; +#else + stoprunning = false; +#endif + } + + if(!stoprunning && stopworrying) + { + info.stopWorrying = true; // don't remove the hook because we need it still running for RequestAbortLuaScript to work + indicateBusy(info.L, true); + } + + if(stoprunning) + { + //lua_sethook(L, NULL, 0, 0); + assert(L->errfunc || L->errorJmp); + luaL_error(L, info.panic ? info.panicMessage : "terminated by user"); + } + + info.panic = false; + } +} + +void printfToOutput(const char* fmt, ...) +{ + va_list list; + va_start(list, fmt); + int len = vscprintf(fmt, list); + char* str = new char[len+1]; + vsprintf(str, fmt, list); + va_end(list); + LuaContextInfo& info = GetCurrentInfo(); + if(info.print) + { + lua_State* L = info.L; + int uid = luaStateToUIDMap[L->l_G->mainthread]; + info.print(uid, str); + info.print(uid, "\r\n"); + worry(L,300); + } + else + { + fprintf(stdout, "%s\n", str); + } + delete[] str; +} + +bool FailVerifyAtFrameBoundary(lua_State* L, const char* funcName, int unstartedSeverity=2, int inframeSeverity=2) +{ + if (!driver->EMU_HasEmulationStarted()) + { + static const char* msg = "cannot call %s() when emulation has not started."; + switch(unstartedSeverity) + { + case 0: break; + case 1: printfToOutput(msg, funcName); break; + default: case 2: luaL_error(L, msg, funcName); break; + } + return true; + } + if(!driver->EMU_IsAtFrameBoundary()) + { + static const char* msg = "cannot call %s() inside an emulation frame."; + switch(inframeSeverity) + { + case 0: break; + case 1: printfToOutput(msg, funcName); break; + default: case 2: luaL_error(L, msg, funcName); break; + } + return true; + } + return false; +} + + +// wrapper for EMU_StepMainLoop that provides a default implementation if ESTEP_NOT_IMPLEMENTED is returned. +// which only works if called from a function whose return value will get returned to Lua directly. +// TODO: actually implement the default case by making the main thread we use into a coroutine and resuming it periodically +static bool stepped_emulation = false; // <-- this is the result of running the macro +#define StepEmulationOnce(allowSleep, allowPause, frameSkip, disableUser, disableCore) \ + switch(driver->EMU_StepMainLoop(allowSleep, allowPause, frameSkip, disableUser, disableCore)) \ + { default: \ + case BaseDriver::ESTEP_NOT_IMPLEMENTED: /*return lua_yield(L, 0);*/ luaL_error(L, "Lua frame advance functions are not yet implemented for this platform, and neither is the fallback implementation."); break;/*TODO*/ \ + case BaseDriver::ESTEP_CALL_AGAIN: stepped_emulation = !driver->EMU_HasEmulationStarted(); break; \ + case BaseDriver::ESTEP_DONE: stepped_emulation = true; break; \ + } + +// same as StepEmulationOnce, except calls EMU_StepMainLoop multiple times if it returns ESTEP_CALL_AGAIN +#define StepEmulation(allowSleep, allowPause, frameSkip, disableUser, disableCore) \ + do { \ + StepEmulationOnce(allowSleep, allowPause, frameSkip, disableUser, disableCore); \ + if(stepped_emulation || (info).panic) break; \ + } while(true) + + +// note: caller must return the value this returns to Lua (at least if nonzero) +int StepEmulationAtSpeed(lua_State* L, SpeedMode speedMode, bool allowPause) +{ + int postponeTime; + bool drawNextFrame; + int worryIntensity; + bool allowSleep; + int frameSkip; + bool disableUserFeedback; + + LuaContextInfo& info = GetCurrentInfo(); + switch(speedMode) + { + default: + case SPEEDMODE_NORMAL: + postponeTime = 0, drawNextFrame = true, worryIntensity = 300; + allowSleep = true; + frameSkip = -1; + disableUserFeedback = false; + break; + case SPEEDMODE_NOTHROTTLE: + postponeTime = 250, drawNextFrame = true, worryIntensity = 200; + allowSleep = driver->EMU_IsEmulationPaused(); + frameSkip = driver->EMU_IsFastForwarding() ? -1 : 0; + disableUserFeedback = false; + break; + case SPEEDMODE_TURBO: + postponeTime = 500, drawNextFrame = true, worryIntensity = 150; + allowSleep = driver->EMU_IsEmulationPaused(); + frameSkip = 16; + disableUserFeedback = false; + break; + case SPEEDMODE_MAXIMUM: + postponeTime = 1000, drawNextFrame = false, worryIntensity = 100; + allowSleep = driver->EMU_IsEmulationPaused(); + frameSkip = 65535; + disableUserFeedback = true; + break; + } + + driver->USR_SetDisplayPostpone(postponeTime, drawNextFrame); + allowPause ? dontworry(info) : worry(L, worryIntensity); + + if(!allowPause && driver->EMU_IsEmulationPaused()) + driver->EMU_PauseEmulation(false); + + StepEmulation(allowSleep, allowPause, frameSkip, disableUserFeedback, false); + return 0; +} + +// acts similar to normal emulation update +DEFINE_LUA_FUNCTION(emu_emulateframe, "") +{ + if(FailVerifyAtFrameBoundary(L, "emu.emulateframe", 0,1)) + return 0; + + return StepEmulationAtSpeed(L, SPEEDMODE_NORMAL, false); +} + +// acts as a fast-forward emulation update that still renders every frame +DEFINE_LUA_FUNCTION(emu_emulateframefastnoskipping, "") +{ + if(FailVerifyAtFrameBoundary(L, "emu.emulateframefastnoskipping", 0,1)) + return 0; + + return StepEmulationAtSpeed(L, SPEEDMODE_NOTHROTTLE, false); +} + +// acts as a fast-forward emulation update +DEFINE_LUA_FUNCTION(emu_emulateframefast, "") +{ + if(FailVerifyAtFrameBoundary(L, "emu.emulateframefast", 0,1)) + return 0; + + return StepEmulationAtSpeed(L, SPEEDMODE_TURBO, false); +} + +// acts as an extremely-fast-forward emulation update +// that also doesn't render any graphics or generate any sounds +DEFINE_LUA_FUNCTION(emu_emulateframeinvisible, "") +{ + if(FailVerifyAtFrameBoundary(L, "emu.emulateframeinvisible", 0,1)) + return 0; + + return StepEmulationAtSpeed(L, SPEEDMODE_MAXIMUM, false); +} + +DEFINE_LUA_FUNCTION(emu_speedmode, "mode") +{ + SpeedMode newSpeedMode = SPEEDMODE_NORMAL; + if(lua_isnumber(L,1)) + newSpeedMode = (SpeedMode)luaL_checkinteger(L,1); + else + { + const char* str = luaL_checkstring(L,1); + if(!stricmp(str, "normal")) + newSpeedMode = SPEEDMODE_NORMAL; + else if(!stricmp(str, "nothrottle")) + newSpeedMode = SPEEDMODE_NOTHROTTLE; + else if(!stricmp(str, "turbo")) + newSpeedMode = SPEEDMODE_TURBO; + else if(!stricmp(str, "maximum")) + newSpeedMode = SPEEDMODE_MAXIMUM; + } + + LuaContextInfo& info = GetCurrentInfo(); + info.speedMode = newSpeedMode; + RefreshScriptSpeedStatus(); + return 0; +} + + +// tells the emulation to wait while the script is doing calculations +// can call this periodically instead of emu.frameadvance +// note that the user can use hotkeys at this time +// (e.g. a savestate could possibly get loaded before emu.wait() returns) +DEFINE_LUA_FUNCTION(emu_wait, "") +{ + LuaContextInfo& info = GetCurrentInfo(); + StepEmulationOnce(false, false, -1, true, true); + dontworry(info); + return 0; +} + + + + + +DEFINE_LUA_FUNCTION(emu_frameadvance, "") +{ + if(FailVerifyAtFrameBoundary(L, "emu.frameadvance", 0,1)) + return emu_wait(L); + + int uid = luaStateToUIDMap[L->l_G->mainthread]; + LuaContextInfo& info = GetCurrentInfo(); + + if(!info.ranFrameAdvance) + { + // otherwise we'll never see the first frame of GUI drawing + if(info.speedMode != SPEEDMODE_MAXIMUM) + driver->USR_RefreshScreen(); + info.ranFrameAdvance = true; + } + + return StepEmulationAtSpeed(L, info.speedMode, true); +} + +DEFINE_LUA_FUNCTION(emu_pause, "") +{ + driver->EMU_PauseEmulation(true); + + LuaContextInfo& info = GetCurrentInfo(); + StepEmulation(true, true, 0, true, true); + + // allow the user to not have to manually unpause + // after restarting a script that used emu.pause() + if(info.panic) + driver->EMU_PauseEmulation(false); + + return 0; +} + +DEFINE_LUA_FUNCTION(emu_unpause, "") +{ + LuaContextInfo& info = GetCurrentInfo(); + driver->EMU_PauseEmulation(false); + return 0; +} + +DEFINE_LUA_FUNCTION(emu_redraw, "") +{ + driver->USR_RefreshScreen(); + worry(L,250); + return 0; +} + + + +DEFINE_LUA_FUNCTION(memory_readbyte, "address") +{ + int address = luaL_checkinteger(L,1); + unsigned char value = (unsigned char)(_MMU_read08<ARMCPU_ARM9>(address) & 0xFF); + lua_settop(L,0); + lua_pushinteger(L, value); + return 1; // we return the number of return values +} +DEFINE_LUA_FUNCTION(memory_readbytesigned, "address") +{ + int address = luaL_checkinteger(L,1); + signed char value = (signed char)(_MMU_read08<ARMCPU_ARM9>(address) & 0xFF); + lua_settop(L,0); + lua_pushinteger(L, value); + return 1; +} +DEFINE_LUA_FUNCTION(vram_readword, "address") +{ + int address = luaL_checkinteger(L,1); + u16 value = T1ReadWord(MMU.ARM9_LCD,address); + lua_settop(L,0); + lua_pushinteger(L, value); + return 1; +} +DEFINE_LUA_FUNCTION(memory_readword, "address") +{ + int address = luaL_checkinteger(L,1); + unsigned short value = (unsigned short)(_MMU_read16<ARMCPU_ARM9>(address) & 0xFFFF); + lua_settop(L,0); + lua_pushinteger(L, value); + return 1; +} +DEFINE_LUA_FUNCTION(memory_readwordsigned, "address") +{ + int address = luaL_checkinteger(L,1); + signed short value = (signed short)(_MMU_read16<ARMCPU_ARM9>(address) & 0xFFFF); + lua_settop(L,0); + lua_pushinteger(L, value); + return 1; +} +DEFINE_LUA_FUNCTION(memory_readdword, "address") +{ + int address = luaL_checkinteger(L,1); + unsigned long value = (unsigned long)(_MMU_read32<ARMCPU_ARM9>(address)); + lua_settop(L,0); + lua_pushnumber(L, value); // can't use pushinteger in this case (out of range) + return 1; +} +DEFINE_LUA_FUNCTION(memory_readdwordsigned, "address") +{ + int address = luaL_checkinteger(L,1); + signed long value = (signed long)(_MMU_read32<ARMCPU_ARM9>(address)); + lua_settop(L,0); + lua_pushinteger(L, value); + return 1; +} + +DEFINE_LUA_FUNCTION(memory_writebyte, "address,value") +{ + int address = luaL_checkinteger(L,1); + unsigned char value = (unsigned char)(luaL_checkinteger(L,2) & 0xFF); + _MMU_write08<ARMCPU_ARM9>(address, value); + return 0; +} +DEFINE_LUA_FUNCTION(memory_writeword, "address,value") +{ + int address = luaL_checkinteger(L,1); + unsigned short value = (unsigned short)(luaL_checkinteger(L,2) & 0xFFFF); + _MMU_write16<ARMCPU_ARM9>(address, value); + return 0; +} +DEFINE_LUA_FUNCTION(vram_writeword, "address,value") +{ + int address = luaL_checkinteger(L,1); + u16 value = (u16)(luaL_checkinteger(L,2) & 0xFFFF); + T1WriteWord(MMU.ARM9_LCD,address,value); + return 0; +} +DEFINE_LUA_FUNCTION(memory_writedword, "address,value") +{ + int address = luaL_checkinteger(L,1); + unsigned long value = (unsigned long)(luaL_checkinteger(L,2)); + _MMU_write32<ARMCPU_ARM9>(address, value); + return 0; +} + +DEFINE_LUA_FUNCTION(memory_readbyterange, "address,length") +{ + int address = luaL_checkinteger(L,1); + int length = luaL_checkinteger(L,2); + + if(length < 0) + { + address += length; + length = -length; + } + + // push the array + lua_createtable(L, abs(length), 0); + + // put all the values into the (1-based) array + for(int a = address, n = 1; n <= length; a++, n++) + { + if(IsHardwareAddressValid(a)) + { + unsigned char value = (unsigned char)(_MMU_read08<ARMCPU_ARM9>(address) & 0xFF); + lua_pushinteger(L, value); + lua_rawseti(L, -2, n); + } + // else leave the value nil + } + + return 1; +} + +DEFINE_LUA_FUNCTION(memory_isvalid, "address") +{ + int address = luaL_checkinteger(L,1); + lua_settop(L,0); + lua_pushboolean(L, IsHardwareAddressValid(address)); + return 1; +} + +struct registerPointerMap +{ + const char* registerName; + unsigned int* pointer; + int dataSize; +}; + +#define RPM_ENTRY(name,var) {name, (unsigned int*)&var, sizeof(var)}, + +registerPointerMap arm9PointerMap [] = { + RPM_ENTRY("r0", NDS_ARM9.R[0]) + RPM_ENTRY("r1", NDS_ARM9.R[1]) + RPM_ENTRY("r2", NDS_ARM9.R[2]) + RPM_ENTRY("r3", NDS_ARM9.R[3]) + RPM_ENTRY("r4", NDS_ARM9.R[4]) + RPM_ENTRY("r5", NDS_ARM9.R[5]) + RPM_ENTRY("r6", NDS_ARM9.R[6]) + RPM_ENTRY("r7", NDS_ARM9.R[7]) + RPM_ENTRY("r8", NDS_ARM9.R[8]) + RPM_ENTRY("r9", NDS_ARM9.R[9]) + RPM_ENTRY("r10", NDS_ARM9.R[10]) + RPM_ENTRY("r11", NDS_ARM9.R[11]) + RPM_ENTRY("r12", NDS_ARM9.R[12]) + RPM_ENTRY("r13", NDS_ARM9.R[13]) + RPM_ENTRY("r14", NDS_ARM9.R[14]) + RPM_ENTRY("r15", NDS_ARM9.R[15]) + RPM_ENTRY("cpsr", NDS_ARM9.CPSR.val) + RPM_ENTRY("spsr", NDS_ARM9.SPSR.val) + {} +}; +registerPointerMap arm7PointerMap [] = { + RPM_ENTRY("r0", NDS_ARM7.R[0]) + RPM_ENTRY("r1", NDS_ARM7.R[1]) + RPM_ENTRY("r2", NDS_ARM7.R[2]) + RPM_ENTRY("r3", NDS_ARM7.R[3]) + RPM_ENTRY("r4", NDS_ARM7.R[4]) + RPM_ENTRY("r5", NDS_ARM7.R[5]) + RPM_ENTRY("r6", NDS_ARM7.R[6]) + RPM_ENTRY("r7", NDS_ARM7.R[7]) + RPM_ENTRY("r8", NDS_ARM7.R[8]) + RPM_ENTRY("r9", NDS_ARM7.R[9]) + RPM_ENTRY("r10", NDS_ARM7.R[10]) + RPM_ENTRY("r11", NDS_ARM7.R[11]) + RPM_ENTRY("r12", NDS_ARM7.R[12]) + RPM_ENTRY("r13", NDS_ARM7.R[13]) + RPM_ENTRY("r14", NDS_ARM7.R[14]) + RPM_ENTRY("r15", NDS_ARM7.R[15]) + RPM_ENTRY("cpsr", NDS_ARM7.CPSR.val) + RPM_ENTRY("spsr", NDS_ARM7.SPSR.val) + {} +}; + +struct cpuToRegisterMap +{ + const char* cpuName; + registerPointerMap* rpmap; +} +cpuToRegisterMaps [] = +{ + {"arm9.", arm9PointerMap}, + {"main.", arm9PointerMap}, + {"arm7.", arm7PointerMap}, + {"sub.", arm7PointerMap}, + {"", arm9PointerMap}, +}; + + +DEFINE_LUA_FUNCTION(memory_getregister, "cpu_dot_registername_string") +{ + const char* qualifiedRegisterName = luaL_checkstring(L,1); + lua_settop(L,0); + for(int cpu = 0; cpu < sizeof(cpuToRegisterMaps)/sizeof(*cpuToRegisterMaps); cpu++) + { + cpuToRegisterMap ctrm = cpuToRegisterMaps[cpu]; + int cpuNameLen = strlen(ctrm.cpuName); + if(!strnicmp(qualifiedRegisterName, ctrm.cpuName, cpuNameLen)) + { + qualifiedRegisterName += cpuNameLen; + for(int reg = 0; ctrm.rpmap[reg].dataSize; reg++) + { + registerPointerMap rpm = ctrm.rpmap[reg]; + if(!stricmp(qualifiedRegisterName, rpm.registerName)) + { + switch(rpm.dataSize) + { default: + case 1: lua_pushinteger(L, *(unsigned char*)rpm.pointer); break; + case 2: lua_pushinteger(L, *(unsigned short*)rpm.pointer); break; + case 4: lua_pushinteger(L, *(unsigned long*)rpm.pointer); break; + } + return 1; + } + } + lua_pushnil(L); + return 1; + } + } + lua_pushnil(L); + return 1; +} +DEFINE_LUA_FUNCTION(memory_setregister, "cpu_dot_registername_string,value") +{ + const char* qualifiedRegisterName = luaL_checkstring(L,1); + unsigned long value = (unsigned long)(luaL_checkinteger(L,2)); + lua_settop(L,0); + for(int cpu = 0; cpu < sizeof(cpuToRegisterMaps)/sizeof(*cpuToRegisterMaps); cpu++) + { + cpuToRegisterMap ctrm = cpuToRegisterMaps[cpu]; + int cpuNameLen = strlen(ctrm.cpuName); + if(!strnicmp(qualifiedRegisterName, ctrm.cpuName, cpuNameLen)) + { + qualifiedRegisterName += cpuNameLen; + for(int reg = 0; ctrm.rpmap[reg].dataSize; reg++) + { + registerPointerMap rpm = ctrm.rpmap[reg]; + if(!stricmp(qualifiedRegisterName, rpm.registerName)) + { + switch(rpm.dataSize) + { default: + case 1: *(unsigned char*)rpm.pointer = (unsigned char)(value & 0xFF); break; + case 2: *(unsigned short*)rpm.pointer = (unsigned short)(value & 0xFFFF); break; + case 4: *(unsigned long*)rpm.pointer = value; break; + } + return 0; + } + } + return 0; + } + } + return 0; +} + +DEFINE_LUA_FUNCTION(state_create, "[location]") +{ + if(lua_isnumber(L,1)) + { + // simply return the integer that got passed in + // (that's as good a savestate object as any for a numbered savestate slot) + lua_settop(L,1); + return 1; + } + + // allocate a pointer to an in-memory/anonymous savestate + EMUFILE_MEMORY** ppEmuFile = (EMUFILE_MEMORY**)lua_newuserdata(L, sizeof(EMUFILE_MEMORY*)); + *ppEmuFile = new EMUFILE_MEMORY(); + luaL_getmetatable(L, "EMUFILE_MEMORY*"); + lua_setmetatable(L, -2); + + return 1; +} + +// savestate.save(location [, option]) +// saves the current emulation state to the given location +// you can pass in either a savestate file number (an integer), +// OR you can pass in a savestate object that was returned by savestate.create() +// if option is "quiet" then any warning messages will be suppressed +// if option is "scriptdataonly" then the state will not actually be saved, but any save callbacks will still get called and their results will be saved (see savestate.registerload()/savestate.registersave()) +DEFINE_LUA_FUNCTION(state_save, "location[,option]") +{ + //const char* option = (lua_type(L,2) == LUA_TSTRING) ? lua_tostring(L,2) : NULL; + //if(option) + //{ + // if(!stricmp(option, "quiet")) // I'm not sure if saving can generate warning messages, but we might as well support suppressing them should they turn out to exist + // g_disableStatestateWarnings = true; + // else if(!stricmp(option, "scriptdataonly")) // TODO + // g_onlyCallSavestateCallbacks = true; + //} + //struct Scope { ~Scope(){ g_disableStatestateWarnings = false; g_onlyCallSavestateCallbacks = false; } } scope; // needs to run even if the following code throws an exception... maybe I should have put this in a "finally" block instead, but this project seems to have something against using the "try" statement + + if(/*!g_onlyCallSavestateCallbacks &&*/ FailVerifyAtFrameBoundary(L, "savestate.save", 2,2)) + return 0; + + int type = lua_type(L,1); + switch(type) + { + case LUA_TNUMBER: // numbered save file + default: + { + int stateNumber = luaL_checkinteger(L,1); + savestate_slot(stateNumber); + } return 0; + case LUA_TUSERDATA: // in-memory save slot + { + EMUFILE_MEMORY** ppEmuFile = (EMUFILE_MEMORY**)luaL_checkudata(L, 1, "EMUFILE_MEMORY*"); + (*ppEmuFile)->fseek(0, SEEK_SET); + + if((*ppEmuFile)->fail()) + luaL_error(L, "failed to save, savestate object was dead."); + + savestate_save(*ppEmuFile, 0); + + if((*ppEmuFile)->fail()) + luaL_error(L, "failed to save savestate!"); + if((*ppEmuFile)->size() == 0) + luaL_error(L, "failed to save, savestate became empty somehow."); + } return 0; + } +} + +// savestate.load(location [, option]) +// loads the current emulation state from the given location +// you can pass in either a savestate file number (an integer), +// OR you can pass in a savestate object that was returned by savestate.create() and has already saved to with savestate.save() +// if option is "quiet" then any warning messages will be suppressed +// if option is "scriptdataonly" then the state will not actually be loaded, but load callbacks will still get called and supplied with the data saved by save callbacks (see savestate.registerload()/savestate.registersave()) +DEFINE_LUA_FUNCTION(state_load, "location[,option]") +{ + //const char* option = (lua_type(L,2) == LUA_TSTRING) ? lua_tostring(L,2) : NULL; + //if(option) + //{ + // if(!stricmp(option, "quiet")) + // g_disableStatestateWarnings = true; + // else if(!stricmp(option, "scriptdataonly")) // TODO + // g_onlyCallSavestateCallbacks = true; + //} + //struct Scope { ~Scope(){ g_disableStatestateWarnings = false; g_onlyCallSavestateCallbacks = false; } } scope; // needs to run even if the following code throws an exception... maybe I should have put this in a "finally" block instead, but this project seems to have something against using the "try" statement + + if(/*!g_onlyCallSavestateCallbacks &&*/ FailVerifyAtFrameBoundary(L, "savestate.load", 2,2)) + return 0; + +// g_disableStatestateWarnings = lua_toboolean(L,2) != 0; + + int type = lua_type(L,1); + switch(type) + { + case LUA_TNUMBER: // numbered save file + default: + { + //LuaContextInfo& info = GetCurrentInfo(); + //if(info.rerecordCountingDisabled) + // SkipNextRerecordIncrement = true; + int stateNumber = luaL_checkinteger(L,1); + loadstate_slot(stateNumber); + } return 0; + case LUA_TUSERDATA: // in-memory save slot + { + EMUFILE_MEMORY** ppEmuFile = (EMUFILE_MEMORY**)luaL_checkudata(L, 1, "EMUFILE_MEMORY*"); + (*ppEmuFile)->fseek(0, SEEK_SET); + + if((*ppEmuFile)->fail()) + luaL_error(L, "failed to load, savestate object was dead."); + if((*ppEmuFile)->size() == 0) + luaL_error(L, "failed to load, savestate wasn't saved first."); + + savestate_load(*ppEmuFile); + + if((*ppEmuFile)->fail()) + luaL_error(L, "failed to load savestate!"); + } return 0; + } +} + +// savestate.loadscriptdata(location) +// returns the user data associated with the given savestate +// without actually loading the rest of that savestate or calling any callbacks. +// you can pass in either a savestate file number (an integer), +// OR you can pass in a savestate object that was returned by savestate.create() +// but note that currently only non-anonymous savestates can have associated scriptdata +// +// also note that this returns the same values +// that would be passed into a registered load function. +// the main reason this exists also is so you can register a load function that +// chooses whether or not to load the scriptdata instead of always loading it, +// and also to provide a nicer interface for loading scriptdata +// without needing to trigger savestate loading first +DEFINE_LUA_FUNCTION(state_loadscriptdata, "location") +{ + int type = lua_type(L,1); + switch(type) + { + case LUA_TNUMBER: // numbered save file + default: + { + // TODO + //int stateNumber = luaL_checkinteger(L,1); + //Set_Current_State(stateNumber, false,false); + //char Name [1024] = {0}; + //Get_State_File_Name(Name); + //{ + // LuaSaveData saveData; + + // char luaSaveFilename [512]; + // strncpy(luaSaveFilename, Name, 512); + // luaSaveFilename[512-(1+7/*strlen(".luasav")*/)] = '\0'; + // strcat(luaSaveFilename, ".luasav"); + // FILE* luaSaveFile = fopen(luaSaveFilename, "rb"); + // if(luaSaveFile) + // { + // saveData.ImportRecords(luaSaveFile); + // fclose(luaSaveFile); + + // int uid = luaStateToUIDMap[L->l_G->mainthread]; + // LuaContextInfo& info = GetCurrentInfo(); + + // lua_settop(L, 0); + // saveData.LoadRecord(uid, info.dataLoadKey, (unsigned int)-1); + // return lua_gettop(L); + // } + //} + } return 0; + case LUA_TUSERDATA: // in-memory save slot + { // there can be no user data associated with those, at least not yet + } return 0; + } +} + +// savestate.savescriptdata(location) +// same as savestate.save(location, "scriptdataonly") +// only provided for consistency with savestate.loadscriptdata(location) +DEFINE_LUA_FUNCTION(state_savescriptdata, "location") +{ + lua_settop(L, 1); + lua_pushstring(L, "scriptdataonly"); + return state_save(L); +} + +#ifndef PUBLIC_RELEASE +#include "gfx3d.h" +class EMUFILE_MEMORY_VERIFIER : public EMUFILE_MEMORY { +public: + EMUFILE_MEMORY_VERIFIER(EMUFILE_MEMORY* underlying) : EMUFILE_MEMORY(underlying->get_vec()) { } + + std::vector<std::string> differences; + + virtual void fwrite(const void *ptr, size_t bytes) + { + if(!failbit) + { + u8* dst = buf()+pos; + const u8* src = (const u8*)ptr; + int differencesAddedThisCall = 0; + for(int i = pos; i < (int)bytes+pos; i++) + { + if(*src != *dst) + { + if(differences.size() == 100) + failbit = true; + else + { + char temp [256]; + sprintf(temp, " " /*"mismatch at "*/ "byte %d(0x%X at 0x%X): %d(0x%X) != %d(0x%X)\n", i, i, dst, *src,*src, *dst,*dst); + + if(ptr == GPU_screen || ptr == gfx3d_convertedScreen) // ignore screen-only differences since frame skipping can cause them and it's probably ok + break; + + differences.push_back(temp); // <-- probably the best place for a breakpoint + + if(++differencesAddedThisCall == 4) + break; + } + } + src++; + dst++; + } + } + + pos += bytes; + } +}; + +// like savestate.save() except instead of actually saving +// it compares against what's already in the savestate +// and throws an error if any differences are found. +// only useful for development (catching desyncs). +DEFINE_LUA_FUNCTION(state_verify, "location[,option]") +{ + int type = lua_type(L,1); + switch(type) + { + case LUA_TNUMBER: // numbered save file + default: + { + luaL_error(L, "savestate.verify only works for in-memory saves."); + } return 0; + case LUA_TUSERDATA: // in-memory save slot + { + EMUFILE_MEMORY** ppEmuFile = (EMUFILE_MEMORY**)luaL_checkudata(L, 1, "EMUFILE_MEMORY*"); + + if((*ppEmuFile)->fail()) + luaL_error(L, "failed to verify, savestate object was dead."); + + EMUFILE_MEMORY_VERIFIER verifier (*ppEmuFile); + savestate_save(&verifier, 0); + if(verifier.differences.size()) + { + fputs("\n", stdout); + for(unsigned int i = 0; i < verifier.differences.size(); i++) + fputs(verifier.differences[i].c_str(), stdout); + luaL_error(L, "failed to verify savestate! %s", verifier.differences[0].c_str()); + } + } return 0; + } +} + +#endif + + + + + + +//joypad lib + +static const char *button_mappings[] = { +// G E W X Y A B S T U D L R F +"debug","R","L","X","Y","A","B","start","select","up","down","left","right","lid" +}; + +static int joy_getArgControllerNum(lua_State* L, int& index) +{ + // well, I think there's only one controller, + // but this should probably stay here for cross-emulator consistency + int type = lua_type(L,index); + if(type == LUA_TSTRING || type == LUA_TNUMBER) + index++; + return 1; +} + +// joypad.set(table buttons) +// +// Sets the joypad state (takes effect at the next frame boundary) +// true -> pressed +// false -> unpressed +// nil -> no change +DEFINE_LUA_FUNCTION(joy_set, "buttonTable") +{ + if(movieMode == MOVIEMODE_PLAY) // don't allow tampering with a playing movie's input + return 0; // (although it might be useful sometimes...) + + if(!NDS_isProcessingUserInput()) + { + // defer this function until when we are processing input + DeferFunctionCall(L, deferredJoySetIDString); + return 0; + } + + int index = 1; + (void)joy_getArgControllerNum(L, index); + luaL_checktype(L, index, LUA_TTABLE); + + UserButtons& buttons = NDS_getProcessingUserInput().buttons; + + for(int i = 0; i < sizeof(button_mappings)/sizeof(*button_mappings); i++) + { + const char* name = button_mappings[i]; + lua_getfield(L, index, name); + if (!lua_isnil(L,-1)) + { + bool pressed = lua_toboolean(L,-1) != 0; + buttons.array[i] = pressed; + } + lua_pop(L,1); + } + + return 0; +} + +// table joypad.read() +// +// Reads the joypad state (what the game sees) +int joy_get_internal(lua_State* L, bool reportUp, bool reportDown) +{ + int index = 1; + (void)joy_getArgControllerNum(L, index); + + lua_newtable(L); + + const UserButtons& buttons = NDS_getFinalUserInput().buttons; + + for(int i = 0; i < sizeof(button_mappings)/sizeof(*button_mappings); i++) + { + const char* name = button_mappings[i]; + bool pressed = buttons.array[i]; + if((pressed && reportDown) || (!pressed && reportUp)) + { + lua_pushboolean(L, pressed); + lua_setfield(L, -2, name); + } + } + + return 1; +} +// joypad.get() +// returns a table of every game button, +// true meaning currently-held and false meaning not-currently-held +// (as of last frame boundary) +// this WILL read input from a currently-playing movie +DEFINE_LUA_FUNCTION(joy_get, "") +{ + return joy_get_internal(L, true, true); +} +// joypad.getdown() +// returns a table of every game button that is currently held +DEFINE_LUA_FUNCTION(joy_getdown, "") +{ + return joy_get_internal(L, false, true); +} +// joypad.getup() +// returns a table of every game button that is not currently held +DEFINE_LUA_FUNCTION(joy_getup, "") +{ + return joy_get_internal(L, true, false); +} + +// table joypad.peek() +// +// Reads the joypad state (what the user is currently pressing/requesting) +int joy_peek_internal(lua_State* L, bool reportUp, bool reportDown) +{ + int index = 1; + (void)joy_getArgControllerNum(L, index); + + lua_newtable(L); + + const UserButtons& buttons = NDS_getRawUserInput().buttons; + + for(int i = 0; i < sizeof(button_mappings)/sizeof(*button_mappings); i++) + { + const char* name = button_mappings[i]; + bool pressed = buttons.array[i]; + if((pressed && reportDown) || (!pressed && reportUp)) + { + lua_pushboolean(L, pressed); + lua_setfield(L, -2, name); + } + } + + return 1; +} + +// joypad.peek() +// returns a table of every game button, +// true meaning currently-held and false meaning not-currently-held +// peek checks which joypad buttons are physically pressed, +// so it will NOT read input from a playing movie, +// it CAN read mid-frame input, +// and it will NOT pay attention to stuff like disabled L+R/U+D +DEFINE_LUA_FUNCTION(joy_peek, "") +{ + return joy_peek_internal(L, true, true); +} +// joypad.peekdown() +// returns a table of every game button that is currently held (according to what joypad.peek() would return) +DEFINE_LUA_FUNCTION(joy_peekdown, "") +{ + return joy_peek_internal(L, false, true); +} +// joypad.peekup() +// returns a table of every game button that is not currently held (according to what joypad.peek() would return) +DEFINE_LUA_FUNCTION(joy_peekup, "") +{ + return joy_peek_internal(L, true, false); +} + + +static const struct ColorMapping +{ + const char* name; + int value; +} +s_colorMapping [] = +{ + {"white", 0xFFFFFFFF}, + {"black", 0x000000FF}, + {"clear", 0x00000000}, + {"gray", 0x7F7F7FFF}, + {"grey", 0x7F7F7FFF}, + {"red", 0xFF0000FF}, + {"orange", 0xFF7F00FF}, + {"yellow", 0xFFFF00FF}, + {"chartreuse",0x7FFF00FF}, + {"green", 0x00FF00FF}, + {"teal", 0x00FF7FFF}, + {"cyan" , 0x00FFFFFF}, + {"blue", 0x0000FFFF}, + {"purple", 0x7F00FFFF}, + {"magenta", 0xFF00FFFF}, +}; + +inline int getcolor_unmodified(lua_State *L, int idx, int defaultColor) +{ + int type = lua_type(L,idx); + switch(type) + { + case LUA_TNUMBER: + { + return lua_tointeger(L,idx); + } break; + case LUA_TSTRING: + { + const char* str = lua_tostring(L,idx); + if(*str == '#') + { + int color; + sscanf(str+1, "%X", &color); + int len = strlen(str+1); + int missing = std::max(0, 8-len); + color <<= missing << 2; + if(missing >= 2) color |= 0xFF; + return color; + } + else for(int i = 0; i<sizeof(s_colorMapping)/sizeof(*s_colorMapping); i++) + { + if(!stricmp(str,s_colorMapping[i].name)) + return s_colorMapping[i].value; + } + if(!strnicmp(str, "rand", 4)) + return ((rand()*255/RAND_MAX) << 8) | ((rand()*255/RAND_MAX) << 16) | ((rand()*255/RAND_MAX) << 24) | 0xFF; + } break; + case LUA_TTABLE: + { + int color = 0xFF; + lua_pushnil(L); // first key + int keyIndex = lua_gettop(L); + int valueIndex = keyIndex + 1; + bool first = true; + while(lua_next(L, idx)) + { + bool keyIsString = (lua_type(L, keyIndex) == LUA_TSTRING); + bool keyIsNumber = (lua_type(L, keyIndex) == LUA_TNUMBER); + int key = keyIsString ? tolower(*lua_tostring(L, keyIndex)) : (keyIsNumber ? lua_tointeger(L, keyIndex) : 0); + int value = lua_tointeger(L, valueIndex); + if(value < 0) value = 0; + if(value > 255) value = 255; + switch(key) + { + case 1: case 'r': color |= value << 24; break; + case 2: case 'g': color |= value << 16; break; + case 3: case 'b': color |= value << 8; break; + case 4: case 'a': color = (color & ~0xFF) | value; break; + } + lua_pop(L, 1); + } + return color; + } break; + case LUA_TFUNCTION: + return 0; + } + return defaultColor; +} +int getcolor(lua_State *L, int idx, int defaultColor) +{ + int color = getcolor_unmodified(L, idx, defaultColor); + LuaContextInfo& info = GetCurrentInfo(); + if(info.transparencyModifier != 255) + { + int alpha = (((color & 0xFF) * info.transparencyModifier) / 255); + if(alpha > 255) alpha = 255; + color = (color & ~0xFF) | alpha; + } + return color; +} + +// r,g,b,a = gui.parsecolor(color) +// examples: +// local r,g,b = gui.parsecolor("green") +// local r,g,b,a = gui.parsecolor(0x7F3FFF7F) +DEFINE_LUA_FUNCTION(gui_parsecolor, "color") +{ + int color = getcolor_unmodified(L, 1, 0); + int r = (color & 0xFF000000) >> 24; + int g = (color & 0x00FF0000) >> 16; + int b = (color & 0x0000FF00) >> 8; + int a = (color & 0x000000FF); + lua_pushinteger(L, r); + lua_pushinteger(L, g); + lua_pushinteger(L, b); + lua_pushinteger(L, a); + return 4; +} + + + +static inline void blend32(u32 *dstPixel, u32 color) +{ + u8 *dst = (u8*) dstPixel; + int r = (color & 0xFF000000) >> 24; + int g = (color & 0x00FF0000) >> 16; + int b = (color & 0x0000FF00) >> 8; + int a = color & 0x000000FF; + + if (a == 255) { + // direct copy + dst[0] = b; + dst[1] = g; + dst[2] = r; + dst[3] = a; + } + else if (a == 0) { + // do not copy + } + else { + // alpha-blending + u8 bo = dst[0]; + u8 go = dst[1]; + u8 ro = dst[2]; + u8 ao = dst[3]; + dst[0] = (((b - bo) * a + (bo << 8)) >> 8); + dst[1] = (((g - go) * a + (go << 8)) >> 8); + dst[2] = (((r - ro) * a + (ro << 8)) >> 8); + dst[3] = ((a + ao) - ((a * ao + 0xFF) >> 8)); + } +} + +static LuaGUIData curGuiData; + +static void prepare_drawing() +{ + curGuiData = GetCurrentInfo().guiData; +} +static void prepare_reading() +{ + curGuiData = GetCurrentInfo().guiData; + u32* buf = (u32*)aggDraw.screen->buf().buf(); + if(buf) + { + curGuiData.data = buf; + curGuiData.stridePix = aggDraw.screen->buf().stride_abs() / 4; + } + else + { +#if defined(WIN32) && !defined(WXPORT) + extern VideoInfo video; + curGuiData.data = video.buffer; + curGuiData.stridePix = 256; +#endif + } +} + +// note: prepare_drawing or prepare_reading must be called, +// before any of the following bunch of gui functions will work properly. + + +// negative -> top +// positive -> bottom +// 0 -> both +static void restrict_to_screen(int ySelectScreen) +{ + if(ySelectScreen > 0) + curGuiData.yMin = (curGuiData.yMin + curGuiData.yMax) >> 1; + else if(ySelectScreen < 0) + curGuiData.yMax = (curGuiData.yMin + curGuiData.yMax) >> 1; +} + +// check if a pixel is in the lua canvas +static FORCEINLINE bool gui_checkboundary(int x, int y) { + return !(x < curGuiData.xMin || x >= curGuiData.xMax || y < curGuiData.yMin || y >= curGuiData.yMax); +} +static FORCEINLINE void gui_adjust_coord(int& x, int& y) { + x += curGuiData.xOrigin; + y += curGuiData.yOrigin; +} +static FORCEINLINE bool gui_checkbox(int x1, int y1, int x2, int y2) { + if((x1 < curGuiData.xMin && x2 < curGuiData.xMin) + || (x1 >= curGuiData.xMax && x2 >= curGuiData.xMax) + || (y1 < curGuiData.yMin && y2 < curGuiData.yMin) + || (y1 >= curGuiData.yMax && y2 >= curGuiData.yMax)) + return false; + return true; +} + +// write a pixel (do not check boundaries for speedup) +static FORCEINLINE void gui_drawpixel_unchecked(int x, int y, u32 color) { + blend32((u32*) &curGuiData.data[y*curGuiData.stridePix+x], color); +} + +// write a pixel (check boundaries) +static FORCEINLINE void gui_drawpixel_checked(int x, int y, u32 color) { + if (gui_checkboundary(x, y)) + gui_drawpixel_unchecked(x, y, color); +} + +static FORCEINLINE u32 gui_getpixel_unchecked(int x, int y) { + return curGuiData.data[y*curGuiData.stridePix+x]; +} +static FORCEINLINE u32 gui_adjust_coord_and_getpixel(int x, int y) { + x += curGuiData.xOrigin; + y += curGuiData.yOrigin; + x = min(max(x, curGuiData.xMin), curGuiData.xMax-1); + y = min(max(y, curGuiData.yMin), curGuiData.yMax-1); + return gui_getpixel_unchecked(x, y); +} + +// draw a line (checks boundaries) +static void gui_drawline_internal(int x1, int y1, int x2, int y2, bool lastPixel, u32 color) +{ + // Note: New version of Bresenham's Line Algorithm + // http://groups.google.co.jp/group/rec.games.roguelike.development/browse_thread/thread/345f4c42c3b25858/29e07a3af3a450e6?show_docid=29e07a3af3a450e6 + + int swappedx = 0; + int swappedy = 0; + + int xtemp = x1-x2; + int ytemp = y1-y2; + if (xtemp == 0 && ytemp == 0) { + gui_drawpixel_checked(x1, y1, color); + return; + } + if (xtemp < 0) { + xtemp = -xtemp; + swappedx = 1; + } + if (ytemp < 0) { + ytemp = -ytemp; + swappedy = 1; + } + + int delta_x = xtemp << 1; + int delta_y = ytemp << 1; + + signed char ix = x1 > x2?1:-1; + signed char iy = y1 > y2?1:-1; + + if (lastPixel) + gui_drawpixel_checked(x2, y2, color); + + if (delta_x >= delta_y) { + int error = delta_y - (delta_x >> 1); + + while (x2 != x1) { + if (error == 0 && !swappedx) + gui_drawpixel_checked(x2+ix, y2, color); + if (error >= 0) { + if (error || (ix > 0)) { + y2 += iy; + error -= delta_x; + } + } + x2 += ix; + gui_drawpixel_checked(x2, y2, color); + if (error == 0 && swappedx) + gui_drawpixel_checked(x2, y2+iy, color); + error += delta_y; + } + } + else { + int error = delta_x - (delta_y >> 1); + + while (y2 != y1) { + if (error == 0 && !swappedy) + gui_drawpixel_checked(x2, y2+iy, color); + if (error >= 0) { + if (error || (iy > 0)) { + x2 += ix; + error -= delta_y; + } + } + y2 += iy; + gui_drawpixel_checked(x2, y2, color); + if (error == 0 && swappedy) + gui_drawpixel_checked(x2+ix, y2, color); + error += delta_x; + } + } +} + +static const u8 Small_Font_Data[] = +{ +#define I +0, +#define a +1 +#define b +2 +#define c +4 +#define d +8 +#define e +16 +// !"#$%&' + I c I b d I I d I a b I c I c I + I c I b d I b d I c d e I a b e I b d I c I + I c I I a b c d e I b I d I b c I I + I c I I b d I b c I c I b I I + I c I I a b c d e I d e I b I a c e I I + I I I b d I e I a d e I a d I I + I c I I I b c d I d e I b c e I I + I I I I c I I I I +// ()*+,-./ + e I b I I I I I I e I + d I c I b e I c I I I I e I + d I c I c d I c I I I I d I + d I c I b c d e I a b c d e I I b c d e I I d I + d I c I c d I c I I I I c I + d I c I b e I c I d I I c d I c I + d I c I I I d I I c d I b I + e I b I I I c I I I b I +// 01234567 + c d I d I c d I c d I b e I b c d e I c d I b c d e I + b e I c d I b e I b e I b e I b I b e I e I + b e I d I e I e I b e I b I b I d I + b e I d I d I c d I b c d e I b c d I b c d I d I + b e I d I c I e I e I e I b e I c I + b e I d I b I b e I e I e I b e I c I + c d I c d e I b c d e I c d I e I b c d I c d I b I + I I I I I I I I +// 89:;<=>? + c d I c d I I I e I I b I c d I + b e I b e I I I d I I c I b e I + b e I b e I c d I d I c I b c d e I d I e I + c d I c d e I c d I d I b I I e I d I + b e I e I I I c I b c d e I d I c I + b e I b e I c d I d I d I I c I I + c d I c d I c d I d I e I I b I c I + I I I c I I I I I +// @ABCDEFG + b c d I c d I b c d I c d I b c d I b c d e I b c d e I c d I + a e I b e I b e I b e I b e I b I b I b e I + a d e I b e I b e I b I b e I b I b I b I + a c e I b c d e I b c d I b I b e I b c d I b c d I b I + a d e I b e I b e I b I b e I b I b I b d e I + a I b e I b e I b e I b e I b I b I b e I + b c d e I b e I b c d I c d I b c d I b c d e I b I c d e I + I I I I I I I I +// HIJKlMNO + b e I b c d I e I b e I b I a e I b e I b c d e I + b e I c I e I b e I b I a b d e I b c e I b e I + b e I c I e I b d I b I a c e I b d e I b e I + b c d e I c I e I b c I b I a c e I b e I b e I + b e I c I e I b d I b I a e I b e I b e I + b e I c I b e I b e I b I a e I b e I b e I + b e I b c d I c d I b e I b c d e I a e I b e I b c d e I + I I I I I I I I +// PQRSTUVW + b c d I c d I b c d I c d e I a b c d e I b e I a e I a e I + b e I b e I b e I b I c I b e I a e I a e I + b e I b e I b e I b I c I b e I a e I a e I + b c d I b e I b c d I c d I c I b e I a e I a e I + b I b e I b e I e I c I b e I b d I a c e I + b I b e I b e I e I c I b e I b d I a b d e I + b I c d I b e I b c d I c I c d I c I a e I + I d e I I I I I I I +// XYZ[\]^_ + a e I a e I a b c d e I d e I b I b c I c I I + a e I a e I e I d I b I c I b d I I + b d I a e I d I d I c I c I I I + c I b d I c I d I c I c I I I + b d I c I b I d I d I c I I I + a e I c I a I d I d I c I I I + a e I c I a b c d e I d I e I c I I I + I I I d e I e I b c I I a b c d e I +// `abcdefg + b I I b I I e I I d e I I + c I I b I I e I I c I I + I c d I b I c d I e I c d I c I c d e I + I e I b c d I b e I c d e I b e I b c d I b e I + I c d e I b e I b I b e I b c d e I c I b e I + I b e I b e I b I b e I b I c I c d e I + I c d e I b c d I c d e I c d e I c d e I c I e I + I I I I I I I c d I +// hijklmno + b I I I b I c I I I I + b I c I c I b I c I I I I + b I I I b I c I a b c d I b c d I c d I + b c d I c I c I b d e I c I a c e I b e I b e I + b e I c I c I b c I c I a c e I b e I b e I + b e I c I c I b d I c I a c e I b e I b e I + b e I c I c I b e I c I a e I b e I c d I + I I b I I I I I I +// pqrstuvw + I I I I c I I I I + I I I I c I I I I + b c d I c d e I b c d I c d e I b c d I b e I b e I a e I + b e I b e I b e I b I c I b e I b e I a e I + b e I b e I b I c d I c I b e I b e I a c e I + b c d I c d e I b I e I c I b e I c d I a b d e I + b I e I b I b c d I d I c d e I c d I a e I + b I e I I I I I I I +// xyz{|}~ + I I I d e I c I b c I I I + I I I d I c I c I I b d I + b e I b e I b c d e I d I c I c I c e I a c e I + c d I b e I e I c d I c I c d I b d I a e I + c d I b e I c d I c d I c I c d I I b d I + b e I c d e I b I d I c I c I I c I + b e I e I b c d e I d I c I c I I I + I b c d I I d e I c I b c I I I +#undef I +#undef a +#undef b +#undef c +#undef d +#undef e +}; + +template<int dxdx, int dydy, int dxdy, int dydx> +static void PutTextInternal (const char *str, int len, short x, short y, int color, int backcolor) +{ + int Opac = color & 0xFF; + int backOpac = backcolor & 0xFF; + int origX = x; + int origY = y; + + if(!Opac && !backOpac) + return; + + while(*str && len) + { + if(dydy > 0 && y >= curGuiData.yMax) break; + if(dydy < 0 && y < curGuiData.yMin) break; + if(dxdy > 0 && x >= curGuiData.xMax) break; + if(dxdy < 0 && x < curGuiData.xMin) break; + + int c = *str++; + if(dxdx > 0 && x >= curGuiData.xMax + || dxdx < 0 && x < curGuiData.xMin + || dydx > 0 && y >= curGuiData.yMax + || dydx < 0 && y < curGuiData.yMin) + { + while (c != '\n') { + c = *str; + if (c == '\0') + break; + str++; + } + } + + if(c == '\n') + { + if(dydy) + { + x = origX; + y += 10 * dydy; + } + else + { + y = origY; + x += 10 * dxdy; + } + continue; + } + else if(c == '\t') // just in case + { + const int tabSpace = 8; + x += (tabSpace-(((x-origX)/5)%tabSpace))*5*dxdx; + y += (tabSpace-(((y-origY)/5)%tabSpace))*5*dydx; + continue; + } + c -= 32; + if((unsigned int)c >= 96) + continue; + + if(c) + { + const u8* Cur_Glyph = (const unsigned char*)&Small_Font_Data + (c%8)+((c/8)*64); + for(int y2 = -1; y2 < 10; y2++) + { + for(int x2 = -1; x2 < 6; x2++) + { + bool on = y2 >= 0 && y2 < 8 && (Cur_Glyph[y2*8] & (1 << x2)); + if(on) + { + gui_drawpixel_checked(x+x2*dxdx+y2*dxdy, y+y2*dydy+x2*dydx, color); + } + else if(backOpac) + { + for(int y3 = max(0,y2-1); y3 <= min(7,y2+1); y3++) + { + for(int x3 = max(0,x2-1); x3 <= min(4,x2+1); x3++) + { + on |= y3 >= 0 && y3 < 8 && (Cur_Glyph[y3*8] & (1 << x3)); + if (on) + goto draw_outline; // speedup? + } + } + if(on) + { +draw_outline: + gui_drawpixel_checked(x+x2*dxdx+y2*dxdy, y+y2*dydy+x2*dydx, backcolor); + } + } + } + } + } + + x += 6*dxdx; + y += 6*dydx; + len--; + } +} + +static int strlinelen(const char* string) +{ + const char* s = string; + while(*s && *s != '\n') + s++; + if(*s) + s++; + return s - string; +} + +static void LuaDisplayString (const char *str, int x, int y, u32 color, u32 outlineColor) +{ + if(!str) + return; + +#if 1 + //if(rotate == 0) + PutTextInternal<1,1,0,0>(str, strlen(str), x, y, color, outlineColor); + //else if(rotate == 90) + // PutTextInternal<0,0,1,-1>(str, strlen(str), x, y, color, outlineColor); + //else if +#else + const char* ptr = str; + while(*ptr && y < curGuiData.yMax) + { + int len = strlinelen(ptr); + int skip = 0; + if(len < 1) len = 1; + + // break up the line if it's too long to display otherwise + if(len > 63) + { + len = 63; + const char* ptr2 = ptr + len-1; + for(int j = len-1; j; j--, ptr2--) + { + if(*ptr2 == ' ' || *ptr2 == '\t') + { + len = j; + skip = 1; + break; + } + } + } + + int xl = 0; + int yl = curGuiData.yMin; + int xh = (curGuiData.xMax - 1 - 1) - 4*len; + int yh = curGuiData.yMax - 1; + int x2 = min(max(x,xl),xh); + int y2 = min(max(y,yl),yh); + + PutTextInternal<1,1,0,0>(ptr,len,x2,y2,color,outlineColor); + + ptr += len + skip; + y += 8; + } +#endif +} + + + + +DEFINE_LUA_FUNCTION(gui_text, "x,y,str[,color=\"white\"[,outline=\"black\"]]") +{ + int x = luaL_checkinteger(L,1); // have to check for errors before deferring + int y = luaL_checkinteger(L,2); + + if(DeferGUIFuncIfNeeded(L)) + return 0; // we have to wait until later to call this function because we haven't emulated the next frame yet + // (the only way to avoid this deferring is to be in a gui.register or emu.registerafter callback) + + const char* str = toCString(L,3); // better than using luaL_checkstring here (more permissive) + + if(str && *str) + { + int foreColor = getcolor(L,4,0xFFFFFFFF); + int backColor = getcolor(L,5,0x000000FF); + + prepare_drawing(); + gui_adjust_coord(x,y); + + LuaDisplayString(str, x, y, foreColor, backColor); + } + + return 0; +} + +DEFINE_LUA_FUNCTION(gui_box, "x1,y1,x2,y2[,fill[,outline]]") +{ + int x1 = luaL_checkinteger(L,1); // have to check for errors before deferring + int y1 = luaL_checkinteger(L,2); + int x2 = luaL_checkinteger(L,3); + int y2 = luaL_checkinteger(L,4); + + if(DeferGUIFuncIfNeeded(L)) + return 0; + + int fillcolor = getcolor(L,5,0xFFFFFF3F); + int outlinecolor = getcolor(L,6,fillcolor|0xFF); + + prepare_drawing(); + restrict_to_screen(y1); + gui_adjust_coord(x1,y1); + gui_adjust_coord(x2,y2); + + if(!gui_checkbox(x1,y1,x2,y2)) + return 0; + + // require x1,y1 <= x2,y2 + if (x1 > x2) + std::swap(x1,x2); + if (y1 > y2) + std::swap(y1,y2); + + // avoid trying to draw lots of offscreen pixels + // (this is intentionally 1 out from the edge here) + x1 = min(max(x1, curGuiData.xMin-1), curGuiData.xMax); + x2 = min(max(x2, curGuiData.xMin-1), curGuiData.xMax); + y1 = min(max(y1, curGuiData.yMin-1), curGuiData.yMax); + y2 = min(max(y2, curGuiData.yMin-1), curGuiData.yMax); + + if(outlinecolor & 0xFF) + { + if(y1 >= curGuiData.yMin) + for (short x = x1+1; x < x2; x++) + gui_drawpixel_unchecked(x,y1,outlinecolor); + + if(x1 >= curGuiData.xMin && x1 < curGuiData.xMax) + { + if(y1 >= curGuiData.yMin) + gui_drawpixel_unchecked(x1,y1,outlinecolor); + for (short y = y1+1; y < y2; y++) + gui_drawpixel_unchecked(x1,y,outlinecolor); + if(y2 < curGuiData.yMax) + gui_drawpixel_unchecked(x1,y2,outlinecolor); + } + + if(y1 != y2 && y2 < curGuiData.yMax) + for (short x = x1+1; x < x2; x++) + gui_drawpixel_unchecked(x,y2,outlinecolor); + if(x1 != x2 && x2 >= curGuiData.xMin && x2 < curGuiData.xMax) + { + if(y1 >= curGuiData.yMin) + gui_drawpixel_unchecked(x2,y1,outlinecolor); + for (short y = y1+1; y < y2; y++) + gui_drawpixel_unchecked(x2,y,outlinecolor); + if(y2 < curGuiData.yMax) + gui_drawpixel_unchecked(x2,y2,outlinecolor); + } + } + + if(fillcolor & 0xFF) + { + for(short y = y1+1; y <= y2-1; y++) + for(short x = x1+1; x <= x2-1; x++) + gui_drawpixel_unchecked(x,y,fillcolor); + } + + return 0; +} +// gui.setpixel(x,y,color) +// color can be a RGB web color like '#ff7030', or with alpha RGBA like '#ff703060' +// or it can be an RGBA hex number like 0xFF703060 +// or it can be a preset color like 'red', 'orange', 'blue', 'white', etc. +DEFINE_LUA_FUNCTION(gui_pixel, "x,y[,color=\"white\"]") +{ + int x = luaL_checkinteger(L,1); // have to check for errors before deferring + int y = luaL_checkinteger(L,2); + + if(DeferGUIFuncIfNeeded(L)) + return 0; + + int color = getcolor(L,3,0xFFFFFFFF); + if(color & 0xFF) + { + prepare_drawing(); + gui_adjust_coord(x,y); + gui_drawpixel_checked(x, y, color); + } + + return 0; +} +// r,g,b = gui.getpixel(x,y) +DEFINE_LUA_FUNCTION(gui_getpixel, "x,y") +{ + prepare_reading(); + + int x = luaL_checkinteger(L,1); + int y = luaL_checkinteger(L,2); + + u32 color = gui_adjust_coord_and_getpixel(x,y); + + int b = (color & 0x000000FF); + int g = (color & 0x0000FF00) >> 8; + int r = (color & 0x00FF0000) >> 16; + + lua_pushinteger(L, r); + lua_pushinteger(L, g); + lua_pushinteger(L, b); + + return 3; +} +DEFINE_LUA_FUNCTION(gui_line, "x1,y1,x2,y2[,color=\"white\"[,skipfirst=false]]") +{ + int x1 = luaL_checkinteger(L,1); // have to check for errors before deferring + int y1 = luaL_checkinteger(L,2); + int x2 = luaL_checkinteger(L,3); + int y2 = luaL_checkinteger(L,4); + + if(DeferGUIFuncIfNeeded(L)) + return 0; + + int color = getcolor(L,5,0xFFFFFFFF); + int skipFirst = lua_toboolean(L,6); + + if(!(color & 0xFF)) + return 0; + + prepare_drawing(); + restrict_to_screen(y1); + gui_adjust_coord(x1,y1); + gui_adjust_coord(x2,y2); + + if(!gui_checkbox(x1,y1,x2,y2)) + return 0; + + gui_drawline_internal(x2, y2, x1, y1, !skipFirst, color); + + return 0; +} + +// gui.opacity(number alphaValue) +// sets the transparency of subsequent draw calls +// 0.0 is completely transparent, 1.0 is completely opaque +// non-integer values are supported and meaningful, as are values greater than 1.0 +// it is not necessary to use this function to get transparency (or the less-recommended gui.transparency() either), +// because you can provide an alpha value in the color argument of each draw call. +// however, it can be convenient to be able to globally modify the drawing transparency +DEFINE_LUA_FUNCTION(gui_setopacity, "alpha_0_to_1") +{ + lua_Number opacF = luaL_checknumber(L,1); + opacF *= 255.0; + if(opacF < 0) opacF = 0; + int opac; + lua_number2int(opac, opacF); + LuaContextInfo& info = GetCurrentInfo(); + info.transparencyModifier = opac; + return 0; +} + +// gui.transparency(number transparencyValue) +// sets the transparency of subsequent draw calls +// 0.0 is completely opaque, 4.0 is completely transparent +// non-integer values are supported and meaningful, as are values less than 0.0 +// this is a legacy function, and the range is from 0 to 4 solely for this reason +// it does the exact same thing as gui.opacity() but with a different argument range +DEFINE_LUA_FUNCTION(gui_settransparency, "transparency_4_to_0") +{ + lua_Number transp = luaL_checknumber(L,1); + lua_Number opacF = 4 - transp; + opacF *= 255.0 / 4.0; + if(opacF < 0) opacF = 0; + int opac; + lua_number2int(opac, opacF); + LuaContextInfo& info = GetCurrentInfo(); + info.transparencyModifier = opac; + return 0; +} + +// takes a screenshot and returns it in gdstr format +// example: gd.createFromGdStr(gui.gdscreenshot()):png("outputimage.png") +DEFINE_LUA_FUNCTION(gui_gdscreenshot, "[whichScreen='both']") +{ + prepare_reading(); + + int selectedScreen = 0; + if(lua_isboolean(L, 1)) + selectedScreen = lua_toboolean(L, 1) ? 1 : -1; + else if(lua_isnumber(L, 1)) + selectedScreen = lua_tointeger(L, 1); + else if(lua_isstring(L, 1)) + { + const char* str = lua_tostring(L, 1); + if(!stricmp(str,"top")) + selectedScreen = -1; + if(!stricmp(str,"bottom")) + selectedScreen = 1; + } + restrict_to_screen(selectedScreen); + + int width = curGuiData.xMax - curGuiData.xMin; + int height = curGuiData.yMax - curGuiData.yMin; + int size = 11 + width * height * 4; + + char* str = new char[size+1]; // TODO: use _alloca instead (but I don't know which compilers support it) + str[size] = 0; + unsigned char* ptr = (unsigned char*)str; + + // GD format header for truecolor image (11 bytes) + *ptr++ = (65534 >> 8) & 0xFF; + *ptr++ = (65534 ) & 0xFF; + *ptr++ = (width >> 8) & 0xFF; + *ptr++ = (width ) & 0xFF; + *ptr++ = (height >> 8) & 0xFF; + *ptr++ = (height ) & 0xFF; + *ptr++ = 1; + *ptr++ = 255; + *ptr++ = 255; + *ptr++ = 255; + *ptr++ = 255; + + u8* Src = (u8*)curGuiData.data + (curGuiData.stridePix*4) * curGuiData.yMin; + + for(int y = curGuiData.yMin; y < curGuiData.yMax; y++, Src += curGuiData.stridePix*4) + { + for(int x = curGuiData.xMin; x < curGuiData.xMax; x++) + { + *ptr++ = 255 - Src[4*x+3]; + *ptr++ = Src[4*x+2]; + *ptr++ = Src[4*x+1]; + *ptr++ = Src[4*x+0]; + } + } + + lua_pushlstring(L, str, size); + delete[] str; + return 1; +} + +// draws a gd image that's in gdstr format to the screen +// example: gui.gdoverlay(gd.createFromPng("myimage.png"):gdStr()) +DEFINE_LUA_FUNCTION(gui_gdoverlay, "[dx=0,dy=0,]gdimage[,sx=0,sy=0,width,height][,alphamul]") +{ + int xStartDst = 0; + int yStartDst = 0; + int xStartSrc = 0; + int yStartSrc = 0; + int width, height; + int numArgs = lua_gettop(L); + + int index = 1; + if(lua_type(L,index) == LUA_TNUMBER) + { + xStartDst = lua_tointeger(L,index++); + if(lua_type(L,index) == LUA_TNUMBER) + yStartDst = lua_tointeger(L,index++); + } + + luaL_checktype(L,index,LUA_TSTRING); // have to check for errors before deferring + + if(DeferGUIFuncIfNeeded(L)) + return 0; + + const unsigned char* ptr = (const unsigned char*)lua_tostring(L,index++); + + const bool defSrcRect = ((numArgs - index + 1) < 2); + if (!defSrcRect) { + xStartSrc = luaL_checkinteger(L, index++); + yStartSrc = luaL_checkinteger(L, index++); + width = luaL_checkinteger(L, index++); + height = luaL_checkinteger(L, index++); + } + + LuaContextInfo& info = GetCurrentInfo(); + int alphaMul = info.transparencyModifier; + if(lua_isnumber(L, index)) + alphaMul = (int)(alphaMul * lua_tonumber(L, index++)); + if(alphaMul <= 0) + return 0; + + // since there aren't that many possible opacity levels, + // do the opacity modification calculations beforehand instead of per pixel + int opacMap[256]; + for(int i = 0; i < 128; i++) + { + int opac = 255 - ((i << 1) | (i & 1)); // gdAlphaMax = 127, not 255 + opac = (opac * alphaMul) / 255; + if(opac < 0) opac = 0; + if(opac > 255) opac = 255; + opacMap[i] = opac; + } + for(int i = 128; i < 256; i++) + opacMap[i] = 0; // what should we do for them, actually? + + // GD format header for truecolor image (11 bytes) + ptr++; + bool trueColor = (*ptr++ == 254); + int gdWidth = *ptr++ << 8; + gdWidth |= *ptr++; + int gdHeight = *ptr++ << 8; + gdHeight |= *ptr++; + int bytespp = (trueColor ? 4 : 1); + if (defSrcRect) { + width = gdWidth; + height = gdHeight; + } + + if ((!trueColor && *ptr) || (trueColor && !*ptr)) { + luaL_error(L, "gdoverlay: inconsistent color type."); + return 0; + } + ptr++; + int colorsTotal = 0; + if (!trueColor) { + colorsTotal = *ptr++ << 8; + colorsTotal |= *ptr++; + } + int transparent = *ptr++ << 24; + transparent |= *ptr++ << 16; + transparent |= *ptr++ << 8; + transparent |= *ptr++; + struct { int r, g, b, a; } pal[256]; + if (!trueColor) for (int i = 0; i < 256; i++) { + pal[i].r = *ptr++; + pal[i].g = *ptr++; + pal[i].b = *ptr++; + pal[i].a = opacMap[*ptr++]; + } + + prepare_drawing(); + u8* Dst = (u8*)curGuiData.data; + gui_adjust_coord(xStartDst,yStartDst); + + int xMin = curGuiData.xMin; + int yMin = curGuiData.yMin; + int xMax = curGuiData.xMax - 1; + int yMax = curGuiData.yMax - 1; + int strideBytes = curGuiData.stridePix * 4; + + // limit source rect + if (xStartSrc < 0) { + width += xStartSrc; + xStartDst -= xStartSrc; + xStartSrc = 0; + } + if (yStartSrc < 0) { + height += yStartSrc; + yStartDst -= yStartSrc; + yStartSrc = 0; + } + if (xStartSrc + width >= gdWidth) + width = gdWidth - xStartSrc; + if (yStartSrc+height >= gdHeight) + height = gdHeight - yStartSrc; + if (width <= 0 || height <= 0) + return 0; + ptr += (yStartSrc * gdWidth + xStartSrc) * bytespp; + + Dst += yStartDst * strideBytes; + for(int y = yStartDst; y < height+yStartDst && y < yMax; y++, Dst += strideBytes) + { + if(y < yMin) + ptr += gdWidth * bytespp; + else + { + int xA = (xStartDst < xMin ? xMin : xStartDst); + int xB = (xStartDst+width > xMax ? xMax : xStartDst+width); + ptr += (xA - xStartDst) * bytespp; + for(int x = xA; x < xB; x++) + { + if (trueColor) { + int opac = opacMap[ptr[0]]; + u32 pix = (opac|(ptr[3]<<8)|(ptr[2]<<16)|(ptr[1]<<24)); + blend32((u32*)(Dst+x*4), pix); + ptr += 4; + } + else { + int palNo = ptr[0]; + u32 pix = (pal[palNo].a|(pal[palNo].b<<8)|(pal[palNo].g<<16)|(pal[palNo].r<<24)); + blend32((u32*)(Dst+x*4), pix); + ptr++; + } + } + ptr += (gdWidth - (xB - xStartDst)) * bytespp; + } + } + + return 0; +} + +static void GetCurrentScriptDir(char* buffer, int bufLen) +{ + LuaContextInfo& info = GetCurrentInfo(); + strncpy(buffer, info.lastFilename.c_str(), bufLen); + buffer[bufLen-1] = 0; + char* slash = std::max(strrchr(buffer, '/'), strrchr(buffer, '\\')); + if(slash) + slash[1] = 0; +} + +DEFINE_LUA_FUNCTION(emu_openscript, "filename") +{ +#if defined(WIN32) && !defined(WXPORT) + char curScriptDir[1024]; GetCurrentScriptDir(curScriptDir, 1024); // make sure we can always find scripts that are in the same directory as the current script + const char* filename = lua_isstring(L,1) ? lua_tostring(L,1) : NULL; + extern const char* OpenLuaScript(const char* filename, const char* extraDirToCheck, bool makeSubservient); + const char* errorMsg = OpenLuaScript(filename, curScriptDir, true); + if(errorMsg) + luaL_error(L, errorMsg); +#endif + return 0; +} + +DEFINE_LUA_FUNCTION(emu_reset, "") +{ + extern bool _HACK_DONT_STOPMOVIE; + _HACK_DONT_STOPMOVIE = true; + NDS_Reset(); + _HACK_DONT_STOPMOVIE = false; + return 0; +} + +static bool IsLuaMenuItem(PlatformMenuItem menuItem) +{ +#if defined(WIN32) && !defined(WXPORT) + return (menuItem >= IDC_LUAMENU_RESERVE_START && menuItem <= IDC_LUAMENU_RESERVE_END); +#else + return false; +#endif +} + +static bool SearchFreeMenuItem(PlatformMenu menu, PlatformMenuItem& menuItem) +{ +#if defined(WIN32) && !defined(WXPORT) + for (UINT menuItemId = IDC_LUAMENU_RESERVE_START; menuItemId <= IDC_LUAMENU_RESERVE_END; menuItemId++) + { + MENUITEMINFO mii; + ZeroMemory(&mii, sizeof(MENUITEMINFO)); + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_ID; + if (!GetMenuItemInfo(menu, menuItemId, FALSE, &mii) && + GetLastError() == ERROR_MENU_ITEM_NOT_FOUND) + { + menuItem = menuItemId; + return true; + } + } + return false; +#else + return false; +#endif +} + +static PlatformMenu AddSubMenu(PlatformMenu topMenu, PlatformMenu menu, const char* menuName) +{ +#if defined(WIN32) && !defined(WXPORT) + LuaContextInfo& info = GetCurrentInfo(); + MENUITEMINFO mii; + + // search existing submenu + for (int index = 0; index < GetMenuItemCount(menu); index++) + { + ZeroMemory(&mii, sizeof(MENUITEMINFO)); + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_ID | MIIM_SUBMENU | MIIM_STRING; + const UINT bufferSize = 128; + TCHAR menuItemText[bufferSize]; + mii.dwTypeData = menuItemText; + mii.cch = bufferSize; + GetMenuItemInfo(menu, index, TRUE, &mii); + + // if exists, return it + if (mii.hSubMenu != NULL && lstrcmp(menuName, mii.dwTypeData) == 0) + { + if (IsLuaMenuItem(mii.wID)) + { + info.menuData.subMenuData.push_back(LuaSubMenuData(menu, mii.hSubMenu, mii.wID)); + } + return mii.hSubMenu; + } + } + + // add new submenu + UINT subMenuId; + if (!SearchFreeMenuItem(topMenu, subMenuId)) + { + return NULL; + } + ZeroMemory(&mii, sizeof(MENUITEMINFO)); + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_SUBMENU; + mii.fType = MFT_STRING; + mii.fState = MFS_ENABLED; + mii.wID = subMenuId; + mii.hSubMenu = CreatePopupMenu(); + mii.dwTypeData = (char*) menuName; + if (!InsertMenuItem(menu, (UINT)-1, TRUE, &mii)) + { + if (mii.hSubMenu != NULL) + { + DestroyMenu(mii.hSubMenu); + } + return NULL; + } + info.menuData.subMenuData.push_back(LuaSubMenuData(menu, mii.hSubMenu, subMenuId)); + return mii.hSubMenu; +#else + return 0; +#endif +} + +bool AddMenuEntries(PlatformMenu topMenu, PlatformMenu menu) +{ +#if defined(WIN32) && !defined(WXPORT) + LuaContextInfo& info = GetCurrentInfo(); + lua_State* L = info.L; + luaL_checktype(L, -1, LUA_TTABLE); + luaL_checkstack(L, 6, ""); + + // for index = 1, #menuEntries + unsigned int count = lua_objlen(L, -1); + for (unsigned int index = 1; index <= count; index++) + { + // switch(type(menuEntries[index])) + lua_rawgeti(L, -1, index); + if (lua_isnil(L, -1)) + { + UINT menuItem; + if (!SearchFreeMenuItem(topMenu, menuItem)) + { + luaL_error(L, "too many menu items"); + return false; + } + + MENUITEMINFO mii; + ZeroMemory(&mii, sizeof(MENUITEMINFO)); + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_ID | MIIM_FTYPE; + mii.wID = menuItem; + mii.fType = MFT_SEPARATOR; + if (!InsertMenuItem(menu, menuItem, FALSE, &mii)) + { + luaL_error(L, "menu item addition failed"); + return false; + } + info.menuData.menuItemMap.insert(map<PlatformMenuItem, PlatformMenu>::value_type(menuItem, menu)); + lua_pop(L, 1); + } + else if (lua_istable(L, -1)) + { + lua_rawgeti(L, -1, 1); + const char* menuName = luaL_checkstring(L, -1); + lua_insert(L, -2); + + lua_rawgeti(L, -1, 2); + if (lua_isfunction(L, -1)) + { + UINT menuItem; + if (!SearchFreeMenuItem(topMenu, menuItem)) + { + luaL_error(L, "too many menu items"); + return false; + } + + MENUITEMINFO mii; + ZeroMemory(&mii, sizeof(MENUITEMINFO)); + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_ID | MIIM_STRING; + mii.wID = menuItem; + mii.dwTypeData = (char*) menuName; + if (!InsertMenuItem(menu, menuItem, FALSE, &mii)) + { + luaL_error(L, "menu item addition failed"); + return false; + } + info.menuData.menuItemMap.insert(map<PlatformMenuItem, PlatformMenu>::value_type(menuItem, menu)); + + lua_getfield(L, LUA_REGISTRYINDEX, menuCallbackIDString); + lua_insert(L, -2); + lua_rawseti(L, -2, menuItem); + + lua_pop(L, 3); + } + else if (lua_istable(L, -1)) + { + HMENU subMenu = AddSubMenu(topMenu, menu, menuName); + if (subMenu == NULL) + { + luaL_error(L, "menu item addition failed"); + return false; + } + if (!AddMenuEntries(topMenu, subMenu)) + { + return false; + } + lua_pop(L, 3); + } + else + { + luaL_typerror(L, -1, "function or table"); + return false; + } + } + else + { + luaL_typerror(L, -1, "nil or table"); + return false; + } + } + return true; +#else + return false; +#endif +} + +DEFINE_LUA_FUNCTION(emu_addmenu, "menuName, menuEntries") +{ +#if defined(WIN32) && !defined(WXPORT) + int nargs = lua_gettop(L); + if (nargs > 1 && !lua_isnil(L, 1)) + { + const char* menuName = luaL_checkstring(L, 1); + luaL_checktype(L, 2, LUA_TTABLE); + lua_settop(L, 2); // drop redundant args + + HMENU menu = mainMenu; + HMENU subMenu = AddSubMenu(menu, menu, menuName); + if (subMenu != NULL) + { + AddMenuEntries(menu, subMenu); + DrawMenuBar(MainWindow->getHWnd()); + } + else + { + luaL_error(L, "menu item addition failed"); + } + } + else + { + //HMENU menu = NULL; // TODO: set popup (right-click) menu + //int index = (nargs > 1) ? 2 : 1; + //luaL_checktype(L, index, LUA_TTABLE); + //lua_settop(L, index); // drop redundant args + //AddMenuEntries(menu, menu); + } +#endif + return 0; +} + +DEFINE_LUA_FUNCTION(emu_setmenuiteminfo, "menuItem, infoTable") +{ + luaL_checktype(L, 1, LUA_TFUNCTION); + luaL_checktype(L, 2, LUA_TTABLE); +#if defined(WIN32) && !defined(WXPORT) + LuaContextInfo& info = GetCurrentInfo(); + map<PlatformMenuItem, PlatformMenu>::iterator it = info.menuData.menuItemMap.begin(); + while(it != info.menuData.menuItemMap.end()) + { + HMENU menu = (*it).second; + UINT menuItem = (*it).first; + lua_getfield(L, LUA_REGISTRYINDEX, menuCallbackIDString); + lua_rawgeti(L, -1, menuItem); + if (lua_rawequal(L, 1, -1) != 0) + { + MENUITEMINFO mii; + ZeroMemory(&mii, sizeof(MENUITEMINFO)); + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_STATE | MIIM_STRING; + GetMenuItemInfo(menu, menuItem, FALSE, &mii); + + mii.fMask = 0; + + lua_getfield(L, 2, "enabled"); + if (lua_isboolean(L, -1)) + { + mii.fMask |= MIIM_STATE; + if (lua_toboolean(L, -1) != 0) + { + mii.fState &= ~MFS_DISABLED; + } + else + { + mii.fState |= MFS_DISABLED; + } + } + else if (!lua_isnil(L, -1)) + { + luaL_where(L, 0); + luaL_error(L, "%s bad argument \"enabled\" (boolean expected, got %s)", + luaL_optstring(L, -1, ""), luaL_typename(L, -2)); + } + lua_pop(L, 1); + + lua_getfield(L, 2, "checked"); + if (lua_isboolean(L, -1)) + { + mii.fMask |= MIIM_STATE; + if (lua_toboolean(L, -1) != 0) + { + mii.fState |= MFS_CHECKED; + } + else + { + mii.fState &= ~MFS_CHECKED; + } + } + else if (!lua_isnil(L, -1)) + { + luaL_where(L, 0); + luaL_error(L, "%s bad argument \"checked\" (boolean expected, got %s)", + luaL_optstring(L, -1, ""), luaL_typename(L, -2)); + } + lua_pop(L, 1); + + lua_getfield(L, 2, "name"); + if (lua_isstring(L, -1)) + { + mii.fMask |= MIIM_STRING; + mii.dwTypeData = (LPSTR) lua_tostring(L, -1); + } + else if (!lua_isnil(L, -1)) + { + luaL_where(L, 0); + luaL_error(L, "%s bad argument \"name\" (string expected, got %s)", + luaL_optstring(L, -1, ""), luaL_typename(L, -2)); + } + SetMenuItemInfo(menu, menuItem, FALSE, &mii); + lua_pop(L, 1); + } + lua_pop(L, 1); + it++; + } +#endif + return 0; +} + +DEFINE_LUA_FUNCTION(emu_registermenustart, "func") +{ + if (!lua_isnil(L,1)) + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L,1); + lua_getfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_ONINITMENU]); + lua_insert(L,1); + lua_setfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_ONINITMENU]); + StopScriptIfFinished(luaStateToUIDMap[L->l_G->mainthread]); + return 1; +} + +// TODO +/* +DEFINE_LUA_FUNCTION(emu_loadrom, "filename") +{ + struct Temp { Temp() {EnableStopAllLuaScripts(false);} ~Temp() {EnableStopAllLuaScripts(true);}} dontStopScriptsHere; + const char* filename = lua_isstring(L,1) ? lua_tostring(L,1) : NULL; + char curScriptDir[1024]; GetCurrentScriptDir(curScriptDir, 1024); + filename = MakeRomPathAbsolute(filename, curScriptDir); + int result = GensLoadRom(filename); + if(result <= 0) + luaL_error(L, "Failed to load ROM \"%s\": %s", filename, result ? "invalid or unsupported" : "cancelled or not found"); + CallRegisteredLuaFunctions(LUACALL_ONSTART); + return 0; +} +*/ +DEFINE_LUA_FUNCTION(emu_getframecount, "") +{ + lua_pushinteger(L, currFrameCounter); + return 1; +} +DEFINE_LUA_FUNCTION(emu_getlagcount, "") +{ + lua_pushinteger(L, TotalLagFrames); + return 1; +} +DEFINE_LUA_FUNCTION(emu_lagged, "") +{ + lua_pushboolean(L, LagFrameFlag); + return 1; +} +DEFINE_LUA_FUNCTION(emu_emulating, "") +{ + lua_pushboolean(L, driver->EMU_HasEmulationStarted()); + return 1; +} +DEFINE_LUA_FUNCTION(emu_atframeboundary, "") +{ + lua_pushboolean(L, driver->EMU_IsAtFrameBoundary()); + return 1; +} +DEFINE_LUA_FUNCTION(movie_getlength, "") +{ + lua_pushinteger(L, currMovieData.records.size()); + return 1; +} +DEFINE_LUA_FUNCTION(movie_isactive, "") +{ + lua_pushboolean(L, movieMode != MOVIEMODE_INACTIVE); + return 1; +} +DEFINE_LUA_FUNCTION(movie_rerecordcount, "") +{ + lua_pushinteger(L, currMovieData.rerecordCount); + return 1; +} +DEFINE_LUA_FUNCTION(movie_setrerecordcount, "") +{ + currMovieData.rerecordCount = luaL_checkinteger(L, 1); + return 0; +} +DEFINE_LUA_FUNCTION(emu_rerecordcounting, "[enabled]") +{ + LuaContextInfo& info = GetCurrentInfo(); + if(lua_gettop(L) == 0) + { + // if no arguments given, return the current value + lua_pushboolean(L, !info.rerecordCountingDisabled); + return 1; + } + else + { + // set rerecord disabling + info.rerecordCountingDisabled = !lua_toboolean(L,1); + return 0; + } +} +DEFINE_LUA_FUNCTION(movie_getreadonly, "") +{ + lua_pushboolean(L, movie_readonly); + return 1; +} +DEFINE_LUA_FUNCTION(movie_setreadonly, "readonly") +{ + movie_readonly = lua_toboolean(L,1) != 0; + +// else if(!movie_readonly) +// luaL_error(L, "movie.setreadonly failed: write permission denied"); + + return 0; +} +DEFINE_LUA_FUNCTION(movie_isrecording, "") +{ + lua_pushboolean(L, movieMode == MOVIEMODE_RECORD); + return 1; +} +DEFINE_LUA_FUNCTION(movie_isplaying, "") +{ + lua_pushboolean(L, movieMode == MOVIEMODE_PLAY); + return 1; +} +DEFINE_LUA_FUNCTION(movie_getmode, "") +{ + switch(movieMode) + { + case MOVIEMODE_PLAY: + lua_pushstring(L, "playback"); + break; + case MOVIEMODE_RECORD: + lua_pushstring(L, "record"); + break; + case MOVIEMODE_INACTIVE: + lua_pushstring(L, "inactive"); + break; + case MOVIEMODE_FINISHED: + lua_pushstring(L, "finished"); + break; + default: + lua_pushnil(L); + break; + } + return 1; +} +DEFINE_LUA_FUNCTION(movie_getname, "") +{ + extern char curMovieFilename[512]; + lua_pushstring(L, curMovieFilename); + return 1; +} +// movie.play() -- plays a movie of the user's choice +// movie.play(filename) -- starts playing a particular movie +// throws an error (with a description) if for whatever reason the movie couldn't be played +DEFINE_LUA_FUNCTION(movie_play, "[filename]") +{ + const char* filename = lua_isstring(L,1) ? lua_tostring(L,1) : NULL; + const char* errorMsg = FCEUI_LoadMovie(filename, true, false, 0); + if(errorMsg) + luaL_error(L, errorMsg); + return 0; +} +DEFINE_LUA_FUNCTION(movie_replay, "") +{ + if(movieMode == MOVIEMODE_INACTIVE) + return 0; + lua_settop(L, 0); + extern char curMovieFilename[512]; + lua_pushstring(L, curMovieFilename); + return movie_play(L); +} +DEFINE_LUA_FUNCTION(movie_close, "") +{ + FCEUI_StopMovie(); + return 0; +} + +DEFINE_LUA_FUNCTION(sound_clear, "") +{ + SPU_ClearOutputBuffer(); + return 0; +} + +#if defined(_WIN32) && !defined(WXPORT) +const char* s_keyToName[256] = +{ + NULL, + "leftclick", + "rightclick", + NULL, + "middleclick", + NULL, + NULL, + NULL, + "backspace", + "tab", + NULL, + NULL, + NULL, + "enter", + NULL, + NULL, + "shift", // 0x10 + "control", + "alt", + "pause", + "capslock", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "escape", + NULL, + NULL, + NULL, + NULL, + "space", // 0x20 + "pageup", + "pagedown", + "end", + "home", + "left", + "up", + "right", + "down", + NULL, + NULL, + NULL, + NULL, + "insert", + "delete", + NULL, + "0","1","2","3","4","5","6","7","8","9", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "A","B","C","D","E","F","G","H","I","J", + "K","L","M","N","O","P","Q","R","S","T", + "U","V","W","X","Y","Z", + NULL, + NULL, + NULL, + NULL, + NULL, + "numpad0","numpad1","numpad2","numpad3","numpad4","numpad5","numpad6","numpad7","numpad8","numpad9", + "numpad*","numpad+", + NULL, + "numpad-","numpad.","numpad/", + "F1","F2","F3","F4","F5","F6","F7","F8","F9","F10","F11","F12", + "F13","F14","F15","F16","F17","F18","F19","F20","F21","F22","F23","F24", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "numlock", + "scrolllock", + NULL, // 0x92 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, // 0xB9 + "semicolon", + "plus", + "comma", + "minus", + "period", + "slash", + "tilde", + NULL, // 0xC1 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, // 0xDA + "leftbracket", + "backslash", + "rightbracket", + "quote", +}; +#endif + + +// input.get() +// takes no input, returns a lua table of entries representing the current input state, +// independent of the joypad buttons the emulated game thinks are pressed +// for example: +// if the user is holding the W key and the left mouse button +// and has the mouse at the bottom-right corner of the game screen, +// then this would return {W=true, leftclick=true, xmouse=319, ymouse=223} +DEFINE_LUA_FUNCTION(input_getcurrentinputstatus, "") +{ + lua_newtable(L); + +#if defined(_WIN32) && !defined(WXPORT) + // keyboard and mouse button status + { + extern bool allowBackgroundInput; + + unsigned char keys [256]; + if(!allowBackgroundInput) + { + if(GetKeyboardState(keys)) + { + for(int i = 1; i < 255; i++) + { + int mask = (i == VK_CAPITAL || i == VK_NUMLOCK || i == VK_SCROLL) ? 0x01 : 0x80; + if(keys[i] & mask) + { + const char* name = s_keyToName[i]; + if(name) + { + lua_pushboolean(L, true); + lua_setfield(L, -2, name); + } + } + } + } + } + else // use a slightly different method that will detect background input: + { + for(int i = 1; i < 255; i++) + { + const char* name = s_keyToName[i]; + if(name) + { + int active; + if(i == VK_CAPITAL || i == VK_NUMLOCK || i == VK_SCROLL) + active = GetKeyState(i) & 0x01; + else + active = GetAsyncKeyState(i) & 0x8000; + if(active) + { + lua_pushboolean(L, true); + lua_setfield(L, -2, name); + } + } + } + } + } + // mouse position in game screen pixel coordinates + { + void UnscaleScreenCoords(s32& x, s32& y); + void ToDSScreenRelativeCoords(s32& x, s32& y, int bottomScreen); + + POINT point; + GetCursorPos(&point); + ScreenToClient(MainWindow->getHWnd(), &point); + s32 x (point.x); + s32 y (point.y); + + UnscaleScreenCoords(x,y); + ToDSScreenRelativeCoords(x,y,1); + + lua_pushinteger(L, x); + lua_setfield(L, -2, "xmouse"); + lua_pushinteger(L, y); + lua_setfield(L, -2, "ymouse"); + } + + worry(L,10); +#else + // NYI (well, return an empty table) +#endif + + return 1; +} + + +// resets our "worry" counter of the Lua state +int dontworry(LuaContextInfo& info) +{ + if(info.stopWorrying) + { + info.stopWorrying = false; + if(info.worryCount) + indicateBusy(info.L, false); + } + info.worryCount = 0; + return 0; +} + +//agg basic shapes +//TODO polygon and polyline, maybe the overloads for roundedRect and curve + +#include "aggdraw.h" + +static int line(lua_State *L) { + + double x1,y1,x2,y2; + x1 = luaL_checknumber(L,1) + 0.5; + y1 = luaL_checknumber(L,2) + 0.5; + x2 = luaL_checknumber(L,3) + 0.5; + y2 = luaL_checknumber(L,4) + 0.5; + + aggDraw.hud->line(x1, y1, x2, y2); + + return 0; +} + +static int triangle(lua_State *L) { + + double x1,y1,x2,y2,x3,y3; + x1 = luaL_checknumber(L,1) + 0.5; + y1 = luaL_checknumber(L,2) + 0.5; + x2 = luaL_checknumber(L,3) + 0.5; + y2 = luaL_checknumber(L,4) + 0.5; + x3 = luaL_checknumber(L,5) + 0.5; + y3 = luaL_checknumber(L,6) + 0.5; + + aggDraw.hud->triangle(x1, y1, x2, y2, x3, y3); + + return 0; +} + +static int rectangle(lua_State *L) { + + double x1,y1,x2,y2; + x1 = luaL_checknumber(L,1) + 0.5; + y1 = luaL_checknumber(L,2) + 0.5; + x2 = luaL_checknumber(L,3) + 0.5; + y2 = luaL_checknumber(L,4) + 0.5; + + aggDraw.hud->rectangle(x1, y1, x2, y2); + + return 0; +} + +static int roundedRect(lua_State *L) { + + double x1,y1,x2,y2,r; + x1 = luaL_checknumber(L,1) + 0.5; + y1 = luaL_checknumber(L,2) + 0.5; + x2 = luaL_checknumber(L,3) + 0.5; + y2 = luaL_checknumber(L,4) + 0.5; + r = luaL_checknumber(L,5); + + aggDraw.hud->roundedRect(x1, y1, x2, y2, r); + + return 0; +} + +static int ellipse(lua_State *L) { + + double cx,cy,rx,ry; + cx = luaL_checknumber(L,1) + 0.5; + cy = luaL_checknumber(L,2) + 0.5; + rx = luaL_checknumber(L,3); + ry = luaL_checknumber(L,4); + + aggDraw.hud->ellipse(cx, cy, rx, ry); + + return 0; +} + +static int arc(lua_State *L) { + + double cx,cy,rx,ry,start,sweep; + cx = luaL_checknumber(L,1) + 0.5; + cy = luaL_checknumber(L,2) + 0.5; + rx = luaL_checknumber(L,3); + ry = luaL_checknumber(L,4); + start = luaL_checknumber(L,5); + sweep = luaL_checknumber(L,6); + + aggDraw.hud->arc(cx, cy,rx, ry, start, sweep); + + return 0; +} + +static int star(lua_State *L) { + + double cx,cy,r1,r2,startAngle; + int numRays; + cx = luaL_checknumber(L,1) + 0.5; + cy = luaL_checknumber(L,2) + 0.5; + r1 = luaL_checknumber(L,3); + r2 = luaL_checknumber(L,4); + startAngle = luaL_checknumber(L,5); + numRays = luaL_checkinteger(L,6); + + aggDraw.hud->star(cx, cy, r1, r2, startAngle, numRays); + + return 0; +} + +static int curve(lua_State *L) { + + double x1,y1,x2,y2,x3,y3; + x1 = luaL_checknumber(L,1) + 0.5; + y1 = luaL_checknumber(L,2) + 0.5; + x2 = luaL_checknumber(L,3) + 0.5; + y2 = luaL_checknumber(L,4) + 0.5; + x3 = luaL_checknumber(L,5) + 0.5; + y3 = luaL_checknumber(L,6) + 0.5; + + aggDraw.hud->curve(x1, y1, x2, y2, x3, y3); + + return 0; +} + +static const struct luaL_reg aggbasicshapes [] = +{ + {"line", line}, + {"triangle", triangle}, + {"rectangle", rectangle}, + {"roundedRect", roundedRect}, + {"ellipse", ellipse}, + {"arc", arc}, + {"star", star}, + {"curve", curve}, +// {"polygon", polygon}, +// {"polyline", polyline}, + {NULL, NULL} +}; + +//agg general attributes +//TODO missing functions, maybe the missing overloads + +static void getColorForAgg(lua_State *L, int&r,int&g,int&b,int&a) +{ + if(lua_gettop(L) == 1) + { + int color = getcolor(L, 1, 0xFF); + r = (color & 0xFF000000) >> 24; + g = (color & 0x00FF0000) >> 16; + b = (color & 0x0000FF00) >> 8; + a = (color & 0x000000FF); + } + else + { + r = luaL_optinteger(L,1,255); + g = luaL_optinteger(L,2,255); + b = luaL_optinteger(L,3,255); + a = luaL_optinteger(L,4,255); + } +} + +static int fillColor(lua_State *L) { + + int r,g,b,a; + getColorForAgg(L, r,g,b,a); + + aggDraw.hud->fillColor(r, g, b, a); + + return 0; +} + +static int noFill(lua_State *L) { + + aggDraw.hud->noFill(); + return 0; +} + +static int lineColor(lua_State *L) { + + int r,g,b,a; + getColorForAgg(L, r,g,b,a); + + aggDraw.hud->lineColor(r, g, b, a); + + return 0; +} + +static int noLine(lua_State *L) { + + aggDraw.hud->noLine(); + return 0; +} + +static int lineWidth(lua_State *L) { + + double w; + w = luaL_checknumber(L,1); + + aggDraw.hud->lineWidth(w); + + return 0; +} + +static const struct luaL_reg agggeneralattributes [] = +{ +// {"blendMode", blendMode}, +// {"imageBlendMode", imageBlendMode}, +// {"imageBlendColor", imageBlendColor}, +// {"masterAlpha", masterAlpha}, +// {"antiAliasGamma", antiAliasGamma}, +// {"font", font}, + {"fillColor", fillColor}, + {"noFill", noFill}, + {"lineColor", lineColor}, + {"noLine", noLine}, +// {"fillLinearGradient", fillLinearGradient}, +// {"lineLinearGradient", lineLinearGradient}, +// {"fillRadialGradient", fillRadialGradient}, +// {"lineRadialGradient", lineRadialGradient}, + {"lineWidth", lineWidth}, +// {"lineCap", lineCap}, +// {"lineJoin", lineJoin}, +// {"fillEvenOdd", fillEvenOdd}, + {NULL, NULL} +}; + +static int setFont(lua_State *L) { + + const char *choice; + choice = luaL_checkstring(L,1); + + aggDraw.hud->setFont(choice); + return 0; +} + +static int text(lua_State *L) { + int x, y; + const char *choice; + + x = luaL_checkinteger(L, 1); + y = luaL_checkinteger(L, 2); + choice = luaL_checkstring(L,3); + + aggDraw.hud->renderTextDropshadowed(x,y,choice); + return 0; +} + +static const struct luaL_reg aggcustom [] = +{ + {"setFont", setFont}, + {"text", text}, + {NULL, NULL} +}; + + +// gui.osdtext(int x, int y, string msg) +// +// Displays the given text on the screen, using the same font and techniques as the +// main HUD. +// +static int gui_osdtext(lua_State *L) +{ + int x = luaL_checkinteger(L,1); // have to check for errors before deferring + int y = luaL_checkinteger(L,2); + + if(DeferGUIFuncIfNeeded(L)) + return 0; // we have to wait until later to call this function because we haven't emulated the next frame yet + // (the only way to avoid this deferring is to be in a gui.register or emu.registerafter callback) + + const char* msg = toCString(L,3); + + osd->addFixed(x, y, "%s", msg); + + return 0; +} + +static int stylus_read(lua_State *L){ + + lua_newtable(L); + + lua_pushinteger(L, nds.scr_touchX >> 4); + lua_setfield(L, -2, "x"); + lua_pushinteger(L, nds.scr_touchY >> 4); + lua_setfield(L, -2, "y"); + lua_pushboolean(L, nds.isTouch); + lua_setfield(L, -2, "touch"); + + return 1; +} +static int stylus_peek(lua_State *L){ + + lua_newtable(L); + + lua_pushinteger(L, NDS_getRawUserInput().touch.touchX >> 4); + lua_setfield(L, -2, "x"); + lua_pushinteger(L, NDS_getRawUserInput().touch.touchY >> 4); + lua_setfield(L, -2, "y"); + lua_pushboolean(L, NDS_getRawUserInput().touch.isTouch?1:0); + lua_setfield(L, -2, "touch"); + + return 1; +} +static int toTouchValue(int pixCoord, int maximum) +{ + pixCoord = std::min(std::max(pixCoord, 0), maximum-1); + return (pixCoord << 4) & 0x0FF0; +} +static int stylus_write(lua_State *L) +{ + if(movieMode == MOVIEMODE_PLAY) // don't allow tampering with a playing movie's input + return 0; // (although it might be useful sometimes...) + + if(!NDS_isProcessingUserInput()) + { + // defer this function until when we are processing input + DeferFunctionCall(L, deferredJoySetIDString); + return 0; + } + + int index = 1; + luaL_checktype(L, index, LUA_TTABLE); + + UserTouch& touch = NDS_getProcessingUserInput().touch; + + lua_getfield(L, index, "x"); + if (!lua_isnil(L,-1)) + touch.touchX = toTouchValue(lua_tointeger(L, -1), 256); + lua_pop(L, 1); + + lua_getfield(L, index, "y"); + if (!lua_isnil(L,-1)) + touch.touchY = toTouchValue(lua_tointeger(L, -1), 192); + lua_pop(L, 1); + + lua_getfield(L, index, "touch"); + if (!lua_isnil(L,-1)) + touch.isTouch = lua_toboolean(L, -1) ? true : false; + lua_pop(L, 1); + + return 0; +} + +static int gcEMUFILE_MEMORY(lua_State *L) +{ + EMUFILE_MEMORY** ppEmuFile = (EMUFILE_MEMORY**)luaL_checkudata(L, 1, "EMUFILE_MEMORY*"); + delete (*ppEmuFile); + *ppEmuFile = 0; + return 0; +} + + +static const struct luaL_reg styluslib [] = +{ + {"get", stylus_read}, + {"peek", stylus_peek}, + {"set", stylus_write}, + // alternative names + {"read", stylus_read}, + {"write", stylus_write}, + {NULL, NULL} +}; + +static const struct luaL_reg emulib [] = +{ + {"frameadvance", emu_frameadvance}, + {"speedmode", emu_speedmode}, + {"wait", emu_wait}, + {"pause", emu_pause}, + {"unpause", emu_unpause}, + {"emulateframe", emu_emulateframe}, + {"emulateframefastnoskipping", emu_emulateframefastnoskipping}, + {"emulateframefast", emu_emulateframefast}, + {"emulateframeinvisible", emu_emulateframeinvisible}, + {"redraw", emu_redraw}, + {"framecount", emu_getframecount}, + {"lagcount", emu_getlagcount}, + {"lagged", emu_lagged}, + {"emulating", emu_emulating}, + {"atframeboundary", emu_atframeboundary}, + {"registerbefore", emu_registerbefore}, + {"registerafter", emu_registerafter}, + {"registerstart", emu_registerstart}, + {"registerexit", emu_registerexit}, + {"persistglobalvariables", emu_persistglobalvariables}, + {"message", emu_message}, + {"print", print}, // sure, why not + {"openscript", emu_openscript}, +// {"loadrom", emu_loadrom}, + {"reset", emu_reset}, + {"addmenu", emu_addmenu}, + {"setmenuiteminfo", emu_setmenuiteminfo}, + {"registermenustart", emu_registermenustart}, + // alternative names +// {"openrom", emu_loadrom}, + {NULL, NULL} +}; +static const struct luaL_reg guilib [] = +{ + {"register", gui_register}, + {"text", gui_text}, + {"box", gui_box}, + {"line", gui_line}, + {"pixel", gui_pixel}, + {"getpixel", gui_getpixel}, + {"opacity", gui_setopacity}, + {"transparency", gui_settransparency}, + {"popup", gui_popup}, + {"parsecolor", gui_parsecolor}, + {"gdscreenshot", gui_gdscreenshot}, + {"gdoverlay", gui_gdoverlay}, + {"redraw", emu_redraw}, // some people might think of this as more of a GUI function + {"osdtext", gui_osdtext}, + // alternative names + {"drawtext", gui_text}, + {"drawbox", gui_box}, + {"drawline", gui_line}, + {"drawpixel", gui_pixel}, + {"setpixel", gui_pixel}, + {"writepixel", gui_pixel}, + {"readpixel", gui_getpixel}, + {"rect", gui_box}, + {"drawrect", gui_box}, + {"drawimage", gui_gdoverlay}, + {"image", gui_gdoverlay}, + {NULL, NULL} +}; +static const struct luaL_reg statelib [] = +{ + {"create", state_create}, + {"save", state_save}, + {"load", state_load}, +#ifndef PUBLIC_RELEASE + {"verify", state_verify}, // for desync catching +#endif + // TODO + //{"loadscriptdata", state_loadscriptdata}, + //{"savescriptdata", state_savescriptdata}, + //{"registersave", state_registersave}, + //{"registerload", state_registerload}, + {NULL, NULL} +}; +static const struct luaL_reg memorylib [] = +{ + {"readbyte", memory_readbyte}, + {"readbytesigned", memory_readbytesigned}, + {"readword", memory_readword}, + {"readwordsigned", memory_readwordsigned}, + {"readdword", memory_readdword}, + {"readdwordsigned", memory_readdwordsigned}, + {"readbyterange", memory_readbyterange}, + {"writebyte", memory_writebyte}, + {"writeword", memory_writeword}, + {"writedword", memory_writedword}, + {"isvalid", memory_isvalid}, + {"getregister", memory_getregister}, + {"setregister", memory_setregister}, + // alternate naming scheme for word and double-word and unsigned + {"readbyteunsigned", memory_readbyte}, + {"readwordunsigned", memory_readword}, + {"readdwordunsigned", memory_readdword}, + {"readshort", memory_readword}, + {"readshortunsigned", memory_readword}, + {"readshortsigned", memory_readwordsigned}, + {"readlong", memory_readdword}, + {"readlongunsigned", memory_readdword}, + {"readlongsigned", memory_readdwordsigned}, + {"writeshort", memory_writeword}, + {"writelong", memory_writedword}, + + {"vram_readword", vram_readword}, + {"vram_writeword", vram_writeword}, + + // memory hooks + {"registerwrite", memory_registerwrite}, + {"registerread", memory_registerread}, + {"registerexec", memory_registerexec}, + // alternate names + {"register", memory_registerwrite}, + {"registerrun", memory_registerexec}, + {"registerexecute", memory_registerexec}, + + {NULL, NULL} +}; +static const struct luaL_reg joylib [] = +{ + {"get", joy_get}, + {"getdown", joy_getdown}, + {"getup", joy_getup}, + {"peek", joy_peek}, + {"peekdown", joy_peekdown}, + {"peekup", joy_peekup}, + {"set", joy_set}, + // alternative names + {"read", joy_get}, + {"write", joy_set}, + {"readdown", joy_getdown}, + {"readup", joy_getup}, + {NULL, NULL} +}; +static const struct luaL_reg inputlib [] = +{ + {"get", input_getcurrentinputstatus}, + {"registerhotkey", input_registerhotkey}, + {"popup", input_popup}, + // alternative names + {"read", input_getcurrentinputstatus}, + {NULL, NULL} +}; +static const struct luaL_reg movielib [] = +{ + {"active", movie_isactive}, + {"recording", movie_isrecording}, + {"playing", movie_isplaying}, + {"mode", movie_getmode}, + + {"length", movie_getlength}, + {"name", movie_getname}, + {"rerecordcount", movie_rerecordcount}, + {"setrerecordcount", movie_setrerecordcount}, + + {"rerecordcounting", emu_rerecordcounting}, + {"readonly", movie_getreadonly}, + {"setreadonly", movie_setreadonly}, + {"framecount", emu_getframecount}, // for those familiar with other emulators that have movie.framecount() instead of emulatorname.framecount() + + {"play", movie_play}, + {"replay", movie_replay}, + {"stop", movie_close}, + + // alternative names + {"open", movie_play}, + {"close", movie_close}, + {"getname", movie_getname}, + {"playback", movie_play}, + {"getreadonly", movie_getreadonly}, + {NULL, NULL} +}; +static const struct luaL_reg soundlib [] = +{ + {"clear", sound_clear}, + {NULL, NULL} +}; + +static const struct CFuncInfo +{ + const char* library; + const char* name; + const char* args; + bool registry; +} +cFuncInfo [] = // this info is stored here to avoid having to change all of Lua's libraries to use something like DEFINE_LUA_FUNCTION +{ + {LUA_STRLIBNAME, "byte", "str[,start[,end]]"}, + {LUA_STRLIBNAME, "char", "...[bytes]"}, + {LUA_STRLIBNAME, "dump", "func"}, + {LUA_STRLIBNAME, "find", "str,pattern[,init[,plain]]"}, + {LUA_STRLIBNAME, "format", "formatstring,..."}, + {LUA_STRLIBNAME, "gfind", "!deprecated!"}, + {LUA_STRLIBNAME, "gmatch", "str,pattern"}, + {LUA_STRLIBNAME, "gsub", "str,pattern,repl[,n]"}, + {LUA_STRLIBNAME, "len", "str"}, + {LUA_STRLIBNAME, "lower", "str"}, + {LUA_STRLIBNAME, "match", "str,pattern[,init]"}, + {LUA_STRLIBNAME, "rep", "str,n"}, + {LUA_STRLIBNAME, "reverse", "str"}, + {LUA_STRLIBNAME, "sub", "str,start[,end]"}, + {LUA_STRLIBNAME, "upper", "str"}, + {NULL, "module", "name[,...]"}, + {NULL, "require", "modname"}, + {LUA_LOADLIBNAME, "loadlib", "libname,funcname"}, + {LUA_LOADLIBNAME, "seeall", "module"}, + {LUA_COLIBNAME, "create", "func"}, + {LUA_COLIBNAME, "resume", "co[,val1,...]"}, + {LUA_COLIBNAME, "running", ""}, + {LUA_COLIBNAME, "status", "co"}, + {LUA_COLIBNAME, "wrap", "func"}, + {LUA_COLIBNAME, "yield", "..."}, + {NULL, "assert", "cond[,message]"}, + {NULL, "collectgarbage", "opt[,arg]"}, + {NULL, "gcinfo", ""}, + {NULL, "dofile", "filename"}, + {NULL, "error", "message[,level]"}, + {NULL, "getfenv", "[level_or_func]"}, + {NULL, "getmetatable", "object"}, + {NULL, "ipairs", "arraytable"}, + {NULL, "load", "func[,chunkname]"}, + {NULL, "loadfile", "[filename]"}, + {NULL, "loadstring", "str[,chunkname]"}, + {NULL, "next", "table[,index]"}, + {NULL, "pairs", "table"}, + {NULL, "pcall", "func,arg1,..."}, + {NULL, "rawequal", "v1,v2"}, + {NULL, "rawget", "table,index"}, + {NULL, "rawset", "table,index,value"}, + {NULL, "select", "index,..."}, + {NULL, "setfenv", "level_or_func,envtable"}, + {NULL, "setmetatable", "table,metatable"}, + {NULL, "tonumber", "str_or_num[,base]"}, + {NULL, "type", "obj"}, + {NULL, "unpack", "list[,i=1[,j=#list]]"}, + {NULL, "xpcall", "func,errhandler"}, + {NULL, "newproxy", "hasmeta"}, + {LUA_MATHLIBNAME, "abs", "x"}, + {LUA_MATHLIBNAME, "acos", "x"}, + {LUA_MATHLIBNAME, "asin", "x"}, + {LUA_MATHLIBNAME, "atan", "x"}, + {LUA_MATHLIBNAME, "atan2", "y,x"}, + {LUA_MATHLIBNAME, "ceil", "x"}, + {LUA_MATHLIBNAME, "cos", "rads"}, + {LUA_MATHLIBNAME, "cosh", "x"}, + {LUA_MATHLIBNAME, "deg", "rads"}, + {LUA_MATHLIBNAME, "exp", "x"}, + {LUA_MATHLIBNAME, "floor", "x"}, + {LUA_MATHLIBNAME, "fmod", "x,y"}, + {LUA_MATHLIBNAME, "frexp", "x"}, + {LUA_MATHLIBNAME, "ldexp", "m,e"}, + {LUA_MATHLIBNAME, "log", "x"}, + {LUA_MATHLIBNAME, "log10", "x"}, + {LUA_MATHLIBNAME, "max", "x,..."}, + {LUA_MATHLIBNAME, "min", "x,..."}, + {LUA_MATHLIBNAME, "modf", "x"}, + {LUA_MATHLIBNAME, "pow", "x,y"}, + {LUA_MATHLIBNAME, "rad", "degs"}, + {LUA_MATHLIBNAME, "random", "[m[,n]]"}, + {LUA_MATHLIBNAME, "randomseed", "x"}, + {LUA_MATHLIBNAME, "sin", "rads"}, + {LUA_MATHLIBNAME, "sinh", "x"}, + {LUA_MATHLIBNAME, "sqrt", "x"}, + {LUA_MATHLIBNAME, "tan", "rads"}, + {LUA_MATHLIBNAME, "tanh", "x"}, + {LUA_IOLIBNAME, "close", "[file]"}, + {LUA_IOLIBNAME, "flush", ""}, + {LUA_IOLIBNAME, "input", "[file]"}, + {LUA_IOLIBNAME, "lines", "[filename]"}, + {LUA_IOLIBNAME, "open", "filename[,mode=\"r\"]"}, + {LUA_IOLIBNAME, "output", "[file]"}, + {LUA_IOLIBNAME, "popen", "prog,[model]"}, + {LUA_IOLIBNAME, "read", "..."}, + {LUA_IOLIBNAME, "tmpfile", ""}, + {LUA_IOLIBNAME, "type", "obj"}, + {LUA_IOLIBNAME, "write", "..."}, + {LUA_OSLIBNAME, "clock", ""}, + {LUA_OSLIBNAME, "date", "[format[,time]]"}, + {LUA_OSLIBNAME, "difftime", "t2,t1"}, + {LUA_OSLIBNAME, "execute", "[command]"}, + {LUA_OSLIBNAME, "exit", "[code]"}, + {LUA_OSLIBNAME, "getenv", "varname"}, + {LUA_OSLIBNAME, "remove", "filename"}, + {LUA_OSLIBNAME, "rename", "oldname,newname"}, + {LUA_OSLIBNAME, "setlocale", "locale[,category]"}, + {LUA_OSLIBNAME, "time", "[timetable]"}, + {LUA_OSLIBNAME, "tmpname", ""}, + {LUA_DBLIBNAME, "debug", ""}, + {LUA_DBLIBNAME, "getfenv", "o"}, + {LUA_DBLIBNAME, "gethook", "[thread]"}, + {LUA_DBLIBNAME, "getinfo", "[thread,]function[,what]"}, + {LUA_DBLIBNAME, "getlocal", "[thread,]level,local"}, + {LUA_DBLIBNAME, "getmetatable", "[object]"}, + {LUA_DBLIBNAME, "getregistry", ""}, + {LUA_DBLIBNAME, "getupvalue", "func,up"}, + {LUA_DBLIBNAME, "setfenv", "object,table"}, + {LUA_DBLIBNAME, "sethook", "[thread,]hook,mask[,count]"}, + {LUA_DBLIBNAME, "setlocal", "[thread,]level,local,value"}, + {LUA_DBLIBNAME, "setmetatable", "object,table"}, + {LUA_DBLIBNAME, "setupvalue", "func,up,value"}, + {LUA_DBLIBNAME, "traceback", "[thread,][message][,level]"}, + {LUA_TABLIBNAME, "concat", "table[,sep[,i[,j]]]"}, + {LUA_TABLIBNAME, "insert", "table,[pos,]value"}, + {LUA_TABLIBNAME, "maxn", "table"}, + {LUA_TABLIBNAME, "remove", "table[,pos]"}, + {LUA_TABLIBNAME, "sort", "table[,comp]"}, + {LUA_TABLIBNAME, "foreach", "table,func"}, + {LUA_TABLIBNAME, "foreachi", "table,func"}, + {LUA_TABLIBNAME, "getn", "table"}, + {LUA_TABLIBNAME, "maxn", "table"}, + {LUA_TABLIBNAME, "setn", "table,value"}, // I know some of these are obsolete but they should still have argument info if they're exposed to the user + {LUA_FILEHANDLE, "setvbuf", "mode[,size]", true}, + {LUA_FILEHANDLE, "lines", "", true}, + {LUA_FILEHANDLE, "read", "...", true}, + {LUA_FILEHANDLE, "flush", "", true}, + {LUA_FILEHANDLE, "seek", "[whence][,offset]", true}, + {LUA_FILEHANDLE, "write", "...", true}, + {LUA_FILEHANDLE, "__tostring", "obj", true}, + {LUA_FILEHANDLE, "__gc", "", true}, + {"_LOADLIB", "__gc", "", true}, +}; + +void registerLibs(lua_State* L) +{ + luaL_openlibs(L); + + luaL_register(L, "emu", emulib); + luaL_register(L, "gui", guilib); + luaL_register(L, "stylus", styluslib); + luaL_register(L, "savestate", statelib); + luaL_register(L, "memory", memorylib); + luaL_register(L, "joypad", joylib); // for game input + luaL_register(L, "input", inputlib); // for user input + luaL_register(L, "movie", movielib); + luaL_register(L, "sound", soundlib); + luaL_register(L, "bit", bit_funcs); // LuaBitOp library + + luaL_register(L, "agg", aggbasicshapes); + luaL_register(L, "agg", agggeneralattributes); + luaL_register(L, "agg", aggcustom); + + lua_settop(L, 0); // clean the stack, because each call to luaL_register leaves a table on top + + // register a few utility functions outside of libraries (in the global namespace) + lua_register(L, "print", print); + lua_register(L, "tostring", tostring); + lua_register(L, "addressof", addressof); + lua_register(L, "copytable", copytable); + + // old bit operation functions + lua_register(L, "AND", bit_band); + lua_register(L, "OR", bit_bor); + lua_register(L, "XOR", bit_bxor); + lua_register(L, "SHIFT", bitshift); + lua_register(L, "BIT", bitbit); + + luabitop_validate(L); + + // populate s_cFuncInfoMap the first time + static bool once = true; + if(once) + { + once = false; + + for(int i = 0; i < sizeof(cFuncInfo)/sizeof(*cFuncInfo); i++) + { + const CFuncInfo& cfi = cFuncInfo[i]; + if(cfi.registry) + { + lua_getregistry(L); + lua_getfield(L, -1, cfi.library); + lua_remove(L, -2); + lua_getfield(L, -1, cfi.name); + lua_remove(L, -2); + } + else if(cfi.library) + { + lua_getfield(L, LUA_GLOBALSINDEX, cfi.library); + lua_getfield(L, -1, cfi.name); + lua_remove(L, -2); + } + else + { + lua_getfield(L, LUA_GLOBALSINDEX, cfi.name); + } + + lua_CFunction func = lua_tocfunction(L, -1); + s_cFuncInfoMap[func] = cfi.args; + lua_pop(L, 1); + } + + // deal with some stragglers + lua_getfield(L, LUA_GLOBALSINDEX, "package"); + lua_getfield(L, -1, "loaders"); + lua_remove(L, -2); + if(lua_istable(L, -1)) + { + for(int i=1;;i++) + { + lua_rawgeti(L, -1, i); + lua_CFunction func = lua_tocfunction(L, -1); + lua_pop(L,1); + if(!func) + break; + s_cFuncInfoMap[func] = "name"; + } + } + lua_pop(L,1); + } + + // push arrays for storing hook functions in + for(int i = 0; i < LUAMEMHOOK_COUNT; i++) + { + lua_newtable(L); + lua_setfield(L, LUA_REGISTRYINDEX, luaMemHookTypeStrings[i]); + } + + // push an array for menu handlers + lua_newtable(L); + lua_setfield(L, LUA_REGISTRYINDEX, menuCallbackIDString); + + // register type + luaL_newmetatable(L, "EMUFILE_MEMORY*"); + lua_pushcfunction(L, gcEMUFILE_MEMORY); + lua_setfield(L, -2, "__gc"); + lua_pop(L, 1); +} + +void ResetInfo(LuaContextInfo& info) +{ + info.L = NULL; + info.started = false; + info.running = false; + info.returned = false; + info.crashed = false; + info.restart = false; + info.restartLater = false; + info.worryCount = 0; + info.stopWorrying = false; + info.panic = false; + info.ranExit = false; + info.numDeferredFuncs = 0; + info.ranFrameAdvance = false; + info.transparencyModifier = 255; + info.speedMode = SPEEDMODE_NORMAL; + info.guiFuncsNeedDeferring = false; + info.dataSaveKey = 0; + info.dataLoadKey = 0; + info.dataSaveLoadKeySet = false; + info.rerecordCountingDisabled = false; + info.numMemHooks = 0; + info.persistVars.clear(); + info.newDefaultData.ClearRecords(); + info.guiData.data = (u32*)aggDraw.hud->buf().buf(); + info.guiData.stridePix = aggDraw.hud->buf().stride_abs() / 4; + info.guiData.xMin = 0; + info.guiData.xMax = 256; + info.guiData.yMin = 0; + info.guiData.yMax = 192 * 2; + info.guiData.xOrigin = 0; + info.guiData.yOrigin = 192; +} + +void OpenLuaContext(int uid, void(*print)(int uid, const char* str), void(*onstart)(int uid), void(*onstop)(int uid, bool statusOK)) +{ + LuaContextInfo* newInfo = new LuaContextInfo(); + ResetInfo(*newInfo); + newInfo->print = print; + newInfo->onstart = onstart; + newInfo->onstop = onstop; + luaContextInfo[uid] = newInfo; +} + +void RunLuaScriptFile(int uid, const char* filenameCStr) +{ + if(luaContextInfo.find(uid) == luaContextInfo.end()) + return; + StopLuaScript(uid); + + LuaContextInfo& info = *luaContextInfo[uid]; + +#ifdef USE_INFO_STACK + infoStack.insert(infoStack.begin(), &info); + struct Scope { ~Scope(){ infoStack.erase(infoStack.begin()); } } scope; // doing it like this makes sure that the info stack gets cleaned up even if an exception is thrown +#endif + + info.nextFilename = filenameCStr; + + // TODO: store script's current directory into LuaContextInfo + static char dirnameCStr[MAX_PATH]; + strcpy(dirnameCStr, filenameCStr); + TrimFilenameFromPath(dirnameCStr); + chdir(dirnameCStr); + + if(info.running) + { + // it's a little complicated, but... the call to luaL_dofile below + // could call a C function that calls this very function again + // additionally, if that happened then the above call to StopLuaScript + // probably couldn't stop the script yet, so instead of continuing, + // we'll set a flag that tells the first call of this function to loop again + // when the script is able to stop safely + info.restart = true; + return; + } + + do + { + std::string filename = info.nextFilename; + + lua_State* L = lua_open(); +#ifndef USE_INFO_STACK + luaStateToContextMap[L] = &info; +#endif + luaStateToUIDMap[L] = uid; + ResetInfo(info); + info.L = L; + info.guiFuncsNeedDeferring = true; + info.lastFilename = filename; + + SetSaveKey(info, FilenameFromPath(filename.c_str())); + info.dataSaveLoadKeySet = false; + + registerLibs(L); + + // register a function to periodically check for inactivity + lua_sethook(L, LuaRescueHook, LUA_MASKCOUNT, HOOKCOUNT); + + // deferred evaluation table + lua_newtable(L); + lua_setfield(L, LUA_REGISTRYINDEX, deferredGUIIDString); + lua_newtable(L); + lua_setfield(L, LUA_REGISTRYINDEX, deferredJoySetIDString); + lua_newtable(L); + lua_setfield(L, LUA_REGISTRYINDEX, refStashString); + + info.started = true; + RefreshScriptStartedStatus(); + if(info.onstart) + info.onstart(uid); + info.running = true; + RefreshScriptSpeedStatus(); + info.returned = false; + int errorcode = luaL_dofile(L,filename.c_str()); + info.running = false; + RefreshScriptSpeedStatus(); + info.returned = true; + + if (errorcode) + { + info.crashed = true; + if(info.print) + { + info.print(uid, lua_tostring(L,-1)); + info.print(uid, "\r\n"); + } + else + { + fprintf(stderr, "%s\n", lua_tostring(L,-1)); + } + StopLuaScript(uid); + } + else + { + dontworry(info); + driver->USR_RefreshScreen(); + StopScriptIfFinished(uid, true); + } + } while(info.restart); +} + +void StopScriptIfFinished(int uid, bool justReturned) +{ + LuaContextInfo& info = *luaContextInfo[uid]; + if(!info.returned) + return; + + // the script has returned, but it is not necessarily done running + // because it may have registered a function that it expects to keep getting called + // so check if it has any registered functions and stop the script only if it doesn't + + bool keepAlive = (info.numMemHooks != 0 || !info.menuData.menuItemMap.empty()); + for(int calltype = 0; calltype < LUACALL_COUNT && !keepAlive; calltype++) + { + lua_State* L = info.L; + if(L) + { + const char* idstring = luaCallIDStrings[calltype]; + lua_getfield(L, LUA_REGISTRYINDEX, idstring); + bool isFunction = lua_isfunction(L, -1); + lua_pop(L, 1); + + if(isFunction) + keepAlive = true; + } + } + + if(keepAlive) + { + if(justReturned) + { + if(info.print) + info.print(uid, "script returned but is still running registered functions\r\n"); + else + fprintf(stdout, "%s\n", "script returned but is still running registered functions"); + } + } + else + { + if(info.print) + info.print(uid, "script finished running\r\n"); + else + fprintf(stdout, "%s\n", "script finished running"); + + StopLuaScript(uid); + } +} + +void RequestAbortLuaScript(int uid, const char* message) +{ + if(luaContextInfo.find(uid) == luaContextInfo.end()) + return; + LuaContextInfo& info = *luaContextInfo[uid]; + lua_State* L = info.L; + if(L) + { + // this probably isn't the right way to do it + // but calling luaL_error here is positively unsafe + // (it seemingly works fine but sometimes corrupts the emulation state in colorful ways) + // and this works pretty well and is definitely safe, so screw it + info.L->hookcount = 1; // run hook function as soon as possible + info.panic = true; // and call luaL_error once we're inside the hook function + if(message) + { + strncpy(info.panicMessage, message, sizeof(info.panicMessage)); + info.panicMessage[sizeof(info.panicMessage)-1] = 0; + } + else + { + // attach file/line info because this is the case where it's most necessary to see that, + // and often it won't be possible for the later luaL_error call to retrieve it otherwise. + // this means sometimes printing multiple file/line numbers if luaL_error does find something, + // but that's fine since more information is probably better anyway. + luaL_where(L,0); // should be 0 and not 1 here to get useful (on force stop) messages + const char* whereString = lua_tostring(L,-1); + snprintf(info.panicMessage, sizeof(info.panicMessage), "%sscript terminated", whereString); + lua_pop(L,1); + } + } +} + +void SetSaveKey(LuaContextInfo& info, const char* key) +{ + info.dataSaveKey = crc32(0, (const unsigned char*)key, strlen(key)); + + if(!info.dataSaveLoadKeySet) + { + info.dataLoadKey = info.dataSaveKey; + info.dataSaveLoadKeySet = true; + } +} +void SetLoadKey(LuaContextInfo& info, const char* key) +{ + info.dataLoadKey = crc32(0, (const unsigned char*)key, strlen(key)); + + if(!info.dataSaveLoadKeySet) + { + info.dataSaveKey = info.dataLoadKey; + info.dataSaveLoadKeySet = true; + } +} + +void HandleCallbackError(lua_State* L, LuaContextInfo& info, int uid, bool stopScript) +{ + info.crashed = true; + if(L->errfunc || L->errorJmp) + luaL_error(L, lua_tostring(L,-1)); + else + { + if(info.print) + { + info.print(uid, lua_tostring(L,-1)); + info.print(uid, "\r\n"); + } + else + { + fprintf(stderr, "%s\n", lua_tostring(L,-1)); + } + if(stopScript) + StopLuaScript(uid); + } +} + +void CallExitFunction(int uid) +{ + LuaContextInfo& info = *luaContextInfo[uid]; + lua_State* L = info.L; + + if(!L) + return; + + dontworry(info); + + // first call the registered exit function if there is one + if(!info.ranExit) + { + info.ranExit = true; + +#ifdef USE_INFO_STACK + infoStack.insert(infoStack.begin(), &info); + struct Scope { ~Scope(){ infoStack.erase(infoStack.begin()); } } scope; +#endif + + //lua_settop(L, 0); + lua_getfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_BEFOREEXIT]); + + int errorcode = 0; + if (lua_isfunction(L, -1)) + { + bool wasRunning = info.running; + info.running = true; + RefreshScriptSpeedStatus(); + + bool wasPanic = info.panic; + info.panic = false; // otherwise we could barely do anything in the exit function + + errorcode = lua_pcall(L, 0, 0, 0); + + info.panic |= wasPanic; // restore panic + + info.running = wasRunning; + RefreshScriptSpeedStatus(); + } + + // save persisted variable info after the exit function runs (even if it crashed) + { + // gather the final value of the variables we're supposed to persist + LuaSaveData newExitData; + { + int numPersistVars = info.persistVars.size(); + for(int i = 0; i < numPersistVars; i++) + { + const char* varName = info.persistVars[i].c_str(); + lua_getfield(L, LUA_GLOBALSINDEX, varName); + int type = lua_type(L,-1); + unsigned int varNameCRC = crc32(0, (const unsigned char*)varName, strlen(varName)); + newExitData.SaveRecordPartial(uid, varNameCRC, -1); + lua_pop(L,1); + } + } + + char path [1024] = {0}; + char* pathTypeChrPtr = ConstructScriptSaveDataPath(path, 1024, info); + + *pathTypeChrPtr = 'd'; + if(info.newDefaultData.recordList) + { + FILE* defaultsFile = fopen(path, "wb"); + if(defaultsFile) + { + info.newDefaultData.ExportRecords(defaultsFile); + fclose(defaultsFile); + } + } + else unlink(path); + + *pathTypeChrPtr = 'e'; + if(newExitData.recordList) + { + FILE* persistFile = fopen(path, "wb"); + if(persistFile) + { + newExitData.ExportRecords(persistFile); + fclose(persistFile); + } + } + else unlink(path); + } + + if (errorcode) + HandleCallbackError(L,info,uid,false); + + } +} + +void StopLuaScript(int uid) +{ + LuaContextInfo* infoPtr = luaContextInfo[uid]; + if(!infoPtr) + return; + + LuaContextInfo& info = *infoPtr; + + if(info.running) + { + // if it's currently running then we can't stop it now without crashing + // so the best we can do is politely request for it to go kill itself + RequestAbortLuaScript(uid); + return; + } + + lua_State* L = info.L; + if(L) + { + CallExitFunction(uid); + + if(info.onstop) + { + info.stopWorrying = true, info.worryCount++, dontworry(info); // clear "busy" status + info.onstop(uid, !info.crashed); // must happen before closing L and after the exit function, otherwise the final GUI state of the script won't be shown properly or at all + } + + if(info.started) // this check is necessary + { + lua_close(L); +#ifndef USE_INFO_STACK + luaStateToContextMap.erase(L); +#endif + luaStateToUIDMap.erase(L); + info.L = NULL; + info.started = false; + + info.numMemHooks = 0; + for(int i = 0; i < LUAMEMHOOK_COUNT; i++) + CalculateMemHookRegions((LuaMemHookType)i); + +#if defined(WIN32) && !defined(WXPORT) + // remove items + map<PlatformMenuItem, PlatformMenu>::iterator it = info.menuData.menuItemMap.begin(); + while(it != info.menuData.menuItemMap.end()) + { + HMENU menu = (*it).second; + UINT menuItem = (*it).first; + DeleteMenu(menu, menuItem, MF_BYCOMMAND); + it++; + } + info.menuData.menuItemMap.clear(); + + // remove submenus + vector<LuaSubMenuData>::reverse_iterator rit = info.menuData.subMenuData.rbegin(); + while(rit != info.menuData.subMenuData.rend()) + { + HMENU menu = (*rit).menu; + UINT menuItem = (*rit).menuItem; + + MENUITEMINFO mii; + ZeroMemory(&mii, sizeof(MENUITEMINFO)); + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_SUBMENU; + GetMenuItemInfo(menu, menuItem, FALSE, &mii); + HMENU subMenu = mii.hSubMenu; + + // delete if it's empty + if (GetMenuItemCount(subMenu) == 0) + { + DeleteMenu(menu, menuItem, MF_BYCOMMAND); + } + rit++; + } + info.menuData.subMenuData.clear(); + DrawMenuBar(MainWindow->getHWnd()); +#endif + } + RefreshScriptStartedStatus(); + } +} + +void CloseLuaContext(int uid) +{ + StopLuaScript(uid); + delete luaContextInfo[uid]; + luaContextInfo.erase(uid); +} + + +TieredRegion hookedRegions [LUAMEMHOOK_COUNT]; + + +// currently disabled for desmume, +// and the performance hit might not be accepable +// unless we can switch the emulation into a whole separate path +// that has this callback enabled. +static void CalculateMemHookRegions(LuaMemHookType hookType) +{ + std::vector<unsigned int> hookedBytes; + std::map<int, LuaContextInfo*>::iterator iter = luaContextInfo.begin(); + std::map<int, LuaContextInfo*>::iterator end = luaContextInfo.end(); + while(iter != end) + { + LuaContextInfo& info = *iter->second; + if(info.numMemHooks) + { + lua_State* L = info.L; + if(L) + { + int top = lua_gettop(L); + lua_getfield(L, LUA_REGISTRYINDEX, luaMemHookTypeStrings[hookType]); + lua_pushnil(L); + while(lua_next(L, -2)) + { + if(lua_isfunction(L, -1)) + { + unsigned int addr = lua_tointeger(L, -2); + hookedBytes.push_back(addr); + } + lua_pop(L, 1); + } + if(!info.crashed) + lua_settop(L, top); + } + } + ++iter; + } + hookedRegions[hookType].Calculate(hookedBytes); +} + + + + + +void CallRegisteredLuaMemHook_LuaMatch(unsigned int address, int size, unsigned int value, LuaMemHookType hookType) +{ + std::map<int, LuaContextInfo*>::iterator iter = luaContextInfo.begin(); + std::map<int, LuaContextInfo*>::iterator end = luaContextInfo.end(); + while(iter != end) + { + LuaContextInfo& info = *iter->second; + if(info.numMemHooks) + { + lua_State* L = info.L; + if(L && !info.panic) + { +#ifdef USE_INFO_STACK + infoStack.insert(infoStack.begin(), &info); + struct Scope { ~Scope(){ infoStack.erase(infoStack.begin()); } } scope; +#endif + int top = lua_gettop(L); + lua_getfield(L, LUA_REGISTRYINDEX, luaMemHookTypeStrings[hookType]); + for(int i = address; i != address+size; i++) + { + lua_rawgeti(L, -1, i); + if (lua_isfunction(L, -1)) + { + bool wasRunning = info.running; + info.running = true; + RefreshScriptSpeedStatus(); + lua_pushinteger(L, address); + lua_pushinteger(L, size); + int errorcode = lua_pcall(L, 2, 0, 0); + info.running = wasRunning; + RefreshScriptSpeedStatus(); + if (errorcode) + { + int uid = iter->first; + HandleCallbackError(L,info,uid,true); + } + break; + } + else + { + lua_pop(L,1); + } + } + if(!info.crashed) + lua_settop(L, top); + } + } + ++iter; + } +} + + +void CallRegisteredLuaMenuHandlers(PlatformMenuItem menuItem) +{ + std::map<int, LuaContextInfo*>::iterator iter = luaContextInfo.begin(); + std::map<int, LuaContextInfo*>::iterator end = luaContextInfo.end(); + while(iter != end) + { + LuaContextInfo& info = *iter->second; + lua_State* L = info.L; + if(L && !info.panic) + { +#ifdef USE_INFO_STACK + infoStack.insert(infoStack.begin(), &info); + struct Scope { ~Scope(){ infoStack.erase(infoStack.begin()); } } scope; +#endif + int top = lua_gettop(L); + lua_getfield(L, LUA_REGISTRYINDEX, menuCallbackIDString); + lua_rawgeti(L, -1, menuItem); + if (lua_isfunction(L, -1)) + { + bool wasRunning = info.running; + info.running = true; + RefreshScriptSpeedStatus(); + int errorcode = lua_pcall(L, 0, 0, 0); + info.running = wasRunning; + RefreshScriptSpeedStatus(); + if (errorcode) + { + int uid = iter->first; + HandleCallbackError(L,info,uid,true); + } + break; + } + else + { + lua_pop(L,1); + } + if(!info.crashed) + lua_settop(L, top); + } + ++iter; + } +} + + +bool AnyLuaActive() +{ + std::map<int, LuaContextInfo*>::iterator iter = luaContextInfo.begin(); + std::map<int, LuaContextInfo*>::iterator end = luaContextInfo.end(); + while(iter != end) + { + LuaContextInfo& info = *iter->second; + if(info.started) + return true; + ++iter; + } + return false; +} + +void CallRegisteredLuaFunctions(LuaCallID calltype) +{ + assert((unsigned int)calltype < (unsigned int)LUACALL_COUNT); + const char* idstring = luaCallIDStrings[calltype]; + + std::map<int, LuaContextInfo*>::iterator iter = luaContextInfo.begin(); + std::map<int, LuaContextInfo*>::iterator end = luaContextInfo.end(); + while(iter != end) + { + int uid = iter->first; + LuaContextInfo& info = *iter->second; + lua_State* L = info.L; + if(L && (!info.panic || calltype == LUACALL_BEFOREEXIT)) + { +#ifdef USE_INFO_STACK + infoStack.insert(infoStack.begin(), &info); + struct Scope { ~Scope(){ infoStack.erase(infoStack.begin()); } } scope; +#endif + // handle deferred GUI function calls and disabling deferring when unnecessary + if(calltype == LUACALL_AFTEREMULATIONGUI || calltype == LUACALL_AFTEREMULATION) + info.guiFuncsNeedDeferring = false; + if(calltype == LUACALL_AFTEREMULATIONGUI) + CallDeferredFunctions(L, deferredGUIIDString); + if(calltype == LUACALL_BEFOREEMULATION) + { + assert(NDS_isProcessingUserInput()); + CallDeferredFunctions(L, deferredJoySetIDString); + } + + int top = lua_gettop(L); + lua_getfield(L, LUA_REGISTRYINDEX, idstring); + + if (lua_isfunction(L, -1)) + { + bool wasRunning = info.running; + info.running = true; + RefreshScriptSpeedStatus(); + int errorcode = lua_pcall(L, 0, 0, 0); + info.running = wasRunning; + RefreshScriptSpeedStatus(); + if (errorcode) + HandleCallbackError(L,info,uid,true); + } + else + { + lua_pop(L, 1); + } + + info.guiFuncsNeedDeferring = true; + if(!info.crashed) + { + lua_settop(L, top); + if(!info.panic) + dontworry(info); + } + } + + ++iter; + } +} + +void CallRegisteredLuaSaveFunctions(int savestateNumber, LuaSaveData& saveData) +{ + const char* idstring = luaCallIDStrings[LUACALL_BEFORESAVE]; + + std::map<int, LuaContextInfo*>::iterator iter = luaContextInfo.begin(); + std::map<int, LuaContextInfo*>::iterator end = luaContextInfo.end(); + while(iter != end) + { + int uid = iter->first; + LuaContextInfo& info = *iter->second; + lua_State* L = info.L; + if(L) + { +#ifdef USE_INFO_STACK + infoStack.insert(infoStack.begin(), &info); + struct Scope { ~Scope(){ infoStack.erase(infoStack.begin()); } } scope; +#endif + + int top = lua_gettop(L); + lua_getfield(L, LUA_REGISTRYINDEX, idstring); + + if (lua_isfunction(L, -1)) + { + bool wasRunning = info.running; + info.running = true; + RefreshScriptSpeedStatus(); + lua_pushinteger(L, savestateNumber); + int errorcode = lua_pcall(L, 1, LUA_MULTRET, 0); + info.running = wasRunning; + RefreshScriptSpeedStatus(); + if (errorcode) + HandleCallbackError(L,info,uid,true); + saveData.SaveRecord(uid, info.dataSaveKey); + } + else + { + lua_pop(L, 1); + } + if(!info.crashed) + lua_settop(L, top); + } + + ++iter; + } +} + + +void CallRegisteredLuaLoadFunctions(int savestateNumber, const LuaSaveData& saveData) +{ + const char* idstring = luaCallIDStrings[LUACALL_AFTERLOAD]; + + std::map<int, LuaContextInfo*>::iterator iter = luaContextInfo.begin(); + std::map<int, LuaContextInfo*>::iterator end = luaContextInfo.end(); + while(iter != end) + { + int uid = iter->first; + LuaContextInfo& info = *iter->second; + lua_State* L = info.L; + if(L) + { +#ifdef USE_INFO_STACK + infoStack.insert(infoStack.begin(), &info); + struct Scope { ~Scope(){ infoStack.erase(infoStack.begin()); } } scope; +#endif + + int top = lua_gettop(L); + lua_getfield(L, LUA_REGISTRYINDEX, idstring); + + if (lua_isfunction(L, -1)) + { + bool wasRunning = info.running; + info.running = true; + RefreshScriptSpeedStatus(); + + // since the scriptdata can be very expensive to load + // (e.g. the registered save function returned some huge tables) + // check the number of parameters the registered load function expects + // and don't bother loading the parameters it wouldn't receive anyway + int numParamsExpected = (L->top - 1)->value.gc->cl.l.p->numparams; + if(numParamsExpected) numParamsExpected--; // minus one for the savestate number we always pass in + + int prevGarbage = lua_gc(L, LUA_GCCOUNT, 0); + + lua_pushinteger(L, savestateNumber); + saveData.LoadRecord(uid, info.dataLoadKey, numParamsExpected); + int n = lua_gettop(L) - 1; + + int errorcode = lua_pcall(L, n, 0, 0); + info.running = wasRunning; + RefreshScriptSpeedStatus(); + if (errorcode) + HandleCallbackError(L,info,uid,true); + else + { + int newGarbage = lua_gc(L, LUA_GCCOUNT, 0); + if(newGarbage - prevGarbage > 50) + { + // now seems to be a very good time to run the garbage collector + // it might take a while now but that's better than taking 10 whiles 9 loads from now + lua_gc(L, LUA_GCCOLLECT, 0); + } + } + } + else + { + lua_pop(L, 1); + } + if(!info.crashed) + lua_settop(L, top); + } + + ++iter; + } +} + +static const unsigned char* s_dbg_dataStart = NULL; +static int s_dbg_dataSize = 0; + + +// can't remember what the best way of doing this is... +#if defined(i386) || defined(__i386) || defined(__i386__) || defined(M_I86) || defined(_M_IX86) || defined(_WIN32) + #define IS_LITTLE_ENDIAN +#endif + +// push a value's bytes onto the output stack +template<typename T> +void PushBinaryItem(T item, std::vector<unsigned char>& output) +{ + unsigned char* buf = (unsigned char*)&item; +#ifdef IS_LITTLE_ENDIAN + for(int i = sizeof(T); i; i--) + output.push_back(*buf++); +#else + int vecsize = output.size(); + for(int i = sizeof(T); i; i--) + output.insert(output.begin() + vecsize, *buf++); +#endif +} +// read a value from the byte stream and advance the stream by its size +template<typename T> +T AdvanceByteStream(const unsigned char*& data, unsigned int& remaining) +{ +#ifdef IS_LITTLE_ENDIAN + T rv = *(T*)data; + data += sizeof(T); +#else + T rv; unsigned char* rvptr = (unsigned char*)&rv; + for(int i = sizeof(T)-1; i>=0; i--) + rvptr[i] = *data++; +#endif + remaining -= sizeof(T); + return rv; +} +// advance the byte stream by a certain size without reading a value +void AdvanceByteStream(const unsigned char*& data, unsigned int& remaining, int amount) +{ + data += amount; + remaining -= amount; +} + +#define LUAEXT_TLONG 30 // 0x1E // 4-byte signed integer +#define LUAEXT_TUSHORT 31 // 0x1F // 2-byte unsigned integer +#define LUAEXT_TSHORT 32 // 0x20 // 2-byte signed integer +#define LUAEXT_TBYTE 33 // 0x21 // 1-byte unsigned integer +#define LUAEXT_TNILS 34 // 0x22 // multiple nils represented by a 4-byte integer (warning: becomes multiple stack entities) +#define LUAEXT_TTABLE 0x40 // 0x40 through 0x4F // tables of different sizes: +#define LUAEXT_BITS_1A 0x01 // size of array part fits in a 1-byte unsigned integer +#define LUAEXT_BITS_2A 0x02 // size of array part fits in a 2-byte unsigned integer +#define LUAEXT_BITS_4A 0x03 // size of array part fits in a 4-byte unsigned integer +#define LUAEXT_BITS_1H 0x04 // size of hash part fits in a 1-byte unsigned integer +#define LUAEXT_BITS_2H 0x08 // size of hash part fits in a 2-byte unsigned integer +#define LUAEXT_BITS_4H 0x0C // size of hash part fits in a 4-byte unsigned integer +#define BITMATCH(x,y) (((x) & (y)) == (y)) + +static void PushNils(std::vector<unsigned char>& output, int& nilcount) +{ + int count = nilcount; + nilcount = 0; + + static const int minNilsWorthEncoding = 6; // because a LUAEXT_TNILS entry is 5 bytes + + if(count < minNilsWorthEncoding) + { + for(int i = 0; i < count; i++) + output.push_back(LUA_TNIL); + } + else + { + output.push_back(LUAEXT_TNILS); + PushBinaryItem<u32>(count, output); + } +} + + +static void LuaStackToBinaryConverter(lua_State* L, int i, std::vector<unsigned char>& output) +{ + int type = lua_type(L, i); + + // the first byte of every serialized item says what Lua type it is + output.push_back(type & 0xFF); + + switch(type) + { + default: + { + //printf("wrote unknown type %d (0x%x)\n", type, type); + //assert(0); + + LuaContextInfo& info = GetCurrentInfo(); + if(info.print) + { + char errmsg [1024]; + sprintf(errmsg, "values of type \"%s\" are not allowed to be returned from registered save functions.\r\n", luaL_typename(L,i)); + info.print(luaStateToUIDMap[L->l_G->mainthread], errmsg); + } + else + { + fprintf(stderr, "values of type \"%s\" are not allowed to be returned from registered save functions.\n", luaL_typename(L,i)); + } + } + break; + case LUA_TNIL: + // no information necessary beyond the type + break; + case LUA_TBOOLEAN: + // serialize as 0 or 1 + output.push_back(lua_toboolean(L,i)); + break; + case LUA_TSTRING: + // serialize as a 0-terminated string of characters + { + const char* str = lua_tostring(L,i); + while(*str) + output.push_back(*str++); + output.push_back('\0'); + } + break; + case LUA_TNUMBER: + { + double num = (double)lua_tonumber(L,i); + s32 inum = (s32)lua_tointeger(L,i); + if(num != inum) + { + PushBinaryItem(num, output); + } + else + { + if((inum & ~0xFF) == 0) + type = LUAEXT_TBYTE; + else if((u16)(inum & 0xFFFF) == inum) + type = LUAEXT_TUSHORT; + else if((s16)(inum & 0xFFFF) == inum) + type = LUAEXT_TSHORT; + else + type = LUAEXT_TLONG; + output.back() = type; + switch(type) + { + case LUAEXT_TLONG: + PushBinaryItem<s32>(inum, output); + break; + case LUAEXT_TUSHORT: + PushBinaryItem<u16>(inum, output); + break; + case LUAEXT_TSHORT: + PushBinaryItem<s16>(inum, output); + break; + case LUAEXT_TBYTE: + output.push_back(inum); + break; + } + } + } + break; + case LUA_TTABLE: + // serialize as a type that describes how many bytes are used for storing the counts, + // followed by the number of array entries if any, then the number of hash entries if any, + // then a Lua value per array entry, then a (key,value) pair of Lua values per hashed entry + // note that the structure of table references are not faithfully serialized (yet) + { + int outputTypeIndex = output.size() - 1; + int arraySize = 0; + int hashSize = 0; + + if(lua_checkstack(L, 4) && std::find(s_tableAddressStack.begin(), s_tableAddressStack.end(), lua_topointer(L,i)) == s_tableAddressStack.end()) + { + s_tableAddressStack.push_back(lua_topointer(L,i)); + struct Scope { ~Scope(){ s_tableAddressStack.pop_back(); } } scope; + + bool wasnil = false; + int nilcount = 0; + arraySize = lua_objlen(L, i); + int arrayValIndex = lua_gettop(L) + 1; + for(int j = 1; j <= arraySize; j++) + { + lua_rawgeti(L, i, j); + bool isnil = lua_isnil(L, arrayValIndex); + if(isnil) + nilcount++; + else + { + if(wasnil) + PushNils(output, nilcount); + LuaStackToBinaryConverter(L, arrayValIndex, output); + } + lua_pop(L, 1); + wasnil = isnil; + } + if(wasnil) + PushNils(output, nilcount); + + if(arraySize) + lua_pushinteger(L, arraySize); // before first key + else + lua_pushnil(L); // before first key + + int keyIndex = lua_gettop(L); + int valueIndex = keyIndex + 1; + while(lua_next(L, i)) + { + assert(lua_type(L, keyIndex) && "nil key in Lua table, impossible"); + assert(lua_type(L, valueIndex) && "nil value in Lua table, impossible"); + LuaStackToBinaryConverter(L, keyIndex, output); + LuaStackToBinaryConverter(L, valueIndex, output); + lua_pop(L, 1); + hashSize++; + } + } + + int outputType = LUAEXT_TTABLE; + if(arraySize & 0xFFFF0000) + outputType |= LUAEXT_BITS_4A; + else if(arraySize & 0xFF00) + outputType |= LUAEXT_BITS_2A; + else if(arraySize & 0xFF) + outputType |= LUAEXT_BITS_1A; + if(hashSize & 0xFFFF0000) + outputType |= LUAEXT_BITS_4H; + else if(hashSize & 0xFF00) + outputType |= LUAEXT_BITS_2H; + else if(hashSize & 0xFF) + outputType |= LUAEXT_BITS_1H; + output[outputTypeIndex] = outputType; + + int insertIndex = outputTypeIndex; + if(BITMATCH(outputType,LUAEXT_BITS_4A) || BITMATCH(outputType,LUAEXT_BITS_2A) || BITMATCH(outputType,LUAEXT_BITS_1A)) + output.insert(output.begin() + (++insertIndex), arraySize & 0xFF); + if(BITMATCH(outputType,LUAEXT_BITS_4A) || BITMATCH(outputType,LUAEXT_BITS_2A)) + output.insert(output.begin() + (++insertIndex), (arraySize & 0xFF00) >> 8); + if(BITMATCH(outputType,LUAEXT_BITS_4A)) + output.insert(output.begin() + (++insertIndex), (arraySize & 0x00FF0000) >> 16), + output.insert(output.begin() + (++insertIndex), (arraySize & 0xFF000000) >> 24); + if(BITMATCH(outputType,LUAEXT_BITS_4H) || BITMATCH(outputType,LUAEXT_BITS_2H) || BITMATCH(outputType,LUAEXT_BITS_1H)) + output.insert(output.begin() + (++insertIndex), hashSize & 0xFF); + if(BITMATCH(outputType,LUAEXT_BITS_4H) || BITMATCH(outputType,LUAEXT_BITS_2H)) + output.insert(output.begin() + (++insertIndex), (hashSize & 0xFF00) >> 8); + if(BITMATCH(outputType,LUAEXT_BITS_4H)) + output.insert(output.begin() + (++insertIndex), (hashSize & 0x00FF0000) >> 16), + output.insert(output.begin() + (++insertIndex), (hashSize & 0xFF000000) >> 24); + + } break; + } +} + + +// complements LuaStackToBinaryConverter +void BinaryToLuaStackConverter(lua_State* L, const unsigned char*& data, unsigned int& remaining) +{ + assert(s_dbg_dataSize - (data - s_dbg_dataStart) == remaining); + + unsigned char type = AdvanceByteStream<unsigned char>(data, remaining); + + switch(type) + { + default: + { + //printf("read unknown type %d (0x%x)\n", type, type); + //assert(0); + + LuaContextInfo& info = GetCurrentInfo(); + if(info.print) + { + char errmsg [1024]; + if(type <= 10 && type != LUA_TTABLE) + sprintf(errmsg, "values of type \"%s\" are not allowed to be loaded into registered load functions. The save state's Lua save data file might be corrupted.\r\n", lua_typename(L,type)); + else + sprintf(errmsg, "The save state's Lua save data file seems to be corrupted.\r\n"); + info.print(luaStateToUIDMap[L->l_G->mainthread], errmsg); + } + else + { + if(type <= 10 && type != LUA_TTABLE) + fprintf(stderr, "values of type \"%s\" are not allowed to be loaded into registered load functions. The save state's Lua save data file might be corrupted.\n", lua_typename(L,type)); + else + fprintf(stderr, "The save state's Lua save data file seems to be corrupted.\n"); + } + } + break; + case LUA_TNIL: + lua_pushnil(L); + break; + case LUA_TBOOLEAN: + lua_pushboolean(L, AdvanceByteStream<u8>(data, remaining)); + break; + case LUA_TSTRING: + lua_pushstring(L, (const char*)data); + AdvanceByteStream(data, remaining, strlen((const char*)data) + 1); + break; + case LUA_TNUMBER: + lua_pushnumber(L, AdvanceByteStream<double>(data, remaining)); + break; + case LUAEXT_TLONG: + lua_pushinteger(L, AdvanceByteStream<s32>(data, remaining)); + break; + case LUAEXT_TUSHORT: + lua_pushinteger(L, AdvanceByteStream<u16>(data, remaining)); + break; + case LUAEXT_TSHORT: + lua_pushinteger(L, AdvanceByteStream<s16>(data, remaining)); + break; + case LUAEXT_TBYTE: + lua_pushinteger(L, AdvanceByteStream<u8>(data, remaining)); + break; + case LUAEXT_TTABLE: + case LUAEXT_TTABLE | LUAEXT_BITS_1A: + case LUAEXT_TTABLE | LUAEXT_BITS_2A: + case LUAEXT_TTABLE | LUAEXT_BITS_4A: + case LUAEXT_TTABLE | LUAEXT_BITS_1H: + case LUAEXT_TTABLE | LUAEXT_BITS_2H: + case LUAEXT_TTABLE | LUAEXT_BITS_4H: + case LUAEXT_TTABLE | LUAEXT_BITS_1A | LUAEXT_BITS_1H: + case LUAEXT_TTABLE | LUAEXT_BITS_2A | LUAEXT_BITS_1H: + case LUAEXT_TTABLE | LUAEXT_BITS_4A | LUAEXT_BITS_1H: + case LUAEXT_TTABLE | LUAEXT_BITS_1A | LUAEXT_BITS_2H: + case LUAEXT_TTABLE | LUAEXT_BITS_2A | LUAEXT_BITS_2H: + case LUAEXT_TTABLE | LUAEXT_BITS_4A | LUAEXT_BITS_2H: + case LUAEXT_TTABLE | LUAEXT_BITS_1A | LUAEXT_BITS_4H: + case LUAEXT_TTABLE | LUAEXT_BITS_2A | LUAEXT_BITS_4H: + case LUAEXT_TTABLE | LUAEXT_BITS_4A | LUAEXT_BITS_4H: + { + unsigned int arraySize = 0; + if(BITMATCH(type,LUAEXT_BITS_4A) || BITMATCH(type,LUAEXT_BITS_2A) || BITMATCH(type,LUAEXT_BITS_1A)) + arraySize |= AdvanceByteStream<u8>(data, remaining); + if(BITMATCH(type,LUAEXT_BITS_4A) || BITMATCH(type,LUAEXT_BITS_2A)) + arraySize |= ((u16)AdvanceByteStream<u8>(data, remaining)) << 8; + if(BITMATCH(type,LUAEXT_BITS_4A)) + arraySize |= ((u32)AdvanceByteStream<u8>(data, remaining)) << 16, + arraySize |= ((u32)AdvanceByteStream<u8>(data, remaining)) << 24; + + unsigned int hashSize = 0; + if(BITMATCH(type,LUAEXT_BITS_4H) || BITMATCH(type,LUAEXT_BITS_2H) || BITMATCH(type,LUAEXT_BITS_1H)) + hashSize |= AdvanceByteStream<u8>(data, remaining); + if(BITMATCH(type,LUAEXT_BITS_4H) || BITMATCH(type,LUAEXT_BITS_2H)) + hashSize |= ((u16)AdvanceByteStream<u8>(data, remaining)) << 8; + if(BITMATCH(type,LUAEXT_BITS_4H)) + hashSize |= ((u32)AdvanceByteStream<u8>(data, remaining)) << 16, + hashSize |= ((u32)AdvanceByteStream<u8>(data, remaining)) << 24; + + lua_createtable(L, arraySize, hashSize); + + unsigned int n = 1; + while(n <= arraySize) + { + if(*data == LUAEXT_TNILS) + { + AdvanceByteStream(data, remaining, 1); + n += AdvanceByteStream<u32>(data, remaining); + } + else + { + BinaryToLuaStackConverter(L, data, remaining); // push value + lua_rawseti(L, -2, n); // table[n] = value + n++; + } + } + + for(unsigned int h = 1; h <= hashSize; h++) + { + BinaryToLuaStackConverter(L, data, remaining); // push key + BinaryToLuaStackConverter(L, data, remaining); // push value + lua_rawset(L, -3); // table[key] = value + } + } + break; + } +} + +static const unsigned char luaBinaryMajorVersion = 9; +static const unsigned char luaBinaryMinorVersion = 1; + +unsigned char* LuaStackToBinary(lua_State* L, unsigned int& size) +{ + int n = lua_gettop(L); + if(n == 0) + return NULL; + + std::vector<unsigned char> output; + output.push_back(luaBinaryMajorVersion); + output.push_back(luaBinaryMinorVersion); + + for(int i = 1; i <= n; i++) + LuaStackToBinaryConverter(L, i, output); + + unsigned char* rv = new unsigned char [output.size()]; + memcpy(rv, &output.front(), output.size()); + size = output.size(); + return rv; +} + +void BinaryToLuaStack(lua_State* L, const unsigned char* data, unsigned int size, unsigned int itemsToLoad) +{ + unsigned char major = *data++; + unsigned char minor = *data++; + size -= 2; + if(luaBinaryMajorVersion != major || luaBinaryMinorVersion != minor) + return; + + while(size > 0 && itemsToLoad > 0) + { + BinaryToLuaStackConverter(L, data, size); + itemsToLoad--; + } +} + +// saves Lua stack into a record and pops it +void LuaSaveData::SaveRecord(int uid, unsigned int key) +{ + LuaContextInfo& info = *luaContextInfo[uid]; + lua_State* L = info.L; + if(!L) + return; + + Record* cur = new Record(); + cur->key = key; + cur->data = LuaStackToBinary(L, cur->size); + cur->next = NULL; + + lua_settop(L,0); + + if(cur->size <= 0) + { + delete cur; + return; + } + + Record* last = recordList; + while(last && last->next) + last = last->next; + if(last) + last->next = cur; + else + recordList = cur; +} + +// pushes a record's data onto the Lua stack +void LuaSaveData::LoadRecord(int uid, unsigned int key, unsigned int itemsToLoad) const +{ + LuaContextInfo& info = *luaContextInfo[uid]; + lua_State* L = info.L; + if(!L) + return; + + Record* cur = recordList; + while(cur) + { + if(cur->key == key) + { + s_dbg_dataStart = cur->data; + s_dbg_dataSize = cur->size; + BinaryToLuaStack(L, cur->data, cur->size, itemsToLoad); + return; + } + cur = cur->next; + } +} + +// saves part of the Lua stack (at the given index) into a record and does NOT pop anything +void LuaSaveData::SaveRecordPartial(int uid, unsigned int key, int idx) +{ + LuaContextInfo& info = *luaContextInfo[uid]; + lua_State* L = info.L; + if(!L) + return; + + if(idx < 0) + idx += lua_gettop(L)+1; + + Record* cur = new Record(); + cur->key = key; + cur->next = NULL; + + if(idx <= lua_gettop(L)) + { + std::vector<unsigned char> output; + output.push_back(luaBinaryMajorVersion); + output.push_back(luaBinaryMinorVersion); + + LuaStackToBinaryConverter(L, idx, output); + + unsigned char* rv = new unsigned char [output.size()]; + memcpy(rv, &output.front(), output.size()); + cur->size = output.size(); + cur->data = rv; + } + + if(cur->size <= 0) + { + delete cur; + return; + } + + Record* last = recordList; + while(last && last->next) + last = last->next; + if(last) + last->next = cur; + else + recordList = cur; +} + +void fwriteint(unsigned int value, FILE* file) +{ + for(int i=0;i<4;i++) + { + int w = value & 0xFF; + fwrite(&w, 1, 1, file); + value >>= 8; + } +} +void freadint(unsigned int& value, FILE* file) +{ + int rv = 0; + for(int i=0;i<4;i++) + { + int r = 0; + fread(&r, 1, 1, file); + rv |= r << (i*8); + } + value = rv; +} + +// writes all records to an already-open file +void LuaSaveData::ExportRecords(void* fileV) const +{ + FILE* file = (FILE*)fileV; + if(!file) + return; + + Record* cur = recordList; + while(cur) + { + fwriteint(cur->key, file); + fwriteint(cur->size, file); + fwrite(cur->data, cur->size, 1, file); + cur = cur->next; + } +} + +// reads records from an already-open file +void LuaSaveData::ImportRecords(void* fileV) +{ + FILE* file = (FILE*)fileV; + if(!file) + return; + + ClearRecords(); + + Record rec; + Record* cur = &rec; + Record* last = NULL; + while(1) + { + freadint(cur->key, file); + freadint(cur->size, file); + + if(feof(file) || ferror(file)) + break; + + cur->data = new unsigned char [cur->size]; + fread(cur->data, cur->size, 1, file); + + Record* next = new Record(); + memcpy(next, cur, sizeof(Record)); + next->next = NULL; + + if(last) + last->next = next; + else + recordList = next; + last = next; + } +} + +void LuaSaveData::ClearRecords() +{ + Record* cur = recordList; + while(cur) + { + Record* del = cur; + cur = cur->next; + + delete[] del->data; + delete del; + } + + recordList = NULL; +} + + + +void DontWorryLua() // everything's going to be OK +{ + std::map<int, LuaContextInfo*>::const_iterator iter = luaContextInfo.begin(); + std::map<int, LuaContextInfo*>::const_iterator end = luaContextInfo.end(); + while(iter != end) + { + dontworry(*iter->second); + ++iter; + } +} + +void EnableStopAllLuaScripts(bool enable) +{ + g_stopAllScriptsEnabled = enable; +} + +void StopAllLuaScripts() +{ + if(!g_stopAllScriptsEnabled) + return; + + std::map<int, LuaContextInfo*>::const_iterator iter = luaContextInfo.begin(); + std::map<int, LuaContextInfo*>::const_iterator end = luaContextInfo.end(); + while(iter != end) + { + int uid = iter->first; + LuaContextInfo& info = *iter->second; + bool wasStarted = info.started; + StopLuaScript(uid); + info.restartLater = wasStarted; + ++iter; + } +} + +void RestartAllLuaScripts() +{ + if(!g_stopAllScriptsEnabled) + return; + + std::map<int, LuaContextInfo*>::const_iterator iter = luaContextInfo.begin(); + std::map<int, LuaContextInfo*>::const_iterator end = luaContextInfo.end(); + while(iter != end) + { + int uid = iter->first; + LuaContextInfo& info = *iter->second; + if(info.restartLater || info.started) + { + info.restartLater = false; + RunLuaScriptFile(uid, info.lastFilename.c_str()); + } + ++iter; + } +} + +// sets anything that needs to depend on the total number of scripts running +void RefreshScriptStartedStatus() +{ + int numScriptsStarted = 0; + + std::map<int, LuaContextInfo*>::const_iterator iter = luaContextInfo.begin(); + std::map<int, LuaContextInfo*>::const_iterator end = luaContextInfo.end(); + while(iter != end) + { + LuaContextInfo& info = *iter->second; + if(info.started) + numScriptsStarted++; + ++iter; + } + +// frameadvSkipLagForceDisable = (numScriptsStarted != 0); // disable while scripts are running because currently lag skipping makes lua callbacks get called twice per frame advance + g_numScriptsStarted = numScriptsStarted; +} + +// sets anything that needs to depend on speed mode or running status of scripts +void RefreshScriptSpeedStatus() +{ + g_anyScriptsHighSpeed = false; + + std::map<int, LuaContextInfo*>::const_iterator iter = luaContextInfo.begin(); + std::map<int, LuaContextInfo*>::const_iterator end = luaContextInfo.end(); + while(iter != end) + { + LuaContextInfo& info = *iter->second; + if(info.running) + if(info.speedMode == SPEEDMODE_TURBO || info.speedMode == SPEEDMODE_MAXIMUM) + g_anyScriptsHighSpeed = true; + ++iter; + } +} + diff --git a/jni/desmume/src/matrix.cpp b/jni/desmume/src/matrix.cpp new file mode 100755 index 0000000..45c68f1 --- /dev/null +++ b/jni/desmume/src/matrix.cpp @@ -0,0 +1,436 @@ +/* + Copyright (C) 2006-2007 shash + Copyright (C) 2007-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <math.h> +#include <assert.h> +#include "matrix.h" +#include "MMU.h" + +void _NOSSE_MatrixMultVec4x4 (const float *matrix, float *vecPtr) +{ + float x = vecPtr[0]; + float y = vecPtr[1]; + float z = vecPtr[2]; + float w = vecPtr[3]; + + vecPtr[0] = x * matrix[0] + y * matrix[4] + z * matrix[ 8] + w * matrix[12]; + vecPtr[1] = x * matrix[1] + y * matrix[5] + z * matrix[ 9] + w * matrix[13]; + vecPtr[2] = x * matrix[2] + y * matrix[6] + z * matrix[10] + w * matrix[14]; + vecPtr[3] = x * matrix[3] + y * matrix[7] + z * matrix[11] + w * matrix[15]; +} + +void MatrixMultVec4x4 (const s32 *matrix, s32 *vecPtr) +{ + const s32 x = vecPtr[0]; + const s32 y = vecPtr[1]; + const s32 z = vecPtr[2]; + const s32 w = vecPtr[3]; + + vecPtr[0] = fx32_shiftdown(fx32_mul(x,matrix[0]) + fx32_mul(y,matrix[4]) + fx32_mul(z,matrix [8]) + fx32_mul(w,matrix[12])); + vecPtr[1] = fx32_shiftdown(fx32_mul(x,matrix[1]) + fx32_mul(y,matrix[5]) + fx32_mul(z,matrix[ 9]) + fx32_mul(w,matrix[13])); + vecPtr[2] = fx32_shiftdown(fx32_mul(x,matrix[2]) + fx32_mul(y,matrix[6]) + fx32_mul(z,matrix[10]) + fx32_mul(w,matrix[14])); + vecPtr[3] = fx32_shiftdown(fx32_mul(x,matrix[3]) + fx32_mul(y,matrix[7]) + fx32_mul(z,matrix[11]) + fx32_mul(w,matrix[15])); +} + +void MatrixMultVec3x3_fixed(const s32 *matrix, s32 *vecPtr) +{ + const s32 x = vecPtr[0]; + const s32 y = vecPtr[1]; + const s32 z = vecPtr[2]; + + vecPtr[0] = fx32_shiftdown(fx32_mul(x,matrix[0]) + fx32_mul(y,matrix[4]) + fx32_mul(z,matrix[8])); + vecPtr[1] = fx32_shiftdown(fx32_mul(x,matrix[1]) + fx32_mul(y,matrix[5]) + fx32_mul(z,matrix[9])); + vecPtr[2] = fx32_shiftdown(fx32_mul(x,matrix[2]) + fx32_mul(y,matrix[6]) + fx32_mul(z,matrix[10])); +} + +//------------------------- +//switched SSE functions: implementations for no SSE +#if !defined(ENABLE_SSE) && defined(HAVE_NEON) + +void MatrixMultVec3x3 (const float *matrix, float *vecPtr) +{ + float x = vecPtr[0]; + float y = vecPtr[1]; + float z = vecPtr[2]; + + vecPtr[0] = x * matrix[0] + y * matrix[4] + z * matrix[ 8]; + vecPtr[1] = x * matrix[1] + y * matrix[5] + z * matrix[ 9]; + vecPtr[2] = x * matrix[2] + y * matrix[6] + z * matrix[10]; +} + +void MatrixTranslate (float *matrix, const float *ptr) +{ + matrix[12] += (matrix[0]*ptr[0])+(matrix[4]*ptr[1])+(matrix[ 8]*ptr[2]); + matrix[13] += (matrix[1]*ptr[0])+(matrix[5]*ptr[1])+(matrix[ 9]*ptr[2]); + matrix[14] += (matrix[2]*ptr[0])+(matrix[6]*ptr[1])+(matrix[10]*ptr[2]); + matrix[15] += (matrix[3]*ptr[0])+(matrix[7]*ptr[1])+(matrix[11]*ptr[2]); +} + +void MatrixScale (float *matrix, const float *ptr) +{ + matrix[0] *= ptr[0]; + matrix[1] *= ptr[0]; + matrix[2] *= ptr[0]; + matrix[3] *= ptr[0]; + + matrix[4] *= ptr[1]; + matrix[5] *= ptr[1]; + matrix[6] *= ptr[1]; + matrix[7] *= ptr[1]; + + matrix[8] *= ptr[2]; + matrix[9] *= ptr[2]; + matrix[10] *= ptr[2]; + matrix[11] *= ptr[2]; +} + +#elif !defined(ENABLE_SSE) && !defined(HAVE_NEON) + +void MatrixMultVec4x4 (const float *matrix, float *vecPtr) +{ + _NOSSE_MatrixMultVec4x4(matrix, vecPtr); +} + +void MatrixMultiply (float *matrix, const float *rightMatrix) +{ + float tmpMatrix[16]; + + tmpMatrix[0] = (matrix[0]*rightMatrix[0])+(matrix[4]*rightMatrix[1])+(matrix[8]*rightMatrix[2])+(matrix[12]*rightMatrix[3]); + tmpMatrix[1] = (matrix[1]*rightMatrix[0])+(matrix[5]*rightMatrix[1])+(matrix[9]*rightMatrix[2])+(matrix[13]*rightMatrix[3]); + tmpMatrix[2] = (matrix[2]*rightMatrix[0])+(matrix[6]*rightMatrix[1])+(matrix[10]*rightMatrix[2])+(matrix[14]*rightMatrix[3]); + tmpMatrix[3] = (matrix[3]*rightMatrix[0])+(matrix[7]*rightMatrix[1])+(matrix[11]*rightMatrix[2])+(matrix[15]*rightMatrix[3]); + + tmpMatrix[4] = (matrix[0]*rightMatrix[4])+(matrix[4]*rightMatrix[5])+(matrix[8]*rightMatrix[6])+(matrix[12]*rightMatrix[7]); + tmpMatrix[5] = (matrix[1]*rightMatrix[4])+(matrix[5]*rightMatrix[5])+(matrix[9]*rightMatrix[6])+(matrix[13]*rightMatrix[7]); + tmpMatrix[6] = (matrix[2]*rightMatrix[4])+(matrix[6]*rightMatrix[5])+(matrix[10]*rightMatrix[6])+(matrix[14]*rightMatrix[7]); + tmpMatrix[7] = (matrix[3]*rightMatrix[4])+(matrix[7]*rightMatrix[5])+(matrix[11]*rightMatrix[6])+(matrix[15]*rightMatrix[7]); + + tmpMatrix[8] = (matrix[0]*rightMatrix[8])+(matrix[4]*rightMatrix[9])+(matrix[8]*rightMatrix[10])+(matrix[12]*rightMatrix[11]); + tmpMatrix[9] = (matrix[1]*rightMatrix[8])+(matrix[5]*rightMatrix[9])+(matrix[9]*rightMatrix[10])+(matrix[13]*rightMatrix[11]); + tmpMatrix[10] = (matrix[2]*rightMatrix[8])+(matrix[6]*rightMatrix[9])+(matrix[10]*rightMatrix[10])+(matrix[14]*rightMatrix[11]); + tmpMatrix[11] = (matrix[3]*rightMatrix[8])+(matrix[7]*rightMatrix[9])+(matrix[11]*rightMatrix[10])+(matrix[15]*rightMatrix[11]); + + tmpMatrix[12] = (matrix[0]*rightMatrix[12])+(matrix[4]*rightMatrix[13])+(matrix[8]*rightMatrix[14])+(matrix[12]*rightMatrix[15]); + tmpMatrix[13] = (matrix[1]*rightMatrix[12])+(matrix[5]*rightMatrix[13])+(matrix[9]*rightMatrix[14])+(matrix[13]*rightMatrix[15]); + tmpMatrix[14] = (matrix[2]*rightMatrix[12])+(matrix[6]*rightMatrix[13])+(matrix[10]*rightMatrix[14])+(matrix[14]*rightMatrix[15]); + tmpMatrix[15] = (matrix[3]*rightMatrix[12])+(matrix[7]*rightMatrix[13])+(matrix[11]*rightMatrix[14])+(matrix[15]*rightMatrix[15]); + + memcpy (matrix, tmpMatrix, sizeof(float)*16); +} + +#endif //switched c/asm functions +//----------------------------------------- + +void MatrixInit (s32 *matrix) +{ + memset (matrix, 0, sizeof(s32)*16); + matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1<<12; +} + +void MatrixInit (float *matrix) +{ + memset (matrix, 0, sizeof(s32)*16); + matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.f; +} + +void MatrixIdentity (s32 *matrix) +{ + matrix[1] = matrix[2] = matrix[3] = matrix[4] = 0; + matrix[6] = matrix[7] = matrix[8] = matrix[9] = 0; + matrix[11] = matrix[12] = matrix[13] = matrix[14] = 0; + matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1<<12; +} + +s32 MatrixGetMultipliedIndex (int index, s32 *matrix, s32 *rightMatrix) +{ + int iMod = index%4, iDiv = (index>>2)<<2; + + s64 temp = ((s64)matrix[iMod ]*rightMatrix[iDiv ])+((s64)matrix[iMod+ 4]*rightMatrix[iDiv+1])+ + ((s64)matrix[iMod+8]*rightMatrix[iDiv+2])+((s64)matrix[iMod+12]*rightMatrix[iDiv+3]); + + return (s32)(temp>>12); +} + +void MatrixSet (s32 *matrix, int x, int y, s32 value) +{ + matrix [x+(y<<2)] = value; +} + +void MatrixCopy (float* matrixDST, const float* matrixSRC) +{ + matrixDST[0] = matrixSRC[0]; + matrixDST[1] = matrixSRC[1]; + matrixDST[2] = matrixSRC[2]; + matrixDST[3] = matrixSRC[3]; + matrixDST[4] = matrixSRC[4]; + matrixDST[5] = matrixSRC[5]; + matrixDST[6] = matrixSRC[6]; + matrixDST[7] = matrixSRC[7]; + matrixDST[8] = matrixSRC[8]; + matrixDST[9] = matrixSRC[9]; + matrixDST[10] = matrixSRC[10]; + matrixDST[11] = matrixSRC[11]; + matrixDST[12] = matrixSRC[12]; + matrixDST[13] = matrixSRC[13]; + matrixDST[14] = matrixSRC[14]; + matrixDST[15] = matrixSRC[15]; + +} + +void MatrixCopy (s32* matrixDST, const s32* matrixSRC) +{ + memcpy(matrixDST,matrixSRC,sizeof(s32)*16); +} + +int MatrixCompare (const s32* matrixDST, const s32* matrixSRC) +{ + return memcmp((void*)matrixDST, matrixSRC, sizeof(s32)*16); +} + +void MatrixStackInit(MatrixStack *stack) +{ + for (int i = 0; i < stack->size; i++) + { + MatrixInit(&stack->matrix[i*16]); + } + stack->position = 0; +} + +void MatrixStackSetMaxSize (MatrixStack *stack, int size) +{ + int i; + + stack->size = (size + 1); + + if (stack->matrix != NULL) { + free (stack->matrix); + } + stack->matrix = new s32[stack->size*16*sizeof(s32)]; + + for (i = 0; i < stack->size; i++) + { + MatrixInit (&stack->matrix[i*16]); + } + + stack->size--; +} + + +MatrixStack::MatrixStack(int size, int type) +{ + MatrixStackSetMaxSize(this,size); + this->type = type; +} + +static void MatrixStackSetStackPosition (MatrixStack *stack, int pos) +{ + stack->position += pos; + + if((stack->position < 0) || (stack->position > stack->size)) + MMU_new.gxstat.se = 1; + + //once upon a time, we tried clamping to the size. + //this utterly broke sims 2 apartment pets. + //changing to wrap around made it work perfectly + stack->position = ((u32)stack->position) & stack->size; +} + +void MatrixStackPushMatrix (MatrixStack *stack, const s32 *ptr) +{ + //printf("Push %i pos %i\n", stack->type, stack->position); + if ((stack->type == 0) || (stack->type == 3)) + MatrixCopy (&stack->matrix[0], ptr); + else + MatrixCopy (&stack->matrix[stack->position*16], ptr); + MatrixStackSetStackPosition (stack, 1); +} + +void MatrixStackPopMatrix (s32 *mtxCurr, MatrixStack *stack, int size) +{ + //printf("Pop %i pos %i (change %d)\n", stack->type, stack->position, -size); + MatrixStackSetStackPosition(stack, -size); + if ((stack->type == 0) || (stack->type == 3)) + MatrixCopy (mtxCurr, &stack->matrix[0]); + else + MatrixCopy (mtxCurr, &stack->matrix[stack->position*16]); +} + +s32 * MatrixStackGetPos (MatrixStack *stack, int pos) +{ + assert(pos<31); + return &stack->matrix[pos*16]; +} + +s32 * MatrixStackGet (MatrixStack *stack) +{ + return &stack->matrix[stack->position*16]; +} + +void MatrixStackLoadMatrix (MatrixStack *stack, int pos, const s32 *ptr) +{ + assert(pos<31); + MatrixCopy (&stack->matrix[pos*16], ptr); +} + +void Vector2Copy(float *dst, const float *src) +{ + dst[0] = src[0]; + dst[1] = src[1]; +} + +void Vector2Add(float *dst, const float *src) +{ + dst[0] += src[0]; + dst[1] += src[1]; +} + +void Vector2Subtract(float *dst, const float *src) +{ + dst[0] -= src[0]; + dst[1] -= src[1]; +} + +float Vector2Dot(const float *a, const float *b) +{ + return (a[0]*b[0]) + (a[1]*b[1]); +} + +/* http://www.gamedev.net/community/forums/topic.asp?topic_id=289972 */ +float Vector2Cross(const float *a, const float *b) +{ + return (a[0]*b[1]) - (a[1]*b[0]); +} + +float Vector3Dot(const float *a, const float *b) +{ + return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; +} + +void Vector3Cross(float* dst, const float *a, const float *b) +{ + dst[0] = a[1]*b[2] - a[2]*b[1]; + dst[1] = a[2]*b[0] - a[0]*b[2]; + dst[2] = a[0]*b[1] - a[1]*b[0]; +} + + +float Vector3Length(const float *a) +{ + float lengthSquared = Vector3Dot(a,a); + float length = sqrt(lengthSquared); + return length; +} + +void Vector3Add(float *dst, const float *src) +{ + dst[0] += src[0]; + dst[1] += src[1]; + dst[2] += src[2]; +} + +void Vector3Subtract(float *dst, const float *src) +{ + dst[0] -= src[0]; + dst[1] -= src[1]; + dst[2] -= src[2]; +} + +void Vector3Scale(float *dst, const float scale) +{ + dst[0] *= scale; + dst[1] *= scale; + dst[2] *= scale; +} + +void Vector3Copy(float *dst, const float *src) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; +} + +void Vector3Normalize(float *dst) +{ + float length = Vector3Length(dst); + Vector3Scale(dst,1.0f/length); +} + +void Vector4Copy(float *dst, const float *src) +{ + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} + + +void MatrixMultiply (s32 *matrix, const s32 *rightMatrix) +{ + s32 tmpMatrix[16]; + + tmpMatrix[0] = fx32_shiftdown(fx32_mul(matrix[0],rightMatrix[0])+fx32_mul(matrix[4],rightMatrix[1])+fx32_mul(matrix[8],rightMatrix[2])+fx32_mul(matrix[12],rightMatrix[3])); + tmpMatrix[1] = fx32_shiftdown(fx32_mul(matrix[1],rightMatrix[0])+fx32_mul(matrix[5],rightMatrix[1])+fx32_mul(matrix[9],rightMatrix[2])+fx32_mul(matrix[13],rightMatrix[3])); + tmpMatrix[2] = fx32_shiftdown(fx32_mul(matrix[2],rightMatrix[0])+fx32_mul(matrix[6],rightMatrix[1])+fx32_mul(matrix[10],rightMatrix[2])+fx32_mul(matrix[14],rightMatrix[3])); + tmpMatrix[3] = fx32_shiftdown(fx32_mul(matrix[3],rightMatrix[0])+fx32_mul(matrix[7],rightMatrix[1])+fx32_mul(matrix[11],rightMatrix[2])+fx32_mul(matrix[15],rightMatrix[3])); + + tmpMatrix[4] = fx32_shiftdown(fx32_mul(matrix[0],rightMatrix[4])+fx32_mul(matrix[4],rightMatrix[5])+fx32_mul(matrix[8],rightMatrix[6])+fx32_mul(matrix[12],rightMatrix[7])); + tmpMatrix[5] = fx32_shiftdown(fx32_mul(matrix[1],rightMatrix[4])+fx32_mul(matrix[5],rightMatrix[5])+fx32_mul(matrix[9],rightMatrix[6])+fx32_mul(matrix[13],rightMatrix[7])); + tmpMatrix[6] = fx32_shiftdown(fx32_mul(matrix[2],rightMatrix[4])+fx32_mul(matrix[6],rightMatrix[5])+fx32_mul(matrix[10],rightMatrix[6])+fx32_mul(matrix[14],rightMatrix[7])); + tmpMatrix[7] = fx32_shiftdown(fx32_mul(matrix[3],rightMatrix[4])+fx32_mul(matrix[7],rightMatrix[5])+fx32_mul(matrix[11],rightMatrix[6])+fx32_mul(matrix[15],rightMatrix[7])); + + tmpMatrix[8] = fx32_shiftdown(fx32_mul(matrix[0],rightMatrix[8])+fx32_mul(matrix[4],rightMatrix[9])+fx32_mul(matrix[8],rightMatrix[10])+fx32_mul(matrix[12],rightMatrix[11])); + tmpMatrix[9] = fx32_shiftdown(fx32_mul(matrix[1],rightMatrix[8])+fx32_mul(matrix[5],rightMatrix[9])+fx32_mul(matrix[9],rightMatrix[10])+fx32_mul(matrix[13],rightMatrix[11])); + tmpMatrix[10] = fx32_shiftdown(fx32_mul(matrix[2],rightMatrix[8])+fx32_mul(matrix[6],rightMatrix[9])+fx32_mul(matrix[10],rightMatrix[10])+fx32_mul(matrix[14],rightMatrix[11])); + tmpMatrix[11] = fx32_shiftdown(fx32_mul(matrix[3],rightMatrix[8])+fx32_mul(matrix[7],rightMatrix[9])+fx32_mul(matrix[11],rightMatrix[10])+fx32_mul(matrix[15],rightMatrix[11])); + + tmpMatrix[12] = fx32_shiftdown(fx32_mul(matrix[0],rightMatrix[12])+fx32_mul(matrix[4],rightMatrix[13])+fx32_mul(matrix[8],rightMatrix[14])+fx32_mul(matrix[12],rightMatrix[15])); + tmpMatrix[13] = fx32_shiftdown(fx32_mul(matrix[1],rightMatrix[12])+fx32_mul(matrix[5],rightMatrix[13])+fx32_mul(matrix[9],rightMatrix[14])+fx32_mul(matrix[13],rightMatrix[15])); + tmpMatrix[14] = fx32_shiftdown(fx32_mul(matrix[2],rightMatrix[12])+fx32_mul(matrix[6],rightMatrix[13])+fx32_mul(matrix[10],rightMatrix[14])+fx32_mul(matrix[14],rightMatrix[15])); + tmpMatrix[15] = fx32_shiftdown(fx32_mul(matrix[3],rightMatrix[12])+fx32_mul(matrix[7],rightMatrix[13])+fx32_mul(matrix[11],rightMatrix[14])+fx32_mul(matrix[15],rightMatrix[15])); + + memcpy(matrix,tmpMatrix,sizeof(s32)*16); +} + +void MatrixScale(s32 *matrix, const s32 *ptr) +{ + //zero 21-sep-2010 - verified unrolling seems faster on my cpu + MACRODO_N(12, + matrix[X] = fx32_shiftdown(fx32_mul(matrix[X],ptr[X>>2])) + ); +} + +void MatrixTranslate(s32 *matrix, const s32 *ptr) +{ + MACRODO_N(4, + { + s64 temp = fx32_shiftup(matrix[X+12]); + temp += fx32_mul(matrix[X+0],ptr[0]); + temp += fx32_mul(matrix[X+4],ptr[1]); + temp += fx32_mul(matrix[X+8],ptr[2]); + matrix[X+12] = fx32_shiftdown(temp); + }); +} + +void MatrixMultVec4x4_M2(const s32 *matrix, s32 *vecPtr) +{ + MatrixMultVec4x4(matrix+16,vecPtr); + MatrixMultVec4x4(matrix,vecPtr); +} diff --git a/jni/desmume/src/matrix.h b/jni/desmume/src/matrix.h new file mode 100755 index 0000000..a590bf8 --- /dev/null +++ b/jni/desmume/src/matrix.h @@ -0,0 +1,380 @@ +/* + Copyright (C) 2006-2007 shash + Copyright (C) 2007-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef MATRIX_H +#define MATRIX_H + +#include <math.h> +#include <string.h> + +#include "types.h" +#include "mem.h" + +#ifdef ENABLE_SSE +#include <xmmintrin.h> +#endif + +#ifdef ENABLE_SSE2 +#include <emmintrin.h> +#endif + +#ifdef HAVE_NEON +extern "C" { +#include "android/math-neon/math_neon.h" +} +#endif + + +struct MatrixStack +{ + MatrixStack(int size, int type); + s32 *matrix; + s32 position; + s32 size; + u8 type; +}; + +void MatrixInit (float *matrix); +void MatrixInit (s32 *matrix); + +//In order to conditionally use these asm optimized functions in visual studio +//without having to make new build types to exclude the assembly files. +//a bit sloppy, but there aint much to it + +float MatrixGetMultipliedIndex (int index, float *matrix, float *rightMatrix); +s32 MatrixGetMultipliedIndex (int index, s32 *matrix, s32 *rightMatrix); +void MatrixSet (s32 *matrix, int x, int y, s32 value); +void MatrixCopy (s32 * matrixDST, const s32 * matrixSRC); +int MatrixCompare (const s32 * matrixDST, const float * matrixSRC); +void MatrixIdentity (s32 *matrix); + +void MatrixStackInit (MatrixStack *stack); +void MatrixStackSetMaxSize (MatrixStack *stack, int size); +void MatrixStackPushMatrix (MatrixStack *stack, const s32 *ptr); +void MatrixStackPopMatrix (s32 *mtxCurr, MatrixStack *stack, int size); +s32* MatrixStackGetPos (MatrixStack *stack, int pos); +s32* MatrixStackGet (MatrixStack *stack); +void MatrixStackLoadMatrix (MatrixStack *stack, int pos, const s32 *ptr); + +void Vector2Copy(float *dst, const float *src); +void Vector2Add(float *dst, const float *src); +void Vector2Subtract(float *dst, const float *src); +float Vector2Dot(const float *a, const float *b); +float Vector2Cross(const float *a, const float *b); + +float Vector3Dot(const float *a, const float *b); +void Vector3Cross(float* dst, const float *a, const float *b); +float Vector3Length(const float *a); +void Vector3Add(float *dst, const float *src); +void Vector3Subtract(float *dst, const float *src); +void Vector3Scale(float *dst, const float scale); +void Vector3Copy(float *dst, const float *src); +void Vector3Normalize(float *dst); + +void Vector4Copy(float *dst, const float *src); + +//these functions are an unreliable, inaccurate floor. +//it should only be used for positive numbers +//this isnt as fast as it could be if we used a visual c++ intrinsic, but those appear not to be universally available +FORCEINLINE u32 u32floor(float f) +{ +#ifdef ENABLE_SSE2 + return (u32)_mm_cvtt_ss2si(_mm_set_ss(f)); +#else + return (u32)f; +#endif +} +FORCEINLINE u32 u32floor(double d) +{ +#ifdef ENABLE_SSE2 + return (u32)_mm_cvttsd_si32(_mm_set_sd(d)); +#else + return (u32)d; +#endif +} + +//same as above but works for negative values too. +//be sure that the results are the same thing as floorf! +FORCEINLINE s32 s32floor(float f) +{ +#ifdef ENABLE_SSE2 + return _mm_cvtss_si32( _mm_add_ss(_mm_set_ss(-0.5f),_mm_add_ss(_mm_set_ss(f), _mm_set_ss(f))) ) >> 1; +#else + return (s32)floorf(f); +#endif +} +FORCEINLINE s32 s32floor(double d) +{ + return s32floor((float)d); +} + +//switched SSE2 functions +//------------- +#ifdef ENABLE_SSE2 + +template<int NUM> +FORCEINLINE void memset_u16_le(void* dst, u16 val) +{ + u32 u32val; + //just for the endian safety + T1WriteWord((u8*)&u32val,0,val); + T1WriteWord((u8*)&u32val,2,val); + ////const __m128i temp = _mm_set_epi32(u32val,u32val,u32val,u32val); + +#if defined(__GNUC__) || defined(__INTEL_COMPILER) + const __m128i temp = _mm_set_epi32(u32val,u32val,u32val,u32val); + MACRODO_N(NUM/8,_mm_store_si128((__m128i*)((u8*)dst+(X)*16), temp)); +#else + __m128 temp; temp.m128_i32[0] = u32val; + //MACRODO_N(NUM/8,_mm_store_si128((__m128i*)((u8*)dst+(X)*16), temp)); + MACRODO_N(NUM/8,_mm_store_ps1((float*)((u8*)dst+(X)*16), temp)); +#endif +} + +#else //no sse2 + +template<int NUM> +static FORCEINLINE void memset_u16_le(void* dst, u16 val) +{ + for(int i=0;i<NUM;i++) + T1WriteWord((u8*)dst,i<<1,val); +} + +#endif + +// NOSSE version always used in gfx3d.cpp +void _NOSSE_MatrixMultVec4x4 (const float *matrix, float *vecPtr); +void MatrixMultVec3x3_fixed(const s32 *matrix, s32 *vecPtr); + +//--------------------------- +//switched SSE functions +#ifdef ENABLE_SSE + +struct SSE_MATRIX +{ + SSE_MATRIX(const float *matrix) + : row0(_mm_load_ps(matrix)) + , row1(_mm_load_ps(matrix+4)) + , row2(_mm_load_ps(matrix+8)) + , row3(_mm_load_ps(matrix+12)) + {} + + union { + __m128 rows[4]; + struct { __m128 row0; __m128 row1; __m128 row2; __m128 row3; }; + }; + +}; + +FORCEINLINE __m128 _util_MatrixMultVec4x4_(const SSE_MATRIX &mat, __m128 vec) +{ + __m128 xmm5 = _mm_shuffle_ps(vec, vec, B8(01010101)); + __m128 xmm6 = _mm_shuffle_ps(vec, vec, B8(10101010)); + __m128 xmm7 = _mm_shuffle_ps(vec, vec, B8(11111111)); + __m128 xmm4 = _mm_shuffle_ps(vec, vec, B8(00000000)); + + xmm4 = _mm_mul_ps(xmm4,mat.row0); + xmm5 = _mm_mul_ps(xmm5,mat.row1); + xmm6 = _mm_mul_ps(xmm6,mat.row2); + xmm7 = _mm_mul_ps(xmm7,mat.row3); + xmm4 = _mm_add_ps(xmm4,xmm5); + xmm4 = _mm_add_ps(xmm4,xmm6); + xmm4 = _mm_add_ps(xmm4,xmm7); + return xmm4; +} + +FORCEINLINE void MatrixMultiply(float * matrix, const float * rightMatrix) +{ + //this seems to generate larger code, including many movaps, but maybe it is less harsh on the registers than the + //more hand-tailored approach + __m128 row0 = _util_MatrixMultVec4x4_((SSE_MATRIX)matrix,_mm_load_ps(rightMatrix)); + __m128 row1 = _util_MatrixMultVec4x4_((SSE_MATRIX)matrix,_mm_load_ps(rightMatrix+4)); + __m128 row2 = _util_MatrixMultVec4x4_((SSE_MATRIX)matrix,_mm_load_ps(rightMatrix+8)); + __m128 row3 = _util_MatrixMultVec4x4_((SSE_MATRIX)matrix,_mm_load_ps(rightMatrix+12)); + _mm_store_ps(matrix,row0); + _mm_store_ps(matrix+4,row1); + _mm_store_ps(matrix+8,row2); + _mm_store_ps(matrix+12,row3); +} + + + +FORCEINLINE void MatrixMultVec4x4(const float *matrix, float *vecPtr) +{ + _mm_store_ps(vecPtr,_util_MatrixMultVec4x4_((SSE_MATRIX)matrix,_mm_load_ps(vecPtr))); +} + +FORCEINLINE void MatrixMultVec4x4_M2(const float *matrix, float *vecPtr) +{ + //there are hardly any gains from merging these manually + MatrixMultVec4x4(matrix+16,vecPtr); + MatrixMultVec4x4(matrix,vecPtr); +} + +FORCEINLINE void MatrixMultVec3x3(const float * matrix, float * vecPtr) +{ + const __m128 vec = _mm_load_ps(vecPtr); + + __m128 xmm5 = _mm_shuffle_ps(vec, vec, B8(01010101)); + __m128 xmm6 = _mm_shuffle_ps(vec, vec, B8(10101010)); + __m128 xmm4 = _mm_shuffle_ps(vec, vec, B8(00000000)); + + const SSE_MATRIX mat(matrix); + + xmm4 = _mm_mul_ps(xmm4,mat.row0); + xmm5 = _mm_mul_ps(xmm5,mat.row1); + xmm6 = _mm_mul_ps(xmm6,mat.row2); + xmm4 = _mm_add_ps(xmm4,xmm5); + xmm4 = _mm_add_ps(xmm4,xmm6); + + _mm_store_ps(vecPtr,xmm4); +} + +FORCEINLINE void MatrixTranslate(float *matrix, const float *ptr) +{ + __m128 xmm4 = _mm_load_ps(ptr); + __m128 xmm5 = _mm_shuffle_ps(xmm4, xmm4, B8(01010101)); + __m128 xmm6 = _mm_shuffle_ps(xmm4, xmm4, B8(10101010)); + xmm4 = _mm_shuffle_ps(xmm4, xmm4, B8(00000000)); + + xmm4 = _mm_mul_ps(xmm4,_mm_load_ps(matrix)); + xmm5 = _mm_mul_ps(xmm5,_mm_load_ps(matrix+4)); + xmm6 = _mm_mul_ps(xmm6,_mm_load_ps(matrix+8)); + xmm4 = _mm_add_ps(xmm4,xmm5); + xmm4 = _mm_add_ps(xmm4,xmm6); + xmm4 = _mm_add_ps(xmm4,_mm_load_ps(matrix+12)); + _mm_store_ps(matrix+12,xmm4); +} + +FORCEINLINE void MatrixScale(float *matrix, const float *ptr) +{ + __m128 xmm4 = _mm_load_ps(ptr); + __m128 xmm5 = _mm_shuffle_ps(xmm4, xmm4, B8(01010101)); + __m128 xmm6 = _mm_shuffle_ps(xmm4, xmm4, B8(10101010)); + xmm4 = _mm_shuffle_ps(xmm4, xmm4, B8(00000000)); + + xmm4 = _mm_mul_ps(xmm4,_mm_load_ps(matrix)); + xmm5 = _mm_mul_ps(xmm5,_mm_load_ps(matrix+4)); + xmm6 = _mm_mul_ps(xmm6,_mm_load_ps(matrix+8)); + _mm_store_ps(matrix,xmm4); + _mm_store_ps(matrix+4,xmm5); + _mm_store_ps(matrix+8,xmm6); +} + +template<int NUM_ROWS> +FORCEINLINE void vector_fix2float(float* matrix, const float divisor) +{ + CTASSERT(NUM_ROWS==3 || NUM_ROWS==4); + + const __m128 val = _mm_set_ps1(divisor); + + _mm_store_ps(matrix,_mm_div_ps(_mm_load_ps(matrix),val)); + _mm_store_ps(matrix+4,_mm_div_ps(_mm_load_ps(matrix+4),val)); + _mm_store_ps(matrix+8,_mm_div_ps(_mm_load_ps(matrix+8),val)); + if(NUM_ROWS==4) + _mm_store_ps(matrix+12,_mm_div_ps(_mm_load_ps(matrix+12),val)); +} + +//WARNING: I do not think this is as fast as a memset, for some reason. +//at least in vc2005 with sse enabled. better figure out why before using it +template<int NUM> +static FORCEINLINE void memset_u8(void* _dst, u8 val) +{ + memset(_dst,val,NUM); + //const u8* dst = (u8*)_dst; + //u32 u32val = (val<<24)|(val<<16)|(val<<8)|val; + //const __m128i temp = _mm_set_epi32(u32val,u32val,u32val,u32val); + //MACRODO_N(NUM/16,_mm_store_si128((__m128i*)(dst+(X)*16), temp)); +} + +#elif defined(HAVE_NEON) + +FORCEINLINE void MatrixMultVec4x4(float *matrix, float *vecPtr) +{ + matvec4_neon(matrix, vecPtr, vecPtr); +} + +FORCEINLINE void MatrixMultVec4x4_M2(float *matrix, float *vecPtr) +{ + matvec4_neon(matrix+16, vecPtr, vecPtr); + matvec4_neon(matrix, vecPtr, vecPtr); +} + +FORCEINLINE void MatrixMultiply(float * matrix, float * rightMatrix) +{ + float ret[16]; + matmul4_neon(matrix, rightMatrix, ret); + memcpy(matrix, ret, sizeof(float)*16); +} + +//TODO: NEON implementations +void MatrixMultVec3x3(const float * matrix, float * vecPtr); +void MatrixTranslate(float *matrix, const float *ptr); +void MatrixScale(float * matrix, const float * ptr); +template<int NUM_ROWS> +FORCEINLINE void vector_fix2float(float* matrix, const float divisor) +{ + for(int i=0;i<NUM_ROWS*4;i++) + matrix[i] /= divisor; +} + +template<int NUM> +static FORCEINLINE void memset_u8(void* dst, u8 val) +{ + memset(dst,val,NUM); +} + +#else //no sse + +void MatrixMultVec4x4 (const float *matrix, float *vecPtr); +void MatrixMultVec3x3(const float * matrix, float * vecPtr); +void MatrixMultiply(float * matrix, const float * rightMatrix); +void MatrixTranslate(float *matrix, const float *ptr); +void MatrixScale(float * matrix, const float * ptr); + +FORCEINLINE void MatrixMultVec4x4_M2(const float *matrix, float *vecPtr) +{ + //there are hardly any gains from merging these manually + MatrixMultVec4x4(matrix+16,vecPtr); + MatrixMultVec4x4(matrix,vecPtr); +} + +template<int NUM_ROWS> +FORCEINLINE void vector_fix2float(float* matrix, const float divisor) +{ + for(int i=0;i<NUM_ROWS*4;i++) + matrix[i] /= divisor; +} + +template<int NUM> +static FORCEINLINE void memset_u8(void* dst, u8 val) +{ + memset(dst,val,NUM); +} + +#endif //switched SSE functions + +void MatrixMultVec4x4 (const s32 *matrix, s32 *vecPtr); + +void MatrixMultVec4x4_M2(const s32 *matrix, s32 *vecPtr); + +void MatrixMultiply(s32* matrix, const s32* rightMatrix); +void MatrixScale(s32 *matrix, const s32 *ptr); +void MatrixTranslate(s32 *matrix, const s32 *ptr); +#endif + diff --git a/jni/desmume/src/mc.cpp b/jni/desmume/src/mc.cpp new file mode 100755 index 0000000..d2e2225 --- /dev/null +++ b/jni/desmume/src/mc.cpp @@ -0,0 +1,1544 @@ +/* + Copyright (C) 2006 thoduv + Copyright (C) 2006-2007 Theo Berkau + Copyright (C) 2008-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include <string.h> +#include "debug.h" +#include "types.h" +#include "mc.h" +#include "movie.h" +#include "readwrite.h" +#include "NDSSystem.h" +#define TIXML_USE_STL +#include "utils/tinyxml/tinyxml.h" + +//temporary hack until we have better error reporting facilities +#ifdef _WINDOWS +#include <windows.h> +#elif defined(_XBOX) +#include <xtl.h> // it`s really need? +#endif + +#define FW_CMD_READ 0x03 +#define FW_CMD_WRITEDISABLE 0x04 +#define FW_CMD_READSTATUS 0x05 +#define FW_CMD_WRITEENABLE 0x06 +#define FW_CMD_PAGEWRITE 0x0A +#define FW_CMD_READ_ID 0x9F + +#define BM_CMD_AUTODETECT 0xFF +#define BM_CMD_WRITESTATUS 0x01 +#define BM_CMD_WRITELOW 0x02 +#define BM_CMD_READLOW 0x03 +#define BM_CMD_WRITEDISABLE 0x04 +#define BM_CMD_READSTATUS 0x05 +#define BM_CMD_WRITEENABLE 0x06 +#define BM_CMD_WRITEHIGH 0x0A +#define BM_CMD_READHIGH 0x0B + +/* FLASH*/ +#define COMM_PAGE_WRITE 0x0A +#define COMM_PAGE_ERASE 0xDB +#define COMM_SECTOR_ERASE 0xD8 +#define COMM_CHIP_ERASE 0xC7 +#define CARDFLASH_READ_BYTES_FAST 0x0B /* Not used*/ +#define CARDFLASH_DEEP_POWDOWN 0xB9 /* Not used*/ +#define CARDFLASH_WAKEUP 0xAB /* Not used*/ + +//since r2203 this was 0x00. +//but baby pals proves finally that it should be 0xFF: +//the game reads its initial sound volumes from uninitialized data, and if it is 0, the game will be silent +//if it is 0xFF then the game starts with its sound and music at max, as presumably it is supposed to. +//so in r3303 I finally changed it (no$ appears definitely to initialized to 0xFF) +static const u8 kUninitializedSaveDataValue = 0xFF; + +static const char* kDesmumeSaveCookie = "|-DESMUME SAVE-|"; + +static const u32 saveSizes[] = {512, // 4k + 8*1024, // 64k + 32*1024, // 512k + 64*1024, // 1Mbit + 256*1024, // 2Mbit + 512*1024, // 4Mbit + 1024*1024, // 8Mbit + 2048*1024, // 16Mbit + 4096*1024, // 32Mbit + 8192*1024, // 64Mbit + 16384*1024, // 128Mbit + 32768*1024, // 256Mbit + 65536*1024, // 512Mbit + 0xFFFFFFFF}; +static const u32 saveSizes_count = ARRAY_SIZE(saveSizes); + +//the lookup table from user save types to save parameters +const int save_types[][2] = { + {MC_TYPE_AUTODETECT,1}, + {MC_TYPE_EEPROM1,MC_SIZE_4KBITS}, + {MC_TYPE_EEPROM2,MC_SIZE_64KBITS}, + {MC_TYPE_EEPROM2,MC_SIZE_512KBITS}, + {MC_TYPE_FRAM,MC_SIZE_256KBITS}, + {MC_TYPE_FLASH,MC_SIZE_2MBITS}, + {MC_TYPE_FLASH,MC_SIZE_4MBITS}, + {MC_TYPE_FLASH,MC_SIZE_8MBITS}, + {MC_TYPE_FLASH,MC_SIZE_16MBITS}, + {MC_TYPE_FLASH,MC_SIZE_32MBITS}, + {MC_TYPE_FLASH,MC_SIZE_64MBITS}, + {MC_TYPE_FLASH,MC_SIZE_128MBITS}, + {MC_TYPE_FLASH,MC_SIZE_256MBITS}, + {MC_TYPE_FLASH,MC_SIZE_512MBITS} +}; + +const char *save_names[] = { + "EEPROM 4kbit", + "EEPROM 64kbit", + "EEPROM 512kbit", + "FRAM 256kbit", + "FLASH 2Mbit", + "FLASH 4Mbit", + "FLASH 8Mbit", + "FLASH 16Mbit", + "FLASH 32Mbit", + "FLASH 64Mbit", + "FLASH 128Mbit", + "FLASH 256Mbit", + "FLASH 512Mbit" +}; + +//forces the currently selected backup type to be current +//(can possibly be used to repair poorly chosen save types discovered late in gameplay i.e. pokemon gamers) +void backup_forceManualBackupType() +{ + MMU_new.backupDevice.forceManualBackupType(); +} + +void backup_setManualBackupType(int type) +{ + CommonSettings.manualBackupType = type; +} + +void mc_init(memory_chip_t *mc, int type) +{ + mc->com = 0; + mc->addr = 0; + mc->addr_shift = 0; + mc->data = NULL; + mc->size = 0; + mc->write_enable = FALSE; + mc->writeable_buffer = FALSE; + mc->type = type; + mc->autodetectsize = 0; + + switch(mc->type) + { + case MC_TYPE_EEPROM1: + mc->addr_size = 1; + break; + case MC_TYPE_EEPROM2: + case MC_TYPE_FRAM: + mc->addr_size = 2; + break; + case MC_TYPE_FLASH: + mc->addr_size = 3; + break; + default: break; + } +} + +u8 *mc_alloc(memory_chip_t *mc, u32 size) +{ + u8 *buffer; + buffer = new u8[size]; + memset(buffer,0,size); + + if (mc->data) delete [] mc->data; + mc->data = buffer; + if(!buffer) { return NULL; } + mc->size = size; + mc->writeable_buffer = TRUE; + + return buffer; +} + +void mc_free(memory_chip_t *mc) +{ + if(mc->data) delete[] mc->data; + mc_init(mc, 0); +} + +void fw_reset_com(memory_chip_t *mc) +{ + if(mc->com == FW_CMD_PAGEWRITE) + { + if (mc->fp) + { + fseek(mc->fp, 0, SEEK_SET); + fwrite(mc->data, mc->size, 1, mc->fp); + } + + if (mc->isFirmware&&CommonSettings.UseExtFirmware) + { + // copy User Settings 1 to User Settings 0 area + memcpy(&mc->data[0x3FE00], &mc->data[0x3FF00], 0x100); + + printf("Firmware: save config"); + FILE *fp = fopen(mc->userfile, "wb"); + if (fp) + { + if (fwrite(&mc->data[0x3FF00], 1, 0x100, fp) == 0x100) // User Settings + { + if (fwrite(&mc->data[0x0002A], 1, 0x1D6, fp) == 0x1D6) // WiFi Settings + { + if (fwrite(&mc->data[0x3FA00], 1, 0x300, fp) == 0x300) // WiFi AP Settings + printf(" - done\n"); + else + printf(" - failed\n"); + } + } + fclose(fp); + } + else + printf(" - failed\n"); + } + + mc->write_enable = FALSE; + } + + mc->com = 0; +} + +u8 fw_transfer(memory_chip_t *mc, u8 data) +{ + if(mc->com == FW_CMD_READ || mc->com == FW_CMD_PAGEWRITE) /* check if we are in a command that needs 3 bytes address */ + { + if(mc->addr_shift > 0) /* if we got a complete address */ + { + mc->addr_shift--; + mc->addr |= data << (mc->addr_shift * 8); /* argument is a byte of address */ + } + else /* if we have received 3 bytes of address, proceed command */ + { + switch(mc->com) + { + case FW_CMD_READ: + if(mc->addr < mc->size) /* check if we can read */ + { + data = mc->data[mc->addr]; /* return byte */ + mc->addr++; /* then increment address */ + } + break; + + case FW_CMD_PAGEWRITE: + if(mc->addr < mc->size) + { + mc->data[mc->addr] = data; /* write byte */ + mc->addr++; + } + break; + } + + } + } + else if(mc->com == FW_CMD_READ_ID) + { + switch(mc->addr) + { + //here is an ID string measured from an old ds fat: 62 16 00 (0x62=sanyo) + //but we chose to use an ST from martin's ds fat string so programs might have a clue as to the firmware size: + //20 40 12 + case 0: + data = 0x20; + mc->addr=1; + break; + case 1: + data = 0x40; //according to gbatek this is the device ID for the flash on someone's ds fat + mc->addr=2; + break; + case 2: + data = 0x12; + mc->addr = 0; + break; + } + } + else if(mc->com == FW_CMD_READSTATUS) + { + return (mc->write_enable ? 0x02 : 0x00); + } + else //finally, check if it's a new command + { + switch(data) + { + case 0: break; //nothing + + case FW_CMD_READ_ID: + mc->addr = 0; + mc->com = FW_CMD_READ_ID; + break; + + case FW_CMD_READ: //read command + mc->addr = 0; + mc->addr_shift = 3; + mc->com = FW_CMD_READ; + break; + + case FW_CMD_WRITEENABLE: //enable writing + if(mc->writeable_buffer) { mc->write_enable = TRUE; } + break; + + case FW_CMD_WRITEDISABLE: //disable writing + mc->write_enable = FALSE; + break; + + case FW_CMD_PAGEWRITE: //write command + if(mc->write_enable) + { + mc->addr = 0; + mc->addr_shift = 3; + mc->com = FW_CMD_PAGEWRITE; + } + else { data = 0; } + break; + + case FW_CMD_READSTATUS: //status register command + mc->com = FW_CMD_READSTATUS; + break; + + default: + printf("Unhandled FW command: %02X\n", data); + break; + } + } + + return data; +} + +bool BackupDevice::save_state(EMUFILE* os) +{ + u32 version = 2; + //v0 + write32le(version,os); + write32le(write_enable,os); + write32le(com,os); + write32le(addr_size,os); + write32le(addr_counter,os); + write32le((u32)state,os); + writebuffer(data,os); + writebuffer(data_autodetect,os); + //v1 + write32le(addr,os); + //v2 + write8le(motionInitState,os); + write8le(motionFlag,os); + return true; +} + +bool BackupDevice::load_state(EMUFILE* is) +{ + u32 version; + if(read32le(&version,is)!=1) return false; + if(version>=0) + { + readbool(&write_enable,is); + read32le(&com,is); + read32le(&addr_size,is); + read32le(&addr_counter,is); + u32 temp; + read32le(&temp,is); + state = (STATE)temp; + readbuffer(data,is); + readbuffer(data_autodetect,is); + } + if(version>=1) + read32le(&addr,is); + if(version>=2) + { + read8le(&motionInitState,is); + read8le(&motionFlag,is); + } + + return true; +} + +BackupDevice::BackupDevice() +{ + isMovieMode = false; + reset(); +} + +//due to unfortunate shortcomings in the emulator architecture, +//at reset-time, we won't have a filename to the .dsv file. +//so the only difference between load_rom (init) and reset is that +//one of them saves the filename +void BackupDevice::load_rom(const char* filename) +{ + isMovieMode = false; + this->filename = filename; + reset(); +} + +void BackupDevice::movie_mode() +{ + isMovieMode = true; + reset(); +} + +void BackupDevice::reset_hardware() +{ + write_enable = FALSE; + com = 0; + addr = addr_counter = 0; + motionInitState = MOTION_INIT_STATE_IDLE; + motionFlag = MOTION_FLAG_NONE; + state = DETECTING; + flushPending = false; + lazyFlushPending = false; +} + +void BackupDevice::reset() +{ + memset(&info, 0, sizeof(info)); + reset_hardware(); + resize(0); + data_autodetect.resize(0); + addr_size = 0; + loadfile(); + + //if the user has requested a manual choice for backup type, and we havent imported a raw save file, then apply it now + if(state == DETECTING && CommonSettings.manualBackupType != MC_TYPE_AUTODETECT) + { + state = RUNNING; + int savetype = save_types[CommonSettings.manualBackupType][0]; + int savesize = save_types[CommonSettings.manualBackupType][1]; + ensure((u32)savesize); //expand properly if necessary + resize(savesize); //truncate if necessary + addr_size = addr_size_for_old_save_type(savetype); + flush(); + } +} + +void BackupDevice::close_rom() +{ + flush(); +} + +u8 BackupDevice::searchFileSaveType(u32 size) +{ + for (u8 i = 1; i < MAX_SAVE_TYPES; i++) + { + if (size == save_types[i][1]) + return (i-1); + } + return 0xFF; +} + +void BackupDevice::reset_command() +{ + //printf("MC RESET\n"); + //for a performance hack, save files are only flushed after each reset command + //(hopefully, after each page) + if(flushPending) + { + flush(); + flushPending = false; + lazyFlushPending = false; + } + + if(state == DETECTING && data_autodetect.size()>0) + { + //we can now safely detect the save address size + u32 autodetect_size = data_autodetect.size(); + + printf("Autodetecting with autodetect_size=%d\n",autodetect_size); + + const u8 sm64_sig[] = {0x01,0x80,0x00,0x00}; + if(autodetect_size == 4 && !memcmp(&data_autodetect[0],sm64_sig,4)) + { + addr_size = 2; + } + else //detect based on rules + switch(autodetect_size) + { + case 0: + case 1: + printf("Catastrophic error while autodetecting save type.\nIt will need to be specified manually\n"); + #ifdef _WINDOWS + MessageBox(0,"Catastrophic Error Code: Camel;\nyour save type has not been autodetected correctly;\nplease report to developers",0,0); + #endif + addr_size = 1; //choose 1 just to keep the busted savefile from growing too big + break; + case 2: + //the modern typical case for small eeproms + addr_size = 1; + break; + case 3: + //another modern typical case.. + //but unfortunately we select this case for spider-man 3, when what it meant to do was + //present the archaic 1+2 case + //it seems that over the hedge does this also. + addr_size = 2; + break; + case 4: + //a modern typical case + addr_size = 3; + break; + default: + //the archaic case: write the address and then some modulo-4 number of bytes + //why modulo 4? who knows. + //SM64 (KOR) makes it here with autodetect_size=11 and nothing interesting in the buffer + addr_size = autodetect_size & 3; + break; + } + + state = RUNNING; + data_autodetect.resize(0); + flush(); + } + + com = 0; +} +u8 BackupDevice::data_command(u8 val, int cpu) +{ + //printf("MC CMD: %02X\n",val); + + //motion: some guessing here... hope it doesn't break anything + if(com == BM_CMD_READLOW && motionInitState == MOTION_INIT_STATE_RECEIVED_4_B && val == 0) + { + motionInitState = MOTION_INIT_STATE_IDLE; + motionFlag |= MOTION_FLAG_ENABLED; + //return 0x04; //return 0x04 to enable motion!!!!! + return 0; //but we return 0 to disable it! since we don't emulate it anyway + } + + //if the game firmly believes we have motion support, then ignore all motion commands, since theyre not emulated. + if(motionFlag & MOTION_FLAG_SENSORMODE) + { + return 0; + } + + if(com == BM_CMD_READLOW || com == BM_CMD_WRITELOW) + { + //handle data or address + if(state == DETECTING) + { + if(com == BM_CMD_WRITELOW) + { + printf("Unexpected backup device initialization sequence using writes!\n"); + } + + //just buffer the data until we're no longer detecting + data_autodetect.push_back(val); + val = 0; + } + else + { + if(addr_counter<addr_size) + { + //continue building address + addr <<= 8; + addr |= val; + addr_counter++; + //if(addr_counter==addr_size) printf("ADR: %08X\n",addr); + } + else + { + //why does tomb raider underworld access 0x180 and go clear through to 0x280? + //should this wrap around at 0 or at 0x100? + if(addr_size == 1) addr &= 0x1FF; + + //address is complete + ensure(addr+1); + if(com == BM_CMD_READLOW) + { + //printf("READ ADR: %08X\n",addr); + val = data[addr]; + //flushPending = true; //is this a good idea? it may slow stuff down, but it is helpful for debugging + lazyFlushPending = true; //lets do this instead + //printf("read: %08X\n",addr); + } + else + { + if(write_enable) + { + //printf("WRITE ADR: %08X\n",addr); + data[addr] = val; + flushPending = true; + //printf("writ: %08X\n",addr); + } + } + addr++; + + } + } + } + else if(com == BM_CMD_READSTATUS) + { + //handle request to read status + LOG("Backup Memory Read Status: %02X\n", write_enable << 1); + return (write_enable << 1) | (3<<2); + } + else + { + //there is no current command. receive one + switch(val) + { + case 0: break; //?? + + case 0xFE: + if(motionInitState == MOTION_INIT_STATE_IDLE) { motionInitState = MOTION_INIT_STATE_FE; return 0; } + break; + case 0xFD: + if(motionInitState == MOTION_INIT_STATE_FE) { motionInitState = MOTION_INIT_STATE_FD; return 0; } + break; + case 0xFB: + if(motionInitState == MOTION_INIT_STATE_FD) { motionInitState = MOTION_INIT_STATE_FB; return 0; } + break; + case 0xF8: + //enable sensor mode + if(motionInitState == MOTION_INIT_STATE_FD) + { + motionInitState = MOTION_INIT_STATE_IDLE; + motionFlag |= MOTION_FLAG_SENSORMODE; + return 0; + } + break; + case 0xF9: + //disable sensor mode + if(motionInitState == MOTION_INIT_STATE_FD) + { + motionInitState = MOTION_INIT_STATE_IDLE; + motionFlag &= ~MOTION_FLAG_SENSORMODE; + return 0; + } + break; + + case 8: + printf("COMMAND%c: Unverified Backup Memory command: %02X FROM %08X\n",(cpu==ARMCPU_ARM9)?'9':'7',val, (cpu==ARMCPU_ARM9)?NDS_ARM9.instruct_adr:NDS_ARM7.instruct_adr); + val = 0xAA; + break; + + case BM_CMD_WRITEDISABLE: + switch(motionInitState) + { + case MOTION_INIT_STATE_IDLE: motionInitState = MOTION_INIT_STATE_RECEIVED_4; break; + case MOTION_INIT_STATE_RECEIVED_4: motionInitState = MOTION_INIT_STATE_RECEIVED_4_B; break; + } + write_enable = FALSE; + break; + + case BM_CMD_READSTATUS: + com = BM_CMD_READSTATUS; + val = (write_enable << 1) | (3<<2); + break; + + case BM_CMD_WRITEENABLE: + write_enable = TRUE; + break; + + case BM_CMD_WRITELOW: + case BM_CMD_READLOW: + //printf("XLO: %08X\n",addr); + com = val; + addr_counter = 0; + addr = 0; + break; + + case BM_CMD_WRITEHIGH: + case BM_CMD_READHIGH: + //printf("XHI: %08X\n",addr); + if(val == BM_CMD_WRITEHIGH) val = BM_CMD_WRITELOW; + if(val == BM_CMD_READHIGH) val = BM_CMD_READLOW; + com = val; + addr_counter = 0; + addr = 0; + if(addr_size==1) { + //"write command that's only available on ST M95040-W that I know of" + //this makes sense, since this device would only have a 256 bytes address space with writelow + //and writehigh would allow access to the upper 256 bytes + //but it was detected in pokemon diamond also during the main save process + addr = 0x1; + } + break; + + default: + printf("COMMAND%c: Unhandled Backup Memory command: %02X FROM %08X\n",(cpu==ARMCPU_ARM9)?'9':'7',val, (cpu==ARMCPU_ARM9)?NDS_ARM9.instruct_adr:NDS_ARM7.instruct_adr); + break; + } //switch(val) + + //motion control state machine broke, return to ground + motionInitState = MOTION_INIT_STATE_IDLE; + } + return val; +} + +//guarantees that the data buffer has room enough for the specified number of bytes +void BackupDevice::ensure(u32 addr) +{ + u32 size = data.size(); + if(size<addr) + { + resize(addr); + } +} + +void BackupDevice::resize(u32 size) +{ + size_t old_size = data.size(); + data.resize(size); + for(u32 i=old_size;i<size;i++) + data[i] = kUninitializedSaveDataValue; +} + +u32 BackupDevice::addr_size_for_old_save_size(int bupmem_size) +{ + switch(bupmem_size) { + case MC_SIZE_4KBITS: + return 1; + case MC_SIZE_64KBITS: + case MC_SIZE_256KBITS: + case MC_SIZE_512KBITS: + return 2; + case MC_SIZE_1MBITS: + case MC_SIZE_2MBITS: + case MC_SIZE_4MBITS: + case MC_SIZE_8MBITS: + case MC_SIZE_16MBITS: + case MC_SIZE_64MBITS: + return 3; + default: + return 0xFFFFFFFF; + } +} + +u32 BackupDevice::addr_size_for_old_save_type(int bupmem_type) +{ + switch(bupmem_type) + { + case MC_TYPE_EEPROM1: + return 1; + case MC_TYPE_EEPROM2: + case MC_TYPE_FRAM: + return 2; + case MC_TYPE_FLASH: + return 3; + default: + return 0xFFFFFFFF; + } +} + + +void BackupDevice::load_old_state(u32 addr_size, u8* data, u32 datasize) +{ + state = RUNNING; + this->addr_size = addr_size; + resize(datasize); + memcpy(&this->data[0],data,datasize); + + //dump back out as a dsv, just to keep things sane + flush(); +} + +//======================================================================= no$GBA +//======================================================================= +//======================================================================= +const char no_GBA_HEADER_ID[] = "NocashGbaBackupMediaSavDataFile"; +const char no_GBA_HEADER_SRAM_ID[] = "SRAM"; + +u32 BackupDevice::get_save_nogba_size(const char* fname) +{ + FILE *fsrc = fopen(fname, "rb"); + if (fsrc) + { + char src[0x50] = {0}; + u32 fsize = 0; + fseek(fsrc, 0, SEEK_END); + fsize = ftell(fsrc); + fseek(fsrc, 0, SEEK_SET); + if (fsize < 0x50) { fclose(fsrc); return 0xFFFFFFFF; } + memset(&src[0], 0, sizeof(src)); + if (fread(src, 1, sizeof(src), fsrc) != sizeof(src)) { fclose(fsrc); return 0xFFFFFFFF; } + + for (u8 i = 0; i < 0x1F; i++) + if (src[i] != no_GBA_HEADER_ID[i]) { fclose(fsrc); return 0xFFFFFFFF; } + if (src[0x1F] != 0x1A) { fclose(fsrc); return 0xFFFFFFFF; } + for (int i = 0; i < 0x4; i++) + if (src[i+0x40] != no_GBA_HEADER_SRAM_ID[i]) { fclose(fsrc); return 0xFFFFFFFF; } + + u32 compressMethod = *((u32*)(src+0x44)); + if (compressMethod == 0) + { fclose(fsrc); return *((u32*)(src+0x48)); } + else + if (compressMethod == 1) + { fclose(fsrc); return *((u32*)(src+0x4C)); } + fclose(fsrc); + } + return 0xFFFFFFFF; +} + +static int no_gba_unpackSAV(void *in_buf, u32 fsize, void *out_buf, u32 &size) +{ + u8 *src = (u8 *)in_buf; + u8 *dst = (u8 *)out_buf; + u32 src_pos = 0; + u32 dst_pos = 0; + u8 cc = 0; + u32 size_unpacked = 0; + u32 size_packed = 0; + u32 compressMethod = 0; + + if (fsize < 0x50) return (1); + + for (int i = 0; i < 0x1F; i++) + { + if (src[i] != no_GBA_HEADER_ID[i]) return (2); + } + if (src[0x1F] != 0x1A) return (2); + for (int i = 0; i < 0x4; i++) + { + if (src[i+0x40] != no_GBA_HEADER_SRAM_ID[i]) return (2); + } + + compressMethod = *((u32*)(src+0x44)); + + if (compressMethod == 0) // unpacked + { + size_unpacked = *((u32*)(src+0x48)); + src_pos = 0x4C; + for (u32 i = 0; i < size_unpacked; i++) + { + dst[dst_pos++] = src[src_pos++]; + } + size = dst_pos; + return (0); + } + + if (compressMethod == 1) // packed (method 1) + { + size_packed = *((u32*)(src+0x48)); + size_unpacked = *((u32*)(src+0x4C)); + + src_pos = 0x50; + while (true) + { + cc = src[src_pos++]; + + if (cc == 0) + { + size = dst_pos; + return (0); + } + + if (cc == 0x80) + { + u16 tsize = *((u16*)(src+src_pos+1)); + for (int t = 0; t < tsize; t++) + dst[dst_pos++] = src[src_pos]; + src_pos += 3; + continue; + } + + if (cc > 0x80) // repeat + { + cc -= 0x80; + for (int t = 0; t < cc; t++) + dst[dst_pos++] = src[src_pos]; + src_pos++; + continue; + } + // copy + for (int t = 0; t < cc; t++) + dst[dst_pos++] = src[src_pos++]; + } + size = dst_pos; + return (0); + } + return (200); +} + +static u32 no_gba_savTrim(void *buf, u32 size) +{ + u32 rows = size / 16; + u32 pos = (size - 16); + u8 *src = (u8*)buf; + + for (unsigned int i = 0; i < rows; i++, pos -= 16) + { + if (src[pos] == 0xFF) + { + for (int t = 0; t < 16; t++) + { + if (src[pos+t] != 0xFF) return (pos+16); + } + } + else + { + return (pos+16); + } + } + return (size); +} + +static u32 no_gba_fillLeft(u32 size) +{ + for (u32 i = 1; i < ARRAY_SIZE(save_types); i++) + { + if (size <= (u32)save_types[i][1]) + return (size + (save_types[i][1] - size)); + } + return size; +} + +bool BackupDevice::load_no_gba(const char *fname, u32 force_size) +{ + FILE *fsrc = fopen(fname, "rb"); + u8 *in_buf = NULL; + u8 *out_buf = NULL; + + if (fsrc) + { + u32 fsize = 0; + fseek(fsrc, 0, SEEK_END); + fsize = ftell(fsrc); + fseek(fsrc, 0, SEEK_SET); + //printf("Open %s file (size %i bytes)\n", fname, fsize); + + in_buf = new u8 [fsize]; + + if (fread(in_buf, 1, fsize, fsrc) == fsize) + { + out_buf = new u8 [8 * 1024 * 1024 / 8]; + u32 size = 0; + + memset(out_buf, 0xFF, 8 * 1024 * 1024 / 8); + if (no_gba_unpackSAV(in_buf, fsize, out_buf, size) == 0) + { + if (force_size > 0) + size = force_size; + //printf("New size %i byte(s)\n", size); + size = no_gba_savTrim(out_buf, size); + //printf("--- new size after trim %i byte(s)\n", size); + size = no_gba_fillLeft(size); + //printf("--- new size after fill %i byte(s)\n", size); + raw_applyUserSettings(size, (force_size > 0)); + resize(size); + for (u32 tt = 0; tt < size; tt++) + data[tt] = out_buf[tt]; + + //dump back out as a dsv, just to keep things sane + flush(); + printf("---- Loaded no$GBA save\n"); + + if (in_buf) delete [] in_buf; + if (out_buf) delete [] out_buf; + fclose(fsrc); + return true; + } + if (out_buf) delete [] out_buf; + } + if (in_buf) delete [] in_buf; + fclose(fsrc); + } + + return false; +} + +bool BackupDevice::save_no_gba(const char* fname) +{ + FILE* outf = fopen(fname,"wb"); + if(!outf) return false; + u32 size = data.size(); + u32 padSize = pad_up_size(size); + if(data.size()>0) + fwrite(&data[0],1,size,outf); + for(u32 i=size;i<padSize;i++) + fputc(0xFF,outf); + + if (padSize < 512 * 1024) + { + for(u32 i=padSize; i<512 * 1024; i++) + fputc(0xFF,outf); + } + fclose(outf); + return true; +} +//======================================================================= end +//======================================================================= +//======================================================================= no$GBA + + +void BackupDevice::loadfile() +{ + //never use save files if we are in movie mode + if(isMovieMode) return; + if(filename.length() ==0) return; //No sense crashing if no filename supplied + + EMUFILE_FILE* inf = new EMUFILE_FILE(filename.c_str(),"rb"); + if(inf->fail()) + { + delete inf; + //no dsv found; we need to try auto-importing a file with .sav extension + printf("DeSmuME .dsv save file not found. Trying to load an old raw .sav file.\n"); + + //change extension to sav + char tmp[MAX_PATH]; + strcpy(tmp,filename.c_str()); + tmp[strlen(tmp)-3] = 0; + strcat(tmp,"sav"); + + inf = new EMUFILE_FILE(tmp,"rb"); + if(inf->fail()) + { + delete inf; + printf("Missing save file %s\n",filename.c_str()); + return; + } + delete inf; + + if (!load_no_gba(tmp)) + load_raw(tmp); + } + else + { + //scan for desmume save footer + const s32 cookieLen = (s32)strlen(kDesmumeSaveCookie); + char *sigbuf = new char[cookieLen]; + inf->fseek(-cookieLen, SEEK_END); + inf->fread(sigbuf,cookieLen); + int cmp = memcmp(sigbuf,kDesmumeSaveCookie,cookieLen); + delete[] sigbuf; + if(cmp) + { + //maybe it is a misnamed raw save file. try loading it that way + printf("Not a DeSmuME .dsv save file. Trying to load as raw.\n"); + delete inf; + if (!load_no_gba(filename.c_str())) + load_raw(filename.c_str()); + return; + } + //desmume format + inf->fseek(-cookieLen, SEEK_END); + inf->fseek(-4, SEEK_CUR); + u32 version = 0xFFFFFFFF; + read32le(&version,inf); + if(version!=0) { + printf("Unknown save file format\n"); + return; + } + inf->fseek(-24, SEEK_CUR); + read32le(&info.size,inf); + read32le(&info.padSize,inf); + read32le(&info.type,inf); + read32le(&info.addr_size,inf); + read32le(&info.mem_size,inf); + + u32 left = 0; + if (CommonSettings.autodetectBackupMethod == 1) + { + if (advsc.isLoaded()) + { + info.type = advsc.getSaveType(); + if (info.type != 0xFF || info.type != 0xFE) + { + u32 adv_size = save_types[info.type+1][1]; + if (info.size > adv_size) + info.size = adv_size; + else + if (info.size < adv_size) + { + left = adv_size - info.size; + info.size = adv_size; + } + } + } + } + //establish the save data + resize(info.size); + inf->fseek(0, SEEK_SET); + if(info.size>0) + inf->fread(&data[0],info.size - left); //read all the raw data we have + state = RUNNING; + addr_size = info.addr_size; + //none of the other fields are used right now + + + if (CommonSettings.autodetectBackupMethod != 1 && info.type == 0) + { + info.type = searchFileSaveType(info.size); + if (info.type == 0xFF) info.type = 0; + } + u32 ss = info.size * 8 / 1024; + if (ss >= 1024) + { + ss /= 1024; + printf("Backup size: %i Mbit\n", ss); + } + else + printf("Backup size: %i Kbit\n", ss); + + delete inf; + } +} + +bool BackupDevice::save_raw(const char* filename) +{ + FILE* outf = fopen(filename,"wb"); + if(!outf) return false; + u32 size = data.size(); + u32 padSize = pad_up_size(size); + if(data.size()>0) + fwrite(&data[0],1,size,outf); + for(u32 i=size;i<padSize;i++) + fputc(kUninitializedSaveDataValue,outf); + fclose(outf); + return true; +} + +u32 BackupDevice::pad_up_size(u32 startSize) +{ + u32 size = startSize; + u32 ctr=0; + while(ctr<saveSizes_count && size > saveSizes[ctr]) ctr++; + u32 padSize = saveSizes[ctr]; + if(padSize == 0xFFFFFFFF) + { + printf("PANIC! Couldn't pad up save size. Refusing to pad.\n"); + padSize = startSize; + } + return padSize; +} + +void BackupDevice::lazy_flush() +{ + if(flushPending || lazyFlushPending) + { + lazyFlushPending = flushPending = false; + flush(); + } +} + +void BackupDevice::flush() +{ + //never use save files if we are in movie mode + if(isMovieMode) return; + + if (filename.length() == 0) return; + + EMUFILE* outf = new EMUFILE_FILE(filename.c_str(),"wb"); + if(!outf->fail()) + { + if(data.size()>0) + outf->fwrite(&data[0],data.size()); + + //write the footer. we use a footer so that we can maximize the chance of the + //save file being recognized as a raw save file by other emulators etc. + + //first, pad up to the next largest known save size. + u32 size = data.size(); + u32 padSize = pad_up_size(size); + + for(u32 i=size;i<padSize;i++) + outf->fputc(kUninitializedSaveDataValue); + + //this is just for humans to read + outf->fprintf("|<--Snip above here to create a raw sav by excluding this DeSmuME savedata footer:"); + + //and now the actual footer + write32le(size,outf); //the size of data that has actually been written + write32le(padSize,outf); //the size we padded it to + write32le(info.type,outf); //save memory type + write32le(addr_size,outf); + write32le(info.size,outf); //save memory size + write32le(0,outf); //version number + outf->fprintf("%s", kDesmumeSaveCookie); //this is what we'll use to recognize the desmume format save + + delete outf; + } + else + { + delete outf; + printf("Unable to open savefile %s\n", filename.c_str()); + } +} + +void BackupDevice::raw_applyUserSettings(u32& size, bool manual) +{ + //respect the user's choice of backup memory type + if(CommonSettings.manualBackupType == MC_TYPE_AUTODETECT && !manual) + { + addr_size = addr_size_for_old_save_size(size); + resize(size); + } + else + { + u32 type = CommonSettings.manualBackupType; + if (manual) + { + u32 res = searchFileSaveType(size); + if (res != 0xFF) type = (res + 1); // +1 - skip autodetect + } + int savetype = save_types[type][0]; + int savesize = save_types[type][1]; + addr_size = addr_size_for_old_save_type(savetype); + if((u32)savesize<size) size = savesize; + resize(savesize); + } + + state = RUNNING; +} + +u32 BackupDevice::get_save_raw_size(const char* fname) +{ + FILE* inf = fopen(fname,"rb"); + if (!inf) return 0xFFFFFFFF; + + fseek(inf, 0, SEEK_END); + u32 size = (u32)ftell(inf); + fclose(inf); + return size; +} + +bool BackupDevice::load_raw(const char* filename, u32 force_size) +{ + FILE* inf = fopen(filename,"rb"); + + if (!inf) return false; + + fseek(inf, 0, SEEK_END); + u32 size = (u32)ftell(inf); + u32 left = 0; + + if (force_size > 0) + { + if (size > force_size) + size = force_size; + else + if (size < force_size) + { + left = force_size - size; + size = force_size; + } + } + + fseek(inf, 0, SEEK_SET); + + raw_applyUserSettings(size, (force_size > 0)); + + fread(&data[0],1,size-left,inf); + fclose(inf); + + //dump back out as a dsv, just to keep things sane + flush(); + + return true; +} + +u32 BackupDevice::get_save_duc_size(const char* fname) +{ + FILE* inf = fopen(fname,"rb"); + if (!inf) return 0xFFFFFFFF; + + fseek(inf, 0, SEEK_END); + u32 size = (u32)ftell(inf); + fclose(inf); + if (size < 500) return 0xFFFFFFFF; + return (size - 500); +} + +bool BackupDevice::load_duc(const char* filename, u32 force_size) +{ + u32 size; + char id[16]; + FILE* file = fopen(filename, "rb"); + + if(!file) return false; + + fseek(file, 0, SEEK_END); + size = (u32)ftell(file) - 500; + fseek(file, 0, SEEK_SET); + + // Make sure we really have the right file + fread((void *)id, sizeof(char), 16, file); + + if (memcmp(id, "ARDS000000000001", 16) != 0) + { + printf("Not recognized as a valid DUC file\n"); + fclose(file); + return false; + } + // Skip the rest of the header since we don't need it + fseek(file, 500, SEEK_SET); + + u32 left = 0; + if (force_size > 0) + { + if (size > force_size) + size = force_size; + else + if (size < force_size) + { + left = force_size - size; + size = force_size; + } + } + + raw_applyUserSettings(size, (force_size > 0)); + + ensure((u32)size); + + fread(&data[0],1,size-left,file); + fclose(file); + + //choose + + flush(); + + return true; + +} + +bool BackupDevice::load_movie(EMUFILE* is) { + + const s32 cookieLen = (s32)strlen(kDesmumeSaveCookie); + + is->fseek(-cookieLen, SEEK_END); + is->fseek(-4, SEEK_CUR); + + u32 version = 0xFFFFFFFF; + is->fread((char*)&version,4); + if(version!=0) { + printf("Unknown save file format\n"); + return false; + } + is->fseek(-24, SEEK_CUR); + + struct{ + u32 size,padSize,type,addr_size,mem_size; + }info; + + is->fread((char*)&info.size,4); + is->fread((char*)&info.padSize,4); + is->fread((char*)&info.type,4); + is->fread((char*)&info.addr_size,4); + is->fread((char*)&info.mem_size,4); + + //establish the save data + resize(info.size); + is->fseek(0, SEEK_SET); + if(info.size>0) + is->fread((char*)&data[0],info.size); + + state = RUNNING; + addr_size = info.addr_size; + //none of the other fields are used right now + + return true; +} + +void BackupDevice::forceManualBackupType() +{ + addr_size = addr_size_for_old_save_size(save_types[CommonSettings.manualBackupType][1]); + state = RUNNING; +} + +// ============================================= ADVANsCEne +u8 ADVANsCEne::checkDB(const char *serial) +{ + loaded = false; + FILE *fp = fopen(database_path, "rb"); + if (fp) + { + char buf[64]; + memset(buf, 0, sizeof(buf)); + if (fread(buf, 1, strlen(_ADVANsCEne_BASE_ID), fp) == strlen(_ADVANsCEne_BASE_ID)) + { + //printf("ID: %s\n", buf); + if (strcmp(buf, _ADVANsCEne_BASE_ID) == 0) + { + if (fread(&versionBase[0], 1, 2, fp) == 2) + { + //printf("Version base: %i.%i\n", versionBase[0], versionBase[1]); + if (fread(&version[0], 1, 4, fp) == 4) + { + //printf("Version: %c%c%c%c\n", version[3], version[2], version[1], version[0]); + if (fread(&createTime, 1, sizeof(time_t), fp) == sizeof(time_t)) + { + memset(buf, 0,sizeof(buf)); + // serial(8) + crc32(4) + save_type(1) = 13 + reserved(8) = 21 + while (true) + { + if (fread(buf, 1, 21, fp) != 21) break; + if (memcmp(&buf[4], serial, 4) == 0) + { + memcpy(&crc32, &buf[8], 4); + //printf("%s founded: crc32=%04X, save type %02X\n", serial, crc32, buf[12]); + saveType = buf[12]; + fclose(fp); + loaded = true; + return true; + } + } + } + } + } + } + } + fclose(fp); + } + return false; +} + +bool ADVANsCEne::getXMLConfig(const char *in_filaname) +{ + TiXmlDocument *xml = NULL; + TiXmlElement *el = NULL; + TiXmlElement *el_configuration = NULL; + TiXmlElement *el_newDat = NULL; + + xml = new TiXmlDocument(); + if (!xml) return false; + if (!xml->LoadFile(in_filaname)) return false; + el = xml->FirstChildElement("dat"); + if (!el) return false; + el_configuration = el->FirstChildElement("configuration"); + if (!el_configuration) return false; + el = el_configuration->FirstChildElement("datName"); if (el) { datName = el->GetText(); } + el = el_configuration->FirstChildElement("datVersion"); if (el) { datVersion = el->GetText(); } + + el_newDat = el_configuration->FirstChildElement("newDat"); + if (!el_newDat) return false; + el = el_newDat->FirstChildElement("datVersionURL"); if (el) { urlVersion = el->GetText(); } + el = el_newDat->FirstChildElement("datURL"); if (el) { urlDat = el->GetText(); } + + delete xml; + return true; +} + +u32 ADVANsCEne::convertDB(const char *in_filaname) +{ + const char *saveTypeNames[] = { "Eeprom - 4 kbit", // EEPROM 4kbit + "Eeprom - 64 kbit", // EEPROM 64kbit + "Eeprom - 512 kbit", // EEPROM 512kbit + "Fram - 256 kbit", // FRAM 256kbit ! + "Flash - 2 mbit", // FLASH 2Mbit + "Flash - 4 mbit", // FLASH 4Mbit + "Flash - 8 mbit", // FLASH 8Mbit + "Flash - 16 mbit", // FLASH 16Mbit ! + "Flash - 32 mbit", // FLASH 32Mbit ! + "Flash - 64 mbit", // FLASH 64Mbit + "Flash - 128 mbit", // FLASH 128Mbit ! + "Flash - 256 mbit", // FLASH 256Mbit ! + "Flash - 512 mbit" // FLASH 512Mbit ! + }; + + TiXmlDocument *xml = NULL; + TiXmlElement *el = NULL; + TiXmlElement *el_serial = NULL; + TiXmlElement *el_games = NULL; + TiXmlElement *el_crc32 = NULL; + TiXmlElement *el_saveType = NULL; + FILE *fp; + u32 crc32 = 0; + u32 reserved = 0; + + printf("Converting DB...\n"); + if (getXMLConfig(in_filaname)) + { + if (!datName) return 0; + if (strcmp(datName, _ADVANsCEne_BASE_NAME) != 0) return 0; + } + + fp = fopen(database_path, "wb"); + if (!fp) return 0; + + // Header + fwrite(_ADVANsCEne_BASE_ID, 1, strlen(_ADVANsCEne_BASE_ID), fp); + fputc(_ADVANsCEne_BASE_VERSION_MAJOR, fp); + fputc(_ADVANsCEne_BASE_VERSION_MINOR, fp); + if (datVersion) + fwrite(datVersion, 1, strlen(datVersion), fp); + else + fputc(0, fp); + time_t __time = time(NULL); + fwrite(&__time, 1, sizeof(time_t), fp); + + xml = new TiXmlDocument(); + if (!xml) { fclose(fp); return 0; } + if (!xml->LoadFile(in_filaname)) { fclose(fp); return 0; } + el = xml->FirstChildElement("dat"); + if (!el) { fclose(fp); return 0; } + el_games = el->FirstChildElement("games"); + if (!el_games) { fclose(fp); return 0; } + el = el_games->FirstChildElement("game"); + if (!el) { fclose(fp); return 0; } + u32 count = 0; + while (el) + { + el_serial = el->FirstChildElement("serial"); + if (fwrite(el_serial->GetText(), 1, 8, fp) != 8) + { + fclose(fp); return 0; + } + // CRC32 + el_crc32 = el->FirstChildElement("files"); + sscanf_s(el_crc32->FirstChildElement("romCRC")->GetText(), "%x", &crc32); + if (fwrite(&crc32, 1, sizeof(u32), fp) != sizeof(u32)) + { + fclose(fp); return 0; + } + // Save type + el_saveType = el->FirstChildElement("saveType"); + if (el_saveType) + { + const char *tmp = el_saveType->GetText(); + if (tmp) + { + if (strcmp(tmp, "None") == 0) + fputc(0xFE, fp); + else + { + bool bUnknown = true; + for (u8 i = 0; i < MAX_SAVE_TYPES; i++) + { + if (strcmp(saveTypeNames[i], "") == 0) continue; + if (strcasecmp(tmp, saveTypeNames[i]) == 0) + { + fputc(i, fp); + bUnknown = false; + break; + } + } + if (bUnknown) + fputc(0xFF, fp); // Unknown + } + } + else + fputc(0xFF, fp); // Unknown + } + fwrite(&reserved, 1, sizeof(u32), fp); + fwrite(&reserved, 1, sizeof(u32), fp); + count++; + el = el->NextSiblingElement("game"); + } + delete xml; + fclose(fp); + if (count > 0) + printf("done\n"); + else + printf("error\n"); + printf("ADVANsCEne converter: %i found\n", count); + return count; +} diff --git a/jni/desmume/src/mc.h b/jni/desmume/src/mc.h new file mode 100755 index 0000000..f949f8f --- /dev/null +++ b/jni/desmume/src/mc.h @@ -0,0 +1,232 @@ +/* + Copyright (C) 2006 thoduv + Copyright (C) 2006 Theo Berkau + Copyright (C) 2008-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __FW_H__ +#define __FW_H__ + +#include <stdio.h> +#include <vector> +#include <string> +#include "types.h" +#include "emufile.h" +#include "common.h" +#include "utils/tinyxml/tinyxml.h" + +#define MAX_SAVE_TYPES 13 +#define MC_TYPE_AUTODETECT 0x0 +#define MC_TYPE_EEPROM1 0x1 +#define MC_TYPE_EEPROM2 0x2 +#define MC_TYPE_FLASH 0x3 +#define MC_TYPE_FRAM 0x4 + +#define MC_SIZE_4KBITS 0x000200 +#define MC_SIZE_64KBITS 0x002000 +#define MC_SIZE_256KBITS 0x008000 +#define MC_SIZE_512KBITS 0x010000 +#define MC_SIZE_1MBITS 0x020000 +#define MC_SIZE_2MBITS 0x040000 +#define MC_SIZE_4MBITS 0x080000 +#define MC_SIZE_8MBITS 0x100000 +#define MC_SIZE_16MBITS 0x200000 +#define MC_SIZE_32MBITS 0x400000 +#define MC_SIZE_64MBITS 0x800000 +#define MC_SIZE_128MBITS 0x1000000 +#define MC_SIZE_256MBITS 0x2000000 +#define MC_SIZE_512MBITS 0x4000000 + +// ============================================= ADVANsCEne +#define _ADVANsCEne_BASE_ID "DeSmuME database (ADVANsCEne)\0x1A" +#define _ADVANsCEne_BASE_VERSION_MAJOR 1 +#define _ADVANsCEne_BASE_VERSION_MINOR 0 +#define _ADVANsCEne_BASE_NAME "ADVANsCEne Nintendo DS Collection" +class ADVANsCEne +{ +private: + char database_path[MAX_PATH]; // DeSmuME save types + u8 versionBase[2]; + char version[4]; + time_t createTime; + u8 saveType; + u32 crc32; + bool loaded; + + // XML + const char *datName; + const char *datVersion; + const char *urlVersion; + const char *urlDat; + bool getXMLConfig(const char *in_filaname); +public: + ADVANsCEne() : saveType(0xFF), + crc32(0), + loaded(false) + { + memset(database_path, 0, sizeof(database_path)); + memset(versionBase, 0, sizeof(versionBase)); + memset(version, 0, sizeof(version)); + } + void setDatabase(const char *path) { loaded = false; strcpy(database_path, path); } + u32 convertDB(const char *in_filaname); + u8 checkDB(const char *serial); + u32 getSaveType() { return saveType; } + u32 getCRC32() { return crc32; } + bool isLoaded() { return loaded; } +}; + + +struct memory_chip_t +{ + u8 com; //persistent command actually handled + u32 addr; //current address for reading/writing + u8 addr_shift; //shift for address (since addresses are transfered by 3 bytes units) + u8 addr_size; //size of addr when writing/reading + + BOOL write_enable; //is write enabled ? + + u8 *data; //memory data + u32 size; //memory size + BOOL writeable_buffer; //is "data" writeable ? + int type; //type of Memory + char *filename; + FILE *fp; + u8 autodetectbuf[32768]; + int autodetectsize; + + // needs only for firmware + bool isFirmware; + char userfile[MAX_PATH]; +}; + +//the new backup system by zeromus +class BackupDevice +{ +public: + BackupDevice(); + + //signals the save system that we are in our regular mode, loading up a rom. initializes for that case. + void load_rom(const char* filename); + //signals the save system that we are in MOVIE mode. doesnt load up a rom, and never saves it. initializes for that case. + void movie_mode(); + + void reset(); + void close_rom(); + void forceManualBackupType(); + void reset_hardware(); + std::string getFilename() { return filename; } + u8 searchFileSaveType(u32 size); + + bool save_state(EMUFILE* os); + bool load_state(EMUFILE* is); + + //commands from mmu + void reset_command(); + u8 data_command(u8,int); + std::vector<u8> data; + + //this info was saved before the last reset (used for savestate compatibility) + struct SavedInfo + { + u32 addr_size; + } savedInfo; + + //and these are used by old savestates + void load_old_state(u32 addr_size, u8* data, u32 datasize); + static u32 addr_size_for_old_save_size(int bupmem_size); + static u32 addr_size_for_old_save_type(int bupmem_type); + + static u32 pad_up_size(u32 startSize); + void raw_applyUserSettings(u32& size, bool manual = false); + + bool load_duc(const char* filename, u32 force_size = 0); + bool load_no_gba(const char *fname, u32 force_size = 0); + bool save_no_gba(const char* fname); + bool load_raw(const char* filename, u32 force_size = 0); + bool save_raw(const char* filename); + bool load_movie(EMUFILE* is); + u32 get_save_duc_size(const char* filename); + u32 get_save_nogba_size(const char* filename); + u32 get_save_raw_size(const char* filename); + + //call me once a second or so to lazy flush the save data + //here's the reason for this system: we want to dump save files when theyre READ + //so that we have a better idea earlier on how large they are. but it slows things down + //way too much if we flush whenever we read. + void lazy_flush(); + void flush(); + + struct { + u32 size,padSize,type,addr_size,mem_size; + } info; + + bool isMovieMode; +private: + std::string filename; + + bool write_enable; //is write enabled? + u32 com; //persistent command actually handled + u32 addr_size, addr_counter; + u32 addr; + + std::vector<u8> data_autodetect; + enum STATE { + DETECTING = 0, RUNNING = 1 + } state; + + enum MOTION_INIT_STATE + { + MOTION_INIT_STATE_IDLE, MOTION_INIT_STATE_RECEIVED_4, MOTION_INIT_STATE_RECEIVED_4_B, + MOTION_INIT_STATE_FE, MOTION_INIT_STATE_FD, MOTION_INIT_STATE_FB + }; + enum MOTION_FLAG + { + MOTION_FLAG_NONE=0, + MOTION_FLAG_ENABLED=1, + MOTION_FLAG_SENSORMODE=2 + }; + u8 motionInitState, motionFlag; + + void loadfile(); + bool _loadfile(const char *fname); + void ensure(u32 addr); + + bool flushPending, lazyFlushPending; + +private: + void resize(u32 size); +}; + +#define NDS_FW_SIZE_V1 (256 * 1024) /* size of fw memory on nds v1 */ +#define NDS_FW_SIZE_V2 (512 * 1024) /* size of fw memory on nds v2 */ + +void mc_init(memory_chip_t *mc, int type); /* reset and init values for memory struct */ +u8 *mc_alloc(memory_chip_t *mc, u32 size); /* alloc mc memory */ +void mc_realloc(memory_chip_t *mc, int type, u32 size); /* realloc mc memory */ +void mc_load_file(memory_chip_t *mc, const char* filename); /* load save file and setup fp */ +void mc_free(memory_chip_t *mc); /* delete mc memory */ +void fw_reset_com(memory_chip_t *mc); /* reset communication with mc */ +u8 fw_transfer(memory_chip_t *mc, u8 data); + +void backup_setManualBackupType(int type); +void backup_forceManualBackupType(); + +extern const char *save_names[]; +extern const int save_types[][2]; + +#endif /*__FW_H__*/ + diff --git a/jni/desmume/src/mem.h b/jni/desmume/src/mem.h new file mode 100755 index 0000000..507efbc --- /dev/null +++ b/jni/desmume/src/mem.h @@ -0,0 +1,188 @@ +/* + Copyright (C) 2005 Theo Berkau + Copyright (C) 2005-2006 Guillaume Duhamel + Copyright (C) 2008-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef MEM_H +#define MEM_H + +#include <stdlib.h> +#include <assert.h> +#include "types.h" + +//this was originally declared in MMU.h but we suffered some organizational problems and had to remove it +enum MMU_ACCESS_TYPE +{ + MMU_AT_CODE, //used for cpu prefetches + MMU_AT_DATA, //used for cpu read/write + MMU_AT_GPU, //used for gpu read/write + MMU_AT_DMA, //used for dma read/write (blocks access to TCM) + MMU_AT_DEBUG, //used for emulator debugging functions (bypasses some debug handling) +}; + +static INLINE u8 T1ReadByte(u8* const mem, const u32 addr) +{ + return mem[addr]; +} + +static INLINE u16 T1ReadWord_guaranteedAligned(void* const mem, const u32 addr) +{ + assert((addr&1)==0); +#ifdef WORDS_BIGENDIAN + return (((u8*)mem)[addr + 1] << 8) | ((u8*)mem)[addr]; +#else + return *(u16*)((u8*)mem + addr); +#endif +} + +static INLINE u16 T1ReadWord(void* const mem, const u32 addr) +{ +#ifdef WORDS_BIGENDIAN + return (((u8*)mem)[addr + 1] << 8) | ((u8*)mem)[addr]; +#else + return *((u16 *) ((u8*)mem + addr)); +#endif +} + +static INLINE u32 T1ReadLong_guaranteedAligned(u8* const mem, const u32 addr) +{ + assert((addr&3)==0); +#ifdef WORDS_BIGENDIAN + return (mem[addr + 3] << 24 | mem[addr + 2] << 16 | + mem[addr + 1] << 8 | mem[addr]); +#else + return *(u32*)(mem + addr); +#endif +} + + +static INLINE u32 T1ReadLong(u8* const mem, u32 addr) +{ + addr &= ~3; +#ifdef WORDS_BIGENDIAN + return (mem[addr + 3] << 24 | mem[addr + 2] << 16 | + mem[addr + 1] << 8 | mem[addr]); +#else + return *(u32*)(mem + addr); +#endif +} + +static INLINE u64 T1ReadQuad(u8* const mem, const u32 addr) +{ +#ifdef WORDS_BIGENDIAN + return (u64(mem[addr + 7]) << 56 | u64(mem[addr + 6]) << 48 | + u64(mem[addr + 5]) << 40 | u64(mem[addr + 4]) << 32 | + u64(mem[addr + 3]) << 24 | u64(mem[addr + 2]) << 16 | + u64(mem[addr + 1]) << 8 | u64(mem[addr ])); +#else + return *((u64 *) (mem + addr)); +#endif +} + +static INLINE void T1WriteByte(u8* const mem, const u32 addr, const u8 val) +{ + mem[addr] = val; +} + +static INLINE void T1WriteWord(u8* const mem, const u32 addr, const u16 val) +{ +#ifdef WORDS_BIGENDIAN + mem[addr + 1] = val >> 8; + mem[addr] = val & 0xFF; +#else + *((u16 *) (mem + addr)) = val; +#endif +} + +static INLINE void T1WriteLong(u8* const mem, const u32 addr, const u32 val) +{ +#ifdef WORDS_BIGENDIAN + mem[addr + 3] = val >> 24; + mem[addr + 2] = (val >> 16) & 0xFF; + mem[addr + 1] = (val >> 8) & 0xFF; + mem[addr] = val & 0xFF; +#else + *((u32 *) (mem + addr)) = val; +#endif +} + +static INLINE void T1WriteQuad(u8* const mem, const u32 addr, const u64 val) +{ +#ifdef WORDS_BIGENDIAN + mem[addr + 7] = (val >> 56); + mem[addr + 6] = (val >> 48) & 0xFF; + mem[addr + 5] = (val >> 40) & 0xFF; + mem[addr + 4] = (val >> 32) & 0xFF; + mem[addr + 3] = (val >> 24) & 0xFF; + mem[addr + 2] = (val >> 16) & 0xFF; + mem[addr + 1] = (val >> 8) & 0xFF; + mem[addr] = val & 0xFF; +#else + *((u64 *) (mem + addr)) = val; +#endif +} + +//static INLINE u8 T2ReadByte(u8* const mem, const u32 addr) +//{ +//#ifdef WORDS_BIGENDIAN +// return mem[addr ^ 1]; +//#else +// return mem[addr]; +//#endif +//} +// + +static INLINE u16 HostReadWord(u8* const mem, const u32 addr) +{ + return *((u16 *) (mem + addr)); +} + +// +//static INLINE u32 T2ReadLong(u8* const mem, const u32 addr) +//{ +//#ifdef WORDS_BIGENDIAN +// return *((u16 *) (mem + addr + 2)) << 16 | *((u16 *) (mem + addr)); +//#else +// return *((u32 *) (mem + addr)); +//#endif +//} +// +//static INLINE void T2WriteByte(u8* const mem, const u32 addr, const u8 val) +//{ +//#ifdef WORDS_BIGENDIAN +// mem[addr ^ 1] = val; +//#else +// mem[addr] = val; +//#endif +//} + +static INLINE void HostWriteWord(u8* const mem, const u32 addr, const u16 val) +{ + *((u16 *) (mem + addr)) = val; +} + +static INLINE void HostWriteTwoWords(u8* const mem, const u32 addr, const u32 val) +{ +#ifdef WORDS_BIGENDIAN + *((u16 *) (mem + addr + 2)) = val >> 16; + *((u16 *) (mem + addr)) = val & 0xFFFF; +#else + *((u32 *) (mem + addr)) = val; +#endif +} + +#endif diff --git a/jni/desmume/src/metaspu/SndOut.cpp b/jni/desmume/src/metaspu/SndOut.cpp new file mode 100755 index 0000000..1377ba5 --- /dev/null +++ b/jni/desmume/src/metaspu/SndOut.cpp @@ -0,0 +1,388 @@ +/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2 + * Developed and maintained by the Pcsx2 Development Team. + * + * Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz] + * + * SPU2-X is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * SPU2-X 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SPU2-X. If not, see <http://www.gnu.org/licenses/>. + */ + +//#include "Global.h" +#include "types.h" +#include "SndOut.h" +#include <assert.h> + +//---------------- +int SndOutLatencyMS = 160; +bool timeStretchDisabled = false; +//---------------- + +StereoOut32 StereoOut32::Empty( 0, 0 ); + +StereoOut32::StereoOut32( const StereoOut16& src ) : + Left( src.Left ), + Right( src.Right ) +{ +} + +StereoOut32::StereoOut32( const StereoOutFloat& src ) : + Left( (s32)(src.Left * 2147483647.0f) ), + Right( (s32)(src.Right * 2147483647.0f) ) +{ +} + +StereoOut16 StereoOut32::DownSample() const +{ + return StereoOut16( + Left >> SndOutVolumeShift, + Right >> SndOutVolumeShift + ); +} + +StereoOut32 StereoOut16::UpSample() const +{ + return StereoOut32( + Left << SndOutVolumeShift, + Right << SndOutVolumeShift + ); + +} + + +//class NullOutModule: public SndOutModule +//{ +//public: +// s32 Init() { return 0; } +// void Close() { } +// s32 Test() const { return 0; } +// void Configure(uptr parent) { } +// bool Is51Out() const { return false; } +// int GetEmptySampleCount() const { return 0; } +// +// const wchar_t* GetIdent() const +// { +// return L"nullout"; +// } +// +// const wchar_t* GetLongName() const +// { +// return L"No Sound (Emulate SPU2 only)"; +// } +// +// void ReadSettings() +// { +// } +// +// void WriteSettings() const +// { +// } +// +//} NullOut; +// +//SndOutModule* mods[]= +//{ +// &NullOut, +//#ifdef _MSC_VER +// XAudio2Out, +// DSoundOut, +// WaveOut, +//#endif +// NULL // signals the end of our list +//}; +// +//int FindOutputModuleById( const wchar_t* omodid ) +//{ +// int modcnt = 0; +// while( mods[modcnt] != NULL ) +// { +// if( wcscmp( mods[modcnt]->GetIdent(), omodid ) == 0 ) +// break; +// ++modcnt; +// } +// return modcnt; +//} + +StereoOut32 *SndBuffer::m_buffer; +s32 SndBuffer::m_size; +s32 SndBuffer::m_rpos; +s32 SndBuffer::m_wpos; +s32 SndBuffer::m_data; + +bool SndBuffer::m_underrun_freeze; +StereoOut32* SndBuffer::sndTempBuffer = NULL; +StereoOut16* SndBuffer::sndTempBuffer16 = NULL; +int SndBuffer::sndTempProgress = 0; + +static int GetAlignedBufferSize( int comp ) +{ + return (comp + SndOutPacketSize-1) & ~(SndOutPacketSize-1); +} + +// Returns TRUE if there is data to be output, or false if no data +// is available to be copied. +bool SndBuffer::CheckUnderrunStatus( int& nSamples, int& quietSampleCount ) +{ + quietSampleCount = 0; + if( m_underrun_freeze ) + { + int toFill = (int)(m_size * ( timeStretchDisabled ? 0.50f : 0.1f ) ); + toFill = GetAlignedBufferSize( toFill ); + + // toFill is now aligned to a SndOutPacket + + if( m_data < toFill ) + { + quietSampleCount = nSamples; + return false; + } + + m_underrun_freeze = false; + //TODO + //if( MsgOverruns() ) + printf(" * SPU2 > Underrun compensation (%d packets buffered)\n", toFill / SndOutPacketSize ); + lastPct = 0.0; // normalize timestretcher + } + else if( m_data < nSamples ) + { + nSamples = m_data; + quietSampleCount = SndOutPacketSize - m_data; + m_underrun_freeze = true; + + if( !timeStretchDisabled ) + timeStretchUnderrun(); + + return nSamples != 0; + } + + return true; +} + +void SndBuffer::_InitFail() +{ + // If a failure occurs, just initialize the NoSound driver. This'll allow + // the game to emulate properly (hopefully), albeit without sound. + //OutputModule = FindOutputModuleById( NullOut.GetIdent() ); + //mods[OutputModule]->Init(); +} + +void SndBuffer::_WriteSamples(StereoOut32 *bData, int nSamples) +{ + int free = m_size-m_data; + m_predictData = 0; + + assert( m_data <= m_size ); + + // Problem: + // If the SPU2 gets out of sync with the SndOut device, the writepos of the + // circular buffer will overtake the readpos, leading to a prolonged period + // of hopscotching read/write accesses (ie, lots of staticy crap sound for + // several seconds). + // + // Compromise: + // When an overrun occurs, we adapt by discarding a portion of the buffer. + // The older portion of the buffer is discarded rather than incoming data, + // so that the overall audio synchronization is better. + + if( free < nSamples ) + { + // Buffer overrun! + // Dump samples from the read portion of the buffer instead of dropping + // the newly written stuff. + + s32 comp; + + if( !timeStretchDisabled ) + { + comp = timeStretchOverrun(); + } + else + { + // Toss half the buffer plus whatever's being written anew: + comp = GetAlignedBufferSize( (m_size + nSamples ) / 2 ); + if( comp > (m_size-SndOutPacketSize) ) comp = m_size-SndOutPacketSize; + } + + m_data -= comp; + m_rpos = (m_rpos+comp) % m_size; + //TODO + //if( MsgOverruns() ) + printf(" * SPU2 > Overrun Compensation (%d packets tossed)\n", comp / SndOutPacketSize ); + lastPct = 0.0; // normalize the timestretcher + } + + // copy in two phases, since there's a chance the packet + // wraps around the buffer (it'd be nice to deal in packets only, but + // the timestretcher and DSP options require flexibility). + + const int endPos = m_wpos + nSamples; + const int secondCopyLen = endPos - m_size; + StereoOut32* wposbuffer = &m_buffer[m_wpos]; + + m_data += nSamples; + if( secondCopyLen > 0 ) + { + nSamples -= secondCopyLen; + memcpy( m_buffer, &bData[nSamples], secondCopyLen * sizeof( *bData ) ); + m_wpos = secondCopyLen; + } + else + m_wpos += nSamples; + + memcpy( wposbuffer, bData, nSamples * sizeof( *bData ) ); +} + +void SndBuffer::Init() +{ + //if( mods[OutputModule] == NULL ) + //{ + // _InitFail(); + // return; + //} + + // initialize sound buffer + // Buffer actually attempts to run ~50%, so allocate near double what + // the requested latency is: + + + m_rpos = 0; + m_wpos = 0; + m_data = 0; + + try + { + const float latencyMS = SndOutLatencyMS * (timeStretchDisabled ? 1.5f : 2.0f ); + m_size = GetAlignedBufferSize( (int)(latencyMS * SampleRate / 1000.0f ) ); + m_buffer = new StereoOut32[m_size]; + m_underrun_freeze = false; + + sndTempBuffer = new StereoOut32[SndOutPacketSize]; + sndTempBuffer16 = new StereoOut16[SndOutPacketSize]; + } + catch( std::bad_alloc& ) + { + // out of memory exception (most likely) + + printf( "Out of memory error occurred while initializing SPU2." ); + _InitFail(); + return; + } + + // clear buffers! + // Fixes loopy sounds on emu resets. + memset( sndTempBuffer, 0, sizeof(StereoOut32) * SndOutPacketSize ); + memset( sndTempBuffer16, 0, sizeof(StereoOut16) * SndOutPacketSize ); + + sndTempProgress = 0; + + soundtouchInit(); // initializes the timestretching + + // some crap + //spdif_set51(mods[OutputModule]->Is51Out()); + + // initialize module + //if( mods[OutputModule]->Init() == -1 ) _InitFail(); +} + +void SndBuffer::Cleanup() +{ + //mods[OutputModule]->Close(); + + soundtouchCleanup(); + + //safe_delete_array( m_buffer ); + //safe_delete_array( sndTempBuffer ); + //safe_delete_array( sndTempBuffer16 ); + delete[] m_buffer; + delete[] sndTempBuffer; + delete[] sndTempBuffer16; +} + +int SndBuffer::m_dsp_progress = 0; + +int SndBuffer::m_timestretch_progress = 0; +int SndBuffer::ssFreeze = 0; + +void SndBuffer::ClearContents() +{ + SndBuffer::soundtouchClearContents(); + SndBuffer::ssFreeze = 30; //Delays sound output for about half a second. +} + +void SndBuffer::Write( const StereoOut32& Sample ) +{ + // Log final output to wavefile. + //WaveDump::WriteCore( 1, CoreSrc_External, Sample.DownSample() ); + + //RecordWrite( Sample.DownSample() ); + + //if(mods[OutputModule] == &NullOut) // null output doesn't need buffering or stretching! :p + // return; + + sndTempBuffer[sndTempProgress++] = Sample; + + // If we haven't accumulated a full packet yet, do nothing more: + if(sndTempProgress < SndOutPacketSize) return; + sndTempProgress = 0; + + //Don't play anything directly after loading a savestate, avoids static killing your speakers. +// if ( ssFreeze > 0 ) +// { +// ssFreeze--; +// return; +// } +//#ifndef __LINUX__ +// else if( dspPluginEnabled ) +// { +// // Convert in, send to winamp DSP, and convert out. +// +// for( int i=0; i<SndOutPacketSize; ++i ) { sndTempBuffer16[i] = sndTempBuffer[i].DownSample(); } +// m_dsp_progress += DspProcess( (s16*)sndTempBuffer16, SndOutPacketSize ); +// +// // Some ugly code to ensure full packet handling: +// int ei = 0; +// while( m_dsp_progress >= SndOutPacketSize ) +// { +// for( int i=0; i<SndOutPacketSize; ++i, ++ei ) { sndTempBuffer[i] = sndTempBuffer16[ei].UpSample(); } +// +// if( !timeStretchDisabled ) +// timeStretchWrite(); +// else +// _WriteSamples(sndTempBuffer, sndTempProgress); +// +// m_dsp_progress -= SndOutPacketSize; +// } +// +// // copy any leftovers to the front of the dsp buffer. +// if( m_dsp_progress > 0 ) +// { +// memcpy( &sndTempBuffer16[ei], sndTempBuffer16, +// sizeof(sndTempBuffer16[0]) * m_dsp_progress +// ); +// } +// } +//#endif +// else + { + if( !timeStretchDisabled ) + timeStretchWrite(); + else + _WriteSamples(sndTempBuffer, SndOutPacketSize); + } +} + +s32 SndBuffer::Test() +{ + //if( mods[OutputModule] == NULL ) + // return -1; + + //return mods[OutputModule]->Test(); + return 0; +} diff --git a/jni/desmume/src/metaspu/SndOut.h b/jni/desmume/src/metaspu/SndOut.h new file mode 100755 index 0000000..d897be1 --- /dev/null +++ b/jni/desmume/src/metaspu/SndOut.h @@ -0,0 +1,556 @@ +/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2 + * Developed and maintained by the Pcsx2 Development Team. + * + * Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz] + * + * SPU2-X is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * SPU2-X 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SPU2-X. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <algorithm> + +struct StereoOut16; +struct StereoOut32; +struct StereoOutFloat; + +struct StereoOut32 +{ + static StereoOut32 Empty; + + s32 Left; + s32 Right; + + StereoOut32() : + Left( 0 ), + Right( 0 ) + { + } + + StereoOut32( s32 left, s32 right ) : + Left( left ), + Right( right ) + { + } + + StereoOut32( const StereoOut16& src ); + explicit StereoOut32( const StereoOutFloat& src ); + + StereoOut16 DownSample() const; + + StereoOut32 operator+( const StereoOut32& right ) const + { + return StereoOut32( + Left + right.Left, + Right + right.Right + ); + } + + StereoOut32 operator/( int src ) const + { + return StereoOut32( Left / src, Right / src ); + } +}; + + +// Number of stereo samples per SndOut block. +// All drivers must work in units of this size when communicating with +// SndOut. +static const int SndOutPacketSize = 512; + +// Overall master volume shift. +// Converts the mixer's 32 bit value into a 16 bit value. +//static const int SndOutVolumeShift = 13; + +//edit - zeromus 23-oct-2009 +//this is hardcoded differently for metaspu +static const int SndOutVolumeShift = 0; + +// Samplerate of the SPU2. For accurate playback we need to match this +// exactly. Trying to scale samplerates and maintain SPU2's Ts timing accuracy +// is too problematic. :) +//this is hardcoded differently for metaspu +//edit - zeromus 23-oct-2009 +////static const int SampleRate = 48000; +//static const int SampleRate = 44100; +//edit - nitsuja: make it use the global sample rate define +#include "../SPU.h" +static const int SampleRate = DESMUME_SAMPLE_RATE; + +extern int FindOutputModuleById( const wchar_t* omodid ); + +struct StereoOut16 +{ + s16 Left; + s16 Right; + + StereoOut16() : + Left( 0 ), + Right( 0 ) + { + } + + StereoOut16( const StereoOut32& src ) : + Left( (s16)src.Left ), + Right( (s16)src.Right ) + { + } + + StereoOut16( s16 left, s16 right ) : + Left( left ), + Right( right ) + { + } + + StereoOut32 UpSample() const; + + void ResampleFrom( const StereoOut32& src ) + { + // Use StereoOut32's built in conversion + *this = src.DownSample(); + } +}; + +struct StereoOutFloat +{ + float Left; + float Right; + + StereoOutFloat() : + Left( 0 ), + Right( 0 ) + { + } + + explicit StereoOutFloat( const StereoOut32& src ) : + Left( src.Left / 2147483647.0f ), + Right( src.Right / 2147483647.0f ) + { + } + + explicit StereoOutFloat( s32 left, s32 right ) : + Left( left / 2147483647.0f ), + Right( right / 2147483647.0f ) + { + } + + StereoOutFloat( float left, float right ) : + Left( left ), + Right( right ) + { + } +}; + +//struct Stereo21Out16 +//{ +// s16 Left; +// s16 Right; +// s16 LFE; +// +// void ResampleFrom( const StereoOut32& src ) +// { +// Left = src.Left >> SndOutVolumeShift; +// Right = src.Right >> SndOutVolumeShift; +// LFE = (src.Left + src.Right) >> (SndOutVolumeShift + 1); +// } +//}; +// +//struct StereoQuadOut16 +//{ +// s16 Left; +// s16 Right; +// s16 LeftBack; +// s16 RightBack; +// +// void ResampleFrom( const StereoOut32& src ) +// { +// Left = src.Left >> SndOutVolumeShift; +// Right = src.Right >> SndOutVolumeShift; +// LeftBack = src.Left >> SndOutVolumeShift; +// RightBack = src.Right >> SndOutVolumeShift; +// } +//}; +// +//struct Stereo41Out16 +//{ +// s16 Left; +// s16 Right; +// s16 LFE; +// s16 LeftBack; +// s16 RightBack; +// +// void ResampleFrom( const StereoOut32& src ) +// { +// Left = src.Left >> SndOutVolumeShift; +// Right = src.Right >> SndOutVolumeShift; +// LFE = (src.Left + src.Right) >> (SndOutVolumeShift + 1); +// LeftBack = src.Left >> SndOutVolumeShift; +// RightBack = src.Right >> SndOutVolumeShift; +// } +//}; +// +//struct Stereo51Out16 +//{ +// s16 Left; +// s16 Right; +// s16 Center; +// s16 LFE; +// s16 LeftBack; +// s16 RightBack; +// +// // Implementation Note: Center and Subwoofer/LFE --> +// // This method is simple and sounds nice. It relies on the speaker/soundcard +// // systems do to their own low pass / crossover. Manual lowpass is wasted effort +// // and can't match solid state results anyway. +// +// void ResampleFrom( const StereoOut32& src ) +// { +// Left = src.Left >> SndOutVolumeShift; +// Right = src.Right >> SndOutVolumeShift; +// Center = (src.Left + src.Right) >> (SndOutVolumeShift + 1); +// LFE = Center; +// LeftBack = src.Left >> SndOutVolumeShift; +// RightBack = src.Right >> SndOutVolumeShift; +// } +//}; +// +//struct Stereo51Out16DplII +//{ +// s16 Left; +// s16 Right; +// s16 Center; +// s16 LFE; +// s16 LeftBack; +// s16 RightBack; +// +// void ResampleFrom( const StereoOut32& src ) +// { +// static const u8 sLogTable[256] = { +// 0x00,0x3C,0x60,0x78,0x8C,0x9C,0xA8,0xB4,0xBE,0xC8,0xD0,0xD8,0xDE,0xE4,0xEA,0xF0, +// 0xF6,0xFA,0xFE,0x04,0x08,0x0C,0x10,0x14,0x16,0x1A,0x1E,0x20,0x24,0x26,0x2A,0x2C, +// 0x2E,0x32,0x34,0x36,0x38,0x3A,0x3E,0x40,0x42,0x44,0x46,0x48,0x4A,0x4C,0x4E,0x50, +// 0x50,0x52,0x54,0x56,0x58,0x5A,0x5A,0x5C,0x5E,0x60,0x60,0x62,0x64,0x66,0x66,0x68, +// 0x6A,0x6A,0x6C,0x6E,0x6E,0x70,0x70,0x72,0x74,0x74,0x76,0x76,0x78,0x7A,0x7A,0x7C, +// 0x7C,0x7E,0x7E,0x80,0x80,0x82,0x82,0x84,0x84,0x86,0x86,0x88,0x88,0x8A,0x8A,0x8C, +// 0x8C,0x8C,0x8E,0x8E,0x90,0x90,0x92,0x92,0x92,0x94,0x94,0x96,0x96,0x96,0x98,0x98, +// 0x9A,0x9A,0x9A,0x9C,0x9C,0x9C,0x9E,0x9E,0xA0,0xA0,0xA0,0xA2,0xA2,0xA2,0xA4,0xA4, +// 0xA4,0xA6,0xA6,0xA6,0xA8,0xA8,0xA8,0xAA,0xAA,0xAA,0xAC,0xAC,0xAC,0xAC,0xAE,0xAE, +// 0xAE,0xB0,0xB0,0xB0,0xB2,0xB2,0xB2,0xB2,0xB4,0xB4,0xB4,0xB6,0xB6,0xB6,0xB6,0xB8, +// 0xB8,0xB8,0xB8,0xBA,0xBA,0xBA,0xBC,0xBC,0xBC,0xBC,0xBE,0xBE,0xBE,0xBE,0xC0,0xC0, +// 0xC0,0xC0,0xC2,0xC2,0xC2,0xC2,0xC2,0xC4,0xC4,0xC4,0xC4,0xC6,0xC6,0xC6,0xC6,0xC8, +// 0xC8,0xC8,0xC8,0xC8,0xCA,0xCA,0xCA,0xCA,0xCC,0xCC,0xCC,0xCC,0xCC,0xCE,0xCE,0xCE, +// 0xCE,0xCE,0xD0,0xD0,0xD0,0xD0,0xD0,0xD2,0xD2,0xD2,0xD2,0xD2,0xD4,0xD4,0xD4,0xD4, +// 0xD4,0xD6,0xD6,0xD6,0xD6,0xD6,0xD8,0xD8,0xD8,0xD8,0xD8,0xD8,0xDA,0xDA,0xDA,0xDA, +// 0xDA,0xDC,0xDC,0xDC,0xDC,0xDC,0xDC,0xDE,0xDE,0xDE,0xDE,0xDE,0xDE,0xE0,0xE0,0xE0, +// }; +// +// static s32 Gfl=0,Gfr=0; +// static s32 LMax=0,RMax=0; +// +// static s32 LAccum; +// static s32 RAccum; +// static s32 ANum; +// +// s32 ValL = src.Left >> (SndOutVolumeShift-8); +// s32 ValR = src.Right >> (SndOutVolumeShift-8); +// +// s32 XL = abs(ValL>>8); +// s32 XR = abs(ValR>>8); +// +// if(XL>LMax) LMax = XL; +// if(XR>RMax) RMax = XR; +// +// ANum++; +// if(ANum>=128) +// { +// ANum=0; +// LAccum = 1+((LAccum * 224 + LMax * 31)>>8); +// RAccum = 1+((RAccum * 224 + RMax * 31)>>8); +// +// LMax = 0; +// RMax = 0; +// +// s32 Tfl=(RAccum)*255/(LAccum); +// s32 Tfr=(LAccum)*255/(RAccum); +// +// int gMax = std::max(Tfl,Tfr); +// Tfl = Tfl*255/gMax; +// Tfr = Tfr*255/gMax; +// +// if(Tfl>255) Tfl=255; +// if(Tfr>255) Tfr=255; +// if(Tfl<1) Tfl=1; +// if(Tfr<1) Tfr=1; +// +// Gfl = (Gfl * 200 + Tfl * 56)>>8; +// Gfr = (Gfr * 200 + Tfr * 56)>>8; +// +// } +// +// s32 L,R,C,SUB,SL,SR; +// +// C=(ValL+ValR)>>1; //16.8 +// +// ValL-=C;//16.8 +// ValR-=C;//16.8 +// +// L=ValL>>8; //16.0 +// R=ValR>>8; //16.0 +// C=C>>8; //16.0 +// SUB = C; +// +// { +// s32 Cfl = 1+sLogTable[Gfl]; +// s32 Cfr = 1+sLogTable[Gfr]; +// +// s32 VL=(ValL>>4) * Cfl; //16.12 +// s32 VR=(ValR>>4) * Cfr; +// +// //s32 SC = (VL-VR)>>15; +// +// SL = (((VR/148 - VL/209)>>4)*Cfr)>>8; +// SR = (((VR/209 - VL/148)>>4)*Cfl)>>8; +// +// } +// +// // Random-ish values to get it to compile +// int GainL = 200; +// int GainR = 200; +// int GainC = 180; +// int GainSL = 230; +// int GainSR = 230; +// int GainLFE = 200; +// int AddCLR = 55; +// +// int AddCX = (C * AddCLR)>>8; +// +// Left = (((L * GainL ))>>8) + AddCX; +// Right = (((R * GainR ))>>8) + AddCX; +// Center = (((C * GainC ))>>8); +// LFE = (((SUB * GainLFE))>>8); +// LeftBack = (((SL * GainSL ))>>8); +// RightBack = (((SR * GainSR ))>>8); +// } +//}; +// +//struct Stereo71Out16 +//{ +// s16 Left; +// s16 Right; +// s16 Center; +// s16 LFE; +// s16 LeftBack; +// s16 RightBack; +// s16 LeftSide; +// s16 RightSide; +// +// void ResampleFrom( const StereoOut32& src ) +// { +// Left = src.Left >> SndOutVolumeShift; +// Right = src.Right >> SndOutVolumeShift; +// Center = (src.Left + src.Right) >> (SndOutVolumeShift + 1); +// LFE = Center; +// LeftBack = src.Left >> SndOutVolumeShift; +// RightBack = src.Right >> SndOutVolumeShift; +// +// LeftSide = src.Left >> (SndOutVolumeShift+1); +// RightSide = src.Right >> (SndOutVolumeShift+1); +// } +//}; +// +//struct Stereo21Out32 +//{ +// s32 Left; +// s32 Right; +// s32 LFE; +//}; +// +//struct Stereo41Out32 +//{ +// s32 Left; +// s32 Right; +// s32 LFE; +// s32 LeftBack; +// s32 RightBack; +//}; +// +//struct Stereo51Out32 +//{ +// s32 Left; +// s32 Right; +// s32 Center; +// s32 LFE; +// s32 LeftBack; +// s32 RightBack; +//}; + +// Developer Note: This is a static class only (all static members). +class SndBuffer +{ +private: + static bool m_underrun_freeze; + static s32 m_predictData; + static float lastPct; + + static StereoOut32* sndTempBuffer; + static StereoOut16* sndTempBuffer16; + + static int sndTempProgress; + static int m_dsp_progress; + + static int m_timestretch_progress; + static int m_timestretch_writepos; + + static StereoOut32 *m_buffer; + static s32 m_size; + static s32 m_rpos; + static s32 m_wpos; + static s32 m_data; + + static float lastEmergencyAdj; + static float cTempo; + static float eTempo; + static int freezeTempo; + static int ssFreeze; + + static void _InitFail(); + static void _WriteSamples(StereoOut32* bData, int nSamples); + static bool CheckUnderrunStatus( int& nSamples, int& quietSampleCount ); + + static void soundtouchInit(); + static void soundtouchClearContents(); + static void soundtouchCleanup(); + static void timeStretchWrite(); + static void timeStretchUnderrun(); + static s32 timeStretchOverrun(); + + static void PredictDataWrite( int samples ); + static float GetStatusPct(); + static void UpdateTempoChange(); + +public: + static void Init(); + static void Cleanup(); + static void Write( const StereoOut32& Sample ); + static s32 Test(); + static void ClearContents(); + + // Note: When using with 32 bit output buffers, the user of this function is responsible + // for shifting the values to where they need to be manually. The fixed point depth of + // the sample output is determined by the SndOutVolumeShift, which is the number of bits + // to shift right to get a 16 bit result. + template< typename T > + static void ReadSamples( T* bData ) + { + int nSamples = SndOutPacketSize; + + // Problem: + // If the SPU2 gets even the least bit out of sync with the SndOut device, + // the readpos of the circular buffer will overtake the writepos, + // leading to a prolonged period of hopscotching read/write accesses (ie, + // lots of staticy crap sound for several seconds). + // + // Fix: + // If the read position overtakes the write position, abort the + // transfer immediately and force the SndOut driver to wait until + // the read buffer has filled up again before proceeding. + // This will cause one brief hiccup that can never exceed the user's + // set buffer length in duration. + + int quietSamples; + if( CheckUnderrunStatus( nSamples, quietSamples ) ) + { + assert( nSamples <= SndOutPacketSize ); + + // [Air] [TODO]: This loop is probably a candidate for SSE2 optimization. + + const int endPos = m_rpos + nSamples; + const int secondCopyLen = endPos - m_size; + const StereoOut32* rposbuffer = &m_buffer[m_rpos]; + + m_data -= nSamples; + + if( secondCopyLen > 0 ) + { + nSamples -= secondCopyLen; + for( int i=0; i<secondCopyLen; i++ ) + bData[nSamples+i].ResampleFrom( m_buffer[i] ); + m_rpos = secondCopyLen; + } + else + m_rpos += nSamples; + + for( int i=0; i<nSamples; i++ ) + bData[i].ResampleFrom( rposbuffer[i] ); + } + + // If quietSamples != 0 it means we have an underrun... + // Let's just dull out some silence, because that's usually the least + // painful way of dealing with underruns: + memset( bData, 0, quietSamples * sizeof(T) ); + } +}; + +//class SndOutModule +//{ +//public: +// // Virtual destructor, because it helps fight C+++ funny-business. +// virtual ~SndOutModule() {} +// +// // Returns a unique identification string for this driver. +// // (usually just matches the driver's cpp filename) +// virtual const wchar_t* GetIdent() const=0; +// +// // Returns the long name / description for this driver. +// // (for use in configuration screen) +// virtual const wchar_t* GetLongName() const=0; +// +// virtual s32 Init()=0; +// virtual void Close()=0; +// virtual s32 Test() const=0; +// +// // Gui function: Used to open the configuration box for this driver. +// virtual void Configure(uptr parent)=0; +// +// // Loads settings from the INI file for this driver +// virtual void ReadSettings()=0; +// +// // Saves settings to the INI file for this driver +// virtual void WriteSettings() const=0; +// +// virtual bool Is51Out() const=0; +// +// // Returns the number of empty samples in the output buffer. +// // (which is effectively the amount of data played since the last update) +// virtual int GetEmptySampleCount() const=0; +//}; +// +// +//#ifdef _MSC_VER +////internal +//extern SndOutModule* WaveOut; +//extern SndOutModule* DSoundOut; +//extern SndOutModule* XAudio2Out; +//#endif +// +//extern SndOutModule* mods[]; +// +//// ===================================================================================================== +// +//extern void RecordStart(); +//extern void RecordStop(); +//extern void RecordWrite( const StereoOut16& sample ); +// +//extern s32 DspLoadLibrary(wchar_t *fileName, int modNum); +//extern void DspCloseLibrary(); +//extern int DspProcess(s16 *buffer, int samples); +//extern void DspUpdate(); // to let the Dsp process window messages diff --git a/jni/desmume/src/metaspu/Timestretcher.cpp b/jni/desmume/src/metaspu/Timestretcher.cpp new file mode 100755 index 0000000..967c31d --- /dev/null +++ b/jni/desmume/src/metaspu/Timestretcher.cpp @@ -0,0 +1,362 @@ +/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2 +* Developed and maintained by the Pcsx2 Development Team. +* +* Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz] +* +* SPU2-X is free software: you can redistribute it and/or modify it under the terms +* of the GNU Lesser General Public License as published by the Free Software Found- +* ation, either version 3 of the License, or (at your option) any later version. +* +* SPU2-X 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 Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>. +*/ + +//#include "Global.h" +#include <math.h> +#include "types.h" +#include "SndOut.h" +//#include "SoundTouch/WavFile.h" + +#ifdef HAVE_LIBSOUNDTOUCH +#include <SoundTouch.h> +#else +#include "SoundTouch/SoundTouch.h" +#endif + +#ifdef _WINDOWS +#include "win32/Dialogs.h" +#endif + + +static soundtouch::SoundTouch* pSoundTouch = NULL; +static int ts_stats_stretchblocks = 0; +static int ts_stats_normalblocks = 0; +static int ts_stats_logcounter = 0; + + +// data prediction amount, used to "commit" data that hasn't +// finished timestretch processing. +s32 SndBuffer::m_predictData; + +// records last buffer status (fill %, range -100 to 100, with 0 being 50% full) +float SndBuffer::lastPct; +float SndBuffer::lastEmergencyAdj; + +float SndBuffer::cTempo = 1; +float SndBuffer::eTempo = 1; +int SndBuffer::freezeTempo = 0; + +void SndBuffer::PredictDataWrite( int samples ) +{ + m_predictData += samples; +} + +// Calculate the buffer status percentage. +// Returns range from -1.0 to 1.0 +// 1.0 = buffer overflow! +// 0.0 = buffer nominal (50% full) +// -1.0 = buffer underflow! +float SndBuffer::GetStatusPct() +{ + // Get the buffer status of the output driver too, so that we can + // obtain a more accurate overall buffer status. + + int drvempty = 0; + //int drvempty = mods[OutputModule]->GetEmptySampleCount(); // / 2; + //TODO + + //ConLog( "Data %d >>> driver: %d predict: %d\n", data, drvempty, predictData ); + + float result = (float)(m_data + m_predictData - drvempty) - (m_size/2); + result /= (m_size/2); + return result; +} + +void SndBuffer::UpdateTempoChange() +{ + if( --freezeTempo > 0 ) + { + return; + } + + float statusPct = GetStatusPct(); + float pctChange = statusPct - lastPct; + + float tempoChange; + float emergencyAdj = 0; + float newcee = cTempo; // workspace var. for cTempo + + // IMPORTANT! + // If you plan to tweak these values, make sure you're using a release build + // OUTSIDE THE DEBUGGER to test it! The Visual Studio debugger can really cause + // erratic behavior in the audio buffers, and makes the timestretcher seem a + // lot more inconsistent than it really is. + + // We have two factors. + // * Distance from nominal buffer status (50% full) + // * The change from previous update to this update. + + // Prediction based on the buffer change: + // (linear seems to work better here) + + tempoChange = pctChange * 0.75f; + + if( statusPct * tempoChange < 0.0f ) + { + // only apply tempo change if it is in synch with the buffer status. + // In other words, if the buffer is high (over 0%), and is decreasing, + // ignore it. It'll just muck things up. + + tempoChange = 0; + } + + // Sudden spikes in framerate can cause the nominal buffer status + // to go critical, in which case we have to enact an emergency + // stretch. The following cubic formulas do that. Values near + // the extremeites give much larger results than those near 0. + // And the value is added only this time, and does not accumulate. + // (otherwise a large value like this would cause problems down the road) + + // Constants: + // Weight - weights the statusPct's "emergency" consideration. + // higher values here will make the buffer perform more drastic + // compensations at the outer edges of the buffer (at -75 or +75% + // or beyond, for example). + + // Range - scales the adjustment to the given range (more or less). + // The actual range is dependent on the weight used, so if you increase + // Weight you'll usually want to decrease Range somewhat to compensate. + + // Prediction based on the buffer fill status: + + const float statusWeight = 2.99f; + const float statusRange = 0.068f; + + // "non-emergency" deadzone: In this area stretching will be strongly discouraged. + // Note: due tot he nature of timestretch latency, it's always a wee bit harder to + // cope with low fps (underruns) than it is high fps (overruns). So to help out a + // little, the low-end portions of this check are less forgiving than the high-sides. + + if( cTempo < 0.965f || cTempo > 1.060f || + pctChange < -0.38f || pctChange > 0.54f || + statusPct < -0.32f || statusPct > 0.39f || + eTempo < 0.89f || eTempo > 1.19f ) + { + emergencyAdj = ( pow( statusPct*statusWeight, 3.0f ) * statusRange); + } + + // Smooth things out by factoring our previous adjustment into this one. + // It helps make the system 'feel' a little smarter by giving it at least + // one packet worth of history to help work off of: + + emergencyAdj = (emergencyAdj * 0.75f) + (lastEmergencyAdj * 0.25f ); + + lastEmergencyAdj = emergencyAdj; + lastPct = statusPct; + + // Accumulate a fraction of the tempo change into the tempo itself. + // This helps the system run "smarter" to games that run consistently + // fast or slow by altering the base tempo to something closer to the + // game's active speed. In tests most games normalize within 2 seconds + // at 100ms latency, which is pretty good (larger buffers normalize even + // quicker). + + newcee += newcee * (tempoChange+emergencyAdj) * 0.03f; + + // Apply tempoChange as a scale of cTempo. That way the effect is proportional + // to the current tempo. (otherwise tempos rate of change at the extremes would + // be too drastic) + + float newTempo = newcee + ( emergencyAdj * cTempo ); + + // ... and as a final optimization, only stretch if the new tempo is outside + // a nominal threshold. Keep this threshold check small, because it could + // cause some serious side effects otherwise. (enlarging the cTempo check above + // is usually better/safer) + if( newTempo < 0.970f || newTempo > 1.045f ) + { + cTempo = (float)newcee; + + if( newTempo < 0.10f ) newTempo = 0.10f; + else if( newTempo > 10.0f ) newTempo = 10.0f; + + if( cTempo < 0.15f ) cTempo = 0.15f; + else if( cTempo > 7.5f ) cTempo = 7.5f; + + pSoundTouch->setTempo( eTempo = (float)newTempo ); + ts_stats_stretchblocks++; + + /*ConLog(" * SPU2: [Nominal %d%%] [Emergency: %d%%] (baseTempo: %d%% ) (newTempo: %d%%) (buffer: %d%%)\n", + //(relation < 0.0) ? "Normalize" : "", + (int)(tempoChange * 100.0 * 0.03), + (int)(emergencyAdj * 100.0), + (int)(cTempo * 100.0), + (int)(newTempo * 100.0), + (int)(statusPct * 100.0) + );*/ + } + else + { + // Nominal operation -- turn off stretching. + // note: eTempo 'slides' toward 1.0 for smoother audio and better + // protection against spikes. + if( cTempo != 1.0f ) + { + cTempo = 1.0f; + eTempo = ( 1.0f + eTempo ) * 0.5f; + pSoundTouch->setTempo( eTempo ); + } + else + { + if( eTempo != cTempo ) + pSoundTouch->setTempo( eTempo=cTempo ); + ts_stats_normalblocks++; + } + } +} + +void SndBuffer::timeStretchUnderrun() +{ + // timeStretcher failed it's job. We need to slow down the audio some. + + cTempo -= (cTempo * 0.12f); + eTempo -= (eTempo * 0.30f); + if( eTempo < 0.1f ) eTempo = 0.1f; + pSoundTouch->setTempo( eTempo ); +} + +s32 SndBuffer::timeStretchOverrun() +{ + // If we overran it means the timestretcher failed. We need to speed + // up audio playback. + cTempo += cTempo * 0.12f; + eTempo += eTempo * 0.40f; + if( eTempo > 7.5f ) eTempo = 7.5f; + pSoundTouch->setTempo( eTempo ); + + // Throw out just a little bit (two packets worth) to help + // give the TS some room to work: + + return SndOutPacketSize*2; +} + +static void CvtPacketToFloat( StereoOut32* srcdest ) +{ + StereoOutFloat* dest = (StereoOutFloat*)srcdest; + const StereoOut32* src = (StereoOut32*)srcdest; + for( uint i=0; i<SndOutPacketSize; ++i, ++dest, ++src ) + *dest = (StereoOutFloat)*src; +} + +// Parameter note: Size should always be a multiple of 128, thanks! +static void CvtPacketToInt( StereoOut32* srcdest, uint size ) +{ + //jASSUME( (size & 127) == 0 ); + + const StereoOutFloat* src = (StereoOutFloat*)srcdest; + StereoOut32* dest = srcdest; + + for( uint i=0; i<size; ++i, ++dest, ++src ) + *dest = (StereoOut32)*src; +} + +void SndBuffer::timeStretchWrite() +{ + bool progress = false; + + // data prediction helps keep the tempo adjustments more accurate. + // The timestretcher returns packets in belated "clump" form. + // Meaning that most of the time we'll get nothing back, and then + // suddenly we'll get several chunks back at once. Thus we use + // data prediction to make the timestretcher more responsive. + + PredictDataWrite( (int)( SndOutPacketSize / eTempo ) ); + CvtPacketToFloat( sndTempBuffer ); + + pSoundTouch->putSamples( (float*)sndTempBuffer, SndOutPacketSize ); + + int tempProgress; + while( tempProgress = pSoundTouch->receiveSamples( (float*)sndTempBuffer, SndOutPacketSize), + tempProgress != 0 ) + { + // Hint: It's assumed that pSoundTouch will return chunks of 128 bytes (it always does as + // long as the SSE optimizations are enabled), which means we can do our own SSE opts here. + + CvtPacketToInt( sndTempBuffer, tempProgress ); + _WriteSamples( sndTempBuffer, tempProgress ); + progress = true; + } + + UpdateTempoChange(); + + //TODO + //if( MsgOverruns() ) + { + if( progress ) + { + if( ++ts_stats_logcounter > 300 ) + { + ts_stats_logcounter = 0; + printf( " * SPU2 > Timestretch Stats > %d%% of packets stretched.\n", + ( ts_stats_stretchblocks * 100 ) / ( ts_stats_normalblocks + ts_stats_stretchblocks ) ); + ts_stats_normalblocks = 0; + ts_stats_stretchblocks = 0; + } + } + } +} + +void SndBuffer::soundtouchInit() +{ + pSoundTouch = new soundtouch::SoundTouch(); + pSoundTouch->setSampleRate(SampleRate); + pSoundTouch->setChannels(2); + + pSoundTouch->setSetting( SETTING_USE_QUICKSEEK, 0 ); + pSoundTouch->setSetting( SETTING_USE_AA_FILTER, 0 ); + +#ifdef _WINDOWS + SoundtouchCfg::ApplySettings( *pSoundTouch ); +#endif + + pSoundTouch->setTempo(1); + + // some timestretch management vars: + + cTempo = 1.0; + eTempo = 1.0; + lastPct = 0; + lastEmergencyAdj = 0; + + // just freeze tempo changes for a while at startup. + // the driver buffers are bogus anyway. + freezeTempo = 16; + m_predictData = 0; +} + +// reset timestretch management vars, and delay updates a bit: +void SndBuffer::soundtouchClearContents() +{ + if( pSoundTouch == NULL ) return; + + pSoundTouch->clear(); + pSoundTouch->setTempo(1); + + cTempo = 1.0; + eTempo = 1.0; + lastPct = 0; + lastEmergencyAdj = 0; + + freezeTempo = 16; + m_predictData = 0; +} + +void SndBuffer::soundtouchCleanup() +{ + //safe_delete( pSoundTouch ); + delete pSoundTouch; +} diff --git a/jni/desmume/src/metaspu/metaspu.cpp b/jni/desmume/src/metaspu/metaspu.cpp new file mode 100755 index 0000000..67ec628 --- /dev/null +++ b/jni/desmume/src/metaspu/metaspu.cpp @@ -0,0 +1,520 @@ +/* Copyright 2009 DeSmuME team + + This file is part of DeSmuME + + DeSmuME 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. + + DeSmuME 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 DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "types.h" +#include "metaspu.h" +#include <queue> +#include <vector> +#include <assert.h> + +//for pcsx2 method +#if defined(_MSC_VER) || defined(HAVE_LIBSOUNDTOUCH) || defined(DESMUME_COCOA) +#include "SndOut.h" +#endif + + +template<typename T> inline T _abs(T val) +{ + if(val<0) return -val; + else return val; +} + +template<typename T> inline T moveValueTowards(T val, T target, T incr) +{ + incr = _abs(incr); + T delta = _abs(target-val); + if(val<target) val += incr; + else if(val>target) val -= incr; + T newDelta = _abs(target-val); + if(newDelta >= delta) + val = target; + return val; +} + + +class ZeromusSynchronizer : public ISynchronizingAudioBuffer +{ +public: + ZeromusSynchronizer() + : mixqueue_go(false) + , + #ifdef NDEBUG + adjustobuf(200,1000) + #else + adjustobuf(22000,44000) + #endif + { + + } + + bool mixqueue_go; + + virtual void enqueue_samples(s16* buf, int samples_provided) + { + for(int i=0;i<samples_provided;i++) { + s16 left = *buf++; + s16 right = *buf++; + adjustobuf.enqueue(left,right); + } + } + + //returns the number of samples actually supplied, which may not match the number requested + virtual int output_samples(s16* buf, int samples_requested) + { + int done = 0; + if(!mixqueue_go) { + if(adjustobuf.size > 200) + mixqueue_go = true; + } + else + { + for(int i=0;i<samples_requested;i++) { + if(adjustobuf.size==0) { + mixqueue_go = false; + break; + } + done++; + s16 left, right; + adjustobuf.dequeue(left,right); + *buf++ = left; + *buf++ = right; + } + } + + return done; + } + +private: + class Adjustobuf + { + public: + Adjustobuf(int _minLatency, int _maxLatency) + : size(0) + , minLatency(_minLatency) + , maxLatency(_maxLatency) + { + rollingTotalSize = 0; + targetLatency = (maxLatency + minLatency)/2; + rate = 1.0f; + cursor = 0.0f; + curr[0] = curr[1] = 0; + kAverageSize = 80000; + } + + float rate, cursor; + int minLatency, targetLatency, maxLatency; + std::queue<s16> buffer; + int size; + s16 curr[2]; + + std::queue<int> statsHistory; + + void enqueue(s16 left, s16 right) + { + buffer.push(left); + buffer.push(right); + size++; + } + + s64 rollingTotalSize; + + u32 kAverageSize; + + void addStatistic() + { + statsHistory.push(size); + rollingTotalSize += size; + if(statsHistory.size()>kAverageSize) + { + rollingTotalSize -= statsHistory.front(); + statsHistory.pop(); + + float averageSize = (float)(rollingTotalSize / kAverageSize); + //static int ctr=0; ctr++; if((ctr&127)==0) printf("avg size: %f curr size: %d rate: %f\n",averageSize,size,rate); + { + float targetRate; + if(averageSize < targetLatency) + { + targetRate = 1.0f - (targetLatency-averageSize)/kAverageSize; + } + else if(averageSize > targetLatency) { + targetRate = 1.0f + (averageSize-targetLatency)/kAverageSize; + } else targetRate = 1.0f; + + //rate = moveValueTowards(rate,targetRate,0.001f); + rate = targetRate; + } + + } + + + } + + void dequeue(s16& left, s16& right) + { + left = right = 0; + addStatistic(); + if(size==0) { return; } + cursor += rate; + while(cursor>1.0f) { + cursor -= 1.0f; + if(size>0) { + curr[0] = buffer.front(); buffer.pop(); + curr[1] = buffer.front(); buffer.pop(); + size--; + } + } + left = curr[0]; + right = curr[1]; + } + } adjustobuf; +}; + +class NitsujaSynchronizer : public ISynchronizingAudioBuffer +{ +private: + struct ssamp + { + s16 l, r; + ssamp() {} + ssamp(s16 ll, s16 rr) : l(ll), r(rr) {} + }; + + std::vector<ssamp> sampleQueue; + + // returns values going between 0 and y-1 in a saw wave pattern, based on x + static FORCEINLINE int pingpong(int x, int y) + { + x %= 2*y; + if(x >= y) + x = 2*y - x - 1; + return x; + + // in case we want to switch to odd buffer sizes for more sharpness + //x %= 2*(y-1); + //if(x >= y) + // x = 2*(y-1) - x; + //return x; + } + + static FORCEINLINE ssamp crossfade (ssamp lhs, ssamp rhs, int cur, int start, int end) + { + if(cur <= start) + return lhs; + if(cur >= end) + return rhs; + + // in case we want sine wave interpolation instead of linear here + //float ang = 3.14159f * (float)(cur - start) / (float)(end - start); + //cur = start + (int)((1-cosf(ang))*0.5f * (end - start)); + + int inNum = cur - start; + int outNum = end - cur; + int denom = end - start; + + int lrv = ((int)lhs.l * outNum + (int)rhs.l * inNum) / denom; + int rrv = ((int)lhs.r * outNum + (int)rhs.r * inNum) / denom; + + return ssamp(lrv,rrv); + } + + static FORCEINLINE void emit_sample(s16*& outbuf, ssamp sample) + { + *outbuf++ = sample.l; + *outbuf++ = sample.r; + } + + static FORCEINLINE void emit_samples(s16*& outbuf, const ssamp* samplebuf, int samples) + { + for(int i=0;i<samples;i++) + emit_sample(outbuf,samplebuf[i]); + } + +public: + NitsujaSynchronizer() + {} + + virtual void enqueue_samples(s16* buf, int samples_provided) + { + for(int i=0;i<samples_provided;i++) + { + sampleQueue.push_back(ssamp(buf[0],buf[1])); + buf += 2; + } + } + + virtual int output_samples(s16* buf, int samples_requested) + { + int audiosize = samples_requested; + int queued = sampleQueue.size(); + + // I am too lazy to deal with odd numbers + audiosize &= ~1; + queued &= ~1; + + if(queued > 0x200 && audiosize > 0) // is there any work to do? + { + // are we going at normal speed? + // or more precisely, are the input and output queues/buffers of similar size? + if(queued > 900 || audiosize > queued * 2) + { + // not normal speed. we have to resample it somehow in this case. + if(audiosize <= queued) + { + // fast forward speed + // this is the easy case, just crossfade it and it sounds ok + for(int i = 0; i < audiosize; i++) + { + int j = i + queued - audiosize; + ssamp outsamp = crossfade(sampleQueue[i],sampleQueue[j], i,0,audiosize); + emit_sample(buf,outsamp); + } + } + else + { + // slow motion speed + // here we take a very different approach, + // instead of crossfading it, we select a single sample from the queue + // and make sure that the index we use to select a sample is constantly moving + // and that it starts at the first sample in the queue and ends on the last one. + // + // hopefully the index doesn't move discontinuously or we'll get slight crackling + // (there might still be a minor bug here that causes this occasionally) + // + // here's a diagram of how the index we sample from moves: + // + // queued (this axis represents the index we sample from. the top means the end of the queue) + // ^ + // | --> audiosize (this axis represents the output index we write to, right meaning forward in output time/position) + // | A C C end + // A A B C C C + // A A A B C C C + // A A A B C C + // A A C + // start + // + // yes, this means we are spending some stretches of time playing the sound backwards, + // but the stretches are short enough that this doesn't sound weird. + // this lets us avoid most crackling problems due to the endpoints matching up. + + // first calculate a shorter-than-full window + // that has minimal slope at the endpoints + // (to further reduce crackling, especially in sine waves) + int beststart = 0, extraAtEnd = 0; + { + int bestend = queued; + static const int worstdiff = 99999999; + int beststartdiff = worstdiff; + int bestenddiff = worstdiff; + for(int i = 0; i < 128; i+=2) + { + int diff = abs(sampleQueue[i].l - sampleQueue[i+1].l) + abs(sampleQueue[i].r - sampleQueue[i+1].r); + if(diff < beststartdiff) + { + beststartdiff = diff; + beststart = i; + } + } + for(int i = queued-3; i > queued-3-128; i-=2) + { + int diff = abs(sampleQueue[i].l - sampleQueue[i+1].l) + abs(sampleQueue[i].r - sampleQueue[i+1].r); + if(diff < bestenddiff) + { + bestenddiff = diff; + bestend = i+1; + } + } + + extraAtEnd = queued - bestend; + queued = bestend - beststart; + + int oksize = queued; + while(oksize + queued*2 + beststart + extraAtEnd <= samples_requested) + oksize += queued*2; + audiosize = oksize; + + for(int x = 0; x < beststart; x++) + { + emit_sample(buf,sampleQueue[x]); + } + sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + beststart); + } + + + int midpointX = audiosize >> 1; + int midpointY = queued >> 1; + + // all we need to do here is calculate the X position of the leftmost "B" in the above diagram. + // TODO: we should calculate it with a simple equation like + // midpointXOffset = min(something,somethingElse); + // but it's a little difficult to work it out exactly + // so here's a stupid search for the value for now: + + int prevA = 999999; + int midpointXOffset = queued/2; + while(true) + { + int a = abs(pingpong(midpointX - midpointXOffset, queued) - midpointY) - midpointXOffset; + if(((a > 0) != (prevA > 0) || (a < 0) != (prevA < 0)) && prevA != 999999) + { + if((a + prevA)&1) // there's some sort of off-by-one problem with this search since we're moving diagonally... + midpointXOffset++; // but this fixes it most of the time... + break; // found it + } + prevA = a; + midpointXOffset--; + if(midpointXOffset < 0) + { + midpointXOffset = 0; + break; // failed to find it. the two sides probably meet exactly in the center. + } + } + + int leftMidpointX = midpointX - midpointXOffset; + int rightMidpointX = midpointX + midpointXOffset; + int leftMidpointY = pingpong(leftMidpointX, queued); + int rightMidpointY = (queued-1) - pingpong((int)audiosize-1 - rightMidpointX + queued*2, queued); + + // output the left almost-half of the sound (section "A") + for(int x = 0; x < leftMidpointX; x++) + { + int i = pingpong(x, queued); + emit_sample(buf,sampleQueue[i]); + } + + // output the middle stretch (section "B") + int y = leftMidpointY; + int dyMidLeft = (leftMidpointY < midpointY) ? 1 : -1; + int dyMidRight = (rightMidpointY > midpointY) ? 1 : -1; + for(int x = leftMidpointX; x < midpointX; x++, y+=dyMidLeft) + emit_sample(buf,sampleQueue[y]); + for(int x = midpointX; x < rightMidpointX; x++, y+=dyMidRight) + emit_sample(buf,sampleQueue[y]); + + // output the end of the queued sound (section "C") + for(int x = rightMidpointX; x < audiosize; x++) + { + int i = (queued-1) - pingpong((int)audiosize-1 - x + queued*2, queued); + emit_sample(buf,sampleQueue[i]); + } + + for(int x = 0; x < extraAtEnd; x++) + { + int i = queued + x; + emit_sample(buf,sampleQueue[i]); + } + queued += extraAtEnd; + audiosize += beststart + extraAtEnd; + } //end else + + sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + queued); + return audiosize; + } + else + { + // normal speed + // just output the samples straightforwardly. + // + // at almost-full speeds (like 50/60 FPS) + // what will happen is that we rapidly fluctuate between entering this branch + // and entering the "slow motion speed" branch above. + // but that's ok! because all of these branches sound similar enough that we can get away with it. + // so the two cases actually complement each other. + + if(audiosize >= queued) + { + emit_samples(buf,&sampleQueue[0],queued); + sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + queued); + return queued; + } + else + { + emit_samples(buf,&sampleQueue[0],audiosize); + sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin()+audiosize); + return audiosize; + } + + } //end normal speed + + } //end if there is any work to do + else + { + return 0; + } + + } //output_samples + +private: + +}; //NitsujaSynchronizer + + +#if defined(_MSC_VER) || defined(HAVE_LIBSOUNDTOUCH) || defined(DESMUME_COCOA) +class PCSX2Synchronizer : public ISynchronizingAudioBuffer +{ +public: + std::queue<s16> readySamples; + PCSX2Synchronizer() + { + SndBuffer::Init(); + } + virtual void enqueue_samples(s16* buf, int samples_provided) + { + for(int i=0;i<samples_provided;i++) + { + StereoOut32 so32(buf[0],buf[1]); + SndBuffer::Write(so32); + buf++; + buf++; + } + } + + virtual int output_samples(s16* buf, int samples_requested) + { + for(int i=0;i<samples_requested;i++) { + if(readySamples.size()==0) { + //SndOutPacketSize + StereoOut16 temp[SndOutPacketSize*2]; + SndBuffer::ReadSamples( temp ); + for(int i=0;i<SndOutPacketSize;i++) { + readySamples.push(temp[i].Left); + readySamples.push(temp[i].Right); + } + } + *buf++ = readySamples.front(); readySamples.pop(); + *buf++ = readySamples.front(); readySamples.pop(); + } + return samples_requested; + } +}; +#endif + + +ISynchronizingAudioBuffer* metaspu_construct(ESynchMethod method) +{ + switch(method) + { + case ESynchMethod_N: return new NitsujaSynchronizer(); + case ESynchMethod_Z: return new ZeromusSynchronizer(); +#if defined(_MSC_VER) || defined(HAVE_LIBSOUNDTOUCH) || defined(DESMUME_COCOA) + case ESynchMethod_P: return new PCSX2Synchronizer(); +#endif + default: return NULL; + } +} diff --git a/jni/desmume/src/metaspu/metaspu.h b/jni/desmume/src/metaspu/metaspu.h new file mode 100755 index 0000000..7a878d5 --- /dev/null +++ b/jni/desmume/src/metaspu/metaspu.h @@ -0,0 +1,65 @@ +/* Copyright 2009-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +//------------------------- +//this file contains the METASPU system +//which is designed to handle the task of audio synchronization +//and is designed to be as portable between multiple emulators +//------------------------- + + +#ifndef _METASPU_H_ +#define _METASPU_H_ + +#include <algorithm> + +template< typename T > +static FORCEINLINE void Clampify( T& src, T min, T max ) +{ + src = std::min( std::max( src, min ), max ); +} + +template< typename T > +static FORCEINLINE T GetClamped( T src, T min, T max ) +{ + return std::min( std::max( src, min ), max ); +} + +class ISynchronizingAudioBuffer +{ +public: + virtual void enqueue_samples(s16* buf, int samples_provided) = 0; + + //returns the number of samples actually supplied, which may not match the number requested + virtual int output_samples(s16* buf, int samples_requested) = 0; +}; + +enum ESynchMode +{ + ESynchMode_DualSynchAsynch, + ESynchMode_Synchronous +}; + +enum ESynchMethod +{ + ESynchMethod_N, //nitsuja's + ESynchMethod_Z, //zero's + ESynchMethod_P, //PCSX2 spu2-x +}; + +ISynchronizingAudioBuffer* metaspu_construct(ESynchMethod method); + +#endif diff --git a/jni/desmume/src/mic.cpp b/jni/desmume/src/mic.cpp new file mode 100755 index 0000000..ac9368e --- /dev/null +++ b/jni/desmume/src/mic.cpp @@ -0,0 +1,208 @@ +/* mic.cpp - this file is part of DeSmuME + * + * Copyright (C) 2009-2011 DeSmuME Team + * + * This file 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, or (at your option) + * any later version. + * + * This file 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; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef WIN32 + +#include <stdlib.h> +#include "mic.h" +#include "NDSSystem.h" +#include "readwrite.h" + +#define MIC_NULL_SAMPLE_VALUE 0 +#define MIC_MAX_BUFFER_SAMPLES 320 +#define MIC_BUFFER_SIZE (sizeof(u8) * MIC_MAX_BUFFER_SAMPLES) +#define NUM_INTERNAL_NOISE_SAMPLES 32 + +static u8 *micSampleBuffer = NULL; // Pointer to the internal sample buffer. +static u8 *micReadPosition = NULL; // Pointer to the read position of the internal sample buffer. +static u8 *micWritePosition = NULL; // Pointer to the write position of the internal sample buffer. +static unsigned int micBufferFillCount; // The number of readable samples in the internal sample buffer. + +static void Mic_BufferClear(void) +{ + if (micSampleBuffer == NULL) { + return; + } + + memset(micSampleBuffer, MIC_NULL_SAMPLE_VALUE, MIC_BUFFER_SIZE); + micReadPosition = micSampleBuffer; + micWritePosition = micSampleBuffer; + micBufferFillCount = 0; +} + +BOOL Mic_Init(void) +{ + BOOL result = FALSE; + + u8 *newBuffer = (u8 *)malloc(MIC_BUFFER_SIZE); + if (newBuffer == NULL) { + return result; + } + + micSampleBuffer = newBuffer; + Mic_BufferClear(); + result = TRUE; + + return result; +} + +void Mic_DeInit(void) +{ + free(micSampleBuffer); + micSampleBuffer = NULL; +} + +void Mic_Reset(void) +{ + *micReadPosition = MIC_NULL_SAMPLE_VALUE; + micWritePosition = micReadPosition; + micBufferFillCount = 0; +} + +static bool Mic_GetActivate(void) +{ + return NDS_getFinalUserInput().mic.micButtonPressed; +} + +static bool Mic_IsBufferFull(void) +{ + return (micBufferFillCount >= MIC_MAX_BUFFER_SAMPLES); +} + +static bool Mic_IsBufferEmpty(void) +{ + return (micBufferFillCount == 0); +} + +static u8 Mic_DefaultBufferRead(void) +{ + u8 theSample = MIC_NULL_SAMPLE_VALUE; + + if (micSampleBuffer == NULL) { + return theSample; + } + + theSample = *micReadPosition; + + if (Mic_IsBufferEmpty()) { + return theSample; + } + + micReadPosition++; + micBufferFillCount--; + + // Move the pointer back to start if we reach the end of the memory block. + if (micReadPosition >= (micSampleBuffer + MIC_BUFFER_SIZE)) { + micReadPosition = micSampleBuffer; + } + + return theSample; +} + +u8 Mic_ReadSample(void) +{ + // All mic modes other than Physical must have the mic hotkey pressed in order + // to work. + if (CommonSettings.micMode != TCommonSettings::Physical && !Mic_GetActivate()) { + return MIC_NULL_SAMPLE_VALUE; + } + + return Mic_DefaultBufferRead(); +} + +static void Mic_DefaultBufferWrite(u8 theSample) +{ + if (micSampleBuffer == NULL || Mic_IsBufferFull()) { + return; + } + + *micWritePosition = theSample; + micWritePosition++; + micBufferFillCount++; + + // Move the pointer back to start if we reach the end of the memory block. + if (micWritePosition >= (micSampleBuffer + MIC_BUFFER_SIZE)) { + micWritePosition = micSampleBuffer; + } +} + +static u8 Mic_GenerateInternalNoiseSample(void) +{ + const u8 noiseSample[NUM_INTERNAL_NOISE_SAMPLES] = + { + 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0xFF, + 0xF4, 0xE1, 0xBF, 0x9A, 0x71, 0x58, 0x5B, 0x5F, 0x62, 0xC2, 0x25, 0x05, 0x01, 0x01, 0x01, 0x01 + }; + static unsigned int i = 0; + + if (++i >= NUM_INTERNAL_NOISE_SAMPLES) { + i = 0; + } + + return noiseSample[i]; +} + +static u8 Mic_GenerateWhiteNoiseSample(void) +{ + return (u8)(rand() & 0xFF); +} + +static u8 Mic_GenerateNullSample(void) +{ + return MIC_NULL_SAMPLE_VALUE; +} + +void Mic_DoNoise(BOOL noise) +{ + u8 (*generator) (void) = NULL; + + if (micSampleBuffer == NULL) { + return; + } + + if (!noise) { + generator = &Mic_GenerateNullSample; + } else if (CommonSettings.micMode == TCommonSettings::InternalNoise) { + generator = &Mic_GenerateInternalNoiseSample; + } else if (CommonSettings.micMode == TCommonSettings::Random) { + generator = &Mic_GenerateWhiteNoiseSample; + } + + if (generator == NULL) { + return; + } + + while (micBufferFillCount < MIC_MAX_BUFFER_SAMPLES) { + Mic_DefaultBufferWrite(generator()); + } +} + +void mic_savestate(EMUFILE* os) +{ + write32le(-1,os); +} + +bool mic_loadstate(EMUFILE* is, int size) +{ + is->fseek(size, SEEK_CUR); + return TRUE; +} + +#endif diff --git a/jni/desmume/src/mic.h b/jni/desmume/src/mic.h new file mode 100755 index 0000000..c717740 --- /dev/null +++ b/jni/desmume/src/mic.h @@ -0,0 +1,44 @@ +/* + Copyright (C) 2009-2011 DeSmuME Team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef MIC_H +#define MIC_H + +#include <iostream> +#include "emufile.h" +#include "types.h" + +#ifdef WIN32 +static char MicSampleName[256]; +bool LoadSample(const char *name); +#endif + +extern int MicDisplay; + +#ifdef FAKE_MIC +void Mic_DoNoise(BOOL); +#endif + +BOOL Mic_Init(void); +void Mic_Reset(void); +void Mic_DeInit(void); +u8 Mic_ReadSample(void); + +void mic_savestate(EMUFILE* os); +bool mic_loadstate(EMUFILE* is, int size); + +#endif // MIC_H diff --git a/jni/desmume/src/mic_alsa.cpp b/jni/desmume/src/mic_alsa.cpp new file mode 100755 index 0000000..8316ff7 --- /dev/null +++ b/jni/desmume/src/mic_alsa.cpp @@ -0,0 +1,174 @@ +/* + Copyright (C) 2009-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <alsa/asoundlib.h> +#include <glib.h> +#include "types.h" +#include "mic.h" +#include "debug.h" +#include "readwrite.h" +#include "emufile.h" + +#define MIC_BUFSIZE 4096 + +BOOL Mic_Inited = FALSE; +u8 Mic_Buffer[2][MIC_BUFSIZE]; +u16 Mic_BufPos; +u8 Mic_PlayBuf; +u8 Mic_WriteBuf; + +int MicButtonPressed; + +/* Alsa stuff */ +static snd_pcm_t *pcm_handle; + +BOOL Mic_Init() +{ + snd_pcm_hw_params_t *hwparams; + snd_pcm_uframes_t mic_bufsize, periods; + int err; + + if (Mic_Inited) + return TRUE; + + if ((err = snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) { + g_printerr("Failed to open device: %s\n", snd_strerror(err)); + return FALSE; + } + + /* Hardware params */ + snd_pcm_hw_params_alloca(&hwparams); + if ((err = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) { + g_printerr("Failed to setup hw parameters: %s\n", snd_strerror(err)); + return FALSE; + } + + if ((err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { + g_printerr("Failed to set access: %s\n", snd_strerror(err)); + return FALSE; + } + + /* 8bit signed, mono, 16000hz */ + if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S8)) < 0) { + g_printerr("Failed to set format: %s\n", snd_strerror(err)); + return FALSE; + } + + if ((err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 1)) < 0) { + g_printerr("Failed to set channels: %s\n", snd_strerror(err)); + return FALSE; + } + + if ((err = snd_pcm_hw_params_set_rate(pcm_handle, hwparams, 16000, 0)) < 0) { + g_printerr("Failed to set rate: %s\n", snd_strerror(err)); + return FALSE; + } + + if ((err = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) { + g_printerr("Failed to set hw parameters: %s\n", snd_strerror(err)); + return FALSE; + } + + /* Query the driver for buffer and period sizes */ + if ((err = snd_pcm_hw_params_get_buffer_size(hwparams, &mic_bufsize)) < 0) { + g_printerr("Failed to get buffer size: %s\n", snd_strerror(err)); + return FALSE; + } + + if ((err = snd_pcm_hw_params_get_period_size(hwparams, &periods, 0)) < 0) { + g_printerr("Failed to get period size: %s\n", snd_strerror(err)); + return FALSE; + } + + Mic_Inited = TRUE; + Mic_Reset(); + + return TRUE; +} + +void Mic_Reset() +{ + if (!Mic_Inited) + return; + + memset(Mic_Buffer, 0, MIC_BUFSIZE * 2); + Mic_BufPos = 0; + Mic_PlayBuf = 1; + Mic_WriteBuf = 0; +} + +void Mic_DeInit() +{ + if (!Mic_Inited) + return; + + Mic_Inited = FALSE; + + snd_pcm_drop(pcm_handle); + snd_pcm_close(pcm_handle); +} + +static void snd_pcm_read() +{ + int error; + + error = snd_pcm_readi(pcm_handle, Mic_Buffer[Mic_WriteBuf], MIC_BUFSIZE); + if (error < 0) + error = snd_pcm_recover(pcm_handle, error, 0); + if (error < 0) + LOG("snd_pcm_readi FAIL!: %s\n", snd_strerror(error)); +} + +u8 Mic_ReadSample() +{ + u8 tmp; + u8 ret; + + if (!Mic_Inited) + return 0; + + tmp = Mic_Buffer[Mic_PlayBuf][Mic_BufPos >> 1]; + + if (Mic_BufPos & 0x1) { + ret = ((tmp & 0x1) << 7); + } else { + ret = ((tmp & 0xFE) >> 1); + snd_pcm_read(); + } + + Mic_BufPos++; + if (Mic_BufPos >= (MIC_BUFSIZE << 1)) { + snd_pcm_read(); + Mic_BufPos = 0; + Mic_PlayBuf ^= 1; + Mic_WriteBuf ^= 1; + } + + return ret; +} + +/* FIXME: stub! */ +void mic_savestate(EMUFILE* os) +{ + write32le((u32)(-1),os); +} + +bool mic_loadstate(EMUFILE* is, int size) +{ + is->fseek(size, SEEK_CUR); + return TRUE; +} diff --git a/jni/desmume/src/mic_openal.cpp b/jni/desmume/src/mic_openal.cpp new file mode 100755 index 0000000..9ebfd9e --- /dev/null +++ b/jni/desmume/src/mic_openal.cpp @@ -0,0 +1,169 @@ +/* + Copyright (C) 2009-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef WIN32 + +#include <AL/al.h> +#include <AL/alc.h> + +#include "types.h" +#include "mic.h" +#include "readwrite.h" +#include "emufile.h" +#include "debug.h" + +#define MIC_BUFSIZE 512 + +BOOL Mic_Inited = FALSE; +u8 Mic_Buffer[2][2*MIC_BUFSIZE]; +u16 Mic_BufPos; +u8 Mic_PlayBuf; +u8 Mic_WriteBuf; + +int MicButtonPressed; + +ALCdevice *alDevice; +ALCdevice *alCaptureDevice; +ALCcontext *alContext; + +BOOL Mic_Init() +{ + ALenum err; + const char *szDefaultCaptureDevice; + + if (!(alDevice = alcOpenDevice(0))) { + INFO("Failed to Initialize Open AL\n"); + return FALSE; + } + if( !(alContext = alcCreateContext(alDevice, 0))) { + INFO("Failed to create OpenAL context\n"); + return FALSE; + } + if( !alcMakeContextCurrent(alContext)) { + INFO("Failed to make OpenAL context current\n"); + return FALSE; + } + alDistanceModel(AL_INVERSE_DISTANCE); + + szDefaultCaptureDevice = alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER); + LOG("Default OpenAL Capture Device is '%s'\n\n", szDefaultCaptureDevice); + + alCaptureDevice = alcCaptureOpenDevice(szDefaultCaptureDevice, 16000, AL_FORMAT_STEREO8, MIC_BUFSIZE); + err = alGetError(); + if (err != AL_NO_ERROR) { + INFO("Failed to alCaptureOpenDevice, ALenum %i\n", err); + return 0; + } + alcCaptureStart(alCaptureDevice); + + Mic_Inited = TRUE; + Mic_Reset(); + + return TRUE; +} + +void Mic_Reset() +{ + if (!Mic_Inited) + return; + + memset(Mic_Buffer, 0, MIC_BUFSIZE*2*2); + Mic_BufPos = 0; + Mic_PlayBuf = 1; + Mic_WriteBuf = 0; +} + +void Mic_DeInit() +{ + if (!Mic_Inited) + return; + + Mic_Inited = FALSE; + + if (alDevice) { + if (alCaptureDevice) { + alcCaptureStop(alCaptureDevice); + alcCaptureCloseDevice(alCaptureDevice); + } + if (alContext) { + alcMakeContextCurrent(0); + alcDestroyContext(alContext); + } + alcCloseDevice(alDevice); + } +} + + +static void alReadSound() +{ + ALenum err; + int num; + + alcGetIntegerv(alCaptureDevice, ALC_CAPTURE_SAMPLES, 1, &num); + if (num < MIC_BUFSIZE-1) { + LOG("not enough microphone data waiting! (%i samples)\n", num); + } else { + LOG("%i samples waiting\n", num); + } + if (num > MIC_BUFSIZE) + num = MIC_BUFSIZE; + + alcCaptureSamples(alCaptureDevice, Mic_Buffer[Mic_WriteBuf], num); + err = alGetError(); + if (err != AL_NO_ERROR) { + INFO("Failed to alcCaptureSamples, ALenum %i\n", err); + return; + } +} + +u8 Mic_ReadSample() +{ + static u8 stats_max; + static u8 stats_min; + u8 ret; + + if (Mic_BufPos >= MIC_BUFSIZE) { + alReadSound(); + Mic_BufPos = 0; + Mic_PlayBuf ^= 1; + Mic_WriteBuf ^= 1; + } + + ret = Mic_Buffer[Mic_PlayBuf][Mic_BufPos >> 1]; + if (ret > stats_max) + stats_max = ret; + if (ret < stats_min) + stats_min = ret; + Mic_BufPos += 2; + + return ret; +} + +void mic_savestate(EMUFILE* os) +{ + write32le(-1,os); +} + +bool mic_loadstate(EMUFILE* is, int size) +{ + is->fseek(size, SEEK_CUR); + return TRUE; +} + +#endif + diff --git a/jni/desmume/src/movie.cpp b/jni/desmume/src/movie.cpp new file mode 100755 index 0000000..6a24dbd --- /dev/null +++ b/jni/desmume/src/movie.cpp @@ -0,0 +1,1250 @@ +/* + Copyright 2008-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#define WIN32_LEAN_AND_MEAN +#include <assert.h> +#include <limits.h> +#include <ctype.h> +#include <time.h> +#include "utils/guid.h" +#include "utils/xstring.h" +#include "utils/datetime.h" +#include "movie.h" +#include "NDSSystem.h" +#include "readwrite.h" +#include "debug.h" +#include "rtc.h" +#include "common.h" +#include "mic.h" +#include "version.h" +#include "GPU_osd.h" +#include "path.h" +#include "emufile.h" + +using namespace std; +bool freshMovie = false; //True when a movie loads, false when movie is altered. Used to determine if a movie has been altered since opening +bool autoMovieBackup = true; + +#define FCEU_PrintError LOG + +#define MOVIE_VERSION 1 + +#ifdef WIN32 +#include ".\windows\main.h" +#endif + +//----movie engine main state + +EMOVIEMODE movieMode = MOVIEMODE_INACTIVE; + +//this should not be set unless we are in MOVIEMODE_RECORD! +EMUFILE* osRecordingMovie = 0; + +int currFrameCounter; +uint32 cur_input_display = 0; +int pauseframe = -1; +bool movie_readonly = true; + +char curMovieFilename[512] = {0}; +MovieData currMovieData; +int currRerecordCount; +bool movie_reset_command = false; +//-------------- + + +void MovieData::clearRecordRange(int start, int len) +{ + for(int i=0;i<len;i++) + records[i+start].clear(); +} + +void MovieData::insertEmpty(int at, int frames) +{ + if(at == -1) + { + int currcount = records.size(); + records.resize(records.size()+frames); + clearRecordRange(currcount,frames); + } + else + { + records.insert(records.begin()+at,frames,MovieRecord()); + clearRecordRange(at,frames); + } +} + + + +void MovieRecord::clear() +{ + pad = 0; + commands = 0; + touch.padding = 0; +} + + +bool MovieRecord::Compare(MovieRecord& compareRec) +{ + //Check pad + if (this->pad != compareRec.pad) + return false; + + //Check Stylus + if (this->touch.padding != compareRec.touch.padding) return false; + if (this->touch.touch != compareRec.touch.touch) return false; + if (this->touch.x != compareRec.touch.x) return false; + if (this->touch.y != compareRec.touch.y) return false; + + //Check comamnds + //if new commands are ever recordable, they need to be added here if we go with this method + if(this->command_reset() != compareRec.command_reset()) return false; + if(this->command_microphone() != compareRec.command_microphone()) return false; + if(this->command_lid() != compareRec.command_lid()) return false; + + return true; +} + +const char MovieRecord::mnemonics[13] = {'R','L','D','U','T','S','B','A','Y','X','W','E','G'}; +void MovieRecord::dumpPad(EMUFILE* fp, u16 pad) +{ + //these are mnemonics for each joystick bit. + //since we usually use the regular joypad, these will be more helpful. + //but any character other than ' ' or '.' should count as a set bit + //maybe other input types will need to be encoded another way.. + for(int bit=0;bit<13;bit++) + { + int bitmask = (1<<(12-bit)); + char mnemonic = mnemonics[bit]; + //if the bit is set write the mnemonic + if(pad & bitmask) + fp->fputc(mnemonic); + else //otherwise write an unset bit + fp->fputc('.'); + } +} + + +void MovieRecord::parsePad(EMUFILE* fp, u16& pad) +{ + + char buf[13]; + fp->fread(buf,13); + pad = 0; + for(int i=0;i<13;i++) + { + pad <<= 1; + pad |= ((buf[i]=='.'||buf[i]==' ')?0:1); + } +} + + +void MovieRecord::parse(MovieData* md, EMUFILE* fp) +{ + //by the time we get in here, the initial pipe has already been extracted + + //extract the commands + commands = u32DecFromIstream(fp); + + fp->fgetc(); //eat the pipe + + parsePad(fp, pad); + touch.x = u32DecFromIstream(fp); + touch.y = u32DecFromIstream(fp); + touch.touch = u32DecFromIstream(fp); + + fp->fgetc(); //eat the pipe + + //should be left at a newline +} + + +void MovieRecord::dump(MovieData* md, EMUFILE* fp, int index) +{ + //dump the misc commands + //*os << '|' << setw(1) << (int)commands; + fp->fputc('|'); + putdec<uint8,1,true>(fp,commands); + + fp->fputc('|'); + dumpPad(fp, pad); + putdec<u8,3,true>(fp,touch.x); fp->fputc(' '); + putdec<u8,3,true>(fp,touch.y); fp->fputc(' '); + putdec<u8,1,true>(fp,touch.touch); + fp->fputc('|'); + + //each frame is on a new line + fp->fputc('\n'); +} + +DateTime FCEUI_MovieGetRTCDefault() +{ + // compatible with old desmume + return DateTime(2009,1,1,0,0,0); +} + +MovieData::MovieData() + : version(MOVIE_VERSION) + , emuVersion(EMU_DESMUME_VERSION_NUMERIC()) + , romChecksum(0) + , rerecordCount(0) + , binaryFlag(false) + , rtcStart(FCEUI_MovieGetRTCDefault()) +{ +} + +void MovieData::truncateAt(int frame) +{ + if((int)records.size() > frame) + records.resize(frame); +} + + +void MovieData::installValue(std::string& key, std::string& val) +{ + //todo - use another config system, or drive this from a little data structure. because this is gross + if(key == "version") + installInt(val,version); + else if(key == "emuVersion") + installInt(val,emuVersion); + else if(key == "rerecordCount") + installInt(val,rerecordCount); + else if(key == "romFilename") + romFilename = val; + else if(key == "romChecksum") + StringToBytes(val,&romChecksum,MD5DATA::size); + else if(key == "romSerial") + romSerial = val; + else if(key == "guid") + guid = Desmume_Guid::fromString(val); + else if(key == "rtcStart") { + // sloppy format check and parse + const char *validFormatStr = "####-##-##T##:##:##Z"; + bool validFormat = true; + for (int i = 0; validFormatStr[i] != '\0'; i++) { + if (validFormatStr[i] != val[i] && + !(validFormatStr[i] == '#' && isdigit(val[i]))) { + validFormat = false; + break; + } + } + if (validFormat) { + struct tm t; + const char *s = val.data(); + int year = atoi(&s[0]); + int mon = atoi(&s[5]); + int day = atoi(&s[8]); + int hour = atoi(&s[11]); + int min = atoi(&s[14]); + int sec = atoi(&s[17]); + rtcStart = DateTime(year,mon,day,hour,min,sec); + } + } + else if(key == "rtcStartNew") { + DateTime::TryParse(val.c_str(),rtcStart); + } + else if(key == "comment") + comments.push_back(mbstowcs(val)); + else if(key == "binary") + installBool(val,binaryFlag); + else if(key == "savestate") + { + int len = Base64StringToBytesLength(val); + if(len == -1) len = HexStringToBytesLength(val); // wasn't base64, try hex + if(len >= 1) + { + savestate.resize(len); + StringToBytes(val,&savestate[0],len); // decodes either base64 or hex + } + } + else if(key == "sram") + { + int len = Base64StringToBytesLength(val); + if(len == -1) len = HexStringToBytesLength(val); // wasn't base64, try hex + if(len >= 1) + { + sram.resize(len); + StringToBytes(val,&sram[0],len); // decodes either base64 or hex + } + } +} + + +int MovieData::dump(EMUFILE* fp, bool binary) +{ + int start = fp->ftell(); + fp->fprintf("version %d\n", version); + fp->fprintf("emuVersion %d\n", emuVersion); + fp->fprintf("rerecordCount %d\n", rerecordCount); + + fp->fprintf("romFilename %s\n", romFilename.c_str()); + fp->fprintf("romChecksum %s\n", u32ToHexString(gameInfo.crc).c_str()); + fp->fprintf("romSerial %s\n", romSerial.c_str()); + fp->fprintf("guid %s\n", guid.toString().c_str()); + fp->fprintf("useExtBios %d\n", CommonSettings.UseExtBIOS?1:0); + fp->fprintf("advancedTiming %d\n", CommonSettings.advanced_timing?1:0); + + if(CommonSettings.UseExtBIOS) + fp->fprintf("swiFromBios %d\n", CommonSettings.SWIFromBIOS?1:0); + + fp->fprintf("useExtFirmware %d\n", CommonSettings.UseExtFirmware?1:0); + + if(CommonSettings.UseExtFirmware) { + fp->fprintf("bootFromFirmware %d\n", CommonSettings.BootFromFirmware?1:0); + } + else { + char temp_str[27]; + int i; + + /* FIXME: harshly only use the lower byte of the UTF-16 character. + * This would cause strange behaviour if the user could set UTF-16 but + * they cannot yet. + */ + for (i = 0; i < CommonSettings.InternalFirmConf.nickname_len; i++) { + temp_str[i] = CommonSettings.InternalFirmConf.nickname[i]; + } + temp_str[i] = '\0'; + fp->fprintf("firmNickname %s\n", temp_str); + for (i = 0; i < CommonSettings.InternalFirmConf.message_len; i++) { + temp_str[i] = CommonSettings.InternalFirmConf.message[i]; + } + temp_str[i] = '\0'; + fp->fprintf("firmMessage %s\n", temp_str); + fp->fprintf("firmFavColour %d\n", CommonSettings.InternalFirmConf.fav_colour); + fp->fprintf("firmBirthMonth %d\n", CommonSettings.InternalFirmConf.birth_month); + fp->fprintf("firmBirthDay %d\n", CommonSettings.InternalFirmConf.birth_day); + fp->fprintf("firmLanguage %d\n", CommonSettings.InternalFirmConf.language); + } + + fp->fprintf("rtcStartNew %s\n", rtcStart.ToString().c_str()); + + for(uint32 i=0;i<comments.size();i++) + fp->fprintf("comment %s\n", wcstombs(comments[i]).c_str()); + + if(binary) + fp->fprintf("binary 1\n"); + + if(savestate.size() != 0) + fp->fprintf("savestate %s\n", BytesToString(&savestate[0],savestate.size()).c_str()); + if(sram.size() != 0) + fp->fprintf("sram %s\n", BytesToString(&sram[0],sram.size()).c_str()); + + if(binary) + { + //put one | to start the binary dump + fp->fputc('|'); + for(int i=0;i<(int)records.size();i++) + records[i].dumpBinary(this,fp,i); + } + else + for(int i=0;i<(int)records.size();i++) + records[i].dump(this,fp,i); + + int end = fp->ftell(); + return end-start; +} + +//yuck... another custom text parser. +bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader) +{ + //TODO - start with something different. like 'desmume movie version 1" + int curr = fp->ftell(); + + //movie must start with "version 1" + char buf[9]; + curr = fp->ftell(); + fp->fread(buf,9); + fp->fseek(curr, SEEK_SET); +// if(fp->fail()) return false; + if(memcmp(buf,"version 1",9)) + return false; + + std::string key,value; + enum { + NEWLINE, KEY, SEPARATOR, VALUE, RECORD, COMMENT + } state = NEWLINE; + bool bail = false; + for(;;) + { + bool iswhitespace, isrecchar, isnewline; + int c; + if(size--<=0) goto bail; + c = fp->fgetc(); + if(c == -1) + goto bail; + iswhitespace = (c==' '||c=='\t'); + isrecchar = (c=='|'); + isnewline = (c==10||c==13); + if(isrecchar && movieData.binaryFlag && !stopAfterHeader) + { + LoadFM2_binarychunk(movieData, fp, size); + return true; + } + switch(state) + { + case NEWLINE: + if(isnewline) goto done; + if(iswhitespace) goto done; + if(isrecchar) + goto dorecord; + //must be a key + key = ""; + value = ""; + goto dokey; + break; + case RECORD: + { + dorecord: + if (stopAfterHeader) return true; + int currcount = movieData.records.size(); + movieData.records.resize(currcount+1); + int preparse = fp->ftell(); + movieData.records[currcount].parse(&movieData, fp); + int postparse = fp->ftell(); + size -= (postparse-preparse); + state = NEWLINE; + break; + } + + case KEY: + dokey: //dookie + state = KEY; + if(iswhitespace) goto doseparator; + if(isnewline) goto commit; + key += c; + break; + case SEPARATOR: + doseparator: + state = SEPARATOR; + if(isnewline) goto commit; + if(!iswhitespace) goto dovalue; + break; + case VALUE: + dovalue: + state = VALUE; + if(isnewline) goto commit; + value += c; + break; + case COMMENT: + default: + break; + } + goto done; + + bail: + bail = true; + if(state == VALUE) goto commit; + goto done; + commit: + movieData.installValue(key,value); + state = NEWLINE; + done: ; + if(bail) break; + } + + return true; +} + + +static void closeRecordingMovie() +{ + if(osRecordingMovie) + { + delete osRecordingMovie; + osRecordingMovie = 0; + } +} + +/// Stop movie playback. +static void StopPlayback() +{ + driver->USR_InfoMessage("Movie playback stopped."); + movieMode = MOVIEMODE_INACTIVE; +} + +/// Stop movie playback without closing the movie. +static void FinishPlayback() +{ + driver->USR_InfoMessage("Movie finished playing."); + movieMode = MOVIEMODE_FINISHED; +} + + +/// Stop movie recording +static void StopRecording() +{ + driver->USR_InfoMessage("Movie recording stopped."); + movieMode = MOVIEMODE_INACTIVE; + + closeRecordingMovie(); +} + + + +void FCEUI_StopMovie() +{ + if(movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_FINISHED) + StopPlayback(); + else if(movieMode == MOVIEMODE_RECORD) + StopRecording(); + + curMovieFilename[0] = 0; + freshMovie = false; +} + + +//begin playing an existing movie +const char* _CDECL_ FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _pauseframe) +{ + //if(!tasedit && !FCEU_IsValidUI(FCEUI_PLAYMOVIE)) + // return; + + // FIXME: name==null indicates to BROWSE to retrieve fname from user (or stdin if that's impossible), + // when called from movie_play + assert(fname); + if(!fname) + return "LoadMovie doesn't support browsing yet"; + + //mbg 6/10/08 - we used to call StopMovie here, but that cleared curMovieFilename and gave us crashes... + if(movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_FINISHED) + StopPlayback(); + else if(movieMode == MOVIEMODE_RECORD) + StopRecording(); + //-------------- + + currMovieData = MovieData(); + + strcpy(curMovieFilename, fname); + //FCEUFILE *fp = FCEU_fopen(fname,0,"rb",0); + //if (!fp) return; + //if(fp->isArchive() && !_read_only) { + // FCEU_PrintError("Cannot open a movie in read+write from an archive."); + // return; + //} + + //LoadFM2(currMovieData, fp->stream, INT_MAX, false); + + + bool loadedfm2 = false; + bool opened = false; +// { + EMUFILE* fp = new EMUFILE_FILE(fname, "rb"); +// if(fs.is_open()) +// { + loadedfm2 = LoadFM2(currMovieData, fp, INT_MAX, false); + opened = true; +// } +// fs.close(); + delete fp; +// } + if(!opened) + { + // for some reason fs.open doesn't work, it has to be a whole new fstream object +// fstream fs (fname, std::ios_base::in); + loadedfm2 = LoadFM2(currMovieData, fp, INT_MAX, false); +// fs.close(); + delete fp; + } + + if(!loadedfm2) + return "failed to load movie"; + + //TODO + //fully reload the game to reinitialize everything before playing any movie + //poweron(true); + + NDS_Reset(); + + ////WE NEED TO LOAD A SAVESTATE + //if(currMovieData.savestate.size() != 0) + //{ + // bool success = MovieData::loadSavestateFrom(&currMovieData.savestate); + // if(!success) return; + //} + lagframecounter=0; + LagFrameFlag=0; + lastLag=0; + TotalLagFrames=0; + + currFrameCounter = 0; + pauseframe = _pauseframe; + movie_readonly = _read_only; + movieMode = MOVIEMODE_PLAY; + currRerecordCount = currMovieData.rerecordCount; + MMU_new.backupDevice.movie_mode(); + if(currMovieData.sram.size() != 0) + { + bool success = MovieData::loadSramFrom(&currMovieData.sram); + if(!success) return "failed to load sram"; + } + freshMovie = true; + ClearAutoHold(); + + if(movie_readonly) + driver->USR_InfoMessage("Replay started Read-Only."); + else + driver->USR_InfoMessage("Replay started Read+Write."); + + return NULL; // success +} + +static void openRecordingMovie(const char* fname) +{ + //osRecordingMovie = FCEUD_UTF8_fstream(fname, "wb"); + osRecordingMovie = new EMUFILE_FILE(fname, "wb"); + /*if(!osRecordingMovie) + FCEU_PrintError("Error opening movie output file: %s",fname);*/ + strcpy(curMovieFilename, fname); +} + +bool MovieData::loadSramFrom(std::vector<u8>* buf) +{ + EMUFILE_MEMORY ms(buf); + MMU_new.backupDevice.load_movie(&ms); + return true; +} + +//static bool FCEUSS_SaveSRAM(EMUFILE* outstream, const std::string& fname) +//{ +// //a temp memory stream. we'll dump some data here and then compress +// //TODO - support dumping directly without compressing to save a buffer copy +////TODO +///* memorystream ms; +// +// //size it +// FILE * fp = fopen( fname.c_str(), "r" ); +// if(!fp) +// return 0; +// +// fseek( fp, 0, SEEK_END ); +// int size = ftell(fp); +// fclose(fp); +// +// filebuf fb; +// fb.open (fname.c_str(), ios::in | ios::binary);//ios::in +// istream is(&fb); +// +// char *buffer = new char[size]; +// +// is.read(buffer, size); +// +// outstream->write((char*)buffer,size); +// +// fb.close(); +//*/ +// +// +// return true; +//} + +//begin recording a new movie +//TODO - BUG - the record-from-another-savestate doesnt work. +void FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, std::string sramfname, const DateTime &rtcstart) +{ + //if(!FCEU_IsValidUI(FCEUI_RECORDMOVIE)) + // return; + + assert(fname); + + FCEUI_StopMovie(); + + openRecordingMovie(fname); + + currFrameCounter = 0; + //LagCounterReset(); + + currMovieData = MovieData(); + currMovieData.guid.newGuid(); + + if(author != L"") currMovieData.comments.push_back(L"author " + author); + currMovieData.romChecksum = gameInfo.crc; + currMovieData.romSerial = gameInfo.ROMserial; + currMovieData.romFilename = path.GetRomName(); + currMovieData.rtcStart = rtcstart; + + NDS_Reset(); + + //todo ? + //poweron(true); + //else + // MovieData::dumpSavestateTo(&currMovieData.savestate,Z_BEST_COMPRESSION); + + if(flag == 1) + EMUFILE::readAllBytes(&currMovieData.sram, sramfname); + + //we are going to go ahead and dump the header. from now on we will only be appending frames + currMovieData.dump(osRecordingMovie, false); + + currFrameCounter=0; + lagframecounter=0; + LagFrameFlag=0; + lastLag=0; + TotalLagFrames=0; + + movieMode = MOVIEMODE_RECORD; + movie_readonly = false; + currRerecordCount = 0; + MMU_new.backupDevice.movie_mode(); + + if(currMovieData.sram.size() != 0) + { + bool success = MovieData::loadSramFrom(&currMovieData.sram); + if(!success) return; + } + + driver->USR_InfoMessage("Movie recording started."); +} + + + //the main interaction point between the emulator and the movie system. + //either dumps the current joystick state or loads one state from the movie. + //deprecated, should use the two functions it has been split into directly + void FCEUMOV_AddInputState() + { + FCEUMOV_HandlePlayback(); + FCEUMOV_HandleRecording(); + } + + void FCEUMOV_HandlePlayback() + { + if(movieMode == MOVIEMODE_PLAY) + { + //stop when we run out of frames + if(currFrameCounter == (int)currMovieData.records.size()) + { + FinishPlayback(); + } + else + { + UserInput& input = NDS_getProcessingUserInput(); + + MovieRecord* mr = &currMovieData.records[currFrameCounter]; + + if(mr->command_microphone()) input.mic.micButtonPressed = 1; + else input.mic.micButtonPressed = 0; + + if(mr->command_reset()) NDS_Reset(); + + if(mr->command_lid()) input.buttons.F = true; + else input.buttons.F = false; + + u16 pad = mr->pad; + input.buttons.R = (((pad>>12)&1)!=0); + input.buttons.L = (((pad>>11)&1)!=0); + input.buttons.D = (((pad>>10)&1)!=0); + input.buttons.U = (((pad>>9)&1)!=0); + input.buttons.T = (((pad>>8)&1)!=0); + input.buttons.S = (((pad>>7)&1)!=0); + input.buttons.B = (((pad>>6)&1)!=0); + input.buttons.A = (((pad>>5)&1)!=0); + input.buttons.Y = (((pad>>4)&1)!=0); + input.buttons.X = (((pad>>3)&1)!=0); + input.buttons.W = (((pad>>2)&1)!=0); + input.buttons.E = (((pad>>1)&1)!=0); + input.buttons.G = (((pad>>0)&1)!=0); + + input.touch.touchX = mr->touch.x << 4; + input.touch.touchY = mr->touch.y << 4; + input.touch.isTouch = mr->touch.touch != 0; + } + + //if we are on the last frame, then pause the emulator if the player requested it + if(currFrameCounter == (int)currMovieData.records.size()-1) + { + /*if(FCEUD_PauseAfterPlayback()) + { + FCEUI_ToggleEmulationPause(); + }*/ + } + + //pause the movie at a specified frame + //if(FCEUMOV_ShouldPause() && FCEUI_EmulationPaused()==0) + //{ + // FCEUI_ToggleEmulationPause(); + // FCEU_DispMessage("Paused at specified movie frame"); + //} + + // it's apparently un-threadsafe to do this here + // (causes crazy flickering in other OSD elements, at least) + // and it's also pretty annoying, + // and the framecounter display already conveys this info as well. + // so, I'm disabling this, at least for now. +// osd->addFixed(180, 176, "%s", "Playback"); + + } + } + + void FCEUMOV_HandleRecording() + { + if(movieMode == MOVIEMODE_RECORD) + { + const UserInput& input = NDS_getFinalUserInput(); + + MovieRecord mr; + + mr.commands = 0; + + if(input.mic.micButtonPressed == 1) + mr.commands = MOVIECMD_MIC; + + mr.pad = nds.pad; + + if(input.buttons.F) + mr.commands = MOVIECMD_LID; + + if(movie_reset_command) { + mr.commands = MOVIECMD_RESET; + movie_reset_command = false; + } + + mr.touch.touch = input.touch.isTouch ? 1 : 0; + mr.touch.x = input.touch.isTouch ? input.touch.touchX >> 4 : 0; + mr.touch.y = input.touch.isTouch ? input.touch.touchY >> 4 : 0; + + assert(mr.touch.touch || (!mr.touch.x && !mr.touch.y)); + //assert(nds.touchX == input.touch.touchX && nds.touchY == input.touch.touchY); + //assert((mr.touch.x << 4) == nds.touchX && (mr.touch.y << 4) == nds.touchY); + + mr.dump(&currMovieData, osRecordingMovie,currMovieData.records.size()); + currMovieData.records.push_back(mr); + + // it's apparently un-threadsafe to do this here + // (causes crazy flickering in other OSD elements, at least) + // and it's also pretty annoying, + // and the framecounter display already conveys this info as well. + // so, I'm disabling this, at least for now. +// osd->addFixed(180, 176, "%s", "Recording"); + } + + /*extern uint8 joy[4]; + memcpy(&cur_input_display,joy,4);*/ + } + + +//TODO +static void FCEUMOV_AddCommand(int cmd) +{ + // do nothing if not recording a movie + if(movieMode != MOVIEMODE_RECORD) + return; + + //printf("%d\n",cmd); + + //MBG TODO BIG TODO TODO TODO + //DoEncode((cmd>>3)&0x3,cmd&0x7,1); +} + +//little endian 4-byte cookies +static const int kMOVI = 0x49564F4D; +static const int kNOMO = 0x4F4D4F4E; + +void mov_savestate(EMUFILE* fp) +{ + //we are supposed to dump the movie data into the savestate + //if(movieMode == MOVIEMODE_RECORD || movieMode == MOVIEMODE_PLAY) + // return currMovieData.dump(os, true); + //else return 0; + if(movieMode != MOVIEMODE_INACTIVE) + { + write32le(kMOVI,fp); + currMovieData.dump(fp, true); + } + else + { + write32le(kNOMO,fp); + } +} + + +bool CheckTimelines(MovieData& stateMovie, MovieData& currMovie, int& errorFr) +{ + bool isInTimeline = true; + int length; + + //First check, make sure we are checking is for a post-movie savestate, we just want to adjust the length for now, we will handle this situation later in another function + if (currFrameCounter <= stateMovie.getNumRecords()) + length = currFrameCounter; //Note: currFrameCounter corresponds to the framecounter in the savestate + else if (currFrameCounter > currMovie.getNumRecords()) //Now that we know the length of the records of the savestate we plan to load, let's match the length against the movie + length = currMovie.getNumRecords(); //If length < currMovie records then this is a "future" event from the current movie, againt we will handle this situation later, we just want to find the right number of frames to compare + else + length = stateMovie.getNumRecords(); + + for (int x = 0; x < length; x++) + { + if (!stateMovie.records[x].Compare(currMovie.records[x])) + { + isInTimeline = false; + errorFr = x; + break; + } + } + + return isInTimeline; +} + + +static bool load_successful; + +bool mov_loadstate(EMUFILE* fp, int size) +{ + load_successful = false; + + u32 cookie; + if(read32le(&cookie,fp) != 1) return false; + if(cookie == kNOMO) + { + if(movieMode == MOVIEMODE_RECORD || movieMode == MOVIEMODE_PLAY) + FinishPlayback(); + return true; + } + else if(cookie != kMOVI) + return false; + + size -= 4; + + if (!movie_readonly && autoMovieBackup && freshMovie) //If auto-backup is on, movie has not been altered this session and the movie is in read+write mode + { + FCEUI_MakeBackupMovie(false); //Backup the movie before the contents get altered, but do not display messages + } + + //a little rule: cant load states in read+write mode with a movie from an archive. + //so we are going to switch it to readonly mode in that case +// if(!movie_readonly +// //*&& FCEU_isFileInArchive(curMovieFilename)*/ +// ) { +// FCEU_PrintError("Cannot loadstate in Read+Write with movie from archive. Movie is now Read-Only."); +// movie_readonly = true; +// } + + MovieData tempMovieData = MovieData(); + //int curr = fp->ftell(); + if(!LoadFM2(tempMovieData, fp, size, false)) { + + // is->seekg((uint32)curr+size); + /* extern bool FCEU_state_loading_old_format; + if(FCEU_state_loading_old_format) { + if(movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_RECORD) { + FCEUI_StopMovie(); + FCEU_PrintError("You have tried to use an old savestate while playing a movie. This is unsupported (since the old savestate has old-format movie data in it which can't be converted on the fly)"); + } + }*/ + return false; + } + + //---------------- + //complex TAS logic for loadstate + //fully conforms to the savestate logic documented in the Laws of TAS + //http://tasvideos.org/LawsOfTAS/OnSavestates.html + //---------------- + + /* + Playback or Recording + Read-only + + * Check that GUID of movie and savestate-movie must match or else error + o on error: a message informing that the savestate doesn't belong to this movie. This is a GUID mismatch error. Give user a choice to load it anyway. + + failstate: if use declines, loadstate attempt canceled, movie can resume as if not attempted if user has backup savstates enabled else stop movie + * Check that movie and savestate-movie are in same timeline. If not then this is a wrong timeline error. + o on error: a message informing that the savestate doesn't belong to this movie + + failstate: loadstate attempt canceled, movie can resume as if not attempted if user has backup savestates enabled else stop movie + * Check that savestate-movie is not greater than movie. If not then this is a future event error and is not allowed in read-only + o on error: message informing that the savestate is from a frame after the last frame of the movie + + failstate - loadstate attempt cancelled, movie can resume if user has backup savesattes enabled, else stop movie + * Check that savestate framcount <= savestate movie length. If not this is a post-movie savestate + o on post-movie: See post-movie event section. + * All error checks have passed, state will be loaded + * Movie contained in the savestate will be discarded + * Movie is now in Playback mode + + Playback, Recording + Read+write + + * Check that GUID of movie and savestate-movie must match or else error + o on error: a message informing that the savestate doesn't belong to this movie. This is a GUID mismatch error. Give user a choice to load it anyway. + + failstate: if use declines, loadstate attempt canceled, movie can resume as if not attempted (stop movie if resume fails)canceled, movie can resume if backup savestates enabled else stopmovie + * Check that savestate framcount <= savestate movie length. If not this is a post-movie savestate + o on post-movie: See post-movie event section. + * savestate passed all error checks and will now be loaded in its entirety and replace movie (note: there will be no truncation yet) + * current framecount will be set to savestate framecount + * on the next frame of input, movie will be truncated to framecount + o (note: savestate-movie can be a future event of the movie timeline, or a completely new timeline and it is still allowed) + * Rerecord count of movie will be incremented + * Movie is now in record mode + + Post-movie savestate event + + * Whan a savestate is loaded and is determined that the savestate-movie length is less than the savestate framecount then it is a post-movie savestate. These occur when a savestate was made during Movie Finished mode. + * If read+write, the entire savestate movie will be loaded and replace current movie. + * If read-only, the savestate movie will be discarded + * Mode will be switched to Move Finished + * Savestate will be loaded + * Current framecount changes to savestate framecount + * User will have control of input as if Movie inactive mode + */ + + + if(movieMode != MOVIEMODE_INACTIVE) + { + //handle moviefile mismatch + if(tempMovieData.guid != currMovieData.guid) + { + //mbg 8/18/08 - this code can be used to turn the error message into an OK/CANCEL + #if defined(WIN32) && !defined(WXPORT) + std::string msg = "There is a mismatch between savestate's movie and current movie.\ncurrent: " + currMovieData.guid.toString() + "\nsavestate: " + tempMovieData.guid.toString() + "\n\nThis means that you have loaded a savestate belonging to a different movie than the one you are playing now.\n\nContinue loading this savestate anyway?"; + int result = MessageBox(MainWindow->getHWnd(),msg.c_str(),"Error loading savestate",MB_OKCANCEL); + if(result == IDCANCEL) + return false; + #else + FCEU_PrintError("Mismatch between savestate's movie and current movie.\ncurrent: %s\nsavestate: %s\n",currMovieData.guid.toString().c_str(),tempMovieData.guid.toString().c_str()); + return false; + #endif + } + + closeRecordingMovie(); + + if(!movie_readonly) + { + currMovieData = tempMovieData; + currMovieData.rerecordCount = currRerecordCount; + } + + if(currFrameCounter > (int)currMovieData.records.size()) + { + // if the frame counter is longer than our current movie, + // switch to "finished" mode. + // this is a mode that behaves like "inactive" + // except it permits switching to play/record by loading an earlier savestate. + // (and we continue to store the finished movie in savestates made while finished) + osd->setLineColor(255,0,0); // let's make the text red too to hopefully catch the user's attention a bit. + FinishPlayback(); + osd->setLineColor(255,255,255); + + //FCEU_PrintError("Savestate is from a frame (%d) after the final frame in the movie (%d). This is not permitted.", currFrameCounter, currMovieData.records.size()-1); + //return false; + } + else if(movie_readonly) + { + //------------------------------------------------------------- + //this code would reload the movie from disk. allegedly it is helpful to hexers, but + //it is way too slow with dsm format. so it is only here as a reminder, and in case someone + //wants to play with it + //------------------------------------------------------------- + //{ + // fstream fs (curMovieFilename); + // if(!LoadFM2(tempMovieData, &fs, INT_MAX, false)) + // { + // FCEU_PrintError("Failed to reload DSM after loading savestate"); + // } + // fs.close(); + // currMovieData = tempMovieData; + //} + //------------------------------------------------------------- + + movieMode = MOVIEMODE_PLAY; + } + else + { + // #ifdef _S9XLUA_H + // if(!FCEU_LuaRerecordCountSkip()) + currRerecordCount++; + // #endif + + currMovieData.rerecordCount = currRerecordCount; + currMovieData.truncateAt(currFrameCounter); + + openRecordingMovie(curMovieFilename); + if(!osRecordingMovie) + { + osd->setLineColor(255, 0, 0); + osd->addLine("Can't save movie file!"); + } + + //printf("DUMPING MOVIE: %d FRAMES\n",currMovieData.records.size()); + currMovieData.dump(osRecordingMovie, false); + movieMode = MOVIEMODE_RECORD; + } + } + + load_successful = true; + freshMovie = false; + + return true; +} + +static void FCEUMOV_PreLoad(void) +{ + load_successful=0; +} + +static bool FCEUMOV_PostLoad(void) +{ + if(movieMode == MOVIEMODE_INACTIVE) + return true; + else + return load_successful; +} + + +bool FCEUI_MovieGetInfo(EMUFILE* fp, MOVIE_INFO& info, bool skipFrameCount) +{ + //MovieData md; + //if(!LoadFM2(md, fp, INT_MAX, skipFrameCount)) + // return false; + // + //info.movie_version = md.version; + //info.poweron = md.savestate.size()==0; + //info.pal = md.palFlag; + //info.nosynchack = true; + //info.num_frames = md.records.size(); + //info.md5_of_rom_used = md.romChecksum; + //info.emu_version_used = md.emuVersion; + //info.name_of_rom_used = md.romFilename; + //info.rerecord_count = md.rerecordCount; + //info.comments = md.comments; + + return true; +} + +bool MovieRecord::parseBinary(MovieData* md, EMUFILE* fp) +{ + commands=fp->fgetc(); + fp->fread((char *) &pad, sizeof pad); + fp->fread((char *) &touch.x, sizeof touch.x); + fp->fread((char *) &touch.y, sizeof touch.y); + fp->fread((char *) &touch.touch, sizeof touch.touch); + return true; +} + + +void MovieRecord::dumpBinary(MovieData* md, EMUFILE* fp, int index) +{ + fp->fputc(md->records[index].commands); + fp->fwrite((char *) &md->records[index].pad, sizeof md->records[index].pad); + fp->fwrite((char *) &md->records[index].touch.x, sizeof md->records[index].touch.x); + fp->fwrite((char *) &md->records[index].touch.y, sizeof md->records[index].touch.y); + fp->fwrite((char *) &md->records[index].touch.touch, sizeof md->records[index].touch.touch); +} + +void LoadFM2_binarychunk(MovieData& movieData, EMUFILE* fp, int size) +{ + int recordsize = 1; //1 for the command + + recordsize = 6; + + assert(size%6==0); + + //find out how much remains in the file + int curr = fp->ftell(); + fp->fseek(0,SEEK_END); + int end = fp->ftell(); + int flen = end-curr; + fp->fseek(curr,SEEK_SET); + + //the amount todo is the min of the limiting size we received and the remaining contents of the file + int todo = std::min(size, flen); + + int numRecords = todo/recordsize; + //printf("LOADED MOVIE: %d records; currFrameCounter: %d\n",numRecords,currFrameCounter); + movieData.records.resize(numRecords); + for(int i=0;i<numRecords;i++) + { + movieData.records[i].parseBinary(&movieData,fp); + } +} + +#include <sstream> + +static bool CheckFileExists(const char* filename) +{ + //This function simply checks to see if the given filename exists + string checkFilename; + + if (filename) + checkFilename = filename; + + //Check if this filename exists + FILE* fp = fopen(checkFilename.c_str(), "rb"); + + if (!fp) + { + return false; + } + else + { + fclose(fp); + return true; + } +} + +void FCEUI_MakeBackupMovie(bool dispMessage) +{ + //This function generates backup movie files + string currentFn; //Current movie fillename + string backupFn; //Target backup filename + string tempFn; //temp used in back filename creation + stringstream stream; + int x; //Temp variable for string manip + bool exist = false; //Used to test if filename exists + bool overflow = false; //Used for special situation when backup numbering exceeds limit + + currentFn = curMovieFilename; //Get current moviefilename + backupFn = curMovieFilename; //Make backup filename the same as current moviefilename + x = backupFn.find_last_of("."); //Find file extension + backupFn = backupFn.substr(0,x); //Remove extension + tempFn = backupFn; //Store the filename at this point + for (unsigned int backNum=0;backNum<999;backNum++) //999 = arbituary limit to backup files + { + stream.str(""); //Clear stream + if (backNum > 99) + stream << "-" << backNum; //assign backNum to stream + else if (backNum <= 99 && backNum >= 10) + stream << "-0" << backNum; //Make it 010, etc if two digits + else + stream << "-00" << backNum; //Make it 001, etc if single digit + backupFn.append(stream.str()); //add number to bak filename + backupFn.append(".bak"); //add extension + + exist = CheckFileExists(backupFn.c_str()); //Check if file exists + + if (!exist) + break; //Yeah yeah, I should use a do loop or something + else + { + backupFn = tempFn; //Before we loop again, reset the filename + + if (backNum == 999) //If 999 exists, we have overflowed, let's handle that + { + backupFn.append("-001.bak"); //We are going to simply overwrite 001.bak + overflow = true; //Flag that we have exceeded limit + break; //Just in case + } + } + } + + MovieData md = currMovieData; //Get current movie data + EMUFILE* outf = new EMUFILE_FILE(backupFn.c_str(),"wb"); //FCEUD_UTF8_fstream(backupFn, "wb"); //open/create file + md.dump(outf,false); //dump movie data + delete outf; //clean up, delete file object + + //TODO, decide if fstream successfully opened the file and print error message if it doesn't + + if (dispMessage) //If we should inform the user + { +// if (overflow) +// FCEUI_DispMessage("Backup overflow, overwriting %s",backupFn.c_str()); //Inform user of overflow +// else +// FCEUI_DispMessage("%s created",backupFn.c_str()); //Inform user of backup filename + } +} + diff --git a/jni/desmume/src/movie.h b/jni/desmume/src/movie.h new file mode 100755 index 0000000..c5ddd6a --- /dev/null +++ b/jni/desmume/src/movie.h @@ -0,0 +1,235 @@ +/* + Copyright 2008-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __MOVIE_H_ +#define __MOVIE_H_ + +#include <vector> +#include <map> +#include <string> +#include <stdlib.h> +#include <time.h> +#include "emufile.h" + +#include "utils/datetime.h" +#include "utils/guid.h" +#include "utils/md5.h" + +#ifdef ANDROID +#include "utils/xstring.h" +#endif + +typedef struct +{ + int movie_version; // version of the movie format in the file + u32 num_frames; + u32 rerecord_count; + bool poweron; + u32 emu_version_used; + MD5DATA md5_of_rom_used; + std::string name_of_rom_used; + + std::vector<std::wstring> comments; + std::vector<std::string> subtitles; +} MOVIE_INFO; + +enum EMOVIEMODE +{ + MOVIEMODE_INACTIVE = 0, + MOVIEMODE_RECORD = 1, + MOVIEMODE_PLAY = 2, + MOVIEMODE_FINISHED = 3, +}; + +enum EMOVIECMD +{ + MOVIECMD_MIC = 1, + MOVIECMD_RESET = 2, + MOVIECMD_LID = 4, +}; + +//RLDUTSBAYXWEG + +class MovieData; +class MovieRecord +{ + +public: + u16 pad; + + union { + struct { + u8 x, y; + u8 touch; + }; + + u32 padding; + } touch; + + //misc commands like reset, etc. + //small now to save space; we might need to support more commands later. + //the disk format will support up to 64bit if necessary + uint8 commands; + bool command_reset() { return (commands&MOVIECMD_RESET)!=0; } + bool command_microphone() { return (commands&MOVIECMD_MIC)!=0; } + bool command_lid() { return (commands&MOVIECMD_LID)!=0; } + + void toggleBit(int bit) + { + pad ^= mask(bit); + } + + void setBit(int bit) + { + pad |= mask(bit); + } + + void clearBit(int bit) + { + pad &= ~mask(bit); + } + + void setBitValue(int bit, bool val) + { + if(val) setBit(bit); + else clearBit(bit); + } + + bool checkBit(int bit) + { + return (pad & mask(bit))!=0; + } + + bool Compare(MovieRecord& compareRec); + void clear(); + + void parse(MovieData* md, EMUFILE* fp); + bool parseBinary(MovieData* md, EMUFILE* fp); + void dump(MovieData* md, EMUFILE* fp, int index); + void dumpBinary(MovieData* md, EMUFILE* fp, int index); + void parsePad(EMUFILE* fp, u16& pad); + void dumpPad(EMUFILE* fp, u16 pad); + + static const char mnemonics[13]; + +private: + int mask(int bit) { return 1<<bit; } +}; + + +class MovieData +{ +public: + MovieData(); + + + int version; + int emuVersion; + //todo - somehow force mutual exclusion for poweron and reset (with an error in the parser) + + u32 romChecksum; + std::string romSerial; + std::string romFilename; + std::vector<u8> savestate; + std::vector<u8> sram; + std::vector<MovieRecord> records; + std::vector<std::wstring> comments; + + int rerecordCount; + Desmume_Guid guid; + + DateTime rtcStart; + + //was the frame data stored in binary? + bool binaryFlag; + + int getNumRecords() { return records.size(); } + + class TDictionary : public std::map<std::string,std::string> + { + public: + bool containsKey(std::string key) + { + return find(key) != end(); + } + + void tryInstallBool(std::string key, bool& val) + { + if(containsKey(key)) + val = atoi(operator [](key).c_str())!=0; + } + + void tryInstallString(std::string key, std::string& val) + { + if(containsKey(key)) + val = operator [](key); + } + + void tryInstallInt(std::string key, int& val) + { + if(containsKey(key)) + val = atoi(operator [](key).c_str()); + } + + }; + + void truncateAt(int frame); + void installValue(std::string& key, std::string& val); + int dump(EMUFILE* fp, bool binary); + void clearRecordRange(int start, int len); + void insertEmpty(int at, int frames); + + static bool loadSavestateFrom(std::vector<u8>* buf); + static void dumpSavestateTo(std::vector<u8>* buf, int compressionLevel); + + static bool loadSramFrom(std::vector<u8>* buf); + //void TryDumpIncremental(); + +private: + void installInt(std::string& val, int& var) + { + var = atoi(val.c_str()); + } + + void installBool(std::string& val, bool& var) + { + var = atoi(val.c_str())!=0; + } +}; + +extern int currFrameCounter; +extern EMOVIEMODE movieMode; //adelikat: main needs this for frame counter display +extern MovieData currMovieData; //adelikat: main needs this for frame counter display + +extern bool movie_reset_command; + +bool FCEUI_MovieGetInfo(EMUFILE* fp, MOVIE_INFO& info, bool skipFrameCount); +void FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, std::string sramfname, const DateTime &rtcstart); +const char* _CDECL_ FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _pauseframe); // returns NULL on success, errmsg on failure +void FCEUI_StopMovie(); +void FCEUMOV_AddInputState(); +void FCEUMOV_HandlePlayback(); +void FCEUMOV_HandleRecording(); +void mov_savestate(EMUFILE* fp); +bool mov_loadstate(EMUFILE* fp, int size); +void LoadFM2_binarychunk(MovieData& movieData, EMUFILE* fp, int size); +bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader); +extern bool movie_readonly; +extern bool ShowInputDisplay; +void FCEUI_MakeBackupMovie(bool dispMessage); +DateTime FCEUI_MovieGetRTCDefault(); +#endif diff --git a/jni/desmume/src/movie_r7b.cpp b/jni/desmume/src/movie_r7b.cpp new file mode 100755 index 0000000..86873c1 --- /dev/null +++ b/jni/desmume/src/movie_r7b.cpp @@ -0,0 +1,1250 @@ +/* + Copyright 2008-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#define WIN32_LEAN_AND_MEAN +#include <assert.h> +#include <limits.h> +#include <ctype.h> +#include <time.h> +#include "utils/guid.h" +#include "utils/xstring.h" +#include "utils/datetime.h" +#include "movie.h" +#include "NDSSystem.h" +#include "readwrite.h" +#include "debug.h" +#include "rtc.h" +#include "common.h" +#include "mic.h" +#include "version.h" +#include "GPU_osd.h" +#include "path.h" +#include "emufile.h" + +using namespace std; +bool freshMovie = false; //True when a movie loads, false when movie is altered. Used to determine if a movie has been altered since opening +bool autoMovieBackup = true; + +#define FCEU_PrintError LOG + +#define MOVIE_VERSION 1 + +#ifdef WIN32 +#include ".\windows\main.h" +#endif + +//----movie engine main state + +EMOVIEMODE movieMode = MOVIEMODE_INACTIVE; + +//this should not be set unless we are in MOVIEMODE_RECORD! +EMUFILE* osRecordingMovie = 0; + +int currFrameCounter; +uint32 cur_input_display = 0; +int pauseframe = -1; +bool movie_readonly = true; + +char curMovieFilename[512] = {0}; +MovieData currMovieData; +int currRerecordCount; +bool movie_reset_command = false; +//-------------- + + +void MovieData::clearRecordRange(int start, int len) +{ + for(int i=0;i<len;i++) + records[i+start].clear(); +} + +void MovieData::insertEmpty(int at, int frames) +{ + if(at == -1) + { + int currcount = records.size(); + records.resize(records.size()+frames); + clearRecordRange(currcount,frames); + } + else + { + records.insert(records.begin()+at,frames,MovieRecord()); + clearRecordRange(at,frames); + } +} + + + +void MovieRecord::clear() +{ + pad = 0; + commands = 0; + touch.padding = 0; +} + + +bool MovieRecord::Compare(MovieRecord& compareRec) +{ + //Check pad + if (this->pad != compareRec.pad) + return false; + + //Check Stylus + if (this->touch.padding != compareRec.touch.padding) return false; + if (this->touch.touch != compareRec.touch.touch) return false; + if (this->touch.x != compareRec.touch.x) return false; + if (this->touch.y != compareRec.touch.y) return false; + + //Check comamnds + //if new commands are ever recordable, they need to be added here if we go with this method + if(this->command_reset() != compareRec.command_reset()) return false; + if(this->command_microphone() != compareRec.command_microphone()) return false; + if(this->command_lid() != compareRec.command_lid()) return false; + + return true; +} + +const char MovieRecord::mnemonics[13] = {'R','L','D','U','T','S','B','A','Y','X','W','E','G'}; +void MovieRecord::dumpPad(EMUFILE* fp, u16 pad) +{ + //these are mnemonics for each joystick bit. + //since we usually use the regular joypad, these will be more helpful. + //but any character other than ' ' or '.' should count as a set bit + //maybe other input types will need to be encoded another way.. + for(int bit=0;bit<13;bit++) + { + int bitmask = (1<<(12-bit)); + char mnemonic = mnemonics[bit]; + //if the bit is set write the mnemonic + if(pad & bitmask) + fp->fputc(mnemonic); + else //otherwise write an unset bit + fp->fputc('.'); + } +} + + +void MovieRecord::parsePad(EMUFILE* fp, u16& pad) +{ + + char buf[13]; + fp->fread(buf,13); + pad = 0; + for(int i=0;i<13;i++) + { + pad <<= 1; + pad |= ((buf[i]=='.'||buf[i]==' ')?0:1); + } +} + + +void MovieRecord::parse(MovieData* md, EMUFILE* fp) +{ + //by the time we get in here, the initial pipe has already been extracted + + //extract the commands + commands = u32DecFromIstream(fp); + + fp->fgetc(); //eat the pipe + + parsePad(fp, pad); + touch.x = u32DecFromIstream(fp); + touch.y = u32DecFromIstream(fp); + touch.touch = u32DecFromIstream(fp); + + fp->fgetc(); //eat the pipe + + //should be left at a newline +} + + +void MovieRecord::dump(MovieData* md, EMUFILE* fp, int index) +{ + //dump the misc commands + //*os << '|' << setw(1) << (int)commands; + fp->fputc('|'); + putdec<uint8,1,true>(fp,commands); + + fp->fputc('|'); + dumpPad(fp, pad); + putdec<u8,3,true>(fp,touch.x); fp->fputc(' '); + putdec<u8,3,true>(fp,touch.y); fp->fputc(' '); + putdec<u8,1,true>(fp,touch.touch); + fp->fputc('|'); + + //each frame is on a new line + fp->fputc('\n'); +} + +DateTime FCEUI_MovieGetRTCDefault() +{ + // compatible with old desmume + return DateTime(2009,1,1,0,0,0); +} + +MovieData::MovieData() + : version(MOVIE_VERSION) + , emuVersion(EMU_DESMUME_VERSION_NUMERIC()) + , romChecksum(0) + , rerecordCount(0) + , binaryFlag(false) + , rtcStart(FCEUI_MovieGetRTCDefault()) +{ +} + +void MovieData::truncateAt(int frame) +{ + if((int)records.size() > frame) + records.resize(frame); +} + + +void MovieData::installValue(std::string& key, std::string& val) +{ + //todo - use another config system, or drive this from a little data structure. because this is gross + if(key == "version") + installInt(val,version); + else if(key == "emuVersion") + installInt(val,emuVersion); + else if(key == "rerecordCount") + installInt(val,rerecordCount); + else if(key == "romFilename") + romFilename = val; + else if(key == "romChecksum") + StringToBytes(val,&romChecksum,MD5DATA::size); + else if(key == "romSerial") + romSerial = val; + else if(key == "guid") + guid = Desmume_Guid::fromString(val); + else if(key == "rtcStart") { + // sloppy format check and parse + const char *validFormatStr = "####-##-##T##:##:##Z"; + bool validFormat = true; + for (int i = 0; validFormatStr[i] != '\0'; i++) { + if (validFormatStr[i] != val[i] && + !(validFormatStr[i] == '#' && isdigit(val[i]))) { + validFormat = false; + break; + } + } + if (validFormat) { + struct tm t; + const char *s = val.data(); + int year = atoi(&s[0]); + int mon = atoi(&s[5]); + int day = atoi(&s[8]); + int hour = atoi(&s[11]); + int min = atoi(&s[14]); + int sec = atoi(&s[17]); + rtcStart = DateTime(year,mon,day,hour,min,sec); + } + } + else if(key == "rtcStartNew") { + DateTime::TryParse(val.c_str(),rtcStart); + } + else if(key == "comment") + comments.push_back(mbstowcs(val)); + else if(key == "binary") + installBool(val,binaryFlag); + else if(key == "savestate") + { + int len = Base64StringToBytesLength(val); + if(len == -1) len = HexStringToBytesLength(val); // wasn't base64, try hex + if(len >= 1) + { + savestate.resize(len); + StringToBytes(val,&savestate[0],len); // decodes either base64 or hex + } + } + else if(key == "sram") + { + int len = Base64StringToBytesLength(val); + if(len == -1) len = HexStringToBytesLength(val); // wasn't base64, try hex + if(len >= 1) + { + sram.resize(len); + StringToBytes(val,&sram[0],len); // decodes either base64 or hex + } + } +} + + +int MovieData::dump(EMUFILE* fp, bool binary) +{ + int start = fp->ftell(); + fp->fprintf("version %d\n", version); + fp->fprintf("emuVersion %d\n", emuVersion); + fp->fprintf("rerecordCount %d\n", rerecordCount); + + fp->fprintf("romFilename %s\n", romFilename.c_str()); + fp->fprintf("romChecksum %s\n", u32ToHexString(gameInfo.crc).c_str()); + fp->fprintf("romSerial %s\n", romSerial.c_str()); + fp->fprintf("guid %s\n", guid.toString().c_str()); + fp->fprintf("useExtBios %d\n", CommonSettings.UseExtBIOS?1:0); + fp->fprintf("advancedTiming %d\n", CommonSettings.advanced_timing?1:0); + + if(CommonSettings.UseExtBIOS) + fp->fprintf("swiFromBios %d\n", CommonSettings.SWIFromBIOS?1:0); + + fp->fprintf("useExtFirmware %d\n", CommonSettings.UseExtFirmware?1:0); + + if(CommonSettings.UseExtFirmware) { + fp->fprintf("bootFromFirmware %d\n", CommonSettings.BootFromFirmware?1:0); + } + else { + char temp_str[27]; + int i; + + /* FIXME: harshly only use the lower byte of the UTF-16 character. + * This would cause strange behaviour if the user could set UTF-16 but + * they cannot yet. + */ + for (i = 0; i < CommonSettings.InternalFirmConf.nickname_len; i++) { + temp_str[i] = CommonSettings.InternalFirmConf.nickname[i]; + } + temp_str[i] = '\0'; + fp->fprintf("firmNickname %s\n", temp_str); + for (i = 0; i < CommonSettings.InternalFirmConf.message_len; i++) { + temp_str[i] = CommonSettings.InternalFirmConf.message[i]; + } + temp_str[i] = '\0'; + fp->fprintf("firmMessage %s\n", temp_str); + fp->fprintf("firmFavColour %d\n", CommonSettings.InternalFirmConf.fav_colour); + fp->fprintf("firmBirthMonth %d\n", CommonSettings.InternalFirmConf.birth_month); + fp->fprintf("firmBirthDay %d\n", CommonSettings.InternalFirmConf.birth_day); + fp->fprintf("firmLanguage %d\n", CommonSettings.InternalFirmConf.language); + } + + fp->fprintf("rtcStartNew %s\n", rtcStart.ToString().c_str()); + + for(uint32 i=0;i<comments.size();i++) + fp->fprintf("comment %s\n", wcstombs(comments[i]).c_str()); + + if(binary) + fp->fprintf("binary 1\n"); + + if(savestate.size() != 0) + fp->fprintf("savestate %s\n", BytesToString(&savestate[0],savestate.size()).c_str()); + if(sram.size() != 0) + fp->fprintf("sram %s\n", BytesToString(&sram[0],sram.size()).c_str()); + + if(binary) + { + //put one | to start the binary dump + fp->fputc('|'); + for(int i=0;i<(int)records.size();i++) + records[i].dumpBinary(this,fp,i); + } + else + for(int i=0;i<(int)records.size();i++) + records[i].dump(this,fp,i); + + int end = fp->ftell(); + return end-start; +} + +//yuck... another custom text parser. +bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader) +{ + //TODO - start with something different. like 'desmume movie version 1" + int curr = fp->ftell(); + + //movie must start with "version 1" + char buf[9]; + curr = fp->ftell(); + fp->fread(buf,9); + fp->fseek(curr, SEEK_SET); +// if(fp->fail()) return false; + if(memcmp(buf,"version 1",9)) + return false; + + std::string key,value; + enum { + NEWLINE, KEY, SEPARATOR, VALUE, RECORD, COMMENT + } state = NEWLINE; + bool bail = false; + for(;;) + { + bool iswhitespace, isrecchar, isnewline; + int c; + if(size--<=0) goto bail; + c = fp->fgetc(); + if(c == -1) + goto bail; + iswhitespace = (c==' '||c=='\t'); + isrecchar = (c=='|'); + isnewline = (c==10||c==13); + if(isrecchar && movieData.binaryFlag && !stopAfterHeader) + { + LoadFM2_binarychunk(movieData, fp, size); + return true; + } + switch(state) + { + case NEWLINE: + if(isnewline) goto done; + if(iswhitespace) goto done; + if(isrecchar) + goto dorecord; + //must be a key + key = ""; + value = ""; + goto dokey; + break; + case RECORD: + { + dorecord: + if (stopAfterHeader) return true; + int currcount = movieData.records.size(); + movieData.records.resize(currcount+1); + int preparse = fp->ftell(); + movieData.records[currcount].parse(&movieData, fp); + int postparse = fp->ftell(); + size -= (postparse-preparse); + state = NEWLINE; + break; + } + + case KEY: + dokey: //dookie + state = KEY; + if(iswhitespace) goto doseparator; + if(isnewline) goto commit; + key += c; + break; + case SEPARATOR: + doseparator: + state = SEPARATOR; + if(isnewline) goto commit; + if(!iswhitespace) goto dovalue; + break; + case VALUE: + dovalue: + state = VALUE; + if(isnewline) goto commit; + value += c; + break; + case COMMENT: + default: + break; + } + goto done; + + bail: + bail = true; + if(state == VALUE) goto commit; + goto done; + commit: + movieData.installValue(key,value); + state = NEWLINE; + done: ; + if(bail) break; + } + + return true; +} + + +static void closeRecordingMovie() +{ + if(osRecordingMovie) + { + delete osRecordingMovie; + osRecordingMovie = 0; + } +} + +/// Stop movie playback. +static void StopPlayback() +{ + driver->USR_InfoMessage("Movie playback stopped."); + movieMode = MOVIEMODE_INACTIVE; +} + +/// Stop movie playback without closing the movie. +static void FinishPlayback() +{ + driver->USR_InfoMessage("Movie finished playing."); + movieMode = MOVIEMODE_FINISHED; +} + + +/// Stop movie recording +static void StopRecording() +{ + driver->USR_InfoMessage("Movie recording stopped."); + movieMode = MOVIEMODE_INACTIVE; + + closeRecordingMovie(); +} + + + +void FCEUI_StopMovie() +{ + if(movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_FINISHED) + StopPlayback(); + else if(movieMode == MOVIEMODE_RECORD) + StopRecording(); + + curMovieFilename[0] = 0; + freshMovie = false; +} + + +//begin playing an existing movie +const char* _CDECL_ FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _pauseframe) +{ + //if(!tasedit && !FCEU_IsValidUI(FCEUI_PLAYMOVIE)) + // return; + + // FIXME: name==null indicates to BROWSE to retrieve fname from user (or stdin if that's impossible), + // when called from movie_play + assert(fname); + if(!fname) + return "LoadMovie doesn't support browsing yet"; + + //mbg 6/10/08 - we used to call StopMovie here, but that cleared curMovieFilename and gave us crashes... + if(movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_FINISHED) + StopPlayback(); + else if(movieMode == MOVIEMODE_RECORD) + StopRecording(); + //-------------- + + currMovieData = MovieData(); + + strcpy(curMovieFilename, fname); + //FCEUFILE *fp = FCEU_fopen(fname,0,"rb",0); + //if (!fp) return; + //if(fp->isArchive() && !_read_only) { + // FCEU_PrintError("Cannot open a movie in read+write from an archive."); + // return; + //} + + //LoadFM2(currMovieData, fp->stream, INT_MAX, false); + + + bool loadedfm2 = false; + bool opened = false; +// { + EMUFILE* fp = new EMUFILE_FILE(fname, "rb"); +// if(fs.is_open()) +// { + loadedfm2 = LoadFM2(currMovieData, fp, INT_MAX, false); + opened = true; +// } +// fs.close(); + delete fp; +// } + if(!opened) + { + // for some reason fs.open doesn't work, it has to be a whole new fstream object +// fstream fs (fname, std::ios_base::in); + loadedfm2 = LoadFM2(currMovieData, fp, INT_MAX, false); +// fs.close(); + delete fp; + } + + if(!loadedfm2) + return "failed to load movie"; + + //TODO + //fully reload the game to reinitialize everything before playing any movie + //poweron(true); + + NDS_Reset(); + + ////WE NEED TO LOAD A SAVESTATE + //if(currMovieData.savestate.size() != 0) + //{ + // bool success = MovieData::loadSavestateFrom(&currMovieData.savestate); + // if(!success) return; + //} + lagframecounter=0; + LagFrameFlag=0; + lastLag=0; + TotalLagFrames=0; + + currFrameCounter = 0; + pauseframe = _pauseframe; + movie_readonly = _read_only; + movieMode = MOVIEMODE_PLAY; + currRerecordCount = currMovieData.rerecordCount; + MMU_new.backupDevice.movie_mode(); + if(currMovieData.sram.size() != 0) + { + bool success = MovieData::loadSramFrom(&currMovieData.sram); + if(!success) return "failed to load sram"; + } + freshMovie = true; + ClearAutoHold(); + + if(movie_readonly) + driver->USR_InfoMessage("Replay started Read-Only."); + else + driver->USR_InfoMessage("Replay started Read+Write."); + + return NULL; // success +} + +static void openRecordingMovie(const char* fname) +{ + //osRecordingMovie = FCEUD_UTF8_fstream(fname, "wb"); + osRecordingMovie = new EMUFILE_FILE(fname, "wb"); + /*if(!osRecordingMovie) + FCEU_PrintError("Error opening movie output file: %s",fname);*/ + strcpy(curMovieFilename, fname); +} + +bool MovieData::loadSramFrom(std::vector<u8>* buf) +{ + EMUFILE_MEMORY ms(buf); + MMU_new.backupDevice.load_movie(&ms); + return true; +} + +//static bool FCEUSS_SaveSRAM(EMUFILE* outstream, const std::string& fname) +//{ +// //a temp memory stream. we'll dump some data here and then compress +// //TODO - support dumping directly without compressing to save a buffer copy +////TODO +///* memorystream ms; +// +// //size it +// FILE * fp = fopen( fname.c_str(), "r" ); +// if(!fp) +// return 0; +// +// fseek( fp, 0, SEEK_END ); +// int size = ftell(fp); +// fclose(fp); +// +// filebuf fb; +// fb.open (fname.c_str(), ios::in | ios::binary);//ios::in +// istream is(&fb); +// +// char *buffer = new char[size]; +// +// is.read(buffer, size); +// +// outstream->write((char*)buffer,size); +// +// fb.close(); +//*/ +// +// +// return true; +//} + +//begin recording a new movie +//TODO - BUG - the record-from-another-savestate doesnt work. +void FCEUI_SaveMovie(const char *fname, std::wstring author, int flag, std::string sramfname, const DateTime &rtcstart) +{ + //if(!FCEU_IsValidUI(FCEUI_RECORDMOVIE)) + // return; + + assert(fname); + + FCEUI_StopMovie(); + + openRecordingMovie(fname); + + currFrameCounter = 0; + //LagCounterReset(); + + currMovieData = MovieData(); + currMovieData.guid.newGuid(); + + if(author != WSTR(L"")) currMovieData.comments.push_back(WSTR(L"author ") + author); + currMovieData.romChecksum = gameInfo.crc; + currMovieData.romSerial = gameInfo.ROMserial; + currMovieData.romFilename = path.GetRomName(); + currMovieData.rtcStart = rtcstart; + + NDS_Reset(); + + //todo ? + //poweron(true); + //else + // MovieData::dumpSavestateTo(&currMovieData.savestate,Z_BEST_COMPRESSION); + + if(flag == 1) + EMUFILE::readAllBytes(&currMovieData.sram, sramfname); + + //we are going to go ahead and dump the header. from now on we will only be appending frames + currMovieData.dump(osRecordingMovie, false); + + currFrameCounter=0; + lagframecounter=0; + LagFrameFlag=0; + lastLag=0; + TotalLagFrames=0; + + movieMode = MOVIEMODE_RECORD; + movie_readonly = false; + currRerecordCount = 0; + MMU_new.backupDevice.movie_mode(); + + if(currMovieData.sram.size() != 0) + { + bool success = MovieData::loadSramFrom(&currMovieData.sram); + if(!success) return; + } + + driver->USR_InfoMessage("Movie recording started."); +} + + + //the main interaction point between the emulator and the movie system. + //either dumps the current joystick state or loads one state from the movie. + //deprecated, should use the two functions it has been split into directly + void FCEUMOV_AddInputState() + { + FCEUMOV_HandlePlayback(); + FCEUMOV_HandleRecording(); + } + + void FCEUMOV_HandlePlayback() + { + if(movieMode == MOVIEMODE_PLAY) + { + //stop when we run out of frames + if(currFrameCounter == (int)currMovieData.records.size()) + { + FinishPlayback(); + } + else + { + UserInput& input = NDS_getProcessingUserInput(); + + MovieRecord* mr = &currMovieData.records[currFrameCounter]; + + if(mr->command_microphone()) input.mic.micButtonPressed = 1; + else input.mic.micButtonPressed = 0; + + if(mr->command_reset()) NDS_Reset(); + + if(mr->command_lid()) input.buttons.F = true; + else input.buttons.F = false; + + u16 pad = mr->pad; + input.buttons.R = (((pad>>12)&1)!=0); + input.buttons.L = (((pad>>11)&1)!=0); + input.buttons.D = (((pad>>10)&1)!=0); + input.buttons.U = (((pad>>9)&1)!=0); + input.buttons.T = (((pad>>8)&1)!=0); + input.buttons.S = (((pad>>7)&1)!=0); + input.buttons.B = (((pad>>6)&1)!=0); + input.buttons.A = (((pad>>5)&1)!=0); + input.buttons.Y = (((pad>>4)&1)!=0); + input.buttons.X = (((pad>>3)&1)!=0); + input.buttons.W = (((pad>>2)&1)!=0); + input.buttons.E = (((pad>>1)&1)!=0); + input.buttons.G = (((pad>>0)&1)!=0); + + input.touch.touchX = mr->touch.x << 4; + input.touch.touchY = mr->touch.y << 4; + input.touch.isTouch = mr->touch.touch != 0; + } + + //if we are on the last frame, then pause the emulator if the player requested it + if(currFrameCounter == (int)currMovieData.records.size()-1) + { + /*if(FCEUD_PauseAfterPlayback()) + { + FCEUI_ToggleEmulationPause(); + }*/ + } + + //pause the movie at a specified frame + //if(FCEUMOV_ShouldPause() && FCEUI_EmulationPaused()==0) + //{ + // FCEUI_ToggleEmulationPause(); + // FCEU_DispMessage("Paused at specified movie frame"); + //} + + // it's apparently un-threadsafe to do this here + // (causes crazy flickering in other OSD elements, at least) + // and it's also pretty annoying, + // and the framecounter display already conveys this info as well. + // so, I'm disabling this, at least for now. +// osd->addFixed(180, 176, "%s", "Playback"); + + } + } + + void FCEUMOV_HandleRecording() + { + if(movieMode == MOVIEMODE_RECORD) + { + const UserInput& input = NDS_getFinalUserInput(); + + MovieRecord mr; + + mr.commands = 0; + + if(input.mic.micButtonPressed == 1) + mr.commands = MOVIECMD_MIC; + + mr.pad = nds.pad; + + if(input.buttons.F) + mr.commands = MOVIECMD_LID; + + if(movie_reset_command) { + mr.commands = MOVIECMD_RESET; + movie_reset_command = false; + } + + mr.touch.touch = input.touch.isTouch ? 1 : 0; + mr.touch.x = input.touch.isTouch ? input.touch.touchX >> 4 : 0; + mr.touch.y = input.touch.isTouch ? input.touch.touchY >> 4 : 0; + + assert(mr.touch.touch || (!mr.touch.x && !mr.touch.y)); + //assert(nds.touchX == input.touch.touchX && nds.touchY == input.touch.touchY); + //assert((mr.touch.x << 4) == nds.touchX && (mr.touch.y << 4) == nds.touchY); + + mr.dump(&currMovieData, osRecordingMovie,currMovieData.records.size()); + currMovieData.records.push_back(mr); + + // it's apparently un-threadsafe to do this here + // (causes crazy flickering in other OSD elements, at least) + // and it's also pretty annoying, + // and the framecounter display already conveys this info as well. + // so, I'm disabling this, at least for now. +// osd->addFixed(180, 176, "%s", "Recording"); + } + + /*extern uint8 joy[4]; + memcpy(&cur_input_display,joy,4);*/ + } + + +//TODO +static void FCEUMOV_AddCommand(int cmd) +{ + // do nothing if not recording a movie + if(movieMode != MOVIEMODE_RECORD) + return; + + //printf("%d\n",cmd); + + //MBG TODO BIG TODO TODO TODO + //DoEncode((cmd>>3)&0x3,cmd&0x7,1); +} + +//little endian 4-byte cookies +static const int kMOVI = 0x49564F4D; +static const int kNOMO = 0x4F4D4F4E; + +void mov_savestate(EMUFILE* fp) +{ + //we are supposed to dump the movie data into the savestate + //if(movieMode == MOVIEMODE_RECORD || movieMode == MOVIEMODE_PLAY) + // return currMovieData.dump(os, true); + //else return 0; + if(movieMode != MOVIEMODE_INACTIVE) + { + write32le(kMOVI,fp); + currMovieData.dump(fp, true); + } + else + { + write32le(kNOMO,fp); + } +} + + +bool CheckTimelines(MovieData& stateMovie, MovieData& currMovie, int& errorFr) +{ + bool isInTimeline = true; + int length; + + //First check, make sure we are checking is for a post-movie savestate, we just want to adjust the length for now, we will handle this situation later in another function + if (currFrameCounter <= stateMovie.getNumRecords()) + length = currFrameCounter; //Note: currFrameCounter corresponds to the framecounter in the savestate + else if (currFrameCounter > currMovie.getNumRecords()) //Now that we know the length of the records of the savestate we plan to load, let's match the length against the movie + length = currMovie.getNumRecords(); //If length < currMovie records then this is a "future" event from the current movie, againt we will handle this situation later, we just want to find the right number of frames to compare + else + length = stateMovie.getNumRecords(); + + for (int x = 0; x < length; x++) + { + if (!stateMovie.records[x].Compare(currMovie.records[x])) + { + isInTimeline = false; + errorFr = x; + break; + } + } + + return isInTimeline; +} + + +static bool load_successful; + +bool mov_loadstate(EMUFILE* fp, int size) +{ + load_successful = false; + + u32 cookie; + if(read32le(&cookie,fp) != 1) return false; + if(cookie == kNOMO) + { + if(movieMode == MOVIEMODE_RECORD || movieMode == MOVIEMODE_PLAY) + FinishPlayback(); + return true; + } + else if(cookie != kMOVI) + return false; + + size -= 4; + + if (!movie_readonly && autoMovieBackup && freshMovie) //If auto-backup is on, movie has not been altered this session and the movie is in read+write mode + { + FCEUI_MakeBackupMovie(false); //Backup the movie before the contents get altered, but do not display messages + } + + //a little rule: cant load states in read+write mode with a movie from an archive. + //so we are going to switch it to readonly mode in that case +// if(!movie_readonly +// //*&& FCEU_isFileInArchive(curMovieFilename)*/ +// ) { +// FCEU_PrintError("Cannot loadstate in Read+Write with movie from archive. Movie is now Read-Only."); +// movie_readonly = true; +// } + + MovieData tempMovieData = MovieData(); + //int curr = fp->ftell(); + if(!LoadFM2(tempMovieData, fp, size, false)) { + + // is->seekg((uint32)curr+size); + /* extern bool FCEU_state_loading_old_format; + if(FCEU_state_loading_old_format) { + if(movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_RECORD) { + FCEUI_StopMovie(); + FCEU_PrintError("You have tried to use an old savestate while playing a movie. This is unsupported (since the old savestate has old-format movie data in it which can't be converted on the fly)"); + } + }*/ + return false; + } + + //---------------- + //complex TAS logic for loadstate + //fully conforms to the savestate logic documented in the Laws of TAS + //http://tasvideos.org/LawsOfTAS/OnSavestates.html + //---------------- + + /* + Playback or Recording + Read-only + + * Check that GUID of movie and savestate-movie must match or else error + o on error: a message informing that the savestate doesn't belong to this movie. This is a GUID mismatch error. Give user a choice to load it anyway. + + failstate: if use declines, loadstate attempt canceled, movie can resume as if not attempted if user has backup savstates enabled else stop movie + * Check that movie and savestate-movie are in same timeline. If not then this is a wrong timeline error. + o on error: a message informing that the savestate doesn't belong to this movie + + failstate: loadstate attempt canceled, movie can resume as if not attempted if user has backup savestates enabled else stop movie + * Check that savestate-movie is not greater than movie. If not then this is a future event error and is not allowed in read-only + o on error: message informing that the savestate is from a frame after the last frame of the movie + + failstate - loadstate attempt cancelled, movie can resume if user has backup savesattes enabled, else stop movie + * Check that savestate framcount <= savestate movie length. If not this is a post-movie savestate + o on post-movie: See post-movie event section. + * All error checks have passed, state will be loaded + * Movie contained in the savestate will be discarded + * Movie is now in Playback mode + + Playback, Recording + Read+write + + * Check that GUID of movie and savestate-movie must match or else error + o on error: a message informing that the savestate doesn't belong to this movie. This is a GUID mismatch error. Give user a choice to load it anyway. + + failstate: if use declines, loadstate attempt canceled, movie can resume as if not attempted (stop movie if resume fails)canceled, movie can resume if backup savestates enabled else stopmovie + * Check that savestate framcount <= savestate movie length. If not this is a post-movie savestate + o on post-movie: See post-movie event section. + * savestate passed all error checks and will now be loaded in its entirety and replace movie (note: there will be no truncation yet) + * current framecount will be set to savestate framecount + * on the next frame of input, movie will be truncated to framecount + o (note: savestate-movie can be a future event of the movie timeline, or a completely new timeline and it is still allowed) + * Rerecord count of movie will be incremented + * Movie is now in record mode + + Post-movie savestate event + + * Whan a savestate is loaded and is determined that the savestate-movie length is less than the savestate framecount then it is a post-movie savestate. These occur when a savestate was made during Movie Finished mode. + * If read+write, the entire savestate movie will be loaded and replace current movie. + * If read-only, the savestate movie will be discarded + * Mode will be switched to Move Finished + * Savestate will be loaded + * Current framecount changes to savestate framecount + * User will have control of input as if Movie inactive mode + */ + + + if(movieMode != MOVIEMODE_INACTIVE) + { + //handle moviefile mismatch + if(tempMovieData.guid != currMovieData.guid) + { + //mbg 8/18/08 - this code can be used to turn the error message into an OK/CANCEL + #if defined(WIN32) && !defined(WXPORT) + std::string msg = "There is a mismatch between savestate's movie and current movie.\ncurrent: " + currMovieData.guid.toString() + "\nsavestate: " + tempMovieData.guid.toString() + "\n\nThis means that you have loaded a savestate belonging to a different movie than the one you are playing now.\n\nContinue loading this savestate anyway?"; + int result = MessageBox(MainWindow->getHWnd(),msg.c_str(),"Error loading savestate",MB_OKCANCEL); + if(result == IDCANCEL) + return false; + #else + FCEU_PrintError("Mismatch between savestate's movie and current movie.\ncurrent: %s\nsavestate: %s\n",currMovieData.guid.toString().c_str(),tempMovieData.guid.toString().c_str()); + return false; + #endif + } + + closeRecordingMovie(); + + if(!movie_readonly) + { + currMovieData = tempMovieData; + currMovieData.rerecordCount = currRerecordCount; + } + + if(currFrameCounter > (int)currMovieData.records.size()) + { + // if the frame counter is longer than our current movie, + // switch to "finished" mode. + // this is a mode that behaves like "inactive" + // except it permits switching to play/record by loading an earlier savestate. + // (and we continue to store the finished movie in savestates made while finished) + osd->setLineColor(255,0,0); // let's make the text red too to hopefully catch the user's attention a bit. + FinishPlayback(); + osd->setLineColor(255,255,255); + + //FCEU_PrintError("Savestate is from a frame (%d) after the final frame in the movie (%d). This is not permitted.", currFrameCounter, currMovieData.records.size()-1); + //return false; + } + else if(movie_readonly) + { + //------------------------------------------------------------- + //this code would reload the movie from disk. allegedly it is helpful to hexers, but + //it is way too slow with dsm format. so it is only here as a reminder, and in case someone + //wants to play with it + //------------------------------------------------------------- + //{ + // fstream fs (curMovieFilename); + // if(!LoadFM2(tempMovieData, &fs, INT_MAX, false)) + // { + // FCEU_PrintError("Failed to reload DSM after loading savestate"); + // } + // fs.close(); + // currMovieData = tempMovieData; + //} + //------------------------------------------------------------- + + movieMode = MOVIEMODE_PLAY; + } + else + { + // #ifdef _S9XLUA_H + // if(!FCEU_LuaRerecordCountSkip()) + currRerecordCount++; + // #endif + + currMovieData.rerecordCount = currRerecordCount; + currMovieData.truncateAt(currFrameCounter); + + openRecordingMovie(curMovieFilename); + if(!osRecordingMovie) + { + osd->setLineColor(255, 0, 0); + osd->addLine("Can't save movie file!"); + } + + //printf("DUMPING MOVIE: %d FRAMES\n",currMovieData.records.size()); + currMovieData.dump(osRecordingMovie, false); + movieMode = MOVIEMODE_RECORD; + } + } + + load_successful = true; + freshMovie = false; + + return true; +} + +static void FCEUMOV_PreLoad(void) +{ + load_successful=0; +} + +static bool FCEUMOV_PostLoad(void) +{ + if(movieMode == MOVIEMODE_INACTIVE) + return true; + else + return load_successful; +} + + +bool FCEUI_MovieGetInfo(EMUFILE* fp, MOVIE_INFO& info, bool skipFrameCount) +{ + //MovieData md; + //if(!LoadFM2(md, fp, INT_MAX, skipFrameCount)) + // return false; + // + //info.movie_version = md.version; + //info.poweron = md.savestate.size()==0; + //info.pal = md.palFlag; + //info.nosynchack = true; + //info.num_frames = md.records.size(); + //info.md5_of_rom_used = md.romChecksum; + //info.emu_version_used = md.emuVersion; + //info.name_of_rom_used = md.romFilename; + //info.rerecord_count = md.rerecordCount; + //info.comments = md.comments; + + return true; +} + +bool MovieRecord::parseBinary(MovieData* md, EMUFILE* fp) +{ + commands=fp->fgetc(); + fp->fread((char *) &pad, sizeof pad); + fp->fread((char *) &touch.x, sizeof touch.x); + fp->fread((char *) &touch.y, sizeof touch.y); + fp->fread((char *) &touch.touch, sizeof touch.touch); + return true; +} + + +void MovieRecord::dumpBinary(MovieData* md, EMUFILE* fp, int index) +{ + fp->fputc(md->records[index].commands); + fp->fwrite((char *) &md->records[index].pad, sizeof md->records[index].pad); + fp->fwrite((char *) &md->records[index].touch.x, sizeof md->records[index].touch.x); + fp->fwrite((char *) &md->records[index].touch.y, sizeof md->records[index].touch.y); + fp->fwrite((char *) &md->records[index].touch.touch, sizeof md->records[index].touch.touch); +} + +void LoadFM2_binarychunk(MovieData& movieData, EMUFILE* fp, int size) +{ + int recordsize = 1; //1 for the command + + recordsize = 6; + + assert(size%6==0); + + //find out how much remains in the file + int curr = fp->ftell(); + fp->fseek(0,SEEK_END); + int end = fp->ftell(); + int flen = end-curr; + fp->fseek(curr,SEEK_SET); + + //the amount todo is the min of the limiting size we received and the remaining contents of the file + int todo = std::min(size, flen); + + int numRecords = todo/recordsize; + //printf("LOADED MOVIE: %d records; currFrameCounter: %d\n",numRecords,currFrameCounter); + movieData.records.resize(numRecords); + for(int i=0;i<numRecords;i++) + { + movieData.records[i].parseBinary(&movieData,fp); + } +} + +#include <sstream> + +static bool CheckFileExists(const char* filename) +{ + //This function simply checks to see if the given filename exists + string checkFilename; + + if (filename) + checkFilename = filename; + + //Check if this filename exists + FILE* fp = fopen(checkFilename.c_str(), "rb"); + + if (!fp) + { + return false; + } + else + { + fclose(fp); + return true; + } +} + +void FCEUI_MakeBackupMovie(bool dispMessage) +{ + //This function generates backup movie files + string currentFn; //Current movie fillename + string backupFn; //Target backup filename + string tempFn; //temp used in back filename creation + stringstream stream; + int x; //Temp variable for string manip + bool exist = false; //Used to test if filename exists + bool overflow = false; //Used for special situation when backup numbering exceeds limit + + currentFn = curMovieFilename; //Get current moviefilename + backupFn = curMovieFilename; //Make backup filename the same as current moviefilename + x = backupFn.find_last_of("."); //Find file extension + backupFn = backupFn.substr(0,x); //Remove extension + tempFn = backupFn; //Store the filename at this point + for (unsigned int backNum=0;backNum<999;backNum++) //999 = arbituary limit to backup files + { + stream.str(""); //Clear stream + if (backNum > 99) + stream << "-" << backNum; //assign backNum to stream + else if (backNum <= 99 && backNum >= 10) + stream << "-0" << backNum; //Make it 010, etc if two digits + else + stream << "-00" << backNum; //Make it 001, etc if single digit + backupFn.append(stream.str()); //add number to bak filename + backupFn.append(".bak"); //add extension + + exist = CheckFileExists(backupFn.c_str()); //Check if file exists + + if (!exist) + break; //Yeah yeah, I should use a do loop or something + else + { + backupFn = tempFn; //Before we loop again, reset the filename + + if (backNum == 999) //If 999 exists, we have overflowed, let's handle that + { + backupFn.append("-001.bak"); //We are going to simply overwrite 001.bak + overflow = true; //Flag that we have exceeded limit + break; //Just in case + } + } + } + + MovieData md = currMovieData; //Get current movie data + EMUFILE* outf = new EMUFILE_FILE(backupFn.c_str(),"wb"); //FCEUD_UTF8_fstream(backupFn, "wb"); //open/create file + md.dump(outf,false); //dump movie data + delete outf; //clean up, delete file object + + //TODO, decide if fstream successfully opened the file and print error message if it doesn't + + if (dispMessage) //If we should inform the user + { +// if (overflow) +// FCEUI_DispMessage("Backup overflow, overwriting %s",backupFn.c_str()); //Inform user of overflow +// else +// FCEUI_DispMessage("%s created",backupFn.c_str()); //Inform user of backup filename + } +} + diff --git a/jni/desmume/src/path.cpp b/jni/desmume/src/path.cpp new file mode 100755 index 0000000..3228fc3 --- /dev/null +++ b/jni/desmume/src/path.cpp @@ -0,0 +1,159 @@ +/* + Copyright (C) 2009-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "types.h" + +#include "path.h" +#include <stdio.h> + +char PathInfo::pathToModule[MAX_PATH]; + +//----------------------------------- +//This is taken from mono Path.cs +static const char InvalidPathChars[] = { + '\x22', '\x3C', '\x3E', '\x7C', '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', + '\x08', '\x09', '\x0A', '\x0B', '\x0C', '\x0D', '\x0E', '\x0F', '\x10', '\x11', '\x12', + '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1A', '\x1B', '\x1C', '\x1D', + '\x1E', '\x1F' +}; + +//but it is sort of windows-specific. Does it work in linux? Maybe we'll have to make it smarter +static const char VolumeSeparatorChar = ':'; +static const char AltDirectorySeparatorChar = '/'; +static bool dirEqualsVolume = (DIRECTORY_DELIMITER_CHAR == VolumeSeparatorChar); + + +bool Path::IsPathRooted (const std::string &path) +{ + if (path.empty()) { + return false; + } + + if (path.find_first_of(InvalidPathChars) != std::string::npos) { + return false; + } + + char c = path[0]; + return (c == DIRECTORY_DELIMITER_CHAR || + c == AltDirectorySeparatorChar || + (!dirEqualsVolume && path.size() > 1 && path[1] == VolumeSeparatorChar)); +} + +std::string Path::GetFileDirectoryPath(std::string filePath) +{ + if (filePath.empty()) { + return ""; + } + + size_t i = filePath.find_last_of(DIRECTORY_DELIMITER_CHAR); + if (i == std::string::npos) { + return filePath; + } + + return filePath.substr(0, i); +} + +std::string Path::GetFileNameFromPath(std::string filePath) +{ + if (filePath.empty()) { + return ""; + } + + size_t i = filePath.find_last_of(DIRECTORY_DELIMITER_CHAR); + if (i == std::string::npos) { + return filePath; + } + + return filePath.substr(i + 1); +} + +std::string Path::GetFileNameWithoutExt(std::string fileName) +{ + if (fileName.empty()) { + return ""; + } + + size_t i = fileName.find_last_of(FILE_EXT_DELIMITER_CHAR); + if (i == std::string::npos) { + return fileName; + } + + return fileName.substr(0, i); +} + +std::string Path::GetFileNameFromPathWithoutExt(std::string filePath) +{ + if (filePath.empty()) { + return ""; + } + + std::string fileName = GetFileNameFromPath(filePath); + + return GetFileNameWithoutExt(fileName); +} + +std::string Path::GetFileExt(std::string fileName) +{ + if (fileName.empty()) { + return ""; + } + + size_t i = fileName.find_last_of(FILE_EXT_DELIMITER_CHAR); + if (i == std::string::npos) { + return fileName; + } + + return fileName.substr(i + 1); +} + +//----------------------------------- +#ifdef _WINDOWS +void FCEUD_MakePathDirs(const char *fname) +{ + char path[MAX_PATH]; + const char* div = fname; + + do + { + const char* fptr = strchr(div, '\\'); + + if(!fptr) + { + fptr = strchr(div, '/'); + } + + if(!fptr) + { + break; + } + + int off = fptr - fname; + strncpy(path, fname, off); + path[off] = '\0'; + mkdir(path); + + div = fptr + 1; + + while(div[0] == '\\' || div[0] == '/') + { + div++; + } + + } while(1); +} +#endif +//------------------------------ \ No newline at end of file diff --git a/jni/desmume/src/path.h b/jni/desmume/src/path.h new file mode 100755 index 0000000..beae7dc --- /dev/null +++ b/jni/desmume/src/path.h @@ -0,0 +1,449 @@ +/* + Copyright (C) 2009-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <string> + +#ifdef _MSC_VER +#define mkdir _mkdir +#endif + +#if defined(_WINDOWS) +#include <winsock2.h> +#include <windows.h> +#include <direct.h> +#include "winutil.h" +#include "common.h" +#if !defined(WXPORT) +#include "resource.h" +#else +#include <glib.h> +#endif /* !WXPORT */ +#elif !defined(DESMUME_COCOA) && !defined(ANDROID) +#include <glib.h> +#endif /* _WINDOWS */ + +#include "time.h" +#include "utils/xstring.h" + +#ifdef _WINDOWS +#define FILE_EXT_DELIMITER_CHAR '.' +#define DIRECTORY_DELIMITER_CHAR '\\' +#else +#define FILE_EXT_DELIMITER_CHAR '.' +#define DIRECTORY_DELIMITER_CHAR '/' +#endif + +#ifdef _WINDOWS +void FCEUD_MakePathDirs(const char *fname); +#endif + +class Path +{ +public: + static bool IsPathRooted (const std::string &path); + static std::string GetFileDirectoryPath(std::string filePath); + static std::string GetFileNameFromPath(std::string filePath); + static std::string GetFileNameWithoutExt(std::string fileName); + static std::string GetFileNameFromPathWithoutExt(std::string filePath); + static std::string GetFileExt(std::string fileName); +}; + +class PathInfo +{ +public: + + std::string path; + std::string RomName; + std::string RomDirectory; + + #define MAX_FORMAT 20 + #define SECTION "PathSettings" + + #define ROMKEY "Roms" + #define BATTERYKEY "Battery" + #define STATEKEY "States" + #define SCREENSHOTKEY "Screenshots" + #define AVIKEY "AviFiles" + #define CHEATKEY "Cheats" + #define R4FORMATKEY "R4format" + #define SOUNDKEY "SoundSamples" + #define FIRMWAREKEY "Firmware" + #define FORMATKEY "format" + #define DEFAULTFORMATKEY "defaultFormat" + #define NEEDSSAVINGKEY "needsSaving" + #define LASTVISITKEY "lastVisit" + #define LUAKEY "Lua" + char screenshotFormat[MAX_FORMAT]; + bool savelastromvisit; + + enum KnownPath + { + FIRSTKNOWNPATH = 0, + ROMS = 0, + BATTERY, + STATES, + SCREENSHOTS, + AVI_FILES, + CHEATS, + SOUNDS, + FIRMWARE, + MODULE, + MAXKNOWNPATH = MODULE + }; + + char pathToRoms[MAX_PATH]; + char pathToBattery[MAX_PATH]; + char pathToStates[MAX_PATH]; + char pathToScreenshots[MAX_PATH]; + char pathToAviFiles[MAX_PATH]; + char pathToCheats[MAX_PATH]; + char pathToSounds[MAX_PATH]; + char pathToFirmware[MAX_PATH]; + static char pathToModule[MAX_PATH]; + char pathToLua[MAX_PATH]; + + void init(const char *filename) { + + path = std::string(filename); + + //extract the internal part of the logical rom name + std::vector<std::string> parts = tokenize_str(filename,"|"); + SetRomName(parts[parts.size()-1].c_str()); + LoadModulePath(); +#if !defined(WIN32) && !defined(DESMUME_COCOA) + ReadPathSettings(); +#endif + + } + + void LoadModulePath() + { +#ifdef ANDROID + return; //set from java +#elif defined(_WINDOWS) + + char *p; + ZeroMemory(pathToModule, sizeof(pathToModule)); + + GetModuleFileName(NULL, pathToModule, sizeof(pathToModule)); + p = pathToModule + lstrlen(pathToModule); + while (p >= pathToModule && *p != DIRECTORY_DELIMITER_CHAR) p--; + if (++p >= pathToModule) *p = 0; +#elif defined(DESMUME_COCOA) + std::string pathStr = Path::GetFileDirectoryPath(path); + + strncpy(pathToModule, pathStr.c_str(), MAX_PATH); +#else + char *cwd = g_build_filename(g_get_user_config_dir(), "desmume", NULL); + g_mkdir_with_parents(cwd, 0755); + strncpy(pathToModule, cwd, MAX_PATH); + g_free(cwd); +#endif + } + + enum Action + { + GET, + SET + }; + + void GetDefaultPath(char *pathToDefault, const char *key, int maxCount) + { +#ifdef _WINDOWS + std::string temp = (std::string)"." + DIRECTORY_DELIMITER_CHAR + pathToDefault; + strncpy(pathToDefault, temp.c_str(), maxCount); +#elif ANDROID + snprintf(pathToDefault, maxCount, "%s/%s", pathToModule, key); +#else + strncpy(pathToDefault, pathToModule, maxCount); +#endif + } + + void ReadKey(char *pathToRead, const char *key) + { +#ifdef _WINDOWS + GetPrivateProfileString(SECTION, key, key, pathToRead, MAX_PATH, IniName); + if(strcmp(pathToRead, key) == 0) { + //since the variables are all intialized in this file they all use MAX_PATH + GetDefaultPath(pathToRead, key, MAX_PATH); + } +#else + //since the variables are all intialized in this file they all use MAX_PATH + GetDefaultPath(pathToRead, key, MAX_PATH); +#endif + } + + void ReadPathSettings() + { + if( ( strcmp(pathToModule, "") == 0) || !pathToModule) + LoadModulePath(); + + ReadKey(pathToRoms, ROMKEY); + ReadKey(pathToBattery, BATTERYKEY); + ReadKey(pathToStates, STATEKEY); + ReadKey(pathToScreenshots, SCREENSHOTKEY); + ReadKey(pathToAviFiles, AVIKEY); + ReadKey(pathToCheats, CHEATKEY); + ReadKey(pathToSounds, SOUNDKEY); + ReadKey(pathToFirmware, FIRMWAREKEY); + ReadKey(pathToLua, LUAKEY); +#ifdef _WINDOWS + GetPrivateProfileString(SECTION, FORMATKEY, "%f_%s_%r", screenshotFormat, MAX_FORMAT, IniName); + savelastromvisit = GetPrivateProfileBool(SECTION, LASTVISITKEY, true, IniName); + currentimageformat = (ImageFormat)GetPrivateProfileInt(SECTION, DEFAULTFORMATKEY, PNG, IniName); + r4Format = (R4Format)GetPrivateProfileInt(SECTION, R4FORMATKEY, R4_CHEAT_DAT, IniName); +#endif + /* + needsSaving = GetPrivateProfileInt(SECTION, NEEDSSAVINGKEY, TRUE, IniName); + if(needsSaving) + { + needsSaving = FALSE; + WritePathSettings(); + }*/ + } + + void SwitchPath(Action action, KnownPath path, char *buffer) + { + char *pathToCopy = 0; + switch(path) + { + case ROMS: + pathToCopy = pathToRoms; + break; + case BATTERY: + pathToCopy = pathToBattery; + break; + case STATES: + pathToCopy = pathToStates; + break; + case SCREENSHOTS: + pathToCopy = pathToScreenshots; + break; + case AVI_FILES: + pathToCopy = pathToAviFiles; + break; + case CHEATS: + pathToCopy = pathToCheats; + break; + case SOUNDS: + pathToCopy = pathToSounds; + break; + case FIRMWARE: + pathToCopy = pathToFirmware; + break; + case MODULE: + pathToCopy = pathToModule; + break; + } + + if(action == GET) + { + std::string thePath = pathToCopy; + std::string relativePath = (std::string)"." + DIRECTORY_DELIMITER_CHAR; + + int len = (int)thePath.size()-1; + + if(len == -1) + thePath = relativePath; + else + if(thePath[len] != DIRECTORY_DELIMITER_CHAR) + thePath += DIRECTORY_DELIMITER_CHAR; + + if(!Path::IsPathRooted(thePath)) + { + thePath = (std::string)pathToModule + thePath; + } + + strncpy(buffer, thePath.c_str(), MAX_PATH); + #ifdef _WINDOWS + FCEUD_MakePathDirs(buffer); + #endif + } + else if(action == SET) + { + int len = strlen(buffer)-1; + if(buffer[len] == DIRECTORY_DELIMITER_CHAR) + buffer[len] = '\0'; + + strncpy(pathToCopy, buffer, MAX_PATH); + } + } + + std::string getpath(KnownPath path) + { + char temp[MAX_PATH]; + SwitchPath(GET, path, temp); + return temp; + } + + void getpath(KnownPath path, char *buffer) + { + SwitchPath(GET, path, buffer); + } + + void setpath(KnownPath path, char *buffer) + { + SwitchPath(SET, path, buffer); + } + + void getfilename(char *buffer, int maxCount) + { + strcpy(buffer,noextension().c_str()); + } + + void getpathnoext(KnownPath path, char *buffer) + { + getpath(path, buffer); + strcat(buffer, GetRomNameWithoutExtension().c_str()); + } + + std::string extension() + { + return Path::GetFileExt(path); + } + + std::string noextension() + { + std::string romNameWithPath = Path::GetFileDirectoryPath(path) + DIRECTORY_DELIMITER_CHAR + Path::GetFileNameWithoutExt(RomName); + + return romNameWithPath; + } + + void formatname(char *output) + { + std::string file; + time_t now = time(NULL); + tm *time_struct = localtime(&now); + srand((unsigned int)now); + + for(int i = 0; i < MAX_FORMAT;i++) + { + char *c = &screenshotFormat[i]; + char tmp[MAX_PATH] = {0}; + + if(*c == '%') + { + c = &screenshotFormat[++i]; + switch(*c) + { + case 'f': + + strcat(tmp, GetRomNameWithoutExtension().c_str()); + break; + case 'D': + strftime(tmp, MAX_PATH, "%d", time_struct); + break; + case 'M': + strftime(tmp, MAX_PATH, "%m", time_struct); + break; + case 'Y': + strftime(tmp, MAX_PATH, "%Y", time_struct); + break; + case 'h': + strftime(tmp, MAX_PATH, "%H", time_struct); + break; + case 'm': + strftime(tmp, MAX_PATH, "%M", time_struct); + break; + case 's': + strftime(tmp, MAX_PATH, "%S", time_struct); + break; + case 'r': + sprintf(tmp, "%d", rand() % RAND_MAX); + break; + } + } + else + { + int j; + for(j=i;j<MAX_FORMAT-i;j++) + if(screenshotFormat[j] != '%') + tmp[j-i]=screenshotFormat[j]; + else + break; + tmp[j-i]='\0'; + } + file += tmp; + } + strncpy(output, file.c_str(), MAX_PATH); + } + + enum R4Format + { +#if defined(_WINDOWS) && !defined(WXPORT) + R4_CHEAT_DAT = IDC_R4TYPE1, + R4_USRCHEAT_DAT = IDC_R4TYPE2 +#else + R4_CHEAT_DAT, + R4_USRCHEAT_DAT +#endif + }; + R4Format r4Format; + + enum ImageFormat + { +#if defined(_WINDOWS) && !defined(WXPORT) + PNG = IDC_PNG, + BMP = IDC_BMP +#else + PNG, + BMP +#endif + }; + + ImageFormat currentimageformat; + + ImageFormat imageformat() { + return currentimageformat; + } + + void SetRomName(const char *filename) + { + std::string romPath = filename; + + RomName = Path::GetFileNameFromPath(romPath); + RomDirectory = Path::GetFileDirectoryPath(romPath); + } + + const char *GetRomName() + { + return RomName.c_str(); + } + + std::string GetRomNameWithoutExtension() + { + return Path::GetFileNameWithoutExt(RomName); + } + + bool isdsgba(std::string fileName) + { + size_t i = fileName.find_last_of(FILE_EXT_DELIMITER_CHAR); + + if (i != std::string::npos) { + fileName = fileName.substr(i - 2); + } + + if(fileName == "ds.gba") { + return true; + } + + return false; + } +}; + +extern PathInfo path; + diff --git a/jni/desmume/src/rasterize.cpp b/jni/desmume/src/rasterize.cpp new file mode 100755 index 0000000..d61ccb2 --- /dev/null +++ b/jni/desmume/src/rasterize.cpp @@ -0,0 +1,1648 @@ +/* + Copyright (C) 2009-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +//nothing in this file should be assumed to be accurate +// +//the shape rasterizers contained herein are based on code supplied by Chris Hecker from +//http://chrishecker.com/Miscellaneous_Technical_Articles + + +//TODO - due to a late change of a y-coord flipping, our winding order is wrong +//this causes us to have to flip the verts for every front-facing poly. +//a performance improvement would be to change the winding order logic +//so that this is done less frequently + +#include "rasterize.h" + +#include <algorithm> +#include <assert.h> +#include <math.h> +#include <string.h> + +#ifndef _MSC_VER +#include <stdint.h> +#endif + +#include "bits.h" +#include "common.h" +#include "matrix.h" +#include "render3D.h" +#include "gfx3d.h" +#include "texcache.h" +#include "NDSSystem.h" +#include "utils/task.h" + +//#undef FORCEINLINE +//#define FORCEINLINE +//#undef INLINE +//#define INLINE + +using std::min; +using std::max; +using std::swap; + +template<typename T> T _min(T a, T b, T c) { return min(min(a,b),c); } +template<typename T> T _max(T a, T b, T c) { return max(max(a,b),c); } +template<typename T> T _min(T a, T b, T c, T d) { return min(_min(a,b,d),c); } +template<typename T> T _max(T a, T b, T c, T d) { return max(_max(a,b,d),c); } + +static const int kUnsetTranslucentPolyID = 255; + +static u8 modulate_table[64][64]; +static u8 decal_table[32][64][64]; +static u8 index_lookup_table[65]; +static u8 index_start_table[8]; + + + +////optimized float floor useful in limited cases +////from http://www.stereopsis.com/FPU.html#convert +////(unfortunately, it relies on certain FPU register settings) +//int Real2Int(double val) +//{ +// const double _double2fixmagic = 68719476736.0*1.5; //2^36 * 1.5, (52-_shiftamt=36) uses limited precisicion to floor +// const int _shiftamt = 16; //16.16 fixed point representation, +// +// #ifdef WORDS_BIGENDIAN +// #define iman_ 1 +// #else +// #define iman_ 0 +// #endif +// +// val = val + _double2fixmagic; +// return ((int*)&val)[iman_] >> _shiftamt; +//} + +//// this probably relies on rounding settings.. +//int Real2Int(float val) +//{ +// //val -= 0.5f; +// //int temp; +// //__asm { +// // fld val; +// // fistp temp; +// //} +// //return temp; +// return 0; +//} + + +//doesnt work yet +static FORCEINLINE int fastFloor(float f) +{ + float temp = f + 1.f; + int ret = (*((u32*)&temp))&0x7FFFFF; + return ret; +} + + +//INLINE static void SubmitVertex(int vert_index, VERT& rawvert) +//{ +// verts[vert_index] = &rawvert; +//} + +static Fragment _screen[256*192]; +static FragmentColor _screenColor[256*192]; + +static FORCEINLINE int iround(float f) { + return (int)f; //lol +} + + +typedef int fixed28_4; + +// handle floor divides and mods correctly +static FORCEINLINE void FloorDivMod(long Numerator, long Denominator, long &Floor, long &Mod, bool& failure) +{ + //These must be caused by invalid or degenerate shapes.. not sure yet. + //check it out in the mario face intro of SM64 + //so, we have to take out the assert. + //I do know that we handle SOME invalid shapes without crashing, + //since I see them acting poppy in a way that doesnt happen in the HW.. so alas it is also incorrect. + //This particular incorrectness is not likely ever to get fixed! + + //assert(Denominator > 0); + + //but we have to bail out since our handling for these cases currently steps scanlines + //the wrong way and goes totally nuts (freezes) + if(Denominator<=0) + failure = true; + + if(Numerator >= 0) { + // positive case, C is okay + Floor = Numerator / Denominator; + Mod = Numerator % Denominator; + } else { + // Numerator is negative, do the right thing + Floor = -((-Numerator) / Denominator); + Mod = (-Numerator) % Denominator; + if(Mod) { + // there is a remainder + Floor--; Mod = Denominator - Mod; + } + } +} + +static FORCEINLINE fixed28_4 FloatToFixed28_4( float Value ) { + return (fixed28_4)(Value * 16); +} +static FORCEINLINE float Fixed28_4ToFloat( fixed28_4 Value ) { + return Value / 16.0f; +} +//inline fixed16_16 FloatToFixed16_16( float Value ) { +// return (fixed16_6)(Value * 65536); +//} +//inline float Fixed16_16ToFloat( fixed16_16 Value ) { +// return Value / 65536.0; +//} +static FORCEINLINE fixed28_4 Fixed28_4Mul( fixed28_4 A, fixed28_4 B ) { + // could make this asm to prevent overflow + return (A * B) / 16; // 28.4 * 28.4 = 24.8 / 16 = 28.4 +} +static FORCEINLINE int Ceil28_4( fixed28_4 Value ) { + int ReturnValue; + int Numerator = Value - 1 + 16; + if(Numerator >= 0) { + ReturnValue = Numerator/16; + } else { + // deal with negative numerators correctly + ReturnValue = -((-Numerator)/16); + ReturnValue -= ((-Numerator) % 16) ? 1 : 0; + } + return ReturnValue; +} + +struct edge_fx_fl { + edge_fx_fl() {} + edge_fx_fl(int Top, int Bottom, VERT** verts, bool& failure); + FORCEINLINE int Step(); + + VERT** verts; + long X, XStep, Numerator, Denominator; // DDA info for x + long ErrorTerm; + int Y, Height; // current y and vertical count + + struct Interpolant { + float curr, step, stepExtra; + FORCEINLINE void doStep() { curr += step; } + FORCEINLINE void doStepExtra() { curr += stepExtra; } + FORCEINLINE void initialize(float top, float bottom, float dx, float dy, long XStep, float XPrestep, float YPrestep) { + dx = 0; + dy *= (bottom-top); + curr = top + YPrestep * dy + XPrestep * dx; + step = XStep * dx + dy; + stepExtra = dx; + } + }; + + static const int NUM_INTERPOLANTS = 7; + union { + struct { + Interpolant invw,z,u,v,color[3]; + }; + Interpolant interpolants[NUM_INTERPOLANTS]; + }; + void FORCEINLINE doStepInterpolants() { for(int i=0;i<NUM_INTERPOLANTS;i++) interpolants[i].doStep(); } + void FORCEINLINE doStepExtraInterpolants() { for(int i=0;i<NUM_INTERPOLANTS;i++) interpolants[i].doStepExtra(); } +}; + +FORCEINLINE edge_fx_fl::edge_fx_fl(int Top, int Bottom, VERT** verts, bool& failure) { + this->verts = verts; + Y = Ceil28_4((fixed28_4)verts[Top]->y); + int YEnd = Ceil28_4((fixed28_4)verts[Bottom]->y); + Height = YEnd - Y; + X = Ceil28_4((fixed28_4)verts[Top]->x); + int XEnd = Ceil28_4((fixed28_4)verts[Bottom]->x); + int Width = XEnd - X; // can be negative + + // even if Height == 0, give some info for horizontal line poly + if(Height != 0 || Width != 0) + { + long dN = long(verts[Bottom]->y - verts[Top]->y); + long dM = long(verts[Bottom]->x - verts[Top]->x); + if (dN != 0) + { + long InitialNumerator = (long)(dM*16*Y - dM*verts[Top]->y + dN*verts[Top]->x - 1 + dN*16); + FloorDivMod(InitialNumerator,dN*16,X,ErrorTerm,failure); + FloorDivMod(dM*16,dN*16,XStep,Numerator,failure); + Denominator = dN*16; + } + else + { + XStep = Width; + Numerator = 0; + ErrorTerm = 0; + Denominator = 1; + dN = 1; + } + + float YPrestep = Fixed28_4ToFloat((fixed28_4)(Y*16 - verts[Top]->y)); + float XPrestep = Fixed28_4ToFloat((fixed28_4)(X*16 - verts[Top]->x)); + + float dy = 1/Fixed28_4ToFloat(dN); + float dx = 1/Fixed28_4ToFloat(dM); + + invw.initialize(1/verts[Top]->w,1/verts[Bottom]->w,dx,dy,XStep,XPrestep,YPrestep); + u.initialize(verts[Top]->u,verts[Bottom]->u,dx,dy,XStep,XPrestep,YPrestep); + v.initialize(verts[Top]->v,verts[Bottom]->v,dx,dy,XStep,XPrestep,YPrestep); + z.initialize(verts[Top]->z,verts[Bottom]->z,dx,dy,XStep,XPrestep,YPrestep); + for(int i=0;i<3;i++) + color[i].initialize(verts[Top]->fcolor[i],verts[Bottom]->fcolor[i],dx,dy,XStep,XPrestep,YPrestep); + } + else + { + memset(this, 0, sizeof(*this)); + this->verts = verts; + } +} + +FORCEINLINE int edge_fx_fl::Step() { + X += XStep; Y++; Height--; + doStepInterpolants(); + + ErrorTerm += Numerator; + if(ErrorTerm >= Denominator) { + X++; + ErrorTerm -= Denominator; + doStepExtraInterpolants(); + } + return Height; +} + + + +static FORCEINLINE void alphaBlend(FragmentColor & dst, const FragmentColor & src) +{ + if(gfx3d.renderState.enableAlphaBlending) + { + if(src.a == 31 || dst.a == 0) + { + dst = src; + } + //else if(src.a == 0) { } //this is not necessary since it was handled earlier + else + { + u8 alpha = src.a+1; + u8 invAlpha = 32 - alpha; + dst.r = (alpha*src.r + invAlpha*dst.r)>>5; + dst.g = (alpha*src.g + invAlpha*dst.g)>>5; + dst.b = (alpha*src.b + invAlpha*dst.b)>>5; + } + + dst.a = max(src.a,dst.a); + } + else + { + if(src.a == 0) + { + //do nothing; the fragment is totally transparent + } + else + { + dst = src; + } + } +} + +// TODO: wire-frame +struct PolyAttr +{ + u32 val; + + bool decalMode; + bool translucentDepthWrite; + bool drawBackPlaneIntersectingPolys; + u8 polyid; + u8 alpha; + bool backfacing; + bool translucent; + u8 fogged; + + bool isVisible(bool backfacing) + { + //this was added after adding multi-bit stencil buffer + //it seems that we also need to prevent drawing back faces of shadow polys for rendering + u32 mode = (val>>4)&0x3; + if(mode==3 && polyid !=0) return !backfacing; + //another reasonable possibility is that we should be forcing back faces to draw (mariokart doesnt use them) + //and then only using a single bit buffer (but a cursory test of this doesnt actually work) + // + //this code needs to be here for shadows in wizard of oz to work. + + switch((val>>6)&3) { + case 0: return false; + case 1: return backfacing; + case 2: return !backfacing; + case 3: return true; + default: assert(false); return false; + } + } + + void setup(u32 polyAttr) + { + val = polyAttr; + decalMode = BIT14(val); + translucentDepthWrite = BIT11(val); + polyid = (polyAttr>>24)&0x3F; + alpha = (polyAttr>>16)&0x1F; + drawBackPlaneIntersectingPolys = BIT12(val); + fogged = BIT15(val); + } + +}; + +template<bool RENDERER> +class RasterizerUnit +{ +public: + + int SLI_MASK, SLI_VALUE; + bool _debug_thisPoly; + + RasterizerUnit() + : _debug_thisPoly(false) + { + } + + TexCacheItem* lastTexKey; + + VERT* verts[MAX_CLIPPED_VERTS]; + + PolyAttr polyAttr; + int polynum; + + + struct Sampler + { + Sampler() {} + + bool enabled; + int width, height; + int wmask, hmask; + int wrap; + int wshift; + int texFormat; + void setup(u32 texParam) + { + texFormat = (texParam>>26)&7; + wshift = ((texParam>>20)&0x07) + 3; + width=(1 << wshift); + height=(8 << ((texParam>>23)&0x07)); + wmask = width-1; + hmask = height-1; + wrap = (texParam>>16)&0xF; + enabled = gfx3d.renderState.enableTexturing && (texFormat!=0); + } + + FORCEINLINE void clamp(int &val, const int size, const int sizemask){ + if(val<0) val = 0; + if(val>sizemask) val = sizemask; + } + FORCEINLINE void hclamp(int &val) { clamp(val,width,wmask); } + FORCEINLINE void vclamp(int &val) { clamp(val,height,hmask); } + + FORCEINLINE void repeat(int &val, const int size, const int sizemask) { + val &= sizemask; + } + FORCEINLINE void hrepeat(int &val) { repeat(val,width,wmask); } + FORCEINLINE void vrepeat(int &val) { repeat(val,height,hmask); } + + FORCEINLINE void flip(int &val, const int size, const int sizemask) { + val &= ((size<<1)-1); + if(val>=size) val = (size<<1)-val-1; + } + FORCEINLINE void hflip(int &val) { flip(val,width,wmask); } + FORCEINLINE void vflip(int &val) { flip(val,height,hmask); } + + FORCEINLINE void dowrap(int& iu, int& iv) + { + switch(wrap) { + //flip none + case 0x0: hclamp(iu); vclamp(iv); break; + case 0x1: hrepeat(iu); vclamp(iv); break; + case 0x2: hclamp(iu); vrepeat(iv); break; + case 0x3: hrepeat(iu); vrepeat(iv); break; + //flip S + case 0x4: hclamp(iu); vclamp(iv); break; + case 0x5: hflip(iu); vclamp(iv); break; + case 0x6: hclamp(iu); vrepeat(iv); break; + case 0x7: hflip(iu); vrepeat(iv); break; + //flip T + case 0x8: hclamp(iu); vclamp(iv); break; + case 0x9: hrepeat(iu); vclamp(iv); break; + case 0xA: hclamp(iu); vflip(iv); break; + case 0xB: hrepeat(iu); vflip(iv); break; + //flip both + case 0xC: hclamp(iu); vclamp(iv); break; + case 0xD: hflip(iu); vclamp(iv); break; + case 0xE: hclamp(iu); vflip(iv); break; + case 0xF: hflip(iu); vflip(iv); break; + } + } + } sampler; + + FORCEINLINE FragmentColor sample(float u, float v) + { + static const FragmentColor white = MakeFragmentColor(63,63,63,31); + if(!sampler.enabled) return white; + + //finally, we can use floor here. but, it is slower than we want. + //the best solution is probably to wait until the pipeline is full of fixed point + s32 iu = s32floor(u); + s32 iv = s32floor(v); + sampler.dowrap(iu,iv); + + FragmentColor color; + color.color = ((u32*)lastTexKey->decoded)[(iv<<sampler.wshift)+iu]; + return color; + } + + struct Shader + { + u8 mode; + float invu, invv, w; + FragmentColor materialColor; + } shader; + + FORCEINLINE void shade(FragmentColor& dst) + { + FragmentColor texColor; + float u,v; + + switch(shader.mode) + { + case 0: //modulate + u = shader.invu*shader.w; + v = shader.invv*shader.w; + texColor = sample(u,v); + dst.r = modulate_table[texColor.r][shader.materialColor.r]; + dst.g = modulate_table[texColor.g][shader.materialColor.g]; + dst.b = modulate_table[texColor.b][shader.materialColor.b]; + dst.a = modulate_table[GFX3D_5TO6(texColor.a)][GFX3D_5TO6(shader.materialColor.a)]>>1; + //dst.a = 28; + //#ifdef _MSC_VER + //if(GetAsyncKeyState(VK_SHIFT)) { + // //debugging tricks + // dst = shader.materialColor; + // if(GetAsyncKeyState(VK_TAB)) { + // u8 alpha = dst.a; + // dst.color = polynum*8+8; + // dst.a = alpha; + // } + //} + //#endif + break; + case 1: //decal + if(sampler.enabled) + { + u = shader.invu*shader.w; + v = shader.invv*shader.w; + texColor = sample(u,v); + dst.r = decal_table[texColor.a][texColor.r][shader.materialColor.r]; + dst.g = decal_table[texColor.a][texColor.g][shader.materialColor.g]; + dst.b = decal_table[texColor.a][texColor.b][shader.materialColor.b]; + dst.a = shader.materialColor.a; + } else dst = shader.materialColor; + break; + case 2: //toon/highlight shading + { + u = shader.invu*shader.w; + v = shader.invv*shader.w; + texColor = sample(u,v); + FragmentColor toonColor = engine->toonTable[shader.materialColor.r>>1]; + + if(gfx3d.renderState.shading == GFX3D_State::HIGHLIGHT) + { + dst.r = modulate_table[texColor.r][shader.materialColor.r]; + dst.g = modulate_table[texColor.g][shader.materialColor.r]; + dst.b = modulate_table[texColor.b][shader.materialColor.r]; + dst.a = modulate_table[GFX3D_5TO6(texColor.a)][GFX3D_5TO6(shader.materialColor.a)]>>1; + + dst.r = min<u8>(63, (dst.r + toonColor.r)); + dst.g = min<u8>(63, (dst.g + toonColor.g)); + dst.b = min<u8>(63, (dst.b + toonColor.b)); + } + else + { + dst.r = modulate_table[texColor.r][toonColor.r]; + dst.g = modulate_table[texColor.g][toonColor.g]; + dst.b = modulate_table[texColor.b][toonColor.b]; + dst.a = modulate_table[GFX3D_5TO6(texColor.a)][GFX3D_5TO6(shader.materialColor.a)]>>1; + } + + } + break; + case 3: //shadows + //is this right? only with the material color? + dst = shader.materialColor; + break; + } + } + + void setupShader(u32 polyattr) + { + shader.mode = (polyattr>>4)&0x3; + } + + FORCEINLINE void pixel(int adr,float r, float g, float b, float invu, float invv, float w, float z) + { + Fragment &destFragment = engine->screen[adr]; + FragmentColor &destFragmentColor = engine->screenColor[adr]; + + u32 depth; + if(gfx3d.renderState.wbuffer) + { + //not sure about this + //this value was chosen to make the skybox, castle window decals, and water level render correctly in SM64 + depth = u32floor(4096*w); + } + else + { + depth = u32floor(z*0x7FFF); + depth <<= 9; + } + + if(polyAttr.decalMode) + { + if ( CommonSettings.GFX3D_Zelda_Shadow_Depth_Hack > 0) + { + if(depth<destFragment.depth - CommonSettings.GFX3D_Zelda_Shadow_Depth_Hack + || depth>destFragment.depth + CommonSettings.GFX3D_Zelda_Shadow_Depth_Hack) + { + goto depth_fail; + } + + } + else + { + if(depth != destFragment.depth) + { + goto depth_fail; + } + } + + } + else + { + if(depth>=destFragment.depth) + { + goto depth_fail; + } + } + + //handle shadow polys + if(shader.mode == 3) + { + if(polyAttr.polyid == 0) + { + goto rejected_fragment; + } + else + { + if(destFragment.stencil==0) + { + goto rejected_fragment; + } + + //shadow polys have a special check here to keep from self-shadowing when user + //has tried to prevent it from happening + //if this isnt here, then the vehicle select in mariokart will look terrible + if(destFragment.polyid.opaque == polyAttr.polyid) + goto rejected_fragment; + } + } + + shader.w = w; + shader.invu = invu; + shader.invv = invv; + + //perspective-correct the colors + r = (r * w) + 0.5f; + g = (g * w) + 0.5f; + b = (b * w) + 0.5f; + + + //this is a HACK: + //we are being very sloppy with our interpolation precision right now + //and rather than fix it, i just want to clamp it + shader.materialColor.r = max(0U,min(63U,u32floor(r))); + shader.materialColor.g = max(0U,min(63U,u32floor(g))); + shader.materialColor.b = max(0U,min(63U,u32floor(b))); + + shader.materialColor.a = polyAttr.alpha; + + //pixel shader + FragmentColor shaderOutput; + shade(shaderOutput); + + //we shouldnt do any of this if we generated a totally transparent pixel + if(shaderOutput.a != 0) + { + //alpha test (don't have any test cases for this...? is it in the right place...?) + if(gfx3d.renderState.enableAlphaTest) + { + if(shaderOutput.a < gfx3d.renderState.alphaTestRef) + goto rejected_fragment; + } + + //handle polyids + bool isOpaquePixel = shaderOutput.a == 31; + if(isOpaquePixel) + { + destFragment.polyid.opaque = polyAttr.polyid; + destFragment.isTranslucentPoly = polyAttr.translucent?1:0; + destFragment.fogged = polyAttr.fogged; + destFragmentColor = shaderOutput; + } + else + { + //dont overwrite pixels on translucent polys with the same polyids + if(destFragment.polyid.translucent == polyAttr.polyid) + goto rejected_fragment; + + //originally we were using a test case of shadows-behind-trees in sm64ds + //but, it looks bad in that game. this is actually correct + //if this isnt correct, then complex shape cart shadows in mario kart don't work right + destFragment.polyid.translucent = polyAttr.polyid; + + //alpha blending and write color + alphaBlend(destFragmentColor, shaderOutput); + + destFragment.fogged &= polyAttr.fogged; + } + + //depth writing + if(isOpaquePixel || polyAttr.translucentDepthWrite) + destFragment.depth = depth; + + } + + //shadow cases: (need multi-bit stencil buffer to cope with all of these, especially the mariokart compelx shadows) + //1. sm64 (standing near signs and blocks) + //2. mariokart (no glitches in shadow shape in kart selector) + //3. mariokart (no junk beneath platform in kart selector / no shadow beneath grate floor in bowser stage) + //(specifically, the shadows in mario kart are complicated concave shapes) + + goto done; + depth_fail: + if(shader.mode == 3 && polyAttr.polyid == 0) + destFragment.stencil++; + rejected_fragment: + done: + ; + + if(shader.mode == 3 && polyAttr.polyid != 0 && destFragment.stencil) + destFragment.stencil--; + } + + //draws a single scanline + FORCEINLINE void drawscanline(edge_fx_fl *pLeft, edge_fx_fl *pRight, bool lineHack) + { + int XStart = pLeft->X; + int width = pRight->X - XStart; + + // HACK: workaround for vertical/slant line poly + if (lineHack && width == 0) + { + int leftWidth = pLeft->XStep; + if (pLeft->ErrorTerm + pLeft->Numerator >= pLeft->Denominator) + leftWidth++; + int rightWidth = pRight->XStep; + if (pRight->ErrorTerm + pRight->Numerator >= pRight->Denominator) + rightWidth++; + width = max(1, max(abs(leftWidth), abs(rightWidth))); + } + + //these are the starting values, taken from the left edge + float invw = pLeft->invw.curr; + float u = pLeft->u.curr; + float v = pLeft->v.curr; + float z = pLeft->z.curr; + float color[3] = { + pLeft->color[0].curr, + pLeft->color[1].curr, + pLeft->color[2].curr }; + + //our dx values are taken from the steps up until the right edge + float invWidth = 1.0f / width; + float dinvw_dx = (pRight->invw.curr - invw) * invWidth; + float du_dx = (pRight->u.curr - u) * invWidth; + float dv_dx = (pRight->v.curr - v) * invWidth; + float dz_dx = (pRight->z.curr - z) * invWidth; + float dc_dx[3] = { + (pRight->color[0].curr - color[0]) * invWidth, + (pRight->color[1].curr - color[1]) * invWidth, + (pRight->color[2].curr - color[2]) * invWidth }; + + int adr = (pLeft->Y*engine->width)+XStart; + + //CONSIDER: in case some other math is wrong (shouldve been clipped OK), we might go out of bounds here. + //better check the Y value. + if(RENDERER && (pLeft->Y<0 || pLeft->Y>191)) { + printf("rasterizer rendering at y=%d! oops!\n",pLeft->Y); + return; + } + if(!RENDERER && (pLeft->Y<0 || pLeft->Y>=engine->height)) { + printf("rasterizer rendering at y=%d! oops!\n",pLeft->Y); + return; + } + + int x = XStart; + + if(x<0) + { + if(RENDERER && !lineHack) + { + printf("rasterizer rendering at x=%d! oops!\n",x); + return; + } + invw += dinvw_dx * -x; + u += du_dx * -x; + v += dv_dx * -x; + z += dz_dx * -x; + color[0] += dc_dx[0] * -x; + color[1] += dc_dx[1] * -x; + color[2] += dc_dx[2] * -x; + adr += -x; + width -= -x; + x = 0; + } + if(x+width > (RENDERER?256:engine->width)) + { + if(RENDERER && !lineHack) + { + printf("rasterizer rendering at x=%d! oops!\n",x+width-1); + return; + } + width = (RENDERER?256:engine->width)-x; + } + + while(width-- > 0) + { + pixel(adr,color[0],color[1],color[2],u,v,1.0f/invw,z); + adr++; + x++; + + invw += dinvw_dx; + u += du_dx; + v += dv_dx; + z += dz_dx; + color[0] += dc_dx[0]; + color[1] += dc_dx[1]; + color[2] += dc_dx[2]; + } + } + + //runs several scanlines, until an edge is finished + template<bool SLI> + void runscanlines(edge_fx_fl *left, edge_fx_fl *right, bool horizontal, bool lineHack) + { + //oh lord, hack city for edge drawing + + //do not overstep either of the edges + int Height = min(left->Height,right->Height); + bool first=true; + + //HACK: special handling for horizontal line poly + if (lineHack && left->Height == 0 && right->Height == 0 && left->Y<192 && left->Y>=0) + { + bool draw = (!SLI || (left->Y & SLI_MASK) == SLI_VALUE); + if(draw) drawscanline(left,right,lineHack); + } + + while(Height--) { + bool draw = (!SLI || (left->Y & SLI_MASK) == SLI_VALUE); + if(draw) drawscanline(left,right,lineHack); + const int xl = left->X; + const int xr = right->X; + const int y = left->Y; + left->Step(); + right->Step(); + + if(!RENDERER && _debug_thisPoly) + { + //debug drawing + bool top = (horizontal&&first); + bool bottom = (!Height&&horizontal); + if(Height || top || bottom) + { + if(draw) + { + int nxl = left->X; + int nxr = right->X; + if(top) { + int xs = min(xl,xr); + int xe = max(xl,xr); + for(int x=xs;x<=xe;x++) { + int adr = (y*engine->width)+x; + engine->screenColor[adr].r = 63; + engine->screenColor[adr].g = 0; + engine->screenColor[adr].b = 0; + } + } else if(bottom) { + int xs = min(xl,xr); + int xe = max(xl,xr); + for(int x=xs;x<=xe;x++) { + int adr = (y*engine->width)+x; + engine->screenColor[adr].r = 63; + engine->screenColor[adr].g = 0; + engine->screenColor[adr].b = 0; + } + } else + { + int xs = min(xl,nxl); + int xe = max(xl,nxl); + for(int x=xs;x<=xe;x++) { + int adr = (y*engine->width)+x; + engine->screenColor[adr].r = 63; + engine->screenColor[adr].g = 0; + engine->screenColor[adr].b = 0; + } + xs = min(xr,nxr); + xe = max(xr,nxr); + for(int x=xs;x<=xe;x++) { + int adr = (y*engine->width)+x; + engine->screenColor[adr].r = 63; + engine->screenColor[adr].g = 0; + engine->screenColor[adr].b = 0; + } + } + + } + } + first = false; + } + } + } + + + //rotates verts counterclockwise + template<int type> + INLINE void rot_verts() { + #define ROTSWAP(X) if(type>X) swap(verts[X-1],verts[X]); + ROTSWAP(1); ROTSWAP(2); ROTSWAP(3); ROTSWAP(4); + ROTSWAP(5); ROTSWAP(6); ROTSWAP(7); ROTSWAP(8); ROTSWAP(9); + } + + //rotate verts until vert0.y is minimum, and then vert0.x is minimum in case of ties + //this is a necessary precondition for our shape engine + template<int type> + void sort_verts(bool backwards) { + //if the verts are backwards, reorder them first + if(backwards) + for(int i=0;i<type/2;i++) + swap(verts[i],verts[type-i-1]); + + for(;;) + { + //this was the only way we could get this to unroll + #define CHECKY(X) if(type>X) if(verts[0]->y > verts[X]->y) goto doswap; + CHECKY(1); CHECKY(2); CHECKY(3); CHECKY(4); + CHECKY(5); CHECKY(6); CHECKY(7); CHECKY(8); CHECKY(9); + break; + + doswap: + rot_verts<type>(); + } + + while(verts[0]->y == verts[1]->y && verts[0]->x > verts[1]->x) + { + rot_verts<type>(); + // hack for VC++ 2010 (bug in compiler optimization?) + // freeze on 3D + // TODO: study it + #if defined(_MSC_VER) && _MSC_VER == 1600 + Sleep(0); // nop + #endif + } + + } + + //This function can handle any convex N-gon up to octagons + //verts must be clockwise. + //I didnt reference anything for this algorithm but it seems like I've seen it somewhere before. + //Maybe it is like crow's algorithm + template<bool SLI> + void shape_engine(int type, bool backwards, bool lineHack) + { + bool failure = false; + + switch(type) { + case 3: sort_verts<3>(backwards); break; + case 4: sort_verts<4>(backwards); break; + case 5: sort_verts<5>(backwards); break; + case 6: sort_verts<6>(backwards); break; + case 7: sort_verts<7>(backwards); break; + case 8: sort_verts<8>(backwards); break; + case 9: sort_verts<9>(backwards); break; + case 10: sort_verts<10>(backwards); break; + default: printf("skipping type %d\n",type); return; + } + + //we are going to step around the polygon in both directions starting from vert 0. + //right edges will be stepped over clockwise and left edges stepped over counterclockwise. + //these variables track that stepping, but in order to facilitate wrapping we start extra high + //for the counter we're decrementing. + int lv = type, rv = 0; + + edge_fx_fl left, right; + bool step_left = true, step_right = true; + for(;;) { + //generate new edges if necessary. we must avoid regenerating edges when they are incomplete + //so that they can be continued on down the shape + assert(rv != type); + int _lv = lv==type?0:lv; //make sure that we ask for vert 0 when the variable contains the starting value + if(step_left) left = edge_fx_fl(_lv,lv-1,(VERT**)&verts, failure); + if(step_right) right = edge_fx_fl(rv,rv+1,(VERT**)&verts, failure); + step_left = step_right = false; + + //handle a failure in the edge setup due to nutty polys + if(failure) + return; + + bool horizontal = left.Y == right.Y; + runscanlines<SLI>(&left,&right,horizontal, lineHack); + + //if we ran out of an edge, step to the next one + if(right.Height == 0) { + step_right = true; + rv++; + } + if(left.Height == 0) { + step_left = true; + lv--; + } + + //this is our completion condition: when our stepped edges meet in the middle + if(lv<=rv+1) break; + } + + } + + SoftRasterizerEngine* engine; + + template<bool SLI> + FORCEINLINE void mainLoop(SoftRasterizerEngine* const engine) + { + this->engine = engine; + lastTexKey = NULL; + + u32 lastPolyAttr = 0; + u32 lastTextureFormat = 0, lastTexturePalette = 0; + + //iterate over polys + bool first=true; + for(int i=0;i<engine->clippedPolyCounter;i++) + { + if(!RENDERER) _debug_thisPoly = (i==engine->_debug_drawClippedUserPoly); + if(!engine->polyVisible[i]) continue; + polynum = i; + + GFX3D_Clipper::TClippedPoly &clippedPoly = engine->clippedPolys[i]; + POLY *poly = clippedPoly.poly; + int type = clippedPoly.type; + + if(first || lastPolyAttr != poly->polyAttr) + { + polyAttr.setup(poly->polyAttr); + polyAttr.translucent = poly->isTranslucent(); + lastPolyAttr = poly->polyAttr; + } + + + if(first || lastTextureFormat != poly->texParam || lastTexturePalette != poly->texPalette) + { + sampler.setup(poly->texParam); + lastTextureFormat = poly->texParam; + lastTexturePalette = poly->texPalette; + } + + first = false; + + lastTexKey = engine->polyTexKeys[i]; + + //hmm... shader gets setup every time because it depends on sampler which may have just changed + setupShader(poly->polyAttr); + + for(int j=0;j<type;j++) + this->verts[j] = &clippedPoly.clipVerts[j]; + for(int j=type;j<MAX_CLIPPED_VERTS;j++) + this->verts[j] = NULL; + + polyAttr.backfacing = engine->polyBackfacing[i]; + + shape_engine<SLI>(type,!polyAttr.backfacing, gfx3d_IsLinePoly(poly)); + } + } + + +}; //rasterizerUnit + +static SoftRasterizerEngine mainSoftRasterizer; + +static Task rasterizerUnitTask[4]; +static RasterizerUnit<true> rasterizerUnit[4]; +static RasterizerUnit<false> _HACK_viewer_rasterizerUnit; +static int rasterizerCores; +static bool rasterizerUnitTasksInited = false; + +static void* execRasterizerUnit(void* arg) +{ + intptr_t which = (intptr_t)arg; + rasterizerUnit[which].mainLoop<true>(&mainSoftRasterizer); + return 0; +} + +static char SoftRastInit(void) +{ + if(!rasterizerUnitTasksInited) + { + rasterizerUnitTasksInited = true; + + _HACK_viewer_rasterizerUnit.SLI_MASK = 1; + _HACK_viewer_rasterizerUnit.SLI_VALUE = 0; + + if(CommonSettings.num_cores>=4) + { + rasterizerCores = 4; + rasterizerUnit[0].SLI_MASK = 3; + rasterizerUnit[1].SLI_MASK = 3; + rasterizerUnit[2].SLI_MASK = 3; + rasterizerUnit[3].SLI_MASK = 3; + rasterizerUnit[0].SLI_VALUE = 0; + rasterizerUnit[1].SLI_VALUE = 1; + rasterizerUnit[2].SLI_VALUE = 2; + rasterizerUnit[3].SLI_VALUE = 3; + rasterizerUnitTask[0].start(false); + rasterizerUnitTask[1].start(false); + rasterizerUnitTask[2].start(false); + rasterizerUnitTask[3].start(false); + } else if(CommonSettings.num_cores>1) + { + rasterizerCores = 2; + rasterizerUnit[0].SLI_MASK = 1; + rasterizerUnit[1].SLI_MASK = 1; + rasterizerUnit[0].SLI_VALUE = 0; + rasterizerUnit[1].SLI_VALUE = 1; + rasterizerUnitTask[0].start(false); + rasterizerUnitTask[1].start(false); + } else { + rasterizerCores = 1; + rasterizerUnit[0].SLI_MASK = 0; + rasterizerUnit[0].SLI_VALUE = 0; + } + } + + static bool tables_generated = false; + if(!tables_generated) + { + tables_generated = true; + + for(int i=0;i<64;i++) + { + for(int j=0;j<64;j++) + { + modulate_table[i][j] = ((i+1) * (j+1) - 1) >> 6; + for(int a=0;a<32;a++) + decal_table[a][i][j] = ((i*a) + (j*(31-a))) >> 5; + } + } + + //these tables are used to increment through vert lists without having to do wrapping logic/math + int idx=0; + for(int i=3;i<=8;i++) + { + index_start_table[i-3] = idx; + for(int j=0;j<i;j++) { + int a = j; + int b = j+1; + if(b==i) b = 0; + index_lookup_table[idx++] = a; + index_lookup_table[idx++] = b; + } + } + } + + TexCache_Reset(); + + printf("SoftRast Initialized with cores=%d\n",rasterizerCores); + return 1; +} + +static void SoftRastReset() { + TexCache_Reset(); +} + +static void SoftRastClose() +{ + for(int i=0;i<4;i++) + rasterizerUnitTask[i].shutdown(); + rasterizerUnitTasksInited = false; +} + +static void SoftRastVramReconfigureSignal() { + TexCache_Invalidate(); +} + +static void SoftRastConvertFramebuffer() +{ + memcpy(gfx3d_convertedScreen,_screenColor,256*192*4); +} + +void SoftRasterizerEngine::initFramebuffer(const int width, const int height, const bool clearImage) +{ + const int todo = width*height; + + Fragment clearFragment; + FragmentColor clearFragmentColor; + clearFragment.isTranslucentPoly = 0; + clearFragmentColor.r = GFX3D_5TO6(gfx3d.renderState.clearColor&0x1F); + clearFragmentColor.g = GFX3D_5TO6((gfx3d.renderState.clearColor>>5)&0x1F); + clearFragmentColor.b = GFX3D_5TO6((gfx3d.renderState.clearColor>>10)&0x1F); + clearFragmentColor.a = ((gfx3d.renderState.clearColor>>16)&0x1F); + clearFragment.polyid.opaque = (gfx3d.renderState.clearColor>>24)&0x3F; + //special value for uninitialized translucent polyid. without this, fires in spiderman2 dont display + //I am not sure whether it is right, though. previously this was cleared to 0, as a guess, + //but in spiderman2 some fires with polyid 0 try to render on top of the background + clearFragment.polyid.translucent = kUnsetTranslucentPolyID; + clearFragment.depth = gfx3d.renderState.clearDepth; + clearFragment.stencil = 0; + clearFragment.isTranslucentPoly = 0; + clearFragment.fogged = BIT15(gfx3d.renderState.clearColor); + for(int i=0;i<todo;i++) + screen[i] = clearFragment; + + if(clearImage) + { + //need to handle this somehow.. + assert(width==256 && height==192); + + u16* clearImage = (u16*)MMU.texInfo.textureSlotAddr[2]; + u16* clearDepth = (u16*)MMU.texInfo.textureSlotAddr[3]; + + //the lion, the witch, and the wardrobe (thats book 1, suck it you new-school numberers) + //uses the scroll registers in the main game engine + u16 scroll = T1ReadWord(MMU.ARM9_REG,0x356); //CLRIMAGE_OFFSET + u16 xscroll = scroll&0xFF; + u16 yscroll = (scroll>>8)&0xFF; + + FragmentColor *dstColor = screenColor; + Fragment *dst = screen; + + for(int iy=0;iy<192;iy++) { + int y = ((iy + yscroll)&255)<<8; + for(int ix=0;ix<256;ix++) { + int x = (ix + xscroll)&255; + int adr = y + x; + + //this is tested by harry potter and the order of the phoenix. + //TODO (optimization) dont do this if we are mapped to blank memory (such as in sonic chronicles) + //(or use a special zero fill in the bulk clearing above) + u16 col = clearImage[adr]; + dstColor->color = RGB15TO6665(col,31*(col>>15)); + + //this is tested quite well in the sonic chronicles main map mode + //where depth values are used for trees etc you can walk behind + u32 depth = clearDepth[adr]; + dst->fogged = BIT15(depth); + //TODO - might consider a lookup table for this + dst->depth = gfx3d_extendDepth_15_to_24(depth&0x7FFF); + + dstColor++; + dst++; + } + } + } + else + for(int i=0;i<todo;i++) + screenColor[i] = clearFragmentColor; +} + +void SoftRasterizerEngine::updateToonTable() +{ + //convert the toon colors + for(int i=0;i<32;i++) { + #ifdef WORDS_BIGENDIAN + u32 u32temp = RGB15TO32_NOALPHA(gfx3d.renderState.u16ToonTable[i]); + toonTable[i].r = (u32temp >> 2) & 0x3F; + toonTable[i].g = (u32temp >> 10) & 0x3F; + toonTable[i].b = (u32temp >> 18) & 0x3F; + #else + toonTable[i].color = (RGB15TO32_NOALPHA(gfx3d.renderState.u16ToonTable[i])>>2)&0x3F3F3F3F; + #endif + //printf("%d %d %d %d\n",toonTable[i].r,toonTable[i].g,toonTable[i].b,toonTable[i].a); + } +} + +void SoftRasterizerEngine::updateFogTable() +{ + u8* fogDensity = MMU.MMU_MEM[ARMCPU_ARM9][0x40] + 0x360; +#if 0 + //TODO - this might be a little slow; + //we might need to hash all the variables and only recompute this when something changes + const int increment = (0x400 >> gfx3d.renderState.fogShift); + for(u32 i=0;i<32768;i++) { + if(i<gfx3d.renderState.fogOffset) { + fogTable[i] = fogDensity[0]; + continue; + } + for(int j=0;j<32;j++) { + u32 value = gfx3d.renderState.fogOffset + increment*(j+1); + if(i<=value) { + if(j==0) { + fogTable[i] = fogDensity[0]; + goto done; + } else { + fogTable[i] = ((value-i)*(fogDensity[j-1]) + (increment-(value-i))*(fogDensity[j]))/increment; + goto done; + } + } + } + fogTable[i] = (fogDensity[31]); + done: ; + } +#else + // this should behave exactly the same as the previous loop, + // except much faster. (because it's not a 2d loop and isn't so branchy either) + // maybe it's fast enough to not need to be cached, now. + const int increment = ((1 << 10) >> gfx3d.renderState.fogShift); + const int incrementDivShift = 10 - gfx3d.renderState.fogShift; + u32 fogOffset = min<u32>(max<u32>(gfx3d.renderState.fogOffset, 0), 32768); + u32 iMin = min<u32>(32768, (( 1 + 1) << incrementDivShift) + fogOffset + 1 - increment); + u32 iMax = min<u32>(32768, ((32 + 1) << incrementDivShift) + fogOffset + 1 - increment); + assert(iMin <= iMax); + memset(fogTable, fogDensity[0], iMin); + for(u32 i = iMin; i < iMax; i++) { + int num = (i - fogOffset + (increment-1)); + int j = (num >> incrementDivShift) - 1; + u32 value = (num & ~(increment-1)) + fogOffset; + u32 diff = value - i; + assert(j >= 1 && j < 32); + fogTable[i] = ((diff*(fogDensity[j-1]) + (increment-diff)*(fogDensity[j])) >> incrementDivShift); + } + memset(fogTable+iMax, fogDensity[31], 32768-iMax); +#endif +} + +void SoftRasterizerEngine::updateFloatColors() +{ + //convert colors to float to get more precision in case we need it + for(int i=0;i<vertlist->count;i++) + vertlist->list[i].color_to_float(); +} + +SoftRasterizerEngine::SoftRasterizerEngine() + : _debug_drawClippedUserPoly(-1) +{ + this->clippedPolys = clipper.clippedPolys = new GFX3D_Clipper::TClippedPoly[POLYLIST_SIZE*2]; +} + +void SoftRasterizerEngine::framebufferProcess() +{ + // this looks ok although it's still pretty much a hack, + // it needs to be redone with low-level accuracy at some point, + // but that should probably wait until the shape renderer is more accurate. + // a good test case for edge marking is Sonic Rush: + // - the edges are completely sharp/opaque on the very brief title screen intro, + // - the level-start intro gets a pseudo-antialiasing effect around the silhouette, + // - the character edges in-level are clearly transparent, and also show well through shield powerups. + if(gfx3d.renderState.enableEdgeMarking && CommonSettings.GFX3D_EdgeMark) + { + //TODO - need to test and find out whether these get grabbed at flush time, or at render time + //we can do this by rendering a 3d frame and then freezing the system, but only changing the edge mark colors + FragmentColor edgeMarkColors[8]; + int edgeMarkDisabled[8]; + + for(int i=0;i<8;i++) + { + u16 col = T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x330+i*2); + edgeMarkColors[i].color = RGB15TO5555(col,gfx3d.state.enableAntialiasing ? 0x0F : 0x1F); + edgeMarkColors[i].r = GFX3D_5TO6(edgeMarkColors[i].r); + edgeMarkColors[i].g = GFX3D_5TO6(edgeMarkColors[i].g); + edgeMarkColors[i].b = GFX3D_5TO6(edgeMarkColors[i].b); + + // this seems to be the only thing that selectively disables edge marking + edgeMarkDisabled[i] = (col == 0x7FFF); + } + + for(int i=0,y=0;y<192;y++) + { + for(int x=0;x<256;x++,i++) + { + Fragment destFragment = screen[i]; + u8 self = destFragment.polyid.opaque; + if(edgeMarkDisabled[self>>3]) continue; + if(destFragment.isTranslucentPoly) continue; + + // > is used instead of != to prevent double edges + // between overlapping polys of different IDs. + // also note that the edge generally goes on the outside, not the inside, (maybe needs to change later) + // and that polys with the same edge color can make edges against each other. + + FragmentColor edgeColor = edgeMarkColors[self>>3]; + +#define PIXOFFSET(dx,dy) ((dx)+(256*(dy))) +#define ISEDGE(dx,dy) ((x+(dx)!=256) && (x+(dx)!=-1) && (y+(dy)!=192) && (y+(dy)!=-1) && self > screen[i+PIXOFFSET(dx,dy)].polyid.opaque) +#define DRAWEDGE(dx,dy) alphaBlend(screenColor[i+PIXOFFSET(dx,dy)], edgeColor) + + bool upleft = ISEDGE(-1,-1); + bool up = ISEDGE( 0,-1); + bool upright = ISEDGE( 1,-1); + bool left = ISEDGE(-1, 0); + bool right = ISEDGE( 1, 0); + bool downleft = ISEDGE(-1, 1); + bool down = ISEDGE( 0, 1); + bool downright = ISEDGE( 1, 1); + + if(upleft && upright && downleft && !downright) + DRAWEDGE(-1,-1); + if(up && !down) + DRAWEDGE(0,-1); + if(upleft && upright && !downleft && downright) + DRAWEDGE(1,-1); + if(left && !right) + DRAWEDGE(-1,0); + if(right && !left) + DRAWEDGE(1,0); + if(upleft && !upright && downleft && downright) + DRAWEDGE(-1,1); + if(down && !up) + DRAWEDGE(0,1); + if(!upleft && upright && downleft && downright) + DRAWEDGE(1,1); + +#undef PIXOFFSET +#undef ISEDGE +#undef DRAWEDGE + + } + } + } + + if(gfx3d.renderState.enableFog && CommonSettings.GFX3D_Fog) + { + u32 r = GFX3D_5TO6((gfx3d.renderState.fogColor)&0x1F); + u32 g = GFX3D_5TO6((gfx3d.renderState.fogColor>>5)&0x1F); + u32 b = GFX3D_5TO6((gfx3d.renderState.fogColor>>10)&0x1F); + u32 a = (gfx3d.renderState.fogColor>>16)&0x1F; + for(int i=0;i<256*192;i++) + { + Fragment &destFragment = screen[i]; + if(!destFragment.fogged) continue; + FragmentColor &destFragmentColor = screenColor[i]; + u32 fogIndex = destFragment.depth>>9; + assert(fogIndex<32768); + u8 fog = fogTable[fogIndex]; + if(fog==127) fog=128; + if(!gfx3d.renderState.enableFogAlphaOnly) + { + destFragmentColor.r = ((128-fog)*destFragmentColor.r + r*fog)>>7; + destFragmentColor.g = ((128-fog)*destFragmentColor.g + g*fog)>>7; + destFragmentColor.b = ((128-fog)*destFragmentColor.b + b*fog)>>7; + } + destFragmentColor.a = ((128-fog)*destFragmentColor.a + a*fog)>>7; + } + } + + ////debug alpha channel framebuffer contents + //for(int i=0;i<256*192;i++) + //{ + // FragmentColor &destFragmentColor = screenColor[i]; + // destFragmentColor.r = destFragmentColor.a; + // destFragmentColor.g = destFragmentColor.a; + // destFragmentColor.b = destFragmentColor.a; + //} +} + +void SoftRasterizerEngine::performClipping(bool hirez) +{ + //submit all polys to clipper + clipper.reset(); + for(int i=0;i<polylist->count;i++) + { + POLY* poly = &polylist->list[indexlist->list[i]]; + VERT* clipVerts[4] = { + &vertlist->list[poly->vertIndexes[0]], + &vertlist->list[poly->vertIndexes[1]], + &vertlist->list[poly->vertIndexes[2]], + poly->type==4 + ?&vertlist->list[poly->vertIndexes[3]] + :NULL + }; + + if(hirez) + clipper.clipPoly<true>(poly,clipVerts); + else + clipper.clipPoly<false>(poly,clipVerts); + } + clippedPolyCounter = clipper.clippedPolyCounter; +} + +template<bool CUSTOM> void SoftRasterizerEngine::performViewportTransforms(int width, int height) +{ + const float xfactor = width/256.0f; + const float yfactor = height/192.0f; + const float xmax = 256.0f*xfactor-(CUSTOM?0.001f:0); //fudge factor to keep from overrunning render buffers + const float ymax = 192.0f*yfactor-(CUSTOM?0.001f:0); + + + //viewport transforms + for(int i=0;i<clippedPolyCounter;i++) + { + GFX3D_Clipper::TClippedPoly &poly = clippedPolys[i]; + for(int j=0;j<poly.type;j++) + { + VERT &vert = poly.clipVerts[j]; + + //homogeneous divide + vert.coord[0] = (vert.coord[0]+vert.coord[3]) / (2*vert.coord[3]); + vert.coord[1] = (vert.coord[1]+vert.coord[3]) / (2*vert.coord[3]); + vert.coord[2] = (vert.coord[2]+vert.coord[3]) / (2*vert.coord[3]); + vert.texcoord[0] /= vert.coord[3]; + vert.texcoord[1] /= vert.coord[3]; + + //CONSIDER: do we need to guarantee that these are in bounds? perhaps not. + //vert.coord[0] = max(0.0f,min(1.0f,vert.coord[0])); + //vert.coord[1] = max(0.0f,min(1.0f,vert.coord[1])); + //vert.coord[2] = max(0.0f,min(1.0f,vert.coord[2])); + + //perspective-correct the colors + vert.fcolor[0] /= vert.coord[3]; + vert.fcolor[1] /= vert.coord[3]; + vert.fcolor[2] /= vert.coord[3]; + + //viewport transformation + VIEWPORT viewport; + viewport.decode(poly.poly->viewport); + vert.coord[0] *= viewport.width * xfactor; + vert.coord[0] += viewport.x * xfactor; + vert.coord[1] *= viewport.height * yfactor; + vert.coord[1] += viewport.y * yfactor; + vert.coord[1] = ymax - vert.coord[1]; + + //well, i guess we need to do this to keep Princess Debut from rendering huge polys. + //there must be something strange going on + vert.coord[0] = max(0.0f,min(xmax,vert.coord[0])); + vert.coord[1] = max(0.0f,min(ymax,vert.coord[1])); + } + } +} +//these templates needed to be instantiated manually +template void SoftRasterizerEngine::performViewportTransforms<true>(int width, int height); +template void SoftRasterizerEngine::performViewportTransforms<false>(int width, int height); + +void SoftRasterizerEngine::performCoordAdjustment(const bool skipBackfacing) +{ + for(int i=0;i<clippedPolyCounter;i++) + { + GFX3D_Clipper::TClippedPoly &clippedPoly = clippedPolys[i]; + int type = clippedPoly.type; + VERT* verts = &clippedPoly.clipVerts[0]; + + //here is a hack which needs to be removed. + //at some point our shape engine needs these to be converted to "fixed point" + //which is currently just a float + for(int j=0;j<type;j++) + for(int k=0;k<2;k++) + verts[j].coord[k] = (float)iround(16.0f * verts[j].coord[k]); + } +} + +void SoftRasterizerEngine::setupTextures(const bool skipBackfacing) +{ + TexCacheItem* lastTexKey = NULL; + u32 lastTextureFormat = 0, lastTexturePalette = 0; + bool needInitTexture = true; + for(int i=0;i<clippedPolyCounter;i++) + { + GFX3D_Clipper::TClippedPoly &clippedPoly = clippedPolys[i]; + POLY *poly = clippedPoly.poly; + + PolyAttr polyAttr; + polyAttr.setup(poly->polyAttr); + + //make sure all the textures we'll need are cached + //(otherwise on a multithreaded system there will be multiple writers-- + //this SHOULD be read-only, although some day the texcache may collect statistics or something + //and then it won't be safe. + if(needInitTexture || lastTextureFormat != poly->texParam || lastTexturePalette != poly->texPalette) + { + lastTexKey = TexCache_SetTexture(TexFormat_15bpp,poly->texParam,poly->texPalette); + lastTextureFormat = poly->texParam; + lastTexturePalette = poly->texPalette; + needInitTexture = false; + } + + //printf("%08X %d\n",poly->texParam,rasterizerUnit[0].textures.currentNum); + polyTexKeys[i] = lastTexKey; + } +} + +void SoftRasterizerEngine::performBackfaceTests() +{ + for(int i=0;i<clippedPolyCounter;i++) + { + GFX3D_Clipper::TClippedPoly &clippedPoly = clippedPolys[i]; + POLY *poly = clippedPoly.poly; + int type = clippedPoly.type; + VERT* verts = &clippedPoly.clipVerts[0]; + + PolyAttr polyAttr; + polyAttr.setup(poly->polyAttr); + + //HACK: backface culling + //this should be moved to gfx3d, but first we need to redo the way the lists are built + //because it is too convoluted right now. + //(must we throw out verts if a poly gets backface culled? if not, then it might be easier) + + //an older approach + //(not good enough for quads and other shapes) + //float ab[2], ac[2]; Vector2Copy(ab, verts[1].coord); Vector2Copy(ac, verts[2].coord); Vector2Subtract(ab, verts[0].coord); + //Vector2Subtract(ac, verts[0].coord); float cross = Vector2Cross(ab, ac); polyAttr.backfacing = (cross>0); + + //a better approach + // we have to support somewhat non-convex polygons (see NSMB world map 1st screen). + // this version should handle those cases better. + int n = type - 1; + float facing = (verts[0].y + verts[n].y) * (verts[0].x - verts[n].x) + + (verts[1].y + verts[0].y) * (verts[1].x - verts[0].x) + + (verts[2].y + verts[1].y) * (verts[2].x - verts[1].x); + for(int j = 2; j < n; j++) + facing += (verts[j+1].y + verts[j].y) * (verts[j+1].x - verts[j].x); + + polyBackfacing[i] = polyAttr.backfacing = (facing < 0); + polyVisible[i] = polyAttr.isVisible(polyAttr.backfacing); + } +} + +void _HACK_Viewer_ExecUnit(SoftRasterizerEngine* engine) +{ + _HACK_viewer_rasterizerUnit.mainLoop<false>(engine); +} + +static void SoftRastRender() +{ + mainSoftRasterizer.polylist = gfx3d.polylist; + mainSoftRasterizer.vertlist = gfx3d.vertlist; + mainSoftRasterizer.indexlist = &gfx3d.indexlist; + mainSoftRasterizer.screen = _screen; + mainSoftRasterizer.screenColor = _screenColor; + mainSoftRasterizer.width = 256; + mainSoftRasterizer.height = 192; + + //setup fog variables (but only if fog is enabled) + if(gfx3d.renderState.enableFog && CommonSettings.GFX3D_Fog) + mainSoftRasterizer.updateFogTable(); + + mainSoftRasterizer.initFramebuffer(256,192,gfx3d.renderState.enableClearImage?true:false); + mainSoftRasterizer.updateToonTable(); + mainSoftRasterizer.updateFloatColors(); + mainSoftRasterizer.performClipping(CommonSettings.GFX3D_HighResolutionInterpolateColor); + mainSoftRasterizer.performViewportTransforms<false>(256,192); + mainSoftRasterizer.performBackfaceTests(); + mainSoftRasterizer.performCoordAdjustment(true); + mainSoftRasterizer.setupTextures(true); + + + if(rasterizerCores==1) + { + rasterizerUnit[0].mainLoop<false>(&mainSoftRasterizer); + } + else + { + for(int i=0;i<rasterizerCores;i++) rasterizerUnitTask[i].execute(execRasterizerUnit,(void*)i); + for(int i=0;i<rasterizerCores;i++) rasterizerUnitTask[i].finish(); + } + + TexCache_EvictFrame(); + + + mainSoftRasterizer.framebufferProcess(); + + // printf("rendered %d of %d polys after backface culling\n",gfx3d.polylist->count-culled,gfx3d.polylist->count); + SoftRastConvertFramebuffer(); +} + +GPU3DInterface gpu3DRasterize = { + "SoftRasterizer", + SoftRastInit, + SoftRastReset, + SoftRastClose, + SoftRastRender, + SoftRastVramReconfigureSignal, +}; + diff --git a/jni/desmume/src/rasterize.h b/jni/desmume/src/rasterize.h new file mode 100755 index 0000000..155e145 --- /dev/null +++ b/jni/desmume/src/rasterize.h @@ -0,0 +1,100 @@ +/* + Copyright (C) 2009-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _RASTERIZE_H_ +#define _RASTERIZE_H_ + +#include "render3D.h" +#include "gfx3d.h" + +extern GPU3DInterface gpu3DRasterize; + +union FragmentColor { + u32 color; + struct { +#ifdef WORDS_BIGENDIAN + u8 a,b,g,r; +#else + u8 r,g,b,a; +#endif + }; +}; + +inline FragmentColor MakeFragmentColor(u8 r, u8 g,u8 b,u8 a) +{ + FragmentColor ret; + ret.r = r; ret.g = g; ret.b = b; ret.a = a; + return ret; +} + +struct Fragment +{ + u32 depth; + + struct + { + u8 opaque, translucent; + } polyid; + + u8 stencil; + + struct + { + u8 isTranslucentPoly:1; + u8 fogged:1; + }; +}; + +class TexCacheItem; + +class SoftRasterizerEngine +{ +public: + //debug: + int _debug_drawClippedUserPoly; + + SoftRasterizerEngine(); + + void initFramebuffer(const int width, const int height, const bool clearImage); + void framebufferProcess(); + void updateToonTable(); + void updateFogTable(); + void updateFloatColors(); + void performClipping(bool hirez); + template<bool CUSTOM> void performViewportTransforms(int width, int height); + void performCoordAdjustment(const bool skipBackfacing); + void performBackfaceTests(); + void setupTextures(const bool skipBackfacing); + + FragmentColor toonTable[32]; + u8 fogTable[32768]; + GFX3D_Clipper clipper; + GFX3D_Clipper::TClippedPoly *clippedPolys; + int clippedPolyCounter; + TexCacheItem* polyTexKeys[POLYLIST_SIZE]; + bool polyVisible[POLYLIST_SIZE]; + bool polyBackfacing[POLYLIST_SIZE]; + Fragment *screen; + FragmentColor *screenColor; + POLYLIST* polylist; + VERTLIST* vertlist; + INDEXLIST* indexlist; + int width, height; +}; + + +#endif diff --git a/jni/desmume/src/readwrite.cpp b/jni/desmume/src/readwrite.cpp new file mode 100755 index 0000000..bea0199 --- /dev/null +++ b/jni/desmume/src/readwrite.cpp @@ -0,0 +1,152 @@ +/* + Copyright (C) 2006-2009 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "readwrite.h" +#include "types.h" + +//well. just for the sake of consistency +int write8le(u8 b, EMUFILE*os) +{ + os->fwrite((char*)&b,1); + return 1; +} + +//well. just for the sake of consistency +int read8le(u8 *Bufo, EMUFILE*is) +{ + if(is->_fread((char*)Bufo,1) != 1) + return 0; + return 1; +} + +///writes a little endian 16bit value to the specified file +int write16le(u16 b, EMUFILE *fp) +{ + u8 s[2]; + s[0]=(u8)b; + s[1]=(u8)(b>>8); + fp->fwrite(s,2); + return 2; +} + + +///writes a little endian 32bit value to the specified file +int write32le(u32 b, EMUFILE *fp) +{ + u8 s[4]; + s[0]=(u8)b; + s[1]=(u8)(b>>8); + s[2]=(u8)(b>>16); + s[3]=(u8)(b>>24); + fp->fwrite(s,4); + return 4; +} + +void writebool(bool b, EMUFILE* os) { write32le(b?1:0,os); } + +int write64le(u64 b, EMUFILE* os) +{ + u8 s[8]; + s[0]=(u8)b; + s[1]=(u8)(b>>8); + s[2]=(u8)(b>>16); + s[3]=(u8)(b>>24); + s[4]=(u8)(b>>32); + s[5]=(u8)(b>>40); + s[6]=(u8)(b>>48); + s[7]=(u8)(b>>56); + os->fwrite((char*)&s,8); + return 8; +} + + +int read32le(u32 *Bufo, EMUFILE *fp) +{ + u32 buf; + if(fp->_fread(&buf,4)<4) + return 0; +#ifdef LOCAL_LE + *(u32*)Bufo=buf; +#else + *(u32*)Bufo=((buf&0xFF)<<24)|((buf&0xFF00)<<8)|((buf&0xFF0000)>>8)|((buf&0xFF000000)>>24); +#endif + return 1; +} + +int read16le(u16 *Bufo, EMUFILE *is) +{ + u16 buf; + if(is->_fread((char*)&buf,2) != 2) + return 0; +#ifdef LOCAL_LE + *Bufo=buf; +#else + *Bufo = LE_TO_LOCAL_16(buf); +#endif + return 1; +} + +int read64le(u64 *Bufo, EMUFILE *is) +{ + u64 buf; + if(is->_fread((char*)&buf,8) != 8) + return 0; +#ifdef LOCAL_LE + *Bufo=buf; +#else + *Bufo = LE_TO_LOCAL_64(buf); +#endif + return 1; +} + +static int read32le(u32 *Bufo, std::istream *is) +{ + u32 buf; + if(is->read((char*)&buf,4).gcount() != 4) + return 0; +#ifdef LOCAL_LE + *(u32*)Bufo=buf; +#else + *(u32*)Bufo=((buf&0xFF)<<24)|((buf&0xFF00)<<8)|((buf&0xFF0000)>>8)|((buf&0xFF000000)>>24); +#endif + return 1; +} + +int readbool(bool *b, EMUFILE* is) +{ + u32 temp; + int ret = read32le(&temp,is); + *b = temp!=0; + return ret; +} + +int readbuffer(std::vector<u8> &vec, EMUFILE* is) +{ + u32 size; + if(read32le(&size,is) != 1) return 0; + vec.resize(size); + if(size>0) is->fread((char*)&vec[0],size); + return 1; +} + +int writebuffer(std::vector<u8>& vec, EMUFILE* os) +{ + u32 size = vec.size(); + write32le(size,os); + if(size>0) os->fwrite((char*)&vec[0],size); + return 1; +} diff --git a/jni/desmume/src/readwrite.h b/jni/desmume/src/readwrite.h new file mode 100755 index 0000000..8c945c9 --- /dev/null +++ b/jni/desmume/src/readwrite.h @@ -0,0 +1,67 @@ +/* + Copyright (C) 2008-2009 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _READWRITE_H_ +#define _READWRITE_H_ + +#include "types.h" +#include "emufile.h" +#include <iostream> +#include <cstdio> +#include <vector> + +//well. just for the sake of consistency +int write8le(u8 b, EMUFILE *fp); +inline int write8le(u8* b, EMUFILE *fp) { return write8le(*b,fp); } +int write16le(u16 b, EMUFILE* os); +int write32le(u32 b, EMUFILE* os); +int write64le(u64 b, EMUFILE* os); +inline int write_double_le(double b, EMUFILE*is) { u64 temp = double_to_u64(b); int ret = write64le(temp,is); return ret; } + +int read8le(u8 *Bufo, EMUFILE*is); +int read16le(u16 *Bufo, EMUFILE*is); +inline int read16le(s16 *Bufo, EMUFILE*is) { return read16le((u16*)Bufo,is); } +int read32le(u32 *Bufo, EMUFILE*is); +inline int read32le(s32 *Bufo, EMUFILE*is) { return read32le((u32*)Bufo,is); } +int read64le(u64 *Bufo, EMUFILE*is); +inline int read_double_le(double *Bufo, EMUFILE*is) { u64 temp; int ret = read64le(&temp,is); *Bufo = u64_to_double(temp); return ret; } +int read16le(u16 *Bufo, std::istream *is); + + +template<typename T> +int readle(T *Bufo, EMUFILE*is) +{ + CTASSERT(sizeof(T)==1||sizeof(T)==2||sizeof(T)==4||sizeof(T)==8); + switch(sizeof(T)) { + case 1: return read8le((u8*)Bufo,is); + case 2: return read16le((u16*)Bufo,is); + case 4: return read32le((u32*)Bufo,is); + case 8: return read64le((u64*)Bufo,is); + default: + return 0; + } +} + + + +int readbool(bool *b, EMUFILE* is); +void writebool(bool b, EMUFILE* os); + +int readbuffer(std::vector<u8> &vec, EMUFILE* is); +int writebuffer(std::vector<u8>& vec, EMUFILE* os); + +#endif diff --git a/jni/desmume/src/registers.h b/jni/desmume/src/registers.h new file mode 100755 index 0000000..4ed2d60 --- /dev/null +++ b/jni/desmume/src/registers.h @@ -0,0 +1,431 @@ +/* + Copyright (C) 2006 Theo Berkau + Copyright (C) 2006-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef REGISTERS_H +#define REGISTERS_H + +#define REG_REGION_MASK 0x0FFFEF80 +#define REG_BASE_DISPx 0x04000000 +#define REG_BASE_DISPA 0x04000000 +#define REG_BASE_DISPB 0x04001000 +#define REG_BASE_DMA 0x04000080 +#define REG_BASE_SIORTCTIMERS 0x04000100 +#define REG_BASE_ROMIPC 0x04000180 +#define REG_BASE_MEMIRQ 0x04000200 +#define REG_BASE_MATH 0x04000280 +#define REG_BASE_OTHER 0x04000300 +#define REG_BASE_RCVPORTS 0x04100000 + +// Display Engine A +#define REG_DISPA_DISPCNT 0x04000000 +#define REG_DISPA_VCOUNT 0x04000006 +#define REG_DISPA_BG0CNT 0x04000008 +#define REG_DISPA_BG1CNT 0x0400000A +#define REG_DISPA_BG2CNT 0x0400000C +#define REG_DISPA_BG3CNT 0x0400000E +#define REG_DISPA_BG0HOFS 0x04000010 +#define REG_DISPA_BG0VOFS 0x04000012 +#define REG_DISPA_BG1HOFS 0x04000014 +#define REG_DISPA_BG1VOFS 0x04000016 +#define REG_DISPA_BG2HOFS 0x04000018 +#define REG_DISPA_BG2VOFS 0x0400001A +#define REG_DISPA_BG3HOFS 0x0400001C +#define REG_DISPA_BG3VOFS 0x0400001E +#define REG_DISPA_BG2PA 0x04000020 +#define REG_DISPA_BG2PB 0x04000022 +#define REG_DISPA_BG2PC 0x04000024 +#define REG_DISPA_BG2PD 0x04000026 +#define REG_DISPA_BG2XL 0x04000028 +#define REG_DISPA_BG2XH 0x0400002A +#define REG_DISPA_BG2YL 0x0400002C +#define REG_DISPA_BG2YH 0x0400002E +#define REG_DISPA_BG3PA 0x04000030 +#define REG_DISPA_BG3PB 0x04000032 +#define REG_DISPA_BG3PC 0x04000034 +#define REG_DISPA_BG3PD 0x04000036 +#define REG_DISPA_BG3XL 0x04000038 +#define REG_DISPA_BG3XH 0x0400003A +#define REG_DISPA_BG3YL 0x0400003C +#define REG_DISPA_BG3YH 0x0400003E +#define REG_DISPA_WIN0H 0x04000040 +#define REG_DISPA_WIN1H 0x04000042 +#define REG_DISPA_WIN0V 0x04000044 +#define REG_DISPA_WIN1V 0x04000046 +#define REG_DISPA_WININ 0x04000048 +#define REG_DISPA_WINOUT 0x0400004A +#define REG_DISPA_MOSAIC 0x0400004C +#define REG_DISPA_BLDCNT 0x04000050 +#define REG_DISPA_BLDALPHA 0x04000052 +#define REG_DISPA_BLDY 0x04000054 +#define REG_DISPA_MASTERBRIGHT 0x0400006C + +// DMA +#define _REG_DMA_CONTROL_MIN 0x040000B0 +#define REG_DMA0SAD 0x040000B0 +#define REG_DMA0SADL 0x040000B0 +#define REG_DMA0SADH 0x040000B2 +#define REG_DMA0DAD 0x040000B4 +#define REG_DMA0DADL 0x040000B4 +#define REG_DMA0DADH 0x040000B6 +#define REG_DMA0CNTL 0x040000B8 +#define REG_DMA0CNTH 0x040000BA +#define REG_DMA1SAD 0x040000BC +#define REG_DMA1SADL 0x040000BC +#define REG_DMA1SADH 0x040000BE +#define REG_DMA1DAD 0x040000C0 +#define REG_DMA1DADL 0x040000C0 +#define REG_DMA1DADH 0x040000C2 +#define REG_DMA1CNTL 0x040000C4 +#define REG_DMA1CNTH 0x040000C6 +#define REG_DMA2SAD 0x040000C8 +#define REG_DMA2SADL 0x040000C8 +#define REG_DMA2SADH 0x040000CA +#define REG_DMA2DAD 0x040000CC +#define REG_DMA2DADL 0x040000CC +#define REG_DMA2DADH 0x040000CE +#define REG_DMA2CNTL 0x040000D0 +#define REG_DMA2CNTH 0x040000D2 +#define REG_DMA3SAD 0x040000D4 +#define REG_DMA3SADL 0x040000D4 +#define REG_DMA3SADH 0x040000D6 +#define REG_DMA3DAD 0x040000D8 +#define REG_DMA3DADL 0x040000D8 +#define REG_DMA3DADH 0x040000DA +#define REG_DMA3CNTL 0x040000DC +#define REG_DMA3CNTH 0x040000DE +#define _REG_DMA_CONTROL_MAX 0x040000DF +#define REG_DMA0FILL 0x040000E0 +#define REG_DMA1FILL 0x040000E4 +#define REG_DMA2FILL 0x040000E8 +#define REG_DMA3FILL 0x040000EC + +// Timers +#define REG_TM0CNTL 0x04000100 +#define REG_TM0CNTH 0x04000102 +#define REG_TM1CNTL 0x04000104 +#define REG_TM1CNTH 0x04000106 +#define REG_TM2CNTL 0x04000108 +#define REG_TM2CNTH 0x0400010A +#define REG_TM3CNTL 0x0400010C +#define REG_TM3CNTH 0x0400010E + +// SIO/Keypad Input/RTC +#define REG_SIODATA32 0x04000120 +#define REG_SIOCNT 0x04000128 +#define REG_KEYINPUT 0x04000130 +#define REG_KEYCNT 0x04000132 +#define REG_RCNT 0x04000134 +#define REG_EXTKEYIN 0x04000136 +#define REG_RTC 0x04000138 + +// IPC +#define REG_IPCSYNC 0x04000180 +#define REG_IPCFIFOCNT 0x04000184 +#define REG_IPCFIFOSEND 0x04000188 + +// ROM +#define REG_AUXSPICNT 0x040001A0 +#define REG_AUXSPIDATA 0x040001A2 +#define REG_GCROMCTRL 0x040001A4 +#define REG_GCCMDOUT 0x040001A8 +#define REG_ENCSEED0L 0x040001B0 +#define REG_ENCSEED1L 0x040001B4 +#define REG_ENCSEED0H 0x040001B8 +#define REG_ENCSEED1H 0x040001BC +#define REG_SPICNT 0x040001C0 +#define REG_SPIDATA 0x040001C2 + +// Memory/IRQ +#define REG_EXMEMCNT 0x04000204 +#define REG_WIFIWAITCNT 0x04000206 +#define REG_IME 0x04000208 +#define REG_IE 0x04000210 +#define REG_IF 0x04000214 +#define REG_VRAMCNTA 0x04000240 +#define REG_VRAMSTAT 0x04000240 +#define REG_VRAMCNTB 0x04000241 +#define REG_WRAMSTAT 0x04000241 +#define REG_VRAMCNTC 0x04000242 +#define REG_VRAMCNTD 0x04000243 +#define REG_VRAMCNTE 0x04000244 +#define REG_VRAMCNTF 0x04000245 +#define REG_VRAMCNTG 0x04000246 +#define REG_WRAMCNT 0x04000247 +#define REG_VRAMCNTH 0x04000248 +#define REG_VRAMCNTI 0x04000249 + +// Math +#define REG_DIVCNT 0x04000280 +#define REG_DIVNUMER 0x04000290 +#define REG_DIVDENOM 0x04000298 +#define REG_DIVRESULT 0x040002A0 +#define REG_DIVREMRESULT 0x040002A8 +#define REG_SQRTCNT 0x040002B0 +#define REG_SQRTRESULT 0x040002B4 +#define REG_SQRTPARAM 0x040002B8 + +// Other +#define REG_POSTFLG 0x04000300 +#define REG_HALTCNT 0x04000301 +#define REG_POWCNT1 0x04000304 +#define REG_POWCNT2 0x04000304 +#define REG_BIOSPROT 0x04000308 + +#define REG_DISPB_DISPCNT 0x04001000 +#define REG_DISPB_BG0CNT 0x04001008 +#define REG_DISPB_BG1CNT 0x0400100A +#define REG_DISPB_BG2CNT 0x0400100C +#define REG_DISPB_BG3CNT 0x0400100E +#define REG_DISPB_BG0HOFS 0x04001010 +#define REG_DISPB_BG0VOFS 0x04001012 +#define REG_DISPB_BG1HOFS 0x04001014 +#define REG_DISPB_BG1VOFS 0x04001016 +#define REG_DISPB_BG2HOFS 0x04001018 +#define REG_DISPB_BG2VOFS 0x0400101A +#define REG_DISPB_BG3HOFS 0x0400101C +#define REG_DISPB_BG3VOFS 0x0400101E +#define REG_DISPB_BG2PA 0x04001020 +#define REG_DISPB_BG2PB 0x04001022 +#define REG_DISPB_BG2PC 0x04001024 +#define REG_DISPB_BG2PD 0x04001026 +#define REG_DISPB_BG2XL 0x04001028 +#define REG_DISPB_BG2XH 0x0400102A +#define REG_DISPB_BG2YL 0x0400102C +#define REG_DISPB_BG2YH 0x0400102E +#define REG_DISPB_BG3PA 0x04001030 +#define REG_DISPB_BG3PB 0x04001032 +#define REG_DISPB_BG3PC 0x04001034 +#define REG_DISPB_BG3PD 0x04001036 +#define REG_DISPB_BG3XL 0x04001038 +#define REG_DISPB_BG3XH 0x0400103A +#define REG_DISPB_BG3YL 0x0400103C +#define REG_DISPB_BG3YH 0x0400103E +#define REG_DISPB_WIN0H 0x04001040 +#define REG_DISPB_WIN1H 0x04001042 +#define REG_DISPB_WIN0V 0x04001044 +#define REG_DISPB_WIN1V 0x04001046 +#define REG_DISPB_WININ 0x04001048 +#define REG_DISPB_WINOUT 0x0400104A +#define REG_DISPB_MOSAIC 0x0400104C +#define REG_DISPB_BLDCNT 0x04001050 +#define REG_DISPB_BLDALPHA 0x04001052 +#define REG_DISPB_BLDY 0x04001054 +#define REG_DISPB_MASTERBRIGHT 0x0400106C + +// Receive ports +#define REG_IPCFIFORECV 0x04100000 +#define REG_GCDATAIN 0x04100010 + + + + + +#define REG_DISPB 0x00001000 +// core A and B specific +#define REG_DISPx_DISPCNT 0x04000000 +#define REG_DISPx_VCOUNT 0x04000006 +#define REG_DISPx_BG0CNT 0x04000008 +#define REG_DISPx_BG1CNT 0x0400000A +#define REG_DISPx_BG2CNT 0x0400000C +#define REG_DISPx_BG3CNT 0x0400000E +#define REG_DISPx_BG0HOFS 0x04000010 +#define REG_DISPx_BG0VOFS 0x04000012 +#define REG_DISPx_BG1HOFS 0x04000014 +#define REG_DISPx_BG1VOFS 0x04000016 +#define REG_DISPx_BG2HOFS 0x04000018 +#define REG_DISPx_BG2VOFS 0x0400001A +#define REG_DISPx_BG3HOFS 0x0400001C +#define REG_DISPx_BG3VOFS 0x0400001E +#define REG_DISPx_BG2PA 0x04000020 +#define REG_DISPx_BG2PB 0x04000022 +#define REG_DISPx_BG2PC 0x04000024 +#define REG_DISPx_BG2PD 0x04000026 +#define REG_DISPx_BG2XL 0x04000028 +#define REG_DISPx_BG2XH 0x0400002A +#define REG_DISPx_BG2YL 0x0400002C +#define REG_DISPx_BG2YH 0x0400002E +#define REG_DISPx_BG3PA 0x04000030 +#define REG_DISPx_BG3PB 0x04000032 +#define REG_DISPx_BG3PC 0x04000034 +#define REG_DISPx_BG3PD 0x04000036 +#define REG_DISPx_BG3XL 0x04000038 +#define REG_DISPx_BG3XH 0x0400003A +#define REG_DISPx_BG3YL 0x0400003C +#define REG_DISPx_BG3YH 0x0400003E +#define REG_DISPx_WIN0H 0x04000040 +#define REG_DISPx_WIN1H 0x04000042 +#define REG_DISPx_WIN0V 0x04000044 +#define REG_DISPx_WIN1V 0x04000046 +#define REG_DISPx_WININ 0x04000048 +#define REG_DISPx_WINOUT 0x0400004A +#define REG_DISPx_MOSAIC 0x0400004C +#define REG_DISPx_BLDCNT 0x04000050 +#define REG_DISPx_BLDALPHA 0x04000052 +#define REG_DISPx_BLDY 0x04000054 +#define REG_DISPx_MASTERBRIGHT 0x0400006C +// core A specific +#define REG_DISPA_DISPSTAT 0x04000004 +#define REG_DISPA_DISP3DCNT 0x04000060 +#define REG_DISPA_DISPCAPCNT 0x04000064 +#define REG_DISPA_DISPMMEMFIFO 0x04000068 + +#define REG_DISPA_DISP3DCNT_BIT_RDLINES_UNDERFLOW 0x1000 +#define REG_DISPA_DISP3DCNT_BIT_RAM_OVERFLOW 0x2000 +#define REG_DISPA_DISP3DCNT_BITS_ACK (REG_DISPA_DISP3DCNT_BIT_RDLINES_UNDERFLOW|REG_DISPA_DISP3DCNT_BIT_RAM_OVERFLOW) + + +#define eng_3D_RDLINES_COUNT 0x04000320 +#define eng_3D_EDGE_COLOR 0x04000330 +#define eng_3D_ALPHA_TEST_REF 0x04000340 +#define eng_3D_CLEAR_COLOR 0x04000350 +#define eng_3D_CLEAR_DEPTH 0x04000354 +#define eng_3D_CLRIMAGE_OFFSET 0x04000356 +#define eng_3D_FOG_COLOR 0x04000358 +#define eng_3D_FOG_OFFSET 0x0400035C +#define eng_3D_FOG_TABLE 0x04000360 +#define eng_3D_TOON_TABLE 0x04000380 +#define eng_3D_GXFIFO 0x04000400 + +// 3d commands +#define cmd_3D_MTX_MODE 0x04000440 +#define cmd_3D_MTX_PUSH 0x04000444 +#define cmd_3D_MTX_POP 0x04000448 +#define cmd_3D_MTX_STORE 0x0400044C +#define cmd_3D_MTX_RESTORE 0x04000450 +#define cmd_3D_MTX_IDENTITY 0x04000454 +#define cmd_3D_MTX_LOAD_4x4 0x04000458 +#define cmd_3D_MTX_LOAD_4x3 0x0400045C +#define cmd_3D_MTX_MULT_4x4 0x04000460 +#define cmd_3D_MTX_MULT_4x3 0x04000464 +#define cmd_3D_MTX_MULT_3x3 0x04000468 +#define cmd_3D_MTX_SCALE 0x0400046C +#define cmd_3D_MTX_TRANS 0x04000470 +#define cmd_3D_COLOR 0x04000480 +#define cmd_3D_NORMA 0x04000484 +#define cmd_3D_TEXCOORD 0x04000488 +#define cmd_3D_VTX_16 0x0400048C +#define cmd_3D_VTX_10 0x04000490 +#define cmd_3D_VTX_XY 0x04000494 +#define cmd_3D_VTX_XZ 0x04000498 +#define cmd_3D_VTX_YZ 0x0400049C +#define cmd_3D_VTX_DIFF 0x040004A0 +#define cmd_3D_POLYGON_ATTR 0x040004A4 +#define cmd_3D_TEXIMAGE_PARAM 0x040004A8 +#define cmd_3D_PLTT_BASE 0x040004AC +#define cmd_3D_DIF_AMB 0x040004C0 +#define cmd_3D_SPE_EMI 0x040004C4 +#define cmd_3D_LIGHT_VECTOR 0x040004C8 +#define cmd_3D_LIGHT_COLOR 0x040004CC +#define cmd_3D_SHININESS 0x040004D0 +#define cmd_3D_BEGIN_VTXS 0x04000500 +#define cmd_3D_END_VTXS 0x04000504 +#define cmd_3D_SWAP_BUFFERS 0x04000540 +#define cmd_3D_VIEWPORT 0x04000580 +#define cmd_3D_BOX_TEST 0x040005C0 +#define cmd_3D_POS_TEST 0x040005C4 +#define cmd_3D_VEC_TEST 0x040005C8 + +#define eng_3D_GXSTAT 0x04000600 +#define eng_3D_RAM_COUNT 0x04000604 +#define eng_3D_DISP_1DOT_DEPTH 0x04000610 +#define eng_3D_POS_RESULT 0x04000620 +#define eng_3D_VEC_RESULT 0x04000630 +#define eng_3D_CLIPMTX_RESULT 0x04000640 +#define eng_3D_VECMTX_RESULT 0x04000680 + +//DSI +#define REG_DSIMODE 0x04004000 + +#define IPCFIFOCNT_SENDEMPTY 0x0001 +#define IPCFIFOCNT_SENDFULL 0x0002 +#define IPCFIFOCNT_SENDIRQEN 0x0004 +#define IPCFIFOCNT_SENDCLEAR 0x0008 +#define IPCFIFOCNT_RECVEMPTY 0x0100 +#define IPCFIFOCNT_RECVFULL 0x0200 +#define IPCFIFOCNT_RECVIRQEN 0x0400 +#define IPCFIFOCNT_FIFOERROR 0x4000 +#define IPCFIFOCNT_FIFOENABLE 0x8000 +#define IPCFIFOCNT_WRITEABLE (IPCFIFOCNT_SENDIRQEN | IPCFIFOCNT_RECVIRQEN | IPCFIFOCNT_FIFOENABLE) + +#define IPCSYNC_IRQ_SEND 0x2000 +#define IPCSYNC_IRQ_RECV 0x4000 + +#define IRQ_BIT_LCD_VBLANK 0 +#define IRQ_BIT_LCD_HBLANK 1 +#define IRQ_BIT_LCD_VMATCH 2 +#define IRQ_BIT_TIMER_0 3 +#define IRQ_BIT_TIMER_1 4 +#define IRQ_BIT_TIMER_2 5 +#define IRQ_BIT_TIMER_3 6 +#define IRQ_BIT_ARM7_SIO 7 +#define IRQ_BIT_DMA_0 8 +#define IRQ_BIT_DMA_2 9 +#define IRQ_BIT_DMA_3 10 +#define IRQ_BIT_DMA_4 11 +#define IRQ_BIT_KEYPAD 12 +#define IRQ_BIT_GAMEPAK 13 +#define IRQ_BIT_IPCSYNC 16 +#define IRQ_BIT_IPCFIFO_SENDEMPTY 17 +#define IRQ_BIT_IPCFIFO_RECVNONEMPTY 18 +#define IRQ_BIT_GC_TRANSFER_COMPLETE 19 +#define IRQ_BIT_GC_IREQ_MC 20 +#define IRQ_BIT_ARM9_GXFIFO 21 +#define IRQ_BIT_ARM7_FOLD 22 +#define IRQ_BIT_ARM7_SPI 23 +#define IRQ_BIT_ARM7_WIFI 24 + +#define IRQ_MASK_LCD_VBLANK (1<<0) +#define IRQ_MASK_LCD_HBLANK (1<<1) +#define IRQ_MASK_LCD_VMATCH (1<<2) +#define IRQ_MASK_TIMER_0 (1<<3) +#define IRQ_MASK_TIMER_1 (1<<4) +#define IRQ_MASK_TIMER_2 (1<<5) +#define IRQ_MASK_TIMER_3 (1<<6) +#define IRQ_MASK_ARM7_SIO (1<<7) +#define IRQ_MASK_DMA_0 (1<<8) +#define IRQ_MASK_DMA_2 (1<<9) +#define IRQ_MASK_DMA_3 (1<<10) +#define IRQ_MASK_DMA_4 (1<<11) +#define IRQ_MASK_KEYPAD (1<<12) +#define IRQ_MASK_GAMEPAK (1<<13) +#define IRQ_MASK_IPCSYNC (1<<16) +#define IRQ_MASK_IPCFIFO_SENDEMPTY (1<<17) +#define IRQ_MASK_IPCFIFO_RECVNONEMPTY (1<<18) +#define IRQ_MASK_GC_TRANSFER_COMPLETE (1<<19) +#define IRQ_MASK_GC_IREQ_MC (1<<20) +#define IRQ_MASK_ARM9_GXFIFO (1<<21) +#define IRQ_MASK_ARM7_FOLD (1<<22) +#define IRQ_MASK_ARM7_SPI (1<<23) +#define IRQ_MASK_ARM7_WIFI (1<<24) + +#define TSC_MEASURE_TEMP1 0 +#define TSC_MEASURE_Y 1 +#define TSC_MEASURE_BATTERY 2 +#define TSC_MEASURE_Z1 3 +#define TSC_MEASURE_Z2 4 +#define TSC_MEASURE_X 5 +#define TSC_MEASURE_AUX 6 +#define TSC_MEASURE_TEMP2 7 + +#define EXMEMCNT_MASK_SLOT2_ARM7 (1<<7) +#define EXMEMCNT_MASK_SLOT2_SRAM_TIME (3) +#define EXMEMCNT_MASK_SLOT2_ROM_1ST_TIME (3<<2) +#define EXMEMCNT_MASK_SLOT2_ROM_2ND_TIME (1<<4) +#define EXMEMCNT_MASK_SLOT2_CLOCKRATE (3<<5) + +#endif diff --git a/jni/desmume/src/render3D.cpp b/jni/desmume/src/render3D.cpp new file mode 100755 index 0000000..f6a7834 --- /dev/null +++ b/jni/desmume/src/render3D.cpp @@ -0,0 +1,54 @@ +/* + Copyright (C) 2006-2007 shash + Copyright (C) 2008-2009 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "render3D.h" + +int cur3DCore = GPU3D_NULL; + +static void NDS_nullFunc1 (void){} +static char NDS_nullFunc2 (void){ return 1; } + +GPU3DInterface gpu3DNull = { + "None", + NDS_nullFunc2, //NDS_3D_Init + NDS_nullFunc1, //NDS_3D_Reset + NDS_nullFunc1, //NDS_3D_Close + NDS_nullFunc1, //NDS_3D_Render + NDS_nullFunc1, //NDS_3D_VramReconfigureSignal +}; + +GPU3DInterface *gpu3D = &gpu3DNull; + +void NDS_3D_SetDriver (int core3DIndex) +{ + cur3DCore = core3DIndex; + gpu3D = core3DList[cur3DCore]; +} + +bool NDS_3D_ChangeCore(int newCore) +{ + gpu3D->NDS_3D_Close(); + NDS_3D_SetDriver(newCore); + if(gpu3D->NDS_3D_Init() == 0) + { + NDS_3D_SetDriver(GPU3D_NULL); + gpu3D->NDS_3D_Init(); + return false; + } + return true; +} diff --git a/jni/desmume/src/render3D.h b/jni/desmume/src/render3D.h new file mode 100755 index 0000000..040dcc0 --- /dev/null +++ b/jni/desmume/src/render3D.h @@ -0,0 +1,65 @@ +/* + Copyright (C) 2006-2007 shash + Copyright (C) 2007-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef RENDER3D_H +#define RENDER3D_H + +#include "types.h" + +//not using this right now +#define CALL_CONVENTION + +typedef struct Render3DInterface +{ + // The name of the plugin, this name will appear in the plugins list + const char * name; + + //called once when the plugin starts up + char (CALL_CONVENTION* NDS_3D_Init) (void); + + //called when the emulator resets (is this necessary?) + void (CALL_CONVENTION* NDS_3D_Reset) (void); + + //called when the plugin shuts down + void (CALL_CONVENTION* NDS_3D_Close) (void); + + //called when the renderer should do its job and render the current display lists + void (CALL_CONVENTION* NDS_3D_Render) (void); + + //called when the emulator reconfigures its vram. you may need to invalidate your texture cache. + void (CALL_CONVENTION* NDS_3D_VramReconfigureSignal) (); + +} GPU3DInterface; + +extern int cur3DCore; + +// gpu 3D core list, per port +extern GPU3DInterface *core3DList[]; + +// Default null plugin +#define GPU3D_NULL 0 +extern GPU3DInterface gpu3DNull; + +// Extern pointer +extern GPU3DInterface *gpu3D; + +void NDS_3D_SetDriver (int core3DIndex); +bool NDS_3D_ChangeCore(int newCore); + +#endif + diff --git a/jni/desmume/src/rtc.cpp b/jni/desmume/src/rtc.cpp new file mode 100755 index 0000000..077d9b7 --- /dev/null +++ b/jni/desmume/src/rtc.cpp @@ -0,0 +1,352 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2008 CrazyMax + Copyright (C) 2008-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +// TODO: interrupt handler + +#include "rtc.h" +#include "common.h" +#include "debug.h" +#include "armcpu.h" +#include <string.h> +#include "saves.h" +#ifdef WIN32 +#include "windows/main.h" +#endif +#include "movie.h" + + +typedef struct +{ + // RTC registers + u8 regStatus1; + u8 regStatus2; + u8 regAdjustment; + u8 regFree; + + // BUS + u8 _prevSCK; + u8 _prevCS; + u8 _prevSIO; + u8 _SCK; + u8 _CS; + u8 _SIO; + u8 _DD; + u16 _REG; + + // command & data + u8 cmd; + u8 cmdStat; + u8 bitsCount; + u8 data[8]; + + u8 cmdBitsSize[8]; +} _RTC; + +_RTC rtc; + +SFORMAT SF_RTC[]={ + { "R000", 1, 1, &rtc.regStatus1}, + { "R010", 1, 1, &rtc.regStatus2}, + { "R020", 1, 1, &rtc.regAdjustment}, + { "R030", 1, 1, &rtc.regFree}, + + { "R040", 1, 1, &rtc._prevSCK}, + { "R050", 1, 1, &rtc._prevCS}, + { "R060", 1, 1, &rtc._prevSIO}, + { "R070", 1, 1, &rtc._SCK}, + { "R080", 1, 1, &rtc._CS}, + { "R090", 1, 1, &rtc._SIO}, + { "R100", 1, 1, &rtc._DD}, + { "R110", 2, 1, &rtc._REG}, + + { "R120", 1, 1, &rtc.cmd}, + { "R130", 1, 1, &rtc.cmdStat}, + { "R140", 1, 1, &rtc.bitsCount}, + { "R150", 1, 8, &rtc.data[0]}, + + { "R160", 1, 8, &rtc.cmdBitsSize[0]}, + + { 0 } +}; + +static const u8 kDefaultCmdBitsSize[8] = {8, 8, 56, 24, 0, 24, 8, 8}; + +static inline u8 toBCD(u8 x) +{ + return ((x / 10) << 4) | (x % 10); +} + +bool moviemode=false; + +DateTime rtcGetTime(void) +{ + DateTime tm; + if(movieMode == MOVIEMODE_INACTIVE) { + return DateTime::get_Now(); + } + else { + //now, you might think it is silly to go through all these conniptions + //when we could just assume that there are 60fps and base the seconds on frameCounter/60 + //but, we were imagining that one day we might need more precision + + const u32 arm9rate_unitsperframe = 560190<<1; + const u32 arm9rate_unitspersecond = (u32)(arm9rate_unitsperframe * 59.8261); + + u64 totalcycles = (u64)arm9rate_unitsperframe * currFrameCounter; + u64 totalseconds=totalcycles/arm9rate_unitspersecond; + + DateTime timer = currMovieData.rtcStart; + return timer.AddSeconds(totalseconds); + } +} + +static void rtcRecv() +{ + //INFO("RTC Read command 0x%02X\n", (rtc.cmd >> 1)); + + memset(&rtc.data[0], 0, sizeof(rtc.data)); + switch (rtc.cmd >> 1) + { + case 0: // status register 1 + //INFO("RTC: read regstatus1 (0x%02X)\n", rtc.regStatus1); + rtc.regStatus1 &= 0x0F; + rtc.data[0] = rtc.regStatus1; + //rtc.regStatus1 &= 0x7F; + break; + case 1: // status register 2 + //INFO("RTC: read regstatus2 (0x%02X)\n", rtc.regStatus1); + rtc.data[0] = rtc.regStatus2; + break; + case 2: // date & time + { + //INFO("RTC: read date & time\n"); + DateTime tm = rtcGetTime(); + rtc.data[0] = toBCD(tm.get_Year() % 100); + rtc.data[1] = toBCD(tm.get_Month()); + rtc.data[2] = toBCD(tm.get_Day()); + + //zero 24-apr-2010 - this is nonsense. + //but it is so wrong, someone mustve thought they knew what they were doing, so i am leaving it... + //rtc.data[3] = (tm.tm_wday + 6) & 7; + //if (rtc.data[3] == 7) rtc.data[3] = 6; + + //do this instead (gbatek seems to say monday=0 but i don't think that is right) + //0=sunday is necessary to make animal crossing behave + //maybe it means "custom assignment" can be specified by the game + rtc.data[3] = tm.get_DayOfWeek(); + + int hour = tm.get_Hour(); + if (!(rtc.regStatus1 & 0x02)) hour %= 12; + rtc.data[4] = ((hour < 12) ? 0x00 : 0x40) | toBCD(hour); + rtc.data[5] = toBCD(tm.get_Minute()); + rtc.data[6] = toBCD(tm.get_Second()); + break; + } + case 3: // time + { + //INFO("RTC: read time\n"); + DateTime tm = rtcGetTime(); + int hour = tm.get_Hour(); + if (!(rtc.regStatus1 & 0x02)) hour %= 12; + rtc.data[0] = ((hour < 12) ? 0x00 : 0x40) | toBCD(hour); + rtc.data[1] = toBCD(tm.get_Minute()); + rtc.data[2] = toBCD(tm.get_Second()); + break; + } + case 4: // freq/alarm 1 + /*if (cmdBitsSize[0x04] == 8) + INFO("RTC: read INT1 freq\n"); + else + INFO("RTC: read INT1 alarm1\n");*/ + //NDS_makeARM7Int(7); + break; + case 5: // alarm 2 + //INFO("RTC: read alarm 2\n"); + break; + case 6: // clock adjust + //INFO("RTC: read clock adjust\n"); + rtc.data[0] = rtc.regAdjustment; + break; + case 7: // free register + //INFO("RTC: read free register\n"); + rtc.data[0] = rtc.regFree; + break; + } +} + +static void rtcSend() +{ + //INFO("RTC write command 0x%02X\n", (rtc.cmd >> 1)); + switch (rtc.cmd >> 1) + { + case 0: // status register 1 + //INFO("RTC: write regstatus1 0x%02X\n", rtc.data[0]); + // rtc.regStatus1 &= 0xF1; + // rtc.regStatus1 |= (rtc.data[0] | 0x0E); + rtc.regStatus1 = rtc.data[0]; + break; + case 1: // status register 2 + //INFO("RTC: write regstatus2 0x%02X\n", rtc.data[0]); + rtc.regStatus2 = rtc.data[0]; + break; + case 2: // date & time + //INFO("RTC: write date & time : %02X %02X %02X %02X %02X %02X %02X\n", rtc.data[0], rtc.data[1], rtc.data[2], rtc.data[3], rtc.data[4], rtc.data[5], rtc.data[6]); + break; + case 3: // time + //INFO("RTC: write time : %02X %02X %02X\n", rtc.data[0], rtc.data[1], rtc.data[2]); + break; + case 4: // freq/alarm 1 + /*if (cmdBitsSize[0x04] == 8) + INFO("RTC: write INT1 freq 0x%02X\n", rtc.data[0]); + else + INFO("RTC: write INT1 alarm1 0x%02X\n", rtc.data[0]);*/ + break; + case 5: // alarm 2 + //INFO("RTC: write alarm 2\n"); + break; + case 6: // clock adjust + //INFO("RTC: write clock adjust\n"); + rtc.regAdjustment = rtc.data[0]; + break; + case 7: // free register + //INFO("RTC: write free register\n"); + rtc.regFree = rtc.data[0]; + break; + } +} + +void rtcInit() +{ + memset(&rtc, 0, sizeof(rtc)); + memcpy(&rtc.cmdBitsSize[0],kDefaultCmdBitsSize,8); + + rtc.regStatus1 |= 0x02; +} + +u16 rtcRead() +{ + //INFO("MMU Read RTC 0x%02X (%03i)\n", rtc._REG, rtc.bitsCount); + return (rtc._REG); +} + +void rtcWrite(u16 val) +{ + //INFO("MMU Write RTC 0x%02X (%03i)\n", val, rtc.bitsCount); + rtc._DD = (val & 0x10) >> 4; + rtc._SIO = rtc._DD?(val & 0x01):rtc._prevSIO; + rtc._SCK = (val & 0x20)?((val & 0x02) >> 1):rtc._prevSCK; + rtc._CS = (val & 0x40)?((val & 0x04) >> 2):rtc._prevCS; + + switch (rtc.cmdStat) + { + case 0: + if ( (!rtc._prevCS) && (rtc._prevSCK) && (rtc._CS) && (rtc._SCK) ) + { + rtc.cmdStat = 1; + rtc.bitsCount = 0; + rtc.cmd = 0; + } + break; + + case 1: + if (!rtc._CS) + { + rtc.cmdStat = 0; + break; + } + + if (rtc._SCK && rtc._DD) break; + if (!rtc._SCK && !rtc._DD) break; + + rtc.cmd |= (rtc._SIO << rtc.bitsCount ); + rtc.bitsCount ++; + if (rtc.bitsCount == 8) + { + //INFO("RTC command 0x%02X\n", rtc.cmd); + + // Little-endian command + if((rtc.cmd & 0x0F) == 0x06) + { + u8 tmp = rtc.cmd; + rtc.cmd = ((tmp & 0x80) >> 7) | ((tmp & 0x40) >> 5) | ((tmp & 0x20) >> 3) | ((tmp & 0x10) >> 1); + } + // Big-endian command + else + { + rtc.cmd &= 0x0F; + } + + if((rtc._prevSCK) && (!rtc._SCK)) + { + rtc.bitsCount = 0; + if ((rtc.cmd >> 1) == 0x04) + { + if ((rtc.regStatus2 & 0x0F) == 0x04) + rtc.cmdBitsSize[rtc.cmd >> 1] = 24; + else + rtc.cmdBitsSize[rtc.cmd >> 1] = 8; + } + if (rtc.cmd & 0x01) + { + rtc.cmdStat = 4; + rtcRecv(); + } + else + { + rtc.cmdStat = 3; + } + } + } + + break; + + case 3: // write: + if( (rtc._prevSCK) && (!rtc._SCK) ) + { + if(rtc._SIO) rtc.data[rtc.bitsCount >> 3] |= (1 << (rtc.bitsCount & 0x07)); + rtc.bitsCount++; + if (rtc.bitsCount == rtc.cmdBitsSize[rtc.cmd >> 1]) + { + rtcSend(); + rtc.cmdStat = 0; + } + } + break; + + case 4: // read: + if( (rtc._prevSCK) && (!rtc._SCK) ) + { + rtc._REG = val; + if((rtc.data[(rtc.bitsCount >> 3)] >> (rtc.bitsCount & 0x07)) & 0x01) + rtc._REG |= 0x01; + else + rtc._REG &= ~0x01; + + rtc.bitsCount++; + if (rtc.bitsCount == rtc.cmdBitsSize[rtc.cmd >> 1] || (!(val & 0x04))) + rtc.cmdStat = 0; + } + break; + + } + + rtc._prevSIO = rtc._SIO; + rtc._prevSCK = rtc._SCK; + rtc._prevCS = rtc._CS; +} diff --git a/jni/desmume/src/rtc.h b/jni/desmume/src/rtc.h new file mode 100755 index 0000000..c2762f7 --- /dev/null +++ b/jni/desmume/src/rtc.h @@ -0,0 +1,32 @@ +/* + Copyright 2006 yopyop + Copyright 2008 CrazyMax + Copyright 2008-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _RTC_H_ +#define _RTC_H_ +#include <stdlib.h> +#include <time.h> +#include "types.h" +#include "utils/datetime.h" + +DateTime rtcGetTime(void); + +extern void rtcInit(); +extern u16 rtcRead(); +extern void rtcWrite(u16 val); +#endif diff --git a/jni/desmume/src/saves.cpp b/jni/desmume/src/saves.cpp new file mode 100755 index 0000000..afb3cad --- /dev/null +++ b/jni/desmume/src/saves.cpp @@ -0,0 +1,1235 @@ +/* + Copyright (C) 2006 Normmatt + Copyright (C) 2006 Theo Berkau + Copyright (C) 2007 Pascal Giard + Copyright (C) 2008-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifdef HAVE_LIBZ +#include <zlib.h> +#endif +#include <stack> +#include <set> +#include <stdio.h> +#include <string.h> +#include <sys/stat.h> +#include <time.h> +#include <fstream> +#include "saves.h" +#include "MMU.h" +#include "NDSSystem.h" +#include "render3D.h" +#include "cp15.h" +#include "GPU_osd.h" +#include "version.h" + +#include "readwrite.h" +#include "gfx3d.h" +#include "movie.h" +#include "mic.h" +#include "MMU_timing.h" + +#include "path.h" + +#ifdef _WINDOWS +#include "windows/main.h" +#elif defined(ANDROID) +#include "android/main.h" +#endif + +int lastSaveState = 0; //Keeps track of last savestate used for quick save/load functions + +//void*v is actually a void** which will be indirected before reading +//since this isnt supported right now, it is declared in here to make things compile +#define SS_INDIRECT 0x80000000 + +savestates_t savestates[NB_STATES]; + +#define SAVESTATE_VERSION 12 +static const char* magic = "DeSmuME SState\0"; + +//a savestate chunk loader can set this if it wants to permit a silent failure (for compatibility) +static bool SAV_silent_fail_flag; + +#define printf LOGW + +SFORMAT SF_ARM7[]={ + { "7INS", 4, 1, &NDS_ARM7.instruction }, + { "7INA", 4, 1, &NDS_ARM7.instruct_adr }, + { "7INN", 4, 1, &NDS_ARM7.next_instruction }, + { "7REG", 4,16, NDS_ARM7.R }, + { "7CPS", 4, 1, &NDS_ARM7.CPSR }, + { "7SPS", 4, 1, &NDS_ARM7.SPSR }, + { "7DUS", 4, 1, &NDS_ARM7.R13_usr }, + { "7EUS", 4, 1, &NDS_ARM7.R14_usr }, + { "7DSV", 4, 1, &NDS_ARM7.R13_svc }, + { "7ESV", 4, 1, &NDS_ARM7.R14_svc }, + { "7DAB", 4, 1, &NDS_ARM7.R13_abt }, + { "7EAB", 4, 1, &NDS_ARM7.R14_abt }, + { "7DUN", 4, 1, &NDS_ARM7.R13_und }, + { "7EUN", 4, 1, &NDS_ARM7.R14_und }, + { "7DIR", 4, 1, &NDS_ARM7.R13_irq }, + { "7EIR", 4, 1, &NDS_ARM7.R14_irq }, + { "78FI", 4, 1, &NDS_ARM7.R8_fiq }, + { "79FI", 4, 1, &NDS_ARM7.R9_fiq }, + { "7AFI", 4, 1, &NDS_ARM7.R10_fiq }, + { "7BFI", 4, 1, &NDS_ARM7.R11_fiq }, + { "7CFI", 4, 1, &NDS_ARM7.R12_fiq }, + { "7DFI", 4, 1, &NDS_ARM7.R13_fiq }, + { "7EFI", 4, 1, &NDS_ARM7.R14_fiq }, + { "7SVC", 4, 1, &NDS_ARM7.SPSR_svc }, + { "7ABT", 4, 1, &NDS_ARM7.SPSR_abt }, + { "7UND", 4, 1, &NDS_ARM7.SPSR_und }, + { "7IRQ", 4, 1, &NDS_ARM7.SPSR_irq }, + { "7FIQ", 4, 1, &NDS_ARM7.SPSR_fiq }, + { "7int", 4, 1, &NDS_ARM7.intVector }, + { "7LDT", 1, 1, &NDS_ARM7.LDTBit }, + { "7Wai", 4, 1, &NDS_ARM7.waitIRQ }, + { "7hef", 4, 1, &NDS_ARM7.halt_IE_and_IF }, + { "7iws", 1, 1, &NDS_ARM7.intrWaitARM_state }, + { 0 } +}; + +SFORMAT SF_ARM9[]={ + { "9INS", 4, 1, &NDS_ARM9.instruction}, + { "9INA", 4, 1, &NDS_ARM9.instruct_adr}, + { "9INN", 4, 1, &NDS_ARM9.next_instruction}, + { "9REG", 4,16, NDS_ARM9.R}, + { "9CPS", 4, 1, &NDS_ARM9.CPSR}, + { "9SPS", 4, 1, &NDS_ARM9.SPSR}, + { "9DUS", 4, 1, &NDS_ARM9.R13_usr}, + { "9EUS", 4, 1, &NDS_ARM9.R14_usr}, + { "9DSV", 4, 1, &NDS_ARM9.R13_svc}, + { "9ESV", 4, 1, &NDS_ARM9.R14_svc}, + { "9DAB", 4, 1, &NDS_ARM9.R13_abt}, + { "9EAB", 4, 1, &NDS_ARM9.R14_abt}, + { "9DUN", 4, 1, &NDS_ARM9.R13_und}, + { "9EUN", 4, 1, &NDS_ARM9.R14_und}, + { "9DIR", 4, 1, &NDS_ARM9.R13_irq}, + { "9EIR", 4, 1, &NDS_ARM9.R14_irq}, + { "98FI", 4, 1, &NDS_ARM9.R8_fiq}, + { "99FI", 4, 1, &NDS_ARM9.R9_fiq}, + { "9AFI", 4, 1, &NDS_ARM9.R10_fiq}, + { "9BFI", 4, 1, &NDS_ARM9.R11_fiq}, + { "9CFI", 4, 1, &NDS_ARM9.R12_fiq}, + { "9DFI", 4, 1, &NDS_ARM9.R13_fiq}, + { "9EFI", 4, 1, &NDS_ARM9.R14_fiq}, + { "9SVC", 4, 1, &NDS_ARM9.SPSR_svc}, + { "9ABT", 4, 1, &NDS_ARM9.SPSR_abt}, + { "9UND", 4, 1, &NDS_ARM9.SPSR_und}, + { "9IRQ", 4, 1, &NDS_ARM9.SPSR_irq}, + { "9FIQ", 4, 1, &NDS_ARM9.SPSR_fiq}, + { "9int", 4, 1, &NDS_ARM9.intVector}, + { "9LDT", 1, 1, &NDS_ARM9.LDTBit}, + { "9Wai", 4, 1, &NDS_ARM9.waitIRQ}, + { "9hef", 4, 1, &NDS_ARM9.halt_IE_and_IF }, + { "9iws", 1, 1, &NDS_ARM7.intrWaitARM_state }, + { 0 } +}; + +SFORMAT SF_MEM[]={ + { "ITCM", 1, sizeof(MMU.ARM9_ITCM), MMU.ARM9_ITCM}, + { "DTCM", 1, sizeof(MMU.ARM9_DTCM), MMU.ARM9_DTCM}, + + //for legacy purposes, WRAX is a separate variable. shouldnt be a problem. + { "WRAM", 1, 0x400000, MMU.MAIN_MEM}, + { "WRAX", 1, 0x400000, MMU.MAIN_MEM+0x400000}, + + //NOTE - this is not as large as the allocated memory. + //the memory is overlarge due to the way our memory map system is setup + //but there are actually no more registers than this + { "9REG", 1, 0x2000, MMU.ARM9_REG}, + + { "VMEM", 1, sizeof(MMU.ARM9_VMEM), MMU.ARM9_VMEM}, + { "OAMS", 1, sizeof(MMU.ARM9_OAM), MMU.ARM9_OAM}, + + //this size is specially chosen to avoid saving the blank space at the end + { "LCDM", 1, 0xA4000, MMU.ARM9_LCD}, + { 0 } +}; + +SFORMAT SF_NDS[]={ + { "_WCY", 4, 1, &nds.wifiCycle}, + { "_TCY", 8, 8, nds.timerCycle}, + { "_VCT", 4, 1, &nds.VCount}, + { "_OLD", 4, 1, &nds.old}, + { "_TPX", 2, 1, &nds.adc_touchX}, + { "_TPY", 2, 1, &nds.adc_touchY}, + { "_TPC", 2, 1, &nds.adc_jitterctr}, + { "_STX", 2, 1, &nds.scr_touchX}, + { "_STY", 2, 1, &nds.scr_touchY}, + { "_TPB", 4, 1, &nds.isTouch}, + { "_DBG", 4, 1, &nds._DebugConsole}, + { "_ENS", 4, 1, &nds.ensataEmulation}, + { "_TYP", 4, 1, &nds.ConsoleType}, + { "_ENH", 4, 1, &nds.ensataHandshake}, + { "_ENI", 4, 1, &nds.ensataIpcSyncCounter}, + { "_SLP", 4, 1, &nds.sleeping}, + { "_FBS", 4, 1, &nds.freezeBus}, + { "_CEJ", 4, 1, &nds.cardEjected}, + { "_PDL", 2, 1, &nds.paddle}, + { "_P00", 1, 1, &nds.power1.lcd}, + { "_P01", 1, 1, &nds.power1.gpuMain}, + { "_P02", 1, 1, &nds.power1.gfx3d_render}, + { "_P03", 1, 1, &nds.power1.gfx3d_geometry}, + { "_P04", 1, 1, &nds.power1.gpuSub}, + { "_P05", 1, 1, &nds.power1.dispswap}, + { "_P06", 1, 1, &nds.power2.speakers}, + { "_P07", 1, 1, &nds.power2.wifi}, + { 0 } +}; + +SFORMAT SF_MMU[]={ + { "M7BI", 1, sizeof(MMU.ARM7_BIOS), MMU.ARM7_BIOS}, + { "M7ER", 1, sizeof(MMU.ARM7_ERAM), MMU.ARM7_ERAM}, + { "M7RG", 1, sizeof(MMU.ARM7_REG), MMU.ARM7_REG}, + { "M7WI", 1, sizeof(MMU.ARM7_WIRAM), MMU.ARM7_WIRAM}, + { "MSWI", 1, sizeof(MMU.SWIRAM), MMU.SWIRAM}, + { "M9RW", 1, 1, &MMU.ARM9_RW_MODE}, + { "MDTC", 4, 1, &MMU.DTCMRegion}, + { "MITC", 4, 1, &MMU.ITCMRegion}, + { "MTIM", 2, 8, MMU.timer}, + { "MTMO", 4, 8, MMU.timerMODE}, + { "MTON", 4, 8, MMU.timerON}, + { "MTRN", 4, 8, MMU.timerRUN}, + { "MTRL", 2, 8, MMU.timerReload}, + { "MIME", 4, 2, MMU.reg_IME}, + { "MIE_", 4, 2, MMU.reg_IE}, + { "MIF_", 4, 2, MMU.reg_IF_bits}, + { "MIFP", 4, 2, MMU.reg_IF_pending}, + + { "MGXC", 8, 1, &MMU.gfx3dCycles}, + + { "M_SX", 1, 2, &MMU.SPI_CNT}, + { "M_SC", 1, 2, &MMU.SPI_CMD}, + { "MASX", 1, 2, &MMU.AUX_SPI_CNT}, + { "MASC", 1, 2, &MMU.AUX_SPI_CMD}, + + { "MDV1", 4, 1, &MMU.divRunning}, + { "MDV2", 8, 1, &MMU.divResult}, + { "MDV3", 8, 1, &MMU.divMod}, + { "MDV5", 8, 1, &MMU.divCycles}, + + { "MSQ1", 4, 1, &MMU.sqrtRunning}, + { "MSQ2", 4, 1, &MMU.sqrtResult}, + { "MSQ4", 8, 1, &MMU.sqrtCycles}, + + //begin memory chips + { "BUCO", 1, 1, &MMU.fw.com}, + { "BUAD", 4, 1, &MMU.fw.addr}, + { "BUAS", 1, 1, &MMU.fw.addr_shift}, + { "BUAZ", 1, 1, &MMU.fw.addr_size}, + { "BUWE", 4, 1, &MMU.fw.write_enable}, + { "BUWR", 4, 1, &MMU.fw.writeable_buffer}, + //end memory chips + + { "MC0A", 4, 1, &MMU.dscard[0].address}, + { "MC0T", 4, 1, &MMU.dscard[0].transfer_count}, + { "MC1A", 4, 1, &MMU.dscard[1].address}, + { "MC1T", 4, 1, &MMU.dscard[1].transfer_count}, + //{ "MCHT", 4, 1, &MMU.CheckTimers}, + //{ "MCHD", 4, 1, &MMU.CheckDMAs}, + + //fifos + { "F0TH", 1, 1, &ipc_fifo[0].head}, + { "F0TL", 1, 1, &ipc_fifo[0].tail}, + { "F0SZ", 1, 1, &ipc_fifo[0].size}, + { "F0BF", 4, 16, ipc_fifo[0].buf}, + { "F1TH", 1, 1, &ipc_fifo[1].head}, + { "F1TL", 1, 1, &ipc_fifo[1].tail}, + { "F1SZ", 1, 1, &ipc_fifo[1].size}, + { "F1BF", 4, 16, ipc_fifo[1].buf}, + + { "FDHD", 4, 1, &disp_fifo.head}, + { "FDTL", 4, 1, &disp_fifo.tail}, + { "FDBF", 4, 0x6000, disp_fifo.buf}, + + { "PMCN", 1, 1, &MMU.powerMan_CntReg}, + { "PMCW", 4, 1, &MMU.powerMan_CntRegWritten}, + { "PMCR", 1, 5, &MMU.powerMan_Reg}, + + { "MR3D", 4, 1, &MMU.reg_DISP3DCNT_bits}, + + { 0 } +}; + +SFORMAT SF_MOVIE[]={ + { "FRAC", 4, 1, &currFrameCounter}, + { "LAGC", 4, 1, &TotalLagFrames}, + { 0 } +}; + +static void mmu_savestate(EMUFILE* os) +{ + u32 version = 6; + write32le(version,os); + + //version 2: + MMU_new.backupDevice.save_state(os); + + //version 3: + MMU_new.gxstat.savestate(os); + for(int i=0;i<2;i++) + for(int j=0;j<4;j++) + MMU_new.dma[i][j].savestate(os); + + MMU_timing.arm9codeFetch.savestate(os, version); + MMU_timing.arm9dataFetch.savestate(os, version); + MMU_timing.arm7codeFetch.savestate(os, version); + MMU_timing.arm7dataFetch.savestate(os, version); + MMU_timing.arm9codeCache.savestate(os, version); + MMU_timing.arm9dataCache.savestate(os, version); + + //version 4: + MMU_new.sqrt.savestate(os); + MMU_new.div.savestate(os); + + //version 6: + MMU_new.dsi_tsc.save_state(os); +} + +// TODO: integrate the new wifi state variables once everything is settled +SFORMAT SF_WIFI[]={ + { "W000", 4, 1, &wifiMac.powerOn}, + { "W010", 4, 1, &wifiMac.powerOnPending}, + + { "W020", 2, 1, &wifiMac.rfStatus}, + { "W030", 2, 1, &wifiMac.rfPins}, + + { "W040", 2, 1, &wifiMac.IE}, + { "W050", 2, 1, &wifiMac.IF}, + + { "W060", 2, 1, &wifiMac.macMode}, + { "W070", 2, 1, &wifiMac.wepMode}, + { "W080", 4, 1, &wifiMac.WEP_enable}, + + { "W100", 2, 1, &wifiMac.TXCnt}, + { "W120", 2, 1, &wifiMac.TXStat}, + + { "W200", 2, 1, &wifiMac.RXCnt}, + { "W210", 2, 1, &wifiMac.RXCheckCounter}, + + { "W220", 1, 6, &wifiMac.mac.bytes}, + { "W230", 1, 6, &wifiMac.bss.bytes}, + + { "W240", 2, 1, &wifiMac.aid}, + { "W250", 2, 1, &wifiMac.pid}, + { "W260", 2, 1, &wifiMac.retryLimit}, + + { "W270", 4, 1, &wifiMac.crystalEnabled}, + { "W280", 8, 1, &wifiMac.usec}, + { "W290", 4, 1, &wifiMac.usecEnable}, + { "W300", 8, 1, &wifiMac.ucmp}, + { "W310", 4, 1, &wifiMac.ucmpEnable}, + { "W320", 2, 1, &wifiMac.eCount}, + { "W330", 4, 1, &wifiMac.eCountEnable}, + + { "WR00", 4, 1, &wifiMac.RF.CFG1.val}, + { "WR01", 4, 1, &wifiMac.RF.IFPLL1.val}, + { "WR02", 4, 1, &wifiMac.RF.IFPLL2.val}, + { "WR03", 4, 1, &wifiMac.RF.IFPLL3.val}, + { "WR04", 4, 1, &wifiMac.RF.RFPLL1.val}, + { "WR05", 4, 1, &wifiMac.RF.RFPLL2.val}, + { "WR06", 4, 1, &wifiMac.RF.RFPLL3.val}, + { "WR07", 4, 1, &wifiMac.RF.RFPLL4.val}, + { "WR08", 4, 1, &wifiMac.RF.CAL1.val}, + { "WR09", 4, 1, &wifiMac.RF.TXRX1.val}, + { "WR10", 4, 1, &wifiMac.RF.PCNT1.val}, + { "WR11", 4, 1, &wifiMac.RF.PCNT2.val}, + { "WR12", 4, 1, &wifiMac.RF.VCOT1.val}, + + { "W340", 1, 105, &wifiMac.BB.data[0]}, + + { "W350", 2, 1, &wifiMac.rfIOCnt.val}, + { "W360", 2, 1, &wifiMac.rfIOStatus.val}, + { "W370", 4, 1, &wifiMac.rfIOData.val}, + { "W380", 2, 1, &wifiMac.bbIOCnt.val}, + + { "W400", 2, 0x1000, &wifiMac.RAM[0]}, + { "W410", 2, 1, &wifiMac.RXRangeBegin}, + { "W420", 2, 1, &wifiMac.RXRangeEnd}, + { "W430", 2, 1, &wifiMac.RXWriteCursor}, + { "W460", 2, 1, &wifiMac.RXReadCursor}, + { "W470", 2, 1, &wifiMac.RXUnits}, + { "W480", 2, 1, &wifiMac.RXBufCount}, + { "W490", 2, 1, &wifiMac.CircBufReadAddress}, + { "W500", 2, 1, &wifiMac.CircBufWriteAddress}, + { "W510", 2, 1, &wifiMac.CircBufRdEnd}, + { "W520", 2, 1, &wifiMac.CircBufRdSkip}, + { "W530", 2, 1, &wifiMac.CircBufWrEnd}, + { "W540", 2, 1, &wifiMac.CircBufWrSkip}, + + { "W580", 2, 0x800, &wifiMac.IOPorts[0]}, + { "W590", 2, 1, &wifiMac.randomSeed}, + + { 0 } +}; + +static bool mmu_loadstate(EMUFILE* is, int size) +{ + //read version + u32 version; + if(read32le(&version,is) != 1) return false; + + if(version == 0 || version == 1) + { + u32 bupmem_size; + u32 addr_size; + + if(version == 0) + { + //version 0 was buggy and didnt save the type. + //it would silently fail if there was a size mismatch + SAV_silent_fail_flag = true; + if(read32le(&bupmem_size,is) != 1) return false; + //if(bupmem_size != MMU.bupmem.size) return false; //mismatch between current initialized and saved size + addr_size = BackupDevice::addr_size_for_old_save_size(bupmem_size); + } + else if(version == 1) + { + //version 1 reinitializes the save system with the type that was saved + u32 bupmem_type; + if(read32le(&bupmem_type,is) != 1) return false; + if(read32le(&bupmem_size,is) != 1) return false; + addr_size = BackupDevice::addr_size_for_old_save_type(bupmem_type); + if(addr_size == 0xFFFFFFFF) + addr_size = BackupDevice::addr_size_for_old_save_size(bupmem_size); + } + + if(addr_size == 0xFFFFFFFF) + return false; + + u8* temp = new u8[bupmem_size]; + is->fread((char*)temp,bupmem_size); + MMU_new.backupDevice.load_old_state(addr_size,temp,bupmem_size); + delete[] temp; + if(is->fail()) return false; + } + + if(version < 2) return true; + + bool ok = MMU_new.backupDevice.load_state(is); + + if(version < 3) return true; + + ok &= MMU_new.gxstat.loadstate(is); + + for(int i=0;i<2;i++) + for(int j=0;j<4;j++) + ok &= MMU_new.dma[i][j].loadstate(is); + + ok &= MMU_timing.arm9codeFetch.loadstate(is, version); + ok &= MMU_timing.arm9dataFetch.loadstate(is, version); + ok &= MMU_timing.arm7codeFetch.loadstate(is, version); + ok &= MMU_timing.arm7dataFetch.loadstate(is, version); + ok &= MMU_timing.arm9codeCache.loadstate(is, version); + ok &= MMU_timing.arm9dataCache.loadstate(is, version); + + if(version < 4) return true; + + ok &= MMU_new.sqrt.loadstate(is,version); + ok &= MMU_new.div.loadstate(is,version); + + //to prevent old savestates from confusing IF bits, mask out ones which had been stored but should have been generated + MMU.reg_IF_bits[0] &= ~0x00200000; + MMU.reg_IF_bits[1] &= ~0x00000000; + + MMU_new.gxstat.fifo_low = gxFIFO.size <= 127; + MMU_new.gxstat.fifo_empty = gxFIFO.size == 0; + + if(version < 5) + MMU.reg_DISP3DCNT_bits = T1ReadWord(MMU.ARM9_REG,0x60); + + if(version < 6) return ok; + + MMU_new.dsi_tsc.load_state(is); + + return ok; +} + +static void cp15_saveone(armcp15_t *cp15, EMUFILE* os) +{ + write32le(cp15->IDCode,os); + write32le(cp15->cacheType,os); + write32le(cp15->TCMSize,os); + write32le(cp15->ctrl,os); + write32le(cp15->DCConfig,os); + write32le(cp15->ICConfig,os); + write32le(cp15->writeBuffCtrl,os); + write32le(cp15->und,os); + write32le(cp15->DaccessPerm,os); + write32le(cp15->IaccessPerm,os); + write32le(cp15->protectBaseSize0,os); + write32le(cp15->protectBaseSize1,os); + write32le(cp15->protectBaseSize2,os); + write32le(cp15->protectBaseSize3,os); + write32le(cp15->protectBaseSize4,os); + write32le(cp15->protectBaseSize5,os); + write32le(cp15->protectBaseSize6,os); + write32le(cp15->protectBaseSize7,os); + write32le(cp15->cacheOp,os); + write32le(cp15->DcacheLock,os); + write32le(cp15->IcacheLock,os); + write32le(cp15->ITCMRegion,os); + write32le(cp15->DTCMRegion,os); + write32le(cp15->processID,os); + write32le(cp15->RAM_TAG,os); + write32le(cp15->testState,os); + write32le(cp15->cacheDbg,os); + for(int i=0;i<8;i++) write32le(cp15->regionWriteMask_USR[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionWriteMask_SYS[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionReadMask_USR[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionReadMask_SYS[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionExecuteMask_USR[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionExecuteMask_SYS[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionWriteSet_USR[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionWriteSet_SYS[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionReadSet_USR[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionReadSet_SYS[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionExecuteSet_USR[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionExecuteSet_SYS[i],os); +} + +static void cp15_savestate(EMUFILE* os) +{ + //version + write32le(1,os); + + cp15_saveone((armcp15_t *)NDS_ARM9.coproc[15],os); + //ARM7 not have coprocessor + //cp15_saveone((armcp15_t *)NDS_ARM7.coproc[15],os); +} + +static bool cp15_loadone(armcp15_t *cp15, EMUFILE* is) +{ + if(!read32le(&cp15->IDCode,is)) return false; + if(!read32le(&cp15->cacheType,is)) return false; + if(!read32le(&cp15->TCMSize,is)) return false; + if(!read32le(&cp15->ctrl,is)) return false; + if(!read32le(&cp15->DCConfig,is)) return false; + if(!read32le(&cp15->ICConfig,is)) return false; + if(!read32le(&cp15->writeBuffCtrl,is)) return false; + if(!read32le(&cp15->und,is)) return false; + if(!read32le(&cp15->DaccessPerm,is)) return false; + if(!read32le(&cp15->IaccessPerm,is)) return false; + if(!read32le(&cp15->protectBaseSize0,is)) return false; + if(!read32le(&cp15->protectBaseSize1,is)) return false; + if(!read32le(&cp15->protectBaseSize2,is)) return false; + if(!read32le(&cp15->protectBaseSize3,is)) return false; + if(!read32le(&cp15->protectBaseSize4,is)) return false; + if(!read32le(&cp15->protectBaseSize5,is)) return false; + if(!read32le(&cp15->protectBaseSize6,is)) return false; + if(!read32le(&cp15->protectBaseSize7,is)) return false; + if(!read32le(&cp15->cacheOp,is)) return false; + if(!read32le(&cp15->DcacheLock,is)) return false; + if(!read32le(&cp15->IcacheLock,is)) return false; + if(!read32le(&cp15->ITCMRegion,is)) return false; + if(!read32le(&cp15->DTCMRegion,is)) return false; + if(!read32le(&cp15->processID,is)) return false; + if(!read32le(&cp15->RAM_TAG,is)) return false; + if(!read32le(&cp15->testState,is)) return false; + if(!read32le(&cp15->cacheDbg,is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionWriteMask_USR[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionWriteMask_SYS[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionReadMask_USR[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionReadMask_SYS[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionExecuteMask_USR[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionExecuteMask_SYS[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionWriteSet_USR[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionWriteSet_SYS[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionReadSet_USR[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionReadSet_SYS[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionExecuteSet_USR[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionExecuteSet_SYS[i],is)) return false; + + return true; +} + +static bool cp15_loadstate(EMUFILE* is, int size) +{ + //read version + u32 version; + if(read32le(&version,is) != 1) return false; + if(version > 1) return false; + + if(!cp15_loadone((armcp15_t *)NDS_ARM9.coproc[15],is)) return false; + + if(version == 0) + { + //ARM7 not have coprocessor + u8 *tmp_buf = new u8 [sizeof(armcp15_t)]; + if (!tmp_buf) return false; + if(!cp15_loadone((armcp15_t *)tmp_buf,is)) return false; + delete [] tmp_buf; + tmp_buf = NULL; + } + + return true; +} + + + +/* Format time and convert to string */ +static char * format_time(time_t cal_time) +{ + struct tm *time_struct; + static char str[64]; + + time_struct=localtime(&cal_time); + strftime(str, sizeof str, "%d-%b-%Y %H:%M:%S", time_struct); + + return(str); +} + +void clear_savestates() +{ + u8 i; + for( i = 0; i < NB_STATES; i++ ) + savestates[i].exists = FALSE; +} + +// Scan for existing savestates and update struct +void scan_savestates() +{ + struct stat sbuf; + char filename[MAX_PATH+1]; + + clear_savestates(); + + for(int i = 0; i < NB_STATES; i++ ) + { + path.getpathnoext(path.STATES, filename); + + if (strlen(filename) + strlen(".dst") + strlen("-2147483648") /* = biggest string for i */ >MAX_PATH) return ; + sprintf(filename+strlen(filename), ".ds%d", i); + if( stat(filename,&sbuf) == -1 ) continue; + savestates[i].exists = TRUE; + strncpy(savestates[i].date, format_time(sbuf.st_mtime),40); + savestates[i].date[40-1] = '\0'; + } + + return ; +} + +void savestate_slot(int num) +{ + struct stat sbuf; + char filename[MAX_PATH+1]; + + lastSaveState = num; //Set last savestate used + + path.getpathnoext(path.STATES, filename); + + if (strlen(filename) + strlen(".dsx") + strlen("-2147483648") /* = biggest string for num */ >MAX_PATH) return ; + sprintf(filename+strlen(filename), ".ds%d", num); + + if (savestate_save(filename)) + { + osd->setLineColor(255, 255, 255); + osd->addLine("Saved to %i slot", num); + } + else + { + osd->setLineColor(255, 0, 0); + osd->addLine("Error saving %i slot", num); + return; + } + + if (num >= 0 && num < NB_STATES) + { + if (stat(filename,&sbuf) != -1) + { + savestates[num].exists = TRUE; + strncpy(savestates[num].date, format_time(sbuf.st_mtime),40); + savestates[num].date[40-1] = '\0'; + } + } +} + +void loadstate_slot(int num) +{ + char filename[MAX_PATH]; + + lastSaveState = num; //Set last savestate used + + path.getpathnoext(path.STATES, filename); + + if (strlen(filename) + strlen(".dsx") + strlen("-2147483648") /* = biggest string for num */ >MAX_PATH) return ; + sprintf(filename+strlen(filename), ".ds%d", num); + if (savestate_load(filename)) + { + osd->setLineColor(255, 255, 255); + osd->addLine("Loaded from %i slot", num); + } + else + { + osd->setLineColor(255, 0, 0); + osd->addLine("Error loading %i slot", num); + } +} + + +// note: guessSF is so we don't have to do a linear search through the SFORMAT array every time +// in the (most common) case that we already know where the next entry is. +static const SFORMAT *CheckS(const SFORMAT *guessSF, const SFORMAT *firstSF, u32 size, u32 count, char *desc) +{ + const SFORMAT *sf = guessSF ? guessSF : firstSF; + while(sf->v) + { + //NOT SUPPORTED RIGHT NOW + //if(sf->size==~0) // Link to another SFORMAT structure. + //{ + // SFORMAT *tmp; + // if((tmp= CheckS((SFORMAT *)sf->v, tsize, desc) )) + // return(tmp); + // sf++; + // continue; + //} + if(!memcmp(desc,sf->desc,4)) + { + if(sf->size != size || sf->count != count) + return 0; + return sf; + } + + // failed to find it, have to keep iterating + if(guessSF) + { + sf = firstSF; + guessSF = NULL; + } + else + { + sf++; + } + } + return 0; +} + + +static bool ReadStateChunk(EMUFILE* is, const SFORMAT *sf, int size) +{ + const SFORMAT *tmp = NULL; + const SFORMAT *guessSF = NULL; + int temp = is->ftell(); + + while(is->ftell()<temp+size) + { + u32 sz, count; + + char toa[4]; + is->fread(toa,4); + if(is->fail()) + return false; + + if(!read32le(&sz,is)) return false; + if(!read32le(&count,is)) return false; + + if((tmp=CheckS(guessSF,sf,sz,count,toa))) + { + #ifdef LOCAL_LE + // no need to ever loop one at a time if not flipping byte order + is->fread((char *)tmp->v,sz*count); + #else + if(sz == 1) { + //special case: read a huge byte array + is->fread((char *)tmp->v,count); + } else { + for(unsigned int i=0;i<count;i++) + { + is->fread((char *)tmp->v + i*sz,sz); + FlipByteOrder((u8*)tmp->v + i*sz,sz); + } + } + #endif + guessSF = tmp + 1; + } + else + { + is->fseek(sz*count,SEEK_CUR); + guessSF = NULL; + } + } // while(...) + return true; +} + + + +static int SubWrite(EMUFILE* os, const SFORMAT *sf) +{ + uint32 acc=0; + +#ifdef DEBUG + std::set<std::string> keyset; +#endif + + const SFORMAT* temp = sf; + while(temp->v) { + const SFORMAT* seek = sf; + while(seek->v && seek != temp) { + if(!strcmp(seek->desc,temp->desc)) { + printf("ERROR! duplicated chunk name: %s\n", temp->desc); + } + seek++; + } + temp++; + } + + while(sf->v) + { + //not supported right now + //if(sf->size==~0) //Link to another struct + //{ + // uint32 tmp; + + // if(!(tmp=SubWrite(os,(SFORMAT *)sf->v))) + // return(0); + // acc+=tmp; + // sf++; + // continue; + //} + + int count = sf->count; + int size = sf->size; + + //add size of current node to the accumulator + acc += 4 + sizeof(sf->size) + sizeof(sf->count); + acc += count * size; + + if(os) //Are we writing or calculating the size of this block? + { + os->fwrite(sf->desc,4); + write32le(sf->size,os); + write32le(sf->count,os); + + #ifdef DEBUG + //make sure we dont dup any keys + if(keyset.find(sf->desc) != keyset.end()) + { + printf("duplicate save key!\n"); + assert(false); + } + keyset.insert(sf->desc); + #endif + + + #ifdef LOCAL_LE + // no need to ever loop one at a time if not flipping byte order + os->fwrite((char *)sf->v,size*count); + #else + if(size == 1) { + //special case: write a huge byte array + os->fwrite((char *)sf->v,count); + } else { + for(int i=0;i<count;i++) { + FlipByteOrder((u8*)sf->v + i*size, size); + os->fwrite((char*)sf->v + i*size,size); + //Now restore the original byte order. + FlipByteOrder((u8*)sf->v + i*size, size); + } + } + #endif + } + sf++; + } + + return(acc); +} + +static int savestate_WriteChunk(EMUFILE* os, int type, const SFORMAT *sf) +{ + write32le(type,os); + if(!sf) return 4; + int bsize = SubWrite((EMUFILE*)0,sf); + write32le(bsize,os); + + if(!SubWrite(os,sf)) + { + return 8; + } + return (bsize+8); +} + +static void savestate_WriteChunk(EMUFILE* os, int type, void (*saveproc)(EMUFILE* os)) +{ + u32 pos1 = os->ftell(); + + //write the type, size(placeholder), and data + write32le(type,os); + os->fseek(4, SEEK_CUR); // skip the size, we write that later + saveproc(os); + + //get the size + u32 pos2 = os->ftell(); + assert(pos2 != (u32)-1); // if this assert fails, saveproc did something bad + u32 size = (pos2 - pos1) - (2 * sizeof(u32)); + + //fill in the actual size + os->fseek(pos1 + sizeof(u32),SEEK_SET); + write32le(size,os); + os->fseek(pos2,SEEK_SET); + +/* +// old version of this function, +// for reference in case the new one above starts misbehaving somehow: + + // - this is retarded. why not write placeholders for size and then write directly to the stream + //and then go back and fill them in + + //get the size + memorystream mstemp; + saveproc(&mstemp); + mstemp.flush(); + u32 size = mstemp.size(); + + //write the type, size, and data + write32le(type,os); + write32le(size,os); + os->write(mstemp.buf(),size); +*/ +} + +static void writechunks(EMUFILE* os); + +bool savestate_save(EMUFILE* outstream, int compressionLevel) +{ + #ifndef HAVE_LIBZ + compressionLevel = Z_NO_COMPRESSION; + #endif + + EMUFILE_MEMORY ms; + EMUFILE* os; + + if(compressionLevel != Z_NO_COMPRESSION) + { + //generate the savestate in memory first + os = (EMUFILE*)&ms; + writechunks(os); + } + else + { + os = outstream; + os->fseek(32,SEEK_SET); //skip the header + writechunks(os); + } + + //save the length of the file + u32 len = os->ftell(); + + u32 comprlen = 0xFFFFFFFF; + u8* cbuf; + + //compress the data + int error = Z_OK; + if(compressionLevel != Z_NO_COMPRESSION) + { + cbuf = ms.buf(); + uLongf comprlen2; + //worst case compression. + //zlib says "0.1% larger than sourceLen plus 12 bytes" + comprlen = (len>>9)+12 + len; + cbuf = new u8[comprlen]; + // Workaround to make it compile under linux 64bit + comprlen2 = comprlen; + error = compress2(cbuf,&comprlen2,ms.buf(),len,compressionLevel); + comprlen = (u32)comprlen2; + } + + //dump the header + outstream->fseek(0,SEEK_SET); + outstream->fwrite(magic,16); + write32le(SAVESTATE_VERSION,outstream); + write32le(EMU_DESMUME_VERSION_NUMERIC(),outstream); //desmume version + write32le(len,outstream); //uncompressed length + write32le(comprlen,outstream); //compressed length (-1 if it is not compressed) + + if(compressionLevel != Z_NO_COMPRESSION) + { + outstream->fwrite((char*)cbuf,comprlen==(u32)-1?len:comprlen); + delete[] cbuf; + } + + return error == Z_OK; +} + +bool savestate_save (const char *file_name) +{ + EMUFILE_MEMORY ms; + size_t elems_written; +#ifdef HAVE_LIBZ + if(!savestate_save(&ms, Z_DEFAULT_COMPRESSION)) +#else + if(!savestate_save(&ms, 0)) +#endif + return false; + FILE* file = fopen(file_name,"wb"); + if(file) + { + elems_written = fwrite(ms.buf(),1,ms.size(),file); + fclose(file); + return (elems_written == ms.size()); + } else return false; +} + +extern SFORMAT SF_RTC[]; + +static void writechunks(EMUFILE* os) { + savestate_WriteChunk(os,1,SF_ARM9); + savestate_WriteChunk(os,2,SF_ARM7); + savestate_WriteChunk(os,3,cp15_savestate); + savestate_WriteChunk(os,4,SF_MEM); + savestate_WriteChunk(os,5,SF_NDS); + savestate_WriteChunk(os,51,nds_savestate); + savestate_WriteChunk(os,60,SF_MMU); + savestate_WriteChunk(os,61,mmu_savestate); + savestate_WriteChunk(os,7,gpu_savestate); + savestate_WriteChunk(os,8,spu_savestate); + savestate_WriteChunk(os,81,mic_savestate); + savestate_WriteChunk(os,90,SF_GFX3D); + savestate_WriteChunk(os,91,gfx3d_savestate); + savestate_WriteChunk(os,100,SF_MOVIE); + savestate_WriteChunk(os,101,mov_savestate); + savestate_WriteChunk(os,110,SF_WIFI); + savestate_WriteChunk(os,120,SF_RTC); + savestate_WriteChunk(os,0xFFFFFFFF,(SFORMAT*)0); +} + +static bool ReadStateChunks(EMUFILE* is, s32 totalsize) +{ + bool ret = true; + while(totalsize > 0) + { + uint32 size; + u32 t; + if(!read32le(&t,is)) { ret=false; break; } + if(t == 0xFFFFFFFF) goto done; + if(!read32le(&size,is)) { ret=false; break; } + switch(t) + { + case 1: if(!ReadStateChunk(is,SF_ARM9,size)) ret=false; break; + case 2: if(!ReadStateChunk(is,SF_ARM7,size)) ret=false; break; + case 3: if(!cp15_loadstate(is,size)) ret=false; break; + case 4: if(!ReadStateChunk(is,SF_MEM,size)) ret=false; break; + case 5: if(!ReadStateChunk(is,SF_NDS,size)) ret=false; break; + case 51: if(!nds_loadstate(is,size)) ret=false; break; + case 60: if(!ReadStateChunk(is,SF_MMU,size)) ret=false; break; + case 61: if(!mmu_loadstate(is,size)) ret=false; break; + case 7: if(!gpu_loadstate(is,size)) ret=false; break; + case 8: if(!spu_loadstate(is,size)) ret=false; break; + case 81: if(!mic_loadstate(is,size)) ret=false; break; + case 90: if(!ReadStateChunk(is,SF_GFX3D,size)) ret=false; break; + case 91: if(!gfx3d_loadstate(is,size)) ret=false; break; + case 100: if(!ReadStateChunk(is,SF_MOVIE, size)) ret=false; break; + case 101: if(!mov_loadstate(is, size)) ret=false; break; + case 110: if(!ReadStateChunk(is,SF_WIFI,size)) ret=false; break; + case 120: if(!ReadStateChunk(is,SF_RTC,size)) ret=false; break; + default: + ret=false; + break; + } + if(!ret) + return false; + } +done: + + return ret; +} + +static void loadstate() +{ + // This should regenerate the vram banks + for (int i = 0; i < 0xA; i++) + _MMU_write08<ARMCPU_ARM9>(0x04000240+i, _MMU_read08<ARMCPU_ARM9>(0x04000240+i)); + + // This should regenerate the graphics power control register + _MMU_write16<ARMCPU_ARM9>(0x04000304, _MMU_read16<ARMCPU_ARM9>(0x04000304)); + + // This should regenerate the graphics configuration + //zero 27-jul-09 : was formerly up to 7F but that wrote to dispfifo which is dumb (one of nitsuja's desynch bugs [that he found, not caused]) + //so then i brought it down to 66 but this resulted in a conceptual bug with affine start registers, which shouldnt get regenerated + //so then i just made this exhaustive list + // for (int i = REG_BASE_DISPA; i<=REG_BASE_DISPA + 0x66; i+=2) + //_MMU_write16<ARMCPU_ARM9>(i, _MMU_read16<ARMCPU_ARM9>(i)); + // for (int i = REG_BASE_DISPB; i<=REG_BASE_DISPB + 0x7F; i+=2) + //_MMU_write16<ARMCPU_ARM9>(i, _MMU_read16<ARMCPU_ARM9>(i)); + static const u8 mainRegenAddr[] = {0x00,0x02,0x08,0x0a,0x0c,0x0e,0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x50,0x52,0x54,0x64,0x66,0x6c}; + static const u8 subRegenAddr[] = {0x00,0x02,0x08,0x0a,0x0c,0x0e,0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x50,0x52,0x54,0x6c}; + for(u32 i=0;i<ARRAY_SIZE(mainRegenAddr);i++) + _MMU_write16<ARMCPU_ARM9>(REG_BASE_DISPA+mainRegenAddr[i], _MMU_read16<ARMCPU_ARM9>(REG_BASE_DISPA+mainRegenAddr[i])); + for(u32 i=0;i<ARRAY_SIZE(subRegenAddr);i++) + _MMU_write16<ARMCPU_ARM9>(REG_BASE_DISPB+subRegenAddr[i], _MMU_read16<ARMCPU_ARM9>(REG_BASE_DISPB+subRegenAddr[i])); + // no need to restore 0x60 since control and MMU.ARM9_REG are both in the savestates, and restoring it could mess up the ack bits anyway + + SetupMMU(nds.Is_DebugConsole(),nds.Is_DSI()); + + execute = !driver->EMU_IsEmulationPaused(); +} + +bool savestate_load(EMUFILE* is) +{ + SAV_silent_fail_flag = false; + char header[16]; + is->fread(header,16); + if(is->fail() || memcmp(header,magic,16)) + return false; + + u32 ssversion,dversion,len,comprlen; + if(!read32le(&ssversion,is)) return false; + if(!read32le(&dversion,is)) return false; + if(!read32le(&len,is)) return false; + if(!read32le(&comprlen,is)) return false; + + if(ssversion != SAVESTATE_VERSION) return false; + + std::vector<u8> buf(len); + + if(comprlen != 0xFFFFFFFF) { +#ifndef HAVE_LIBZ + //without libz, we can't decompress this savestate + return false; +#endif + std::vector<char> cbuf(comprlen); + is->fread(&cbuf[0],comprlen); + if(is->fail()) return false; + +#ifdef HAVE_LIBZ + uLongf uncomprlen = len; + int error = uncompress((uint8*)&buf[0],&uncomprlen,(uint8*)&cbuf[0],comprlen); + if(error != Z_OK || uncomprlen != len) + return false; +#endif + } else { + is->fread((char*)&buf[0],len-32); + } + + //GO!! READ THE SAVESTATE + //THERE IS NO GOING BACK NOW + //reset the emulator first to clean out the host's state + + //while the series of resets below should work, + //we are testing the robustness of the savestate system with this full reset. + //the full reset wipes more things, so we can make sure that they are being restored correctly + extern bool _HACK_DONT_STOPMOVIE; + _HACK_DONT_STOPMOVIE = true; + NDS_Reset(); + _HACK_DONT_STOPMOVIE = false; + + //reset some options to their old defaults which werent saved + nds._DebugConsole = FALSE; + + //GPU_Reset(MainScreen.gpu, 0); + //GPU_Reset(SubScreen.gpu, 1); + //gfx3d_reset(); + //gpu3D->NDS_3D_Reset(); + //SPU_Reset(); + + EMUFILE_MEMORY mstemp(&buf); + bool x = ReadStateChunks(&mstemp,(s32)len); + + if(!x && !SAV_silent_fail_flag) + { + printf("Error loading savestate. It failed halfway through;\nSince there is no savestate backup system, your current game session is wrecked"); +#ifdef _WINDOWS + //HACK! we really need a better way to handle this kind of feedback + MessageBox(0,"Error loading savestate. It failed halfway through;\nSince there is no savestate backup system, your current game session is wrecked",0,0); +#endif + return false; + } + + loadstate(); + + if(nds.ConsoleType != CommonSettings.ConsoleType) { + printf("WARNING: forcing console type to: ConsoleType=%d\n",nds.ConsoleType); + } + + if((nds._DebugConsole!=0) != CommonSettings.DebugConsole) { + printf("WARNING: forcing console debug mode to: debugmode=%s\n",nds._DebugConsole?"TRUE":"FALSE"); + } + + + return true; +} + +bool savestate_load(const char *file_name) +{ + EMUFILE_FILE f(file_name,"rb"); + if(f.fail()) return false; + + return savestate_load(&f); +} + +static std::stack<EMUFILE_MEMORY*> rewindFreeList; +static std::vector<EMUFILE_MEMORY*> rewindbuffer; + +int rewindstates = 16; +int rewindinterval = 4; + +void rewindsave () { + + if(currFrameCounter % rewindinterval) + return; + + //printf("rewindsave"); printf("%d%s", currFrameCounter, "\n"); + + + EMUFILE_MEMORY *ms; + if(!rewindFreeList.empty()) { + ms = rewindFreeList.top(); + rewindFreeList.pop(); + } else { + ms = new EMUFILE_MEMORY(1024*1024*12); + } + + if(!savestate_save(ms, Z_NO_COMPRESSION)) + return; + + rewindbuffer.push_back(ms); + + if((int)rewindbuffer.size() > rewindstates) { + delete *rewindbuffer.begin(); + rewindbuffer.erase(rewindbuffer.begin()); + } +} + +void dorewind() +{ + if(currFrameCounter % rewindinterval) + return; + + //printf("rewind\n"); + + int size = rewindbuffer.size(); + + if(size < 1) { + printf("rewind buffer empty\n"); + return; + } + + printf("%d", size); + + EMUFILE_MEMORY* loadms = rewindbuffer[size-1]; + loadms->fseek(32, SEEK_SET); + + ReadStateChunks(loadms,loadms->size()-32); + loadstate(); + + if(rewindbuffer.size()>1) + { + rewindFreeList.push(loadms); + rewindbuffer.pop_back(); + } + +} diff --git a/jni/desmume/src/saves.h b/jni/desmume/src/saves.h new file mode 100755 index 0000000..5c03b2a --- /dev/null +++ b/jni/desmume/src/saves.h @@ -0,0 +1,72 @@ +/* + Copyright (C) 2006 Normmatt + Copyright (C) 2007 Pascal Giard + Copyright (C) 2007-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SRAM_H +#define _SRAM_H + +#include "types.h" + +#define NB_STATES 10 + +extern int lastSaveState; + +typedef struct +{ + BOOL exists; + char date[40]; +} savestates_t; + + +struct SFORMAT +{ + //a string description of the element + const char *desc; + + //the size of each element + u32 size; + + //the number of each element + u32 count; + + //a void* to the data or a void** to the data + void *v; +}; + +extern savestates_t savestates[NB_STATES]; + +void clear_savestates(); +void scan_savestates(); +u8 sram_read (u32 address); +void sram_write (u32 address, u8 value); +int sram_load (const char *file_name); +int sram_save (const char *file_name); + +bool savestate_load (const char *file_name); +bool savestate_save (const char *file_name); + +void savestate_slot(int num); +void loadstate_slot(int num); + +bool savestate_load(class EMUFILE* is); +bool savestate_save(class EMUFILE* outstream, int compressionLevel); + +void dorewind(); +void rewindsave(); + +#endif diff --git a/jni/desmume/src/shaders.h b/jni/desmume/src/shaders.h new file mode 100755 index 0000000..3d89d3a --- /dev/null +++ b/jni/desmume/src/shaders.h @@ -0,0 +1,88 @@ +/* + Copyright (C) 2008-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* Predefined OpenGL shaders */ + +/* Vertex shader */ +const char *vertexShader = {"\ + varying vec4 pos; \n\ + void main() \n\ + { \n\ + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \n\ + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; \n\ + gl_FrontColor = gl_Color; \n\ + pos = gl_Position; \n\ + } \n\ +"}; + +/* Fragment shader */ +const char *fragmentShader = {"\ + uniform sampler1D toonTable; \n\ + uniform sampler2D tex2d; \n\ + uniform int hasTexture; \n\ + uniform int texBlending; \n\ + uniform int oglWBuffer; \n\ + varying vec4 pos; \n\ + void main() \n\ + { \n\ + vec4 texColor = vec4(1.0, 1.0, 1.0, 1.0); \n\ + vec4 flagColor; \n\ + \ + if(hasTexture != 0) \n\ + { \n\ + texColor = texture2D(tex2d, gl_TexCoord[0].st); \n\ + } \n\ + flagColor = texColor; \n\ + if(texBlending == 0) \n\ + { \n\ + flagColor = gl_Color * texColor; \n\ + } \n\ + else \n\ + if(texBlending == 1) \n\ + { \n\ + if (texColor.a == 0.0 || hasTexture == 0) \n\ + flagColor.rgb = gl_Color.rgb;\n\ + else \n\ + if (texColor.a == 1.0) \n\ + flagColor.rgb = texColor.rgb;\n\ + else \n\ + flagColor.rgb = texColor.rgb * (1.0-texColor.a) + gl_Color.rgb * texColor.a;\n\ + flagColor.a = gl_Color.a; \n\ + } \n\ + else \n\ + if(texBlending == 2) \n\ + { \n\ + vec3 toonColor = vec3(texture1D(toonTable, gl_Color.r).rgb); \n\ + flagColor.rgb = texColor.rgb * toonColor.rgb;\n\ + flagColor.a = texColor.a * gl_Color.a;\n\ + } \n\ + else \n\ + if(texBlending == 3) \n\ + { \n\ + vec3 toonColor = vec3(texture1D(toonTable, gl_Color.r).rgb); \n\ + flagColor.rgb = texColor.rgb * gl_Color.rgb + toonColor.rgb; \n\ + flagColor.a = texColor.a * gl_Color.a; \n\ + } \n\ + if (oglWBuffer == 1) \n\ + // TODO \n\ + gl_FragDepth = (pos.z / pos.w) * 0.5 + 0.5; \n\ + else \n\ + gl_FragDepth = (pos.z / pos.w) * 0.5 + 0.5; \n\ + gl_FragColor = flagColor; \n\ + } \n\ +"}; + diff --git a/jni/desmume/src/slot1.cpp b/jni/desmume/src/slot1.cpp new file mode 100755 index 0000000..28654ed --- /dev/null +++ b/jni/desmume/src/slot1.cpp @@ -0,0 +1,111 @@ +/* + Copyright (C) 2010-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <string> + +#include "types.h" +#include "slot1.h" + +#include "emufile.h" +#include "utils/vfat.h" + +extern SLOT1INTERFACE slot1None; +extern SLOT1INTERFACE slot1Retail; +extern SLOT1INTERFACE slot1R4; +extern SLOT1INTERFACE slot1Retail_NAND; + +static EMUFILE* fatImage = NULL; +static std::string fatDir; + +SLOT1INTERFACE slot1List[NDS_SLOT1_COUNT] = { + slot1None, + slot1Retail, + slot1R4, + slot1Retail_NAND +}; + +SLOT1INTERFACE slot1_device = slot1Retail; //default for frontends that dont even configure this +u8 slot1_device_type = NDS_SLOT1_RETAIL; + +static void scanDir() +{ + if(fatDir == "") return; + + if (fatImage) + { + delete fatImage; + fatImage = NULL; + } + + VFAT vfat; + if(vfat.build(fatDir.c_str(),16)) + { + fatImage = vfat.detach(); + } +} + +BOOL slot1Init() +{ + if (slot1_device_type == NDS_SLOT1_R4) + scanDir(); + return slot1_device.init(); +} + +void slot1Close() +{ + slot1_device.close(); + + //be careful to do this second, maybe the device will write something more + if (fatImage) + { + delete fatImage; + fatImage = NULL; + } +} + +void slot1Reset() +{ + slot1_device.reset(); +} + +BOOL slot1Change(NDS_SLOT1_TYPE changeToType) +{ + if (changeToType > NDS_SLOT1_COUNT || changeToType < 0) return FALSE; + slot1_device.close(); + slot1_device_type = changeToType; + slot1_device = slot1List[slot1_device_type]; + if (changeToType == NDS_SLOT1_R4) + scanDir(); + printf("Slot 1: %s\n", slot1_device.name); + return slot1_device.init(); +} + +void slot1SetFatDir(const std::string& dir) +{ + //printf("FAT path %s\n", dir.c_str()); + fatDir = dir; +} + +std::string slot1GetFatDir() +{ + return fatDir; +} + +EMUFILE* slot1GetFatImage() +{ + return fatImage; +} \ No newline at end of file diff --git a/jni/desmume/src/slot1.h b/jni/desmume/src/slot1.h new file mode 100755 index 0000000..219a28c --- /dev/null +++ b/jni/desmume/src/slot1.h @@ -0,0 +1,79 @@ +/* + Copyright (C) 2010-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __SLOT1_H__ +#define __SLOT1_H__ + +#include <string> +#include "common.h" +#include "types.h" +#include "debug.h" + +class EMUFILE; + +struct SLOT1INTERFACE +{ + // The name of the plugin, this name will appear in the plugins list + const char * name; + + //called once when the plugin starts up + BOOL (*init)(void); + + //called when the emulator resets + void (*reset)(void); + + //called when the plugin shuts down + void (*close)(void); + + //called when the user configurating plugin + void (*config)(void); + + //called when the emulator write to addon + void (*write08)(u8 PROCNUM, u32 adr, u8 val); + void (*write16)(u8 PROCNUM, u32 adr, u16 val); + void (*write32)(u8 PROCNUM, u32 adr, u32 val); + + //called when the emulator read from addon + u8 (*read08)(u8 PROCNUM, u32 adr); + u16 (*read16)(u8 PROCNUM, u32 adr); + u32 (*read32)(u8 PROCNUM, u32 adr); + + //called when the user get info about addon pak (description) + void (*info)(char *info); +}; + +enum NDS_SLOT1_TYPE +{ + NDS_SLOT1_NONE, + NDS_SLOT1_RETAIL, + NDS_SLOT1_R4, + NDS_SLOT1_RETAIL_NAND, // used in Made in Ore/WarioWare D.I.Y. + NDS_SLOT1_COUNT // use for counter addons - MUST TO BE LAST!!! +}; + +extern SLOT1INTERFACE slot1_device; // current slot1 device +extern SLOT1INTERFACE slot1List[NDS_SLOT1_COUNT]; +extern u8 slot1_device_type; + +BOOL slot1Init(); +void slot1Close(); +void slot1Reset(); +BOOL slot1Change(NDS_SLOT1_TYPE type); // change current adddon +void slot1SetFatDir(const std::string& dir); +std::string slot1GetFatDir(); +EMUFILE* slot1GetFatImage(); +#endif //__SLOT1_H__ diff --git a/jni/desmume/src/sndsdl.cpp b/jni/desmume/src/sndsdl.cpp new file mode 100755 index 0000000..2160654 --- /dev/null +++ b/jni/desmume/src/sndsdl.cpp @@ -0,0 +1,224 @@ +/* + Copyright (C) 2005-2006 Theo Berkau + Copyright (C) 2006-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include <string.h> + +#include <SDL.h> +#include "types.h" +#include "SPU.h" +#include "sndsdl.h" +#include "debug.h" + +#ifdef _XBOX +#include <xtl.h> +#include <VectorIntrinsics.h> +#include <process.h> +#endif + +int SNDSDLInit(int buffersize); +void SNDSDLDeInit(); +void SNDSDLUpdateAudio(s16 *buffer, u32 num_samples); +u32 SNDSDLGetAudioSpace(); +void SNDSDLMuteAudio(); +void SNDSDLUnMuteAudio(); +void SNDSDLSetVolume(int volume); + +SoundInterface_struct SNDSDL = { +SNDCORE_SDL, +"SDL Sound Interface", +SNDSDLInit, +SNDSDLDeInit, +SNDSDLUpdateAudio, +SNDSDLGetAudioSpace, +SNDSDLMuteAudio, +SNDSDLUnMuteAudio, +SNDSDLSetVolume +}; + +static u16 *stereodata16; +static u32 soundoffset; +static volatile u32 soundpos; +static u32 soundlen; +static u32 soundbufsize; +static SDL_AudioSpec audiofmt; + +////////////////////////////////////////////////////////////////////////////// +#ifdef _XBOX +static volatile bool doterminate; +static volatile bool terminated; + +DWORD WINAPI SNDXBOXThread( LPVOID ) +{ + for(;;) { + if(doterminate) break; + { + SPU_Emulate_user(); + } + Sleep(10); + } + terminated = true; + return 0; +} +#endif + + +static void MixAudio(void *userdata, Uint8 *stream, int len) { + int i; + Uint8 *soundbuf=(Uint8 *)stereodata16; + + for (i = 0; i < len; i++) + { + if (soundpos >= soundbufsize) + soundpos = 0; + + stream[i] = soundbuf[soundpos]; + soundpos++; + } +} + +////////////////////////////////////////////////////////////////////////////// + +int SNDSDLInit(int buffersize) +{ + if (SDL_InitSubSystem(SDL_INIT_AUDIO) != 0) + return -1; + + audiofmt.freq = 44100; + audiofmt.format = AUDIO_S16SYS; + audiofmt.channels = 2; + audiofmt.samples = (audiofmt.freq / 60) * 2; + audiofmt.callback = MixAudio; + audiofmt.userdata = NULL; + + //samples should be a power of 2 according to SDL-doc + //so normalize it to the nearest power of 2 here + u32 normSamples = 512; + while (normSamples < audiofmt.samples) + normSamples <<= 1; + + audiofmt.samples = normSamples; + + soundlen = audiofmt.freq / 60; // 60 for NTSC + soundbufsize = buffersize * sizeof(s16) * 2; + + if (SDL_OpenAudio(&audiofmt, NULL) != 0) + { + return -1; + } + + if ((stereodata16 = (u16 *)malloc(soundbufsize)) == NULL) + return -1; + + memset(stereodata16, 0, soundbufsize); + + soundpos = 0; + + SDL_PauseAudio(0); + +#ifdef _XBOX + doterminate = false; + terminated = false; + CreateThread(0,0,SNDXBOXThread,0,0,0); +#endif + + return 0; +} + +////////////////////////////////////////////////////////////////////////////// + +void SNDSDLDeInit() +{ +#ifdef _XBOX + doterminate = true; + while(!terminated) { + Sleep(1); + } +#endif + SDL_CloseAudio(); + + if (stereodata16) + free(stereodata16); +} + +////////////////////////////////////////////////////////////////////////////// + +void SNDSDLUpdateAudio(s16 *buffer, u32 num_samples) +{ + u32 copy1size=0, copy2size=0; + SDL_LockAudio(); + + if ((soundbufsize - soundoffset) < (num_samples * sizeof(s16) * 2)) + { + copy1size = (soundbufsize - soundoffset); + copy2size = (num_samples * sizeof(s16) * 2) - copy1size; + } + else + { + copy1size = (num_samples * sizeof(s16) * 2); + copy2size = 0; + } + + memcpy((((u8 *)stereodata16)+soundoffset), buffer, copy1size); +// ScspConvert32uto16s((s32 *)leftchanbuffer, (s32 *)rightchanbuffer, (s16 *)(((u8 *)stereodata16)+soundoffset), copy1size / sizeof(s16) / 2); + + if (copy2size) + memcpy(stereodata16, ((u8 *)buffer)+copy1size, copy2size); +// ScspConvert32uto16s((s32 *)leftchanbuffer, (s32 *)rightchanbuffer, (s16 *)stereodata16, copy2size / sizeof(s16) / 2); + + soundoffset += copy1size + copy2size; + soundoffset %= soundbufsize; + + SDL_UnlockAudio(); +} + +////////////////////////////////////////////////////////////////////////////// + +u32 SNDSDLGetAudioSpace() +{ + u32 freespace=0; + + if (soundoffset > soundpos) + freespace = soundbufsize - soundoffset + soundpos; + else + freespace = soundpos - soundoffset; + + return (freespace / sizeof(s16) / 2); +} + +////////////////////////////////////////////////////////////////////////////// + +void SNDSDLMuteAudio() +{ + SDL_PauseAudio(1); +} + +////////////////////////////////////////////////////////////////////////////// + +void SNDSDLUnMuteAudio() +{ + SDL_PauseAudio(0); +} + +////////////////////////////////////////////////////////////////////////////// + +void SNDSDLSetVolume(int volume) +{ +} + +////////////////////////////////////////////////////////////////////////////// diff --git a/jni/desmume/src/sndsdl.h b/jni/desmume/src/sndsdl.h new file mode 100755 index 0000000..c110160 --- /dev/null +++ b/jni/desmume/src/sndsdl.h @@ -0,0 +1,24 @@ +/* + Copyright 2005-2006 Theo Berkau + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef SNDSDL_H +#define SNDSDL_H + +#define SNDCORE_SDL 2 + +extern SoundInterface_struct SNDSDL; +#endif diff --git a/jni/desmume/src/texcache.cpp b/jni/desmume/src/texcache.cpp new file mode 100755 index 0000000..9c9691b --- /dev/null +++ b/jni/desmume/src/texcache.cpp @@ -0,0 +1,713 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2006-2007 shash + Copyright (C) 2008-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <string.h> +#include <algorithm> +#include <assert.h> +#include <map> + +#include "texcache.h" + +#include "bits.h" +#include "common.h" +#include "debug.h" +#include "gfx3d.h" +#include "NDSSystem.h" + +using std::min; +using std::max; + +//only dump this from ogl renderer. for now, softrasterizer creates things in an incompatible pixel format +//#define DEBUG_DUMP_TEXTURE + +#define CONVERT(color,alpha) ((TEXFORMAT == TexFormat_32bpp)?(RGB15TO32(color,alpha)):RGB15TO6665(color,alpha)) + +//This class represents a number of regions of memory which should be viewed as contiguous +class MemSpan +{ +public: + static const int MAXSIZE = 17; //max size for textures: 1024*1024*2 bytes / 128*1024 banks + 1 for wraparound + + MemSpan() + : numItems(0), size(0) + {} + + int numItems; + + struct Item { + u32 start; + u32 len; + u8* ptr; + u32 ofs; //offset within the memspan + } items[MAXSIZE]; + + int size; + + //this MemSpan shall be considered the first argument to a standard memcmp + //the length shall be as specified in this MemSpan, unless you specify otherwise + int memcmp(void* buf2, int size=-1) + { + if(size==-1) size = this->size; + size = min(this->size,size); + for(int i=0;i<numItems;i++) + { + Item &item = items[i]; + int todo = min((int)item.len,size); + size -= todo; + int temp = ::memcmp(item.ptr,((u8*)buf2)+item.ofs,todo); + if(temp) return temp; + if(size == 0) break; + } + return 0; + } + + //TODO - get rid of duplication between these two methods. + + //dumps the memspan to the specified buffer + //you may set size to limit the size to be copied + int dump(void* buf, int size=-1) + { + if(size==-1) size = this->size; + size = min(this->size,size); + u8* bufptr = (u8*)buf; + int done = 0; + for(int i=0;i<numItems;i++) + { + Item item = items[i]; + int todo = min((int)item.len,size); + size -= todo; + done += todo; + memcpy(bufptr,item.ptr,todo); + bufptr += todo; + if(size==0) return done; + } + return done; + } + + // this function does the same than dump + // but works for both little and big endian + // when buf is an u16 array + int dump16(void* buf, int size=-1) + { + if(size==-1) size = this->size; + size = min(this->size,size); + u16* bufptr = (u16*)buf; + int done = 0; + for(int i=0;i<numItems;i++) + { + Item item = items[i]; + u8 * src = (u8 *) item.ptr; + int todo = min((int)item.len,size); + size -= todo; + done += todo; + for(int j = 0;j < todo / 2;j++) + { + u16 tmp; + tmp = *src++; + tmp |= *(src++) << 8; + *bufptr++ = tmp; + } + if(size==0) return done; + } + return done; + } +}; + +//creates a MemSpan in texture memory +static MemSpan MemSpan_TexMem(u32 ofs, u32 len) +{ + MemSpan ret; + ret.size = len; + u32 currofs = 0; + while(len) { + MemSpan::Item &curr = ret.items[ret.numItems++]; + curr.start = ofs&0x1FFFF; + u32 slot = (ofs>>17)&3; //slots will wrap around + curr.len = min(len,0x20000-curr.start); + curr.ofs = currofs; + len -= curr.len; + ofs += curr.len; + currofs += curr.len; + u8* ptr = MMU.texInfo.textureSlotAddr[slot]; + + //TODO - dont alert if the masterbrightnesses are max or min + if(ptr == MMU.blank_memory) { + PROGINFO("Tried to reference unmapped texture memory: slot %d\n",slot); + } + curr.ptr = ptr + curr.start; + } + return ret; +} + +//creates a MemSpan in texture palette memory +static MemSpan MemSpan_TexPalette(u32 ofs, u32 len) +{ + MemSpan ret; + ret.size = len; + u32 currofs = 0; + while(len) { + MemSpan::Item &curr = ret.items[ret.numItems++]; + curr.start = ofs&0x3FFF; + u32 slot = (ofs>>14)&7; //this masks to 8 slots, but there are really only 6 + if(slot>5) { + PROGINFO("Texture palette overruns texture memory. Wrapping at palette slot 0.\n"); + slot -= 5; + } + curr.len = min(len,0x4000-curr.start); + curr.ofs = currofs; + len -= curr.len; + ofs += curr.len; + //if(len != 0) + //here is an actual test case of bank spanning + currofs += curr.len; + u8* ptr = MMU.texInfo.texPalSlot[slot]; + + //TODO - dont alert if the masterbrightnesses are max or min + if(ptr == MMU.blank_memory) { + PROGINFO("Tried to reference unmapped texture palette memory: 16k slot #%d\n",slot); + } + curr.ptr = ptr + curr.start; + } + return ret; +} + +#if defined (DEBUG_DUMP_TEXTURE) && defined (WIN32) +#define DO_DEBUG_DUMP_TEXTURE +static void DebugDumpTexture(TexCacheItem* item) +{ + static int ctr=0; + char fname[100]; + sprintf(fname,"c:\\dump\\%d.bmp", ctr); + ctr++; + + NDS_WriteBMP_32bppBuffer(item->sizeX,item->sizeY,item->decoded,fname); +} +#endif + +class TexCache +{ +public: + TexCache() + : cache_size(0) + {} + + TTexCacheItemMultimap index; + + //this ought to be enough for anyone + //static const u32 kMaxCacheSize = 64*1024*1024; + //changed by zeromus on 15-dec. I couldnt find any games that were getting anywhere NEAR 64 + static const u32 kMaxCacheSize = 16*1024*1024; + //metal slug burns through sprites so fast, it can test it pretty quickly though + + //this is not really precise, it is off by a constant factor + u32 cache_size; + + void list_remove(TexCacheItem* item) + { + index.erase(item->iterator); + cache_size -= item->decode_len; + } + + void list_push_front(TexCacheItem* item) + { + item->iterator = index.insert(std::make_pair(item->texformat,item)); + cache_size += item->decode_len; + } + + template<TexCache_TexFormat TEXFORMAT> + TexCacheItem* scan(u32 format, u32 texpal) + { + //for each texformat, number of palette entries + static const int palSizes[] = {0, 32, 4, 16, 256, 0, 8, 0}; + + //for each texformat, multiplier from numtexels to numbytes (fixed point 30.2) + static const int texSizes[] = {0, 4, 1, 2, 4, 1, 4, 8}; + + //used to hold a copy of the palette specified for this texture + u16 pal[256]; + + u32 textureMode = (unsigned short)((format>>26)&0x07); + u32 sizeX=(8 << ((format>>20)&0x07)); + u32 sizeY=(8 << ((format>>23)&0x07)); + u32 imageSize = sizeX*sizeY; + + u8 *adr; + + u32 paletteAddress; + + switch (textureMode) + { + case TEXMODE_I2: + paletteAddress = texpal<<3; + break; + case TEXMODE_A3I5: //a3i5 + case TEXMODE_I4: //i4 + case TEXMODE_I8: //i8 + case TEXMODE_A5I3: //a5i3 + case TEXMODE_16BPP: //16bpp + case TEXMODE_4X4: //4x4 + default: + paletteAddress = texpal<<4; + break; + } + + //analyze the texture memory mapping and the specifications of this texture + int palSize = palSizes[textureMode]; + int texSize = (imageSize*texSizes[textureMode])>>2; //shifted because the texSizes multiplier is fixed point + MemSpan ms = MemSpan_TexMem((format&0xFFFF)<<3,texSize); + MemSpan mspal = MemSpan_TexPalette(paletteAddress,palSize*2); + + //determine the location for 4x4 index data + u32 indexBase; + if((format & 0xc000) == 0x8000) indexBase = 0x30000; + else indexBase = 0x20000; + + u32 indexOffset = (format&0x3FFF)<<2; + + int indexSize = 0; + MemSpan msIndex; + if(textureMode == TEXMODE_4X4) + { + indexSize = imageSize>>3; + msIndex = MemSpan_TexMem(indexOffset+indexBase,indexSize); + } + + + //dump the palette to a temp buffer, so that we don't have to worry about memory mapping. + //this isnt such a problem with texture memory, because we read sequentially from it. + //however, we read randomly from palette memory, so the mapping is more costly. + #ifdef WORDS_BIGENDIAN + mspal.dump16(pal); + #else + mspal.dump(pal); + #endif + + //TODO - as a special optimization, keep the last item returned and check it first + + for(std::pair<TTexCacheItemMultimap::iterator,TTexCacheItemMultimap::iterator> + iters = index.equal_range(format); + iters.first != iters.second; + ++iters.first) + { + TexCacheItem* curr = iters.first->second; + + //conditions where we reject matches: + //when the teximage or texpal params dont match + //(this is our key for identifying textures in the cache) + //NEW: due to using format as a key we dont need to check this anymore + //if(curr->texformat != format) continue; + if(curr->texpal != texpal) continue; + + //we're being asked for a different format than what we had cached. + //TODO - this could be done at the entire cache level instead of checking repeatedly + if(curr->cacheFormat != TEXFORMAT) goto REJECT; + + //the texture matches params, but isnt suspected invalid. accept it. + if (!curr->suspectedInvalid) return curr; + + //we suspect the texture may be invalid. we need to do a byte-for-byte comparison to re-establish that it is valid: + + //when the palettes dont match: + //note that we are considering 4x4 textures to have a palette size of 0. + //they really have a potentially HUGE palette, too big for us to handle like a normal palette, + //so they go through a different system + if(mspal.size != 0 && memcmp(curr->dump.palette,pal,mspal.size)) goto REJECT; + + //when the texture data doesn't match + if(ms.memcmp(&curr->dump.texture[0],curr->dump.textureSize)) goto REJECT; + + //if the texture is 4x4 then the index data must match + if(textureMode == TEXMODE_4X4) + { + if(msIndex.memcmp(curr->dump.texture + curr->dump.textureSize,curr->dump.indexSize)) goto REJECT; + } + + //we found a match. just return it + //REMINDER to make it primary/newest when we have smarter code + //list_remove(curr); + //list_push_front(curr); + curr->suspectedInvalid = false; + return curr; + + REJECT: + //we found a cached item for the current address, but the data is stale. + //for a variety of complicated reasons, we need to throw it out right this instant. + list_remove(curr); + delete curr; + break; + } + + //item was not found. recruit an existing one (the oldest), or create a new one + //evict(); //reduce the size of the cache if necessary + //TODO - as a peculiarity of the texcache, eviction must happen after the entire 3d frame runs + //to support separate cache and read passes + TexCacheItem* newitem = new TexCacheItem(); + newitem->suspectedInvalid = false; + newitem->texformat = format; + newitem->cacheFormat = TEXFORMAT; + newitem->texpal = texpal; + newitem->sizeX=sizeX; + newitem->sizeY=sizeY; + newitem->invSizeX=1.0f/((float)(sizeX)); + newitem->invSizeY=1.0f/((float)(sizeY)); + newitem->decode_len = sizeX*sizeY*4; + newitem->mode = textureMode; + newitem->decoded = new u8[newitem->decode_len]; + list_push_front(newitem); + //printf("allocating: up to %d with %d items\n",cache_size,index.size()); + + u32 *dwdst = (u32*)newitem->decoded; + + //dump palette data for cache keying + if(palSize) + { + memcpy(newitem->dump.palette, pal, palSize*2); + } + + //dump texture and 4x4 index data for cache keying + const int texsize = newitem->dump.textureSize = ms.size; + const int indexsize = newitem->dump.indexSize = msIndex.size; + newitem->dump.texture = new u8[texsize+indexsize]; + ms.dump(&newitem->dump.texture[0],newitem->dump.maxTextureSize); //dump texture + if(textureMode == TEXMODE_4X4) + msIndex.dump(newitem->dump.texture+newitem->dump.textureSize,newitem->dump.indexSize); //dump 4x4 + + + //============================================================================ + //Texture conversion + //============================================================================ + + const u32 opaqueColor = TEXFORMAT==TexFormat_32bpp?255:31; + u32 palZeroTransparent = (1-((format>>29)&1))*opaqueColor; + + switch (newitem->mode) + { + case TEXMODE_A3I5: + { + for(int j=0;j<ms.numItems;j++) { + adr = ms.items[j].ptr; + for(u32 x = 0; x < ms.items[j].len; x++) + { + u16 c = pal[*adr&31]; + u8 alpha = *adr>>5; + if(TEXFORMAT == TexFormat_15bpp) + *dwdst++ = RGB15TO6665(c,material_3bit_to_5bit[alpha]); + else + *dwdst++ = RGB15TO32(c,material_3bit_to_8bit[alpha]); + adr++; + } + } + break; + } + + case TEXMODE_I2: + { + for(int j=0;j<ms.numItems;j++) { + adr = ms.items[j].ptr; + for(u32 x = 0; x < ms.items[j].len; x++) + { + u8 bits; + u16 c; + + bits = (*adr)&0x3; + c = pal[bits]; + *dwdst++ = CONVERT(c,(bits == 0) ? palZeroTransparent : opaqueColor); + + bits = ((*adr)>>2)&0x3; + c = pal[bits]; + *dwdst++ = CONVERT(c,(bits == 0) ? palZeroTransparent : opaqueColor); + + bits = ((*adr)>>4)&0x3; + c = pal[bits]; + *dwdst++ = CONVERT(c,(bits == 0) ? palZeroTransparent : opaqueColor); + + bits = ((*adr)>>6)&0x3; + c = pal[bits]; + *dwdst++ = CONVERT(c,(bits == 0) ? palZeroTransparent : opaqueColor); + + adr++; + } + } + break; + } + case TEXMODE_I4: + { + for(int j=0;j<ms.numItems;j++) { + adr = ms.items[j].ptr; + for(u32 x = 0; x < ms.items[j].len; x++) + { + u8 bits; + u16 c; + + bits = (*adr)&0xF; + c = pal[bits]; + *dwdst++ = CONVERT(c,(bits == 0) ? palZeroTransparent : opaqueColor); + + bits = ((*adr)>>4); + c = pal[bits]; + *dwdst++ = CONVERT(c,(bits == 0) ? palZeroTransparent : opaqueColor); + adr++; + } + } + break; + } + case TEXMODE_I8: + { + for(int j=0;j<ms.numItems;j++) { + adr = ms.items[j].ptr; + for(u32 x = 0; x < ms.items[j].len; ++x) + { + u16 c = pal[*adr]; + *dwdst++ = CONVERT(c,(*adr == 0) ? palZeroTransparent : opaqueColor); + adr++; + } + } + } + break; + case TEXMODE_4X4: + { + //RGB16TO32 is used here because the other conversion macros result in broken interpolation logic + + if(ms.numItems != 1) { + PROGINFO("Your 4x4 texture has overrun its texture slot.\n"); + } + //this check isnt necessary since the addressing is tied to the texture data which will also run out: + //if(msIndex.numItems != 1) PROGINFO("Your 4x4 texture index has overrun its slot.\n"); + + #define PAL4X4(offset) ( *(u16*)( MMU.texInfo.texPalSlot[((paletteAddress + (offset)*2)>>14)&0x7] + ((paletteAddress + (offset)*2)&0x3FFF) ) ) + + u16* slot1; + u32* map = (u32*)ms.items[0].ptr; + u32 limit = ms.items[0].len<<2; + u32 d = 0; + if ( (format & 0xc000) == 0x8000) + // texel are in slot 2 + slot1=(u16*)&MMU.texInfo.textureSlotAddr[1][((format & 0x3FFF)<<2)+0x010000]; + else + slot1=(u16*)&MMU.texInfo.textureSlotAddr[1][(format & 0x3FFF)<<2]; + + u16 yTmpSize = (sizeY>>2); + u16 xTmpSize = (sizeX>>2); + + //this is flagged whenever a 4x4 overruns its slot. + //i am guessing we just generate black in that case + bool dead = false; + + for (int y = 0; y < yTmpSize; y ++) + { + u32 tmpPos[4]={(y<<2)*sizeX,((y<<2)+1)*sizeX, + ((y<<2)+2)*sizeX,((y<<2)+3)*sizeX}; + for (int x = 0; x < xTmpSize; x ++, d++) + { + if(d >= limit) + dead = true; + + if(dead) { + for (int sy = 0; sy < 4; sy++) + { + u32 currentPos = (x<<2) + tmpPos[sy]; + dwdst[currentPos] = dwdst[currentPos+1] = dwdst[currentPos+2] = dwdst[currentPos+3] = 0; + } + continue; + } + + u32 currBlock = map[d]; + u16 pal1 = slot1[d]; + u16 pal1offset = (pal1 & 0x3FFF)<<1; + u8 mode = pal1>>14; + u32 tmp_col[4]; + + tmp_col[0]=RGB16TO32(PAL4X4(pal1offset),255); + tmp_col[1]=RGB16TO32(PAL4X4(pal1offset+1),255); + + switch (mode) + { + case 0: + tmp_col[2]=RGB16TO32(PAL4X4(pal1offset+2),255); + tmp_col[3]=RGB16TO32(0x7FFF,0); + break; + case 1: + tmp_col[2]=(((tmp_col[0]&0xFF)+(tmp_col[1]&0xff))>>1)| + (((tmp_col[0]&(0xFF<<8))+(tmp_col[1]&(0xFF<<8)))>>1)| + (((tmp_col[0]&(0xFF<<16))+(tmp_col[1]&(0xFF<<16)))>>1)| + (0xff<<24); + tmp_col[3]=RGB16TO32(0x7FFF,0); + break; + case 2: + tmp_col[2]=RGB16TO32(PAL4X4(pal1offset+2),255); + tmp_col[3]=RGB16TO32(PAL4X4(pal1offset+3),255); + break; + case 3: + { + u32 red1, red2; + u32 green1, green2; + u32 blue1, blue2; + u16 tmp1, tmp2; + + red1=tmp_col[0]&0xff; + green1=(tmp_col[0]>>8)&0xff; + blue1=(tmp_col[0]>>16)&0xff; + red2=tmp_col[1]&0xff; + green2=(tmp_col[1]>>8)&0xff; + blue2=(tmp_col[1]>>16)&0xff; + + tmp1=((red1*5+red2*3)>>6)| + (((green1*5+green2*3)>>6)<<5)| + (((blue1*5+blue2*3)>>6)<<10); + tmp2=((red2*5+red1*3)>>6)| + (((green2*5+green1*3)>>6)<<5)| + (((blue2*5+blue1*3)>>6)<<10); + + tmp_col[2]=RGB16TO32(tmp1,255); + tmp_col[3]=RGB16TO32(tmp2,255); + break; + } + } + + if(TEXFORMAT==TexFormat_15bpp) + { + for(int i=0;i<4;i++) + { + tmp_col[i] >>= 2; + tmp_col[i] &= 0x3F3F3F3F; + u32 a = tmp_col[i]>>24; + tmp_col[i] &= 0x00FFFFFF; + tmp_col[i] |= (a>>1)<<24; + } + } + + //TODO - this could be more precise for 32bpp mode (run it through the color separation table) + + //set all 16 texels + for (int sy = 0; sy < 4; sy++) + { + // Texture offset + u32 currentPos = (x<<2) + tmpPos[sy]; + u8 currRow = (u8)((currBlock>>(sy<<3))&0xFF); + + dwdst[currentPos] = tmp_col[currRow&3]; + dwdst[currentPos+1] = tmp_col[(currRow>>2)&3]; + dwdst[currentPos+2] = tmp_col[(currRow>>4)&3]; + dwdst[currentPos+3] = tmp_col[(currRow>>6)&3]; + } + + + } + } + + + break; + } + case TEXMODE_A5I3: + { + for(int j=0;j<ms.numItems;j++) { + adr = ms.items[j].ptr; + for(u32 x = 0; x < ms.items[j].len; ++x) + { + u16 c = pal[*adr&0x07]; + u8 alpha = (*adr>>3); + if(TEXFORMAT == TexFormat_15bpp) + *dwdst++ = RGB15TO6665(c,alpha); + else + *dwdst++ = RGB15TO32(c,material_5bit_to_8bit[alpha]); + adr++; + } + } + break; + } + case TEXMODE_16BPP: + { + for(int j=0;j<ms.numItems;j++) { + u16* map = (u16*)ms.items[j].ptr; + int len = ms.items[j].len>>1; + for(int x = 0; x < len; ++x) + { + u16 c = map[x]; + int alpha = ((c&0x8000)?opaqueColor:0); + *dwdst++ = CONVERT(c&0x7FFF,alpha); + } + } + break; + } + } //switch(texture format) + +#ifdef DO_DEBUG_DUMP_TEXTURE + DebugDumpTexture(newitem); +#endif + + return newitem; + } //scan() + + void invalidate() + { + for(TTexCacheItemMultimap::iterator it(index.begin()); it != index.end(); ++it) + it->second->suspectedInvalid = true; + } + + void evict(u32 target = kMaxCacheSize) + { + //debug print + //printf("%d %d/%d\n",index.size(),cache_size/1024,target/1024); + + //dont do anything unless we're over the target + if(cache_size<target) return; + + //aim at cutting the cache to half of the max size + target/=2; + + //evicts items in an arbitrary order until it is less than the max cache size + //TODO - do this based on age and not arbitrarily + while(cache_size > target) + { + if(index.size()==0) break; //just in case.. doesnt seem possible, cache_size wouldve been 0 + + TexCacheItem* item = index.begin()->second; + list_remove(item); + //printf("evicting! totalsize:%d\n",cache_size); + delete item; + } + } +} texCache; + +void TexCache_Reset() +{ + texCache.evict(0); +} + +void TexCache_Invalidate() +{ + //note that this gets called whether texdata or texpalette gets reconfigured. + texCache.invalidate(); +} + +TexCacheItem* TexCache_SetTexture(TexCache_TexFormat TEXFORMAT, u32 format, u32 texpal) +{ + switch(TEXFORMAT) + { + case TexFormat_32bpp: return texCache.scan<TexFormat_32bpp>(format,texpal); + case TexFormat_15bpp: return texCache.scan<TexFormat_15bpp>(format,texpal); + default: assert(false); return NULL; + } +} + +//call this periodically to keep the tex cache clean +void TexCache_EvictFrame() +{ + texCache.evict(); +} diff --git a/jni/desmume/src/texcache.h b/jni/desmume/src/texcache.h new file mode 100755 index 0000000..5096cca --- /dev/null +++ b/jni/desmume/src/texcache.h @@ -0,0 +1,83 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2006-2007 shash + Copyright (C) 2008-2009 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _TEXCACHE_H_ +#define _TEXCACHE_H_ + +#include "common.h" +#include <map> + +enum TexCache_TexFormat +{ + TexFormat_None, //used when nothing yet is cached + TexFormat_32bpp, //used by ogl renderer + TexFormat_15bpp //used by rasterizer +}; + +class TexCacheItem; + +typedef std::multimap<u32,TexCacheItem*> TTexCacheItemMultimap; + +class TexCacheItem +{ +public: + TexCacheItem() + : decode_len(0) + , decoded(NULL) + , suspectedInvalid(false) + , deleteCallback(NULL) + , cacheFormat(TexFormat_None) + {} + ~TexCacheItem() { + delete[] decoded; + if(deleteCallback) deleteCallback(this); + } + u32 decode_len; + u32 mode; + u8* decoded; //decoded texture data + bool suspectedInvalid; + TTexCacheItemMultimap::iterator iterator; + + u32 texformat, texpal; + u32 sizeX, sizeY; + float invSizeX, invSizeY; + + u64 texid; //used by ogl renderer for the texid + void (*deleteCallback)(TexCacheItem*); + + TexCache_TexFormat cacheFormat; + + struct Dump { + ~Dump() { + delete[] texture; + } + int textureSize, indexSize; + static const int maxTextureSize=128*1024; + u8* texture; + u8 palette[256*2]; + } dump; +}; + +void TexCache_Invalidate(); +void TexCache_Reset(); +void TexCache_EvictFrame(); + +TexCacheItem* TexCache_SetTexture(TexCache_TexFormat TEXFORMAT, u32 format, u32 texpal); + +#endif diff --git a/jni/desmume/src/thumb_instructions.cpp b/jni/desmume/src/thumb_instructions.cpp new file mode 100755 index 0000000..4e5106f --- /dev/null +++ b/jni/desmume/src/thumb_instructions.cpp @@ -0,0 +1,1172 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2008 shash + Copyright (C) 2008-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "bios.h" +#include "debug.h" +#include "MMU.h" +#include "NDSSystem.h" +#include "thumb_instructions.h" +#include "MMU_timing.h" +#include <assert.h> + +#define cpu (&ARMPROC) +#define TEMPLATE template<int PROCNUM> + +#define REG_NUM(i, n) (((i)>>n)&0x7) + +//----------------------------------------------------------------------------- +// Undefined instruction +//----------------------------------------------------------------------------- +TEMPLATE static u32 FASTCALL OP_UND_THUMB(const u32 i) +{ + INFO("THUMB%c: Undefined instruction: 0x%08X (%s) PC=0x%08X\n", cpu->proc_ID?'7':'9', cpu->instruction, decodeIntruction(true, cpu->instruction), cpu->instruct_adr); + TRAPUNDEF(cpu); + return 1; +} + +//----------------------------------------------------------------------------- +// LSL +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_LSL_0(const u32 i) +{ + cpu->R[REG_NUM(i, 0)] = cpu->R[REG_NUM(i, 3)]; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_LSL(const u32 i) +{ + u32 v = (i>>6) & 0x1F; + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 3)], 32-v); + cpu->R[REG_NUM(i, 0)] = (cpu->R[REG_NUM(i, 3)] << v); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_LSL_REG(const u32 i) +{ + u32 v = cpu->R[REG_NUM(i, 3)] & 0xFF; + + if(v == 0) + { + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 2; + } + if(v<32) + { + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], 32-v); + cpu->R[REG_NUM(i, 0)] <<= v; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 2; + } + if(v==32) + cpu->CPSR.bits.C = BIT0(cpu->R[REG_NUM(i, 0)]); + else + cpu->CPSR.bits.C = 0; + + cpu->R[REG_NUM(i, 0)] = 0; + cpu->CPSR.bits.N = 0; + cpu->CPSR.bits.Z = 1; + + return 2; +} + +//----------------------------------------------------------------------------- +// LSR +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_LSR_0(const u32 i) +{ + cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 3)]); + cpu->R[REG_NUM(i, 0)] = 0; + cpu->CPSR.bits.N = 0; + cpu->CPSR.bits.Z = 1; + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_LSR(const u32 i) +{ + u32 v = (i>>6) & 0x1F; + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 3)], v-1); + cpu->R[REG_NUM(i, 0)] = (cpu->R[REG_NUM(i, 3)] >> v); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_LSR_REG(const u32 i) +{ + u32 v = cpu->R[REG_NUM(i, 3)] & 0xFF; + + if(v == 0) + { + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 2; + } + if(v<32) + { + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1); + cpu->R[REG_NUM(i, 0)] >>= v; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 2; + } + if(v==32) + cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]); + else + cpu->CPSR.bits.C = 0; + cpu->R[REG_NUM(i, 0)] = 0; + cpu->CPSR.bits.N = 0; + cpu->CPSR.bits.Z = 1; + + return 2; +} + +//----------------------------------------------------------------------------- +// ASR +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_ASR_0(const u32 i) +{ + cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 3)]); + cpu->R[REG_NUM(i, 0)] = BIT31(cpu->R[REG_NUM(i, 3)])*0xFFFFFFFF; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_ASR(const u32 i) +{ + u32 v = (i>>6) & 0x1F; + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 3)], v-1); + cpu->R[REG_NUM(i, 0)] = (u32)(((s32)cpu->R[REG_NUM(i, 3)]) >> v); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_ASR_REG(const u32 i) +{ + u32 v = cpu->R[REG_NUM(i, 3)] & 0xFF; + + if(v == 0) + { + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 2; + } + if(v<32) + { + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1); + cpu->R[REG_NUM(i, 0)] = (u32)(((s32)cpu->R[REG_NUM(i, 0)]) >> v); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 2; + } + + cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->R[REG_NUM(i, 0)] = BIT31(cpu->R[REG_NUM(i, 0)])*0xFFFFFFFF; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 2; +} + +//----------------------------------------------------------------------------- +// ADD +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_ADD_IMM3(const u32 i) +{ + u32 imm3 = (i >> 6) & 0x07; + u32 Rn = cpu->R[REG_NUM(i, 3)]; + + if (imm3 == 0) // mov 2 + { + cpu->R[REG_NUM(i, 0)] = Rn; + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + cpu->CPSR.bits.C = 0; + cpu->CPSR.bits.V = 0; + return 1; + } + + cpu->R[REG_NUM(i, 0)] = Rn + imm3; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + cpu->CPSR.bits.C = CarryFrom(Rn, imm3); + cpu->CPSR.bits.V = OverflowFromADD(cpu->R[REG_NUM(i, 0)], Rn, imm3); + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_ADD_IMM8(const u32 i) +{ + u32 imm8 = (i & 0xFF); + u32 Rd = cpu->R[REG_NUM(i, 8)]; + + cpu->R[REG_NUM(i, 8)] = Rd + imm8; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 8)]); + cpu->CPSR.bits.Z = (cpu->R[REG_NUM(i, 8)] == 0); + cpu->CPSR.bits.C = CarryFrom(Rd, imm8); + cpu->CPSR.bits.V = OverflowFromADD(cpu->R[REG_NUM(i, 8)], Rd, imm8); + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_ADD_REG(const u32 i) +{ + u32 Rn = cpu->R[REG_NUM(i, 3)]; + u32 Rm = cpu->R[REG_NUM(i, 6)]; + + cpu->R[REG_NUM(i, 0)] = Rn + Rm; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + cpu->CPSR.bits.C = CarryFrom(Rn, Rm); + cpu->CPSR.bits.V = OverflowFromADD(cpu->R[REG_NUM(i, 0)], Rn, Rm); + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_ADD_SPE(const u32 i) +{ + u32 Rd = REG_NUM(i, 0) | ((i>>4)&8); + + cpu->R[Rd] += cpu->R[REG_POS(i, 3)]; + + if(Rd==15) + { + cpu->next_instruction = cpu->R[15]; + return 3; + } + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_ADD_2PC(const u32 i) +{ + cpu->R[REG_NUM(i, 8)] = (cpu->R[15]&0xFFFFFFFC) + ((i&0xFF)<<2); + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_ADD_2SP(const u32 i) +{ + cpu->R[REG_NUM(i, 8)] = cpu->R[13] + ((i&0xFF)<<2); + + return 1; +} + +//----------------------------------------------------------------------------- +// SUB +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_SUB_IMM3(const u32 i) +{ + u32 imm3 = (i>>6) & 0x07; + u32 Rn = cpu->R[REG_NUM(i, 3)]; + u32 tmp = Rn - imm3; + + cpu->R[REG_NUM(i, 0)] = tmp; + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = (tmp == 0); + cpu->CPSR.bits.C = !BorrowFrom(Rn, imm3); + cpu->CPSR.bits.V = OverflowFromSUB(tmp, Rn, imm3); + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_SUB_IMM8(const u32 i) +{ + u32 imm8 = (i & 0xFF); + u32 Rd = cpu->R[REG_NUM(i, 8)]; + u32 tmp = Rd - imm8; + + cpu->R[REG_NUM(i, 8)] = tmp; + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = (tmp == 0); + cpu->CPSR.bits.C = !BorrowFrom(Rd, imm8); + cpu->CPSR.bits.V = OverflowFromSUB(tmp, Rd, imm8); + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_SUB_REG(const u32 i) +{ + u32 Rn = cpu->R[REG_NUM(i, 3)]; + u32 Rm = cpu->R[REG_NUM(i, 6)]; + u32 tmp = Rn - Rm; + + cpu->R[REG_NUM(i, 0)] = tmp; + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = (tmp == 0); + cpu->CPSR.bits.C = !BorrowFrom(Rn, Rm); + cpu->CPSR.bits.V = OverflowFromSUB(tmp, Rn, Rm); + + return 1; +} + +//----------------------------------------------------------------------------- +// MOV +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_MOV_IMM8(const u32 i) +{ + cpu->R[REG_NUM(i, 8)] = (i & 0xFF); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 8)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 8)] == 0; + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_MOV_SPE(const u32 i) +{ + u32 Rd = REG_NUM(i, 0) | ((i>>4)&8); + + cpu->R[Rd] = cpu->R[REG_POS(i, 3)]; + + if(Rd==15) + { + cpu->next_instruction = cpu->R[15]; + return 3; + } + + return 1; +} + +//----------------------------------------------------------------------------- +// CMP +//----------------------------------------------------------------------------- +TEMPLATE static u32 FASTCALL OP_CMP_IMM8(const u32 i) +{ + u32 tmp = cpu->R[REG_NUM(i, 8)] - (i & 0xFF); + + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = tmp == 0; + cpu->CPSR.bits.C = !BorrowFrom(cpu->R[REG_NUM(i, 8)], (i & 0xFF)); + cpu->CPSR.bits.V = OverflowFromSUB(tmp, cpu->R[REG_NUM(i, 8)], (i & 0xFF)); + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_CMP(const u32 i) +{ + u32 tmp = cpu->R[REG_NUM(i, 0)] - cpu->R[REG_NUM(i, 3)]; + + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = tmp == 0; + cpu->CPSR.bits.C = !BorrowFrom(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)]); + cpu->CPSR.bits.V = OverflowFromSUB(tmp, cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)]); + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_CMP_SPE(const u32 i) +{ + u32 Rn = (i&7) | ((i>>4)&8); + + u32 tmp = cpu->R[Rn] - cpu->R[REG_POS(i, 3)]; + + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = tmp == 0; + cpu->CPSR.bits.C = !BorrowFrom(cpu->R[Rn], cpu->R[REG_POS(i, 3)]); + cpu->CPSR.bits.V = OverflowFromSUB(tmp, cpu->R[Rn], cpu->R[REG_POS(i, 3)]); + + return 1; +} + +//----------------------------------------------------------------------------- +// AND +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_AND(const u32 i) +{ + cpu->R[REG_NUM(i, 0)] &= cpu->R[REG_NUM(i, 3)]; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 1; +} + +//----------------------------------------------------------------------------- +// EOR +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_EOR(const u32 i) +{ + cpu->R[REG_NUM(i, 0)] ^= cpu->R[REG_NUM(i, 3)]; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 1; +} + +//----------------------------------------------------------------------------- +// ADC +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_ADC_REG(const u32 i) +{ + u32 Rd = cpu->R[REG_NUM(i, 0)]; + u32 Rm = cpu->R[REG_NUM(i, 3)]; + + if (!cpu->CPSR.bits.C) + { + cpu->R[REG_NUM(i, 0)] = Rd + Rm; + cpu->CPSR.bits.C = cpu->R[REG_NUM(i, 0)] < Rm; + } + else + { + cpu->R[REG_NUM(i, 0)] = Rd + Rm + 1; + cpu->CPSR.bits.C = cpu->R[REG_NUM(i, 0)] <= Rm; + } + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = (cpu->R[REG_NUM(i, 0)] == 0); + cpu->CPSR.bits.V = BIT31((Rd ^ Rm ^ -1) & (Rd ^ cpu->R[REG_NUM(i, 0)])); + + return 1; +} + +//----------------------------------------------------------------------------- +// SBC +//----------------------------------------------------------------------------- +TEMPLATE static u32 FASTCALL OP_SBC_REG(const u32 i) +{ + u32 Rd = cpu->R[REG_NUM(i, 0)]; + u32 Rm = cpu->R[REG_NUM(i, 3)]; + + if (!cpu->CPSR.bits.C) + { + cpu->R[REG_NUM(i, 0)] = Rd - Rm - 1; + cpu->CPSR.bits.C = Rd > Rm; + } + else + { + cpu->R[REG_NUM(i, 0)] = Rd - Rm; + cpu->CPSR.bits.C = Rd >= Rm; + } + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = (cpu->R[REG_NUM(i, 0)] == 0); + cpu->CPSR.bits.V = BIT31((Rd ^ Rm) & (Rd ^ cpu->R[REG_NUM(i, 0)])); + + return 1; +} + +//----------------------------------------------------------------------------- +// ROR +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_ROR_REG(const u32 i) +{ + u32 v = cpu->R[REG_NUM(i, 3)] & 0xFF; + + if(v == 0) + { + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 2; + } + + v &= 0x1F; + if(v == 0) + { + cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 2; + } + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1); + cpu->R[REG_NUM(i, 0)] = ROR(cpu->R[REG_NUM(i, 0)], v); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 2; +} + +//----------------------------------------------------------------------------- +// TST +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_TST(const u32 i) +{ + u32 tmp = cpu->R[REG_NUM(i, 0)] & cpu->R[REG_NUM(i, 3)]; + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = (tmp == 0); + + return 1; +} + +//----------------------------------------------------------------------------- +// NEG +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_NEG(const u32 i) +{ + u32 Rm = cpu->R[REG_NUM(i, 3)]; + + cpu->R[REG_NUM(i, 0)] = (u32)((s32)0 - (s32)Rm); + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = (cpu->R[REG_NUM(i, 0)] == 0); + cpu->CPSR.bits.C = !BorrowFrom(0, Rm); + cpu->CPSR.bits.V = OverflowFromSUB(cpu->R[REG_NUM(i, 0)], 0, Rm); + + return 1; +} + +//----------------------------------------------------------------------------- +// CMN +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_CMN(const u32 i) +{ + u32 tmp = cpu->R[REG_NUM(i, 0)] + cpu->R[REG_NUM(i, 3)]; + + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = tmp == 0; + cpu->CPSR.bits.C = CarryFrom(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)]); + cpu->CPSR.bits.V = OverflowFromADD(tmp, cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)]); + + return 1; +} + +//----------------------------------------------------------------------------- +// ORR +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_ORR(const u32 i) +{ + cpu->R[REG_NUM(i, 0)] |= cpu->R[REG_NUM(i, 3)]; + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = (cpu->R[REG_NUM(i, 0)] == 0); + + return 1; +} + +//----------------------------------------------------------------------------- +// BIC +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_BIC(const u32 i) +{ + cpu->R[REG_NUM(i, 0)] &= (~cpu->R[REG_NUM(i, 3)]); + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = (cpu->R[REG_NUM(i, 0)] == 0); + + return 1; +} + +//----------------------------------------------------------------------------- +// MVN +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_MVN(const u32 i) +{ + cpu->R[REG_NUM(i, 0)] = (~cpu->R[REG_NUM(i, 3)]); + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 1; +} + +//----------------------------------------------------------------------------- +// MUL +//----------------------------------------------------------------------------- + +#define MUL_Mxx_END_THUMB(c) \ + v >>= 8; \ + if((v==0)||(v==0xFFFFFF)) \ + return c+1; \ + v >>= 8; \ + if((v==0)||(v==0xFFFF)) \ + return c+2; \ + v >>= 8; \ + if((v==0)||(v==0xFF)) \ + return c+3; \ + return c+4; \ + +TEMPLATE static u32 FASTCALL OP_MUL_REG(const u32 i) +{ + u32 v = cpu->R[REG_NUM(i, 3)]; + + // FIXME: + //------ Rd = (Rm * Rd)[31:0] + //------ u64 res = ((u64)cpu->R[REG_NUM(i, 0)] * (u64)v)); + //------ cpu->R[REG_NUM(i, 0)] = (u32)(res & 0xFFFFFFFF); + //------ + + cpu->R[REG_NUM(i, 0)] *= v; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + //The MUL instruction is defined to leave the C flag unchanged in ARMv5 and above. + //In earlier versions of the architecture, the value of the C flag was UNPREDICTABLE + //after a MUL instruction. + + if (!cpu->LDTBit) // ARM4T 1S + mI, m = 3 + return 4; + + MUL_Mxx_END_THUMB(1); +} + +//----------------------------------------------------------------------------- +// STRB / LDRB +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_STRB_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>6)&0x1F); + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_NUM(i, 0)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2, adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>6)&0x1F); + cpu->R[REG_NUM(i, 0)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3, adr); +} + + +TEMPLATE static u32 FASTCALL OP_STRB_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_NUM(i, 0)]); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_WRITE>(2, adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRB_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; + cpu->R[REG_NUM(i, 0)] = (u32)READ8(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3, adr); +} + +//----------------------------------------------------------------------------- +// LDRSB +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_LDRSB_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; + cpu->R[REG_NUM(i, 0)] = (u32)((s8)READ8(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,8,MMU_AD_READ>(3, adr); +} + +//----------------------------------------------------------------------------- +// STRH / LDRH +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_STRH_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>5)&0x3E); + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_NUM(i, 0)]); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_WRITE>(2, adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRH_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>5)&0x3E); + cpu->R[REG_NUM(i, 0)] = (u32)READ16(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3, adr); +} + + +TEMPLATE static u32 FASTCALL OP_STRH_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; + WRITE16(cpu->mem_if->data, adr, ((u16)cpu->R[REG_NUM(i, 0)])); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_WRITE>(2, adr); +} + +TEMPLATE static u32 FASTCALL OP_LDRH_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; + cpu->R[REG_NUM(i, 0)] = (u32)READ16(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3, adr); +} + +//----------------------------------------------------------------------------- +// LDRSH +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_LDRSH_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; + cpu->R[REG_NUM(i, 0)] = (u32)((s16)READ16(cpu->mem_if->data, adr)); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_READ>(3, adr); +} + +//----------------------------------------------------------------------------- +// STR / LDR +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_STR_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>4)&0x7C); + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 0)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2, adr); +} + +TEMPLATE static u32 FASTCALL OP_LDR_IMM_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>4)&0x7C); + u32 tempValue = READ32(cpu->mem_if->data, adr); + adr = (adr&3)*8; + tempValue = (tempValue>>adr) | (tempValue<<(32-adr)); + cpu->R[REG_NUM(i, 0)] = tempValue; + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_READ>(3, adr); +} + + +TEMPLATE static u32 FASTCALL OP_STR_REG_OFF(const u32 i) +{ + u32 adr = cpu->R[REG_NUM(i, 6)] + cpu->R[REG_NUM(i, 3)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 0)]); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_WRITE>(2, adr); +} + +TEMPLATE static u32 FASTCALL OP_LDR_REG_OFF(const u32 i) +{ + u32 adr = (cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]); + u32 tempValue = READ32(cpu->mem_if->data, adr); + adr = (adr&3)*8; + tempValue = (tempValue>>adr) | (tempValue<<(32-adr)); + cpu->R[REG_NUM(i, 0)] = tempValue; + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_READ>(3, adr); +} + +TEMPLATE static u32 FASTCALL OP_STR_SPREL(const u32 i) +{ + u32 adr = cpu->R[13] + ((i&0xFF)<<2); + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 8)]); + + return MMU_aluMemAccessCycles<PROCNUM,16,MMU_AD_WRITE>(2, adr); +} + +TEMPLATE static u32 FASTCALL OP_LDR_SPREL(const u32 i) +{ + u32 adr = cpu->R[13] + ((i&0xFF)<<2); + cpu->R[REG_NUM(i, 8)] = READ32(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_READ>(3, adr); +} + +TEMPLATE static u32 FASTCALL OP_LDR_PCREL(const u32 i) +{ + u32 adr = (cpu->R[15]&0xFFFFFFFC) + ((i&0xFF)<<2); + + cpu->R[REG_NUM(i, 8)] = READ32(cpu->mem_if->data, adr); + + return MMU_aluMemAccessCycles<PROCNUM,32,MMU_AD_READ>(3, adr); +} + +//----------------------------------------------------------------------------- +// Adjust SP +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_ADJUST_P_SP(const u32 i) +{ + cpu->R[13] += ((i&0x7F)<<2); + + return 1; +} + +TEMPLATE static u32 FASTCALL OP_ADJUST_M_SP(const u32 i) +{ + cpu->R[13] -= ((i&0x7F)<<2); + + return 1; +} + +//----------------------------------------------------------------------------- +// PUSH / POP +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_PUSH(const u32 i) +{ + u32 adr = cpu->R[13] - 4; + u32 c = 0, j; + + for(j = 0; j<8; j++) + if(BIT_N(i, 7-j)) + { + WRITE32(cpu->mem_if->data, adr, cpu->R[7-j]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(adr); + adr -= 4; + } + cpu->R[13] = adr + 4; + + return MMU_aluMemCycles<PROCNUM>(3, c); +} + +TEMPLATE static u32 FASTCALL OP_PUSH_LR(const u32 i) +{ + u32 adr = cpu->R[13] - 4; + u32 c = 0, j; + + WRITE32(cpu->mem_if->data, adr, cpu->R[14]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(adr); + adr -= 4; + + for(j = 0; j<8; j++) + if(BIT_N(i, 7-j)) + { + WRITE32(cpu->mem_if->data, adr, cpu->R[7-j]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(adr); + adr -= 4; + } + cpu->R[13] = adr + 4; + + return MMU_aluMemCycles<PROCNUM>(4, c); +} + +TEMPLATE static u32 FASTCALL OP_POP(const u32 i) +{ + u32 adr = cpu->R[13]; + u32 c = 0, j; + + for(j = 0; j<8; j++) + if(BIT_N(i, j)) + { + cpu->R[j] = READ32(cpu->mem_if->data, adr); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(adr); + adr += 4; + } + cpu->R[13] = adr; + + return MMU_aluMemCycles<PROCNUM>(2, c); +} + +// In ARMv5 and above, bit[0] of the loaded value +// determines whether execution continues after this branch in ARM state or in Thumb state, as though the +// following instruction had been executed: +// BX (loaded_value) +// In T variants of ARMv4, bit[0] of the loaded value is ignored and execution continues in Thumb state, as +// though the following instruction had been executed: +// MOV PC,(loaded_value) +TEMPLATE static u32 FASTCALL OP_POP_PC(const u32 i) +{ + u32 adr = cpu->R[13]; + u32 c = 0, j; + u32 v = 0; + + for(j = 0; j<8; j++) + if(BIT_N(i, j)) + { + cpu->R[j] = READ32(cpu->mem_if->data, adr); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(adr); + adr += 4; + } + + v = READ32(cpu->mem_if->data, adr); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(adr); + if(cpu->LDTBit) + cpu->CPSR.bits.T = BIT0(v); + + cpu->R[15] = v & 0xFFFFFFFE; + cpu->next_instruction = cpu->R[15]; + + cpu->R[13] = adr + 4; + return MMU_aluMemCycles<PROCNUM>(5, c); +} + +//----------------------------------------------------------------------------- +// STMIA / LDMIA +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_STMIA_THUMB(const u32 i) +{ + u32 adr = cpu->R[REG_NUM(i, 8)]; + u32 c = 0, j; + u32 erList = 1; //Empty Register List + + // ------ ARM_REF: + // ------ If <Rn> is specified in <registers>: + // ------ * If <Rn> is the lowest-numbered register specified in <registers>, the original value of <Rn> is stored. + // ------ * Otherwise, the stored value of <Rn> is UNPREDICTABLE. + if (BIT_N(i, REG_NUM(i, 8))) + printf("STMIA with Rb in Rlist\n"); + + for(j = 0; j<8; j++) + { + if(BIT_N(i, j)) + { + WRITE32(cpu->mem_if->data, adr, cpu->R[j]); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(adr); + adr += 4; + erList = 0; //Register List isnt empty + } + } + + if (erList) + printf("STMIA with Empty Rlist\n"); + + cpu->R[REG_NUM(i, 8)] = adr; + return MMU_aluMemCycles<PROCNUM>(2, c); +} + +TEMPLATE static u32 FASTCALL OP_LDMIA_THUMB(const u32 i) +{ + u32 regIndex = REG_NUM(i, 8); + u32 adr = cpu->R[regIndex]; + u32 c = 0, j; + u32 erList = 1; //Empty Register List + + //if (BIT_N(i, regIndex)) + // printf("LDMIA with Rb in Rlist at %08X\n",cpu->instruct_adr); + + for(j = 0; j<8; j++) + { + if(BIT_N(i, j)) + { + cpu->R[j] = READ32(cpu->mem_if->data, adr); + c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_READ>(adr); + adr += 4; + erList = 0; //Register List isnt empty + } + } + + if (erList) + printf("LDMIA with Empty Rlist\n"); + + // ARM_REF: THUMB: Causes base register write-back, and is not optional + // ARM_REF: If the base register <Rn> is specified in <registers>, the final value of <Rn> is the loaded value + // (not the written-back value). + if (!BIT_N(i, regIndex)) + cpu->R[regIndex] = adr; + + return MMU_aluMemCycles<PROCNUM>(3, c); +} + +//----------------------------------------------------------------------------- +// BKPT +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_BKPT_THUMB(const u32 i) +{ + // TODO + printf("THUMB%c: Unimplemented opcode BKPT\n", PROCNUM?'7':'9'); + return 1; +} + +//----------------------------------------------------------------------------- +// SWI +//----------------------------------------------------------------------------- + +TEMPLATE static u32 FASTCALL OP_SWI_THUMB(const u32 i) +{ + u32 swinum = i & 0xFF; + + //ideas-style debug prints (execute this SWI with the null terminated string address in R0) + if(swinum==0xFC) { + IdeasLog(cpu); + return 0; + } + + //if the user has changed the intVector to point away from the nds bioses, + //then it doesn't really make any sense to use the builtin SWI's since + //the bios ones aren't getting called anyway + bool bypassBuiltinSWI = + (cpu->intVector == 0x00000000 && PROCNUM==0) + || (cpu->intVector == 0xFFFF0000 && PROCNUM==1); + + if(cpu->swi_tab && !bypassBuiltinSWI) { + //zero 25-dec-2008 - in arm, we were masking to 0x1F. + //this is probably safer since an invalid opcode could crash the emu + //zero 30-jun-2009 - but they say that the ideas 0xFF should crash the device... + //u32 swinum = cpu->instruction & 0xFF; + swinum &= 0x1F; + //printf("%d ARM SWI %d\n",PROCNUM,swinum); + return cpu->swi_tab[swinum]() + 3; + } + else { + /* we use an irq thats not in the irq tab, as + it was replaced due to a changed intVector */ + Status_Reg tmp = cpu->CPSR; + armcpu_switchMode(cpu, SVC); /* enter svc mode */ + cpu->R[14] = cpu->next_instruction; /* jump to swi Vector */ + cpu->SPSR = tmp; /* save old CPSR as new SPSR */ + cpu->CPSR.bits.T = 0; /* handle as ARM32 code */ + cpu->CPSR.bits.I = 1; + cpu->changeCPSR(); + cpu->R[15] = cpu->intVector + 0x08; + cpu->next_instruction = cpu->R[15]; + return 3; + } +} + +//----------------------------------------------------------------------------- +// Branch +//----------------------------------------------------------------------------- + +#define SIGNEEXT_IMM11(i) (((i)&0x7FF) | (BIT10(i) * 0xFFFFF800)) + +TEMPLATE static u32 FASTCALL OP_B_COND(const u32 i) +{ + if(!TEST_COND((i>>8)&0xF, 0, cpu->CPSR)) + return 1; + + cpu->R[15] += (u32)((s8)(i&0xFF))<<1; + cpu->next_instruction = cpu->R[15]; + return 3; +} + +TEMPLATE static u32 FASTCALL OP_B_UNCOND(const u32 i) +{ + //nocash message detection + const u16 last = _MMU_read16<PROCNUM,MMU_AT_DEBUG>(cpu->instruct_adr-2); + const u16 next = _MMU_read16<PROCNUM,MMU_AT_DEBUG>(cpu->instruct_adr+2); + static const u16 mov_r12_r12 = 0x46E4; + if(last == mov_r12_r12 && next == 0x6464) + { + NocashMessage(cpu,6); + } + + cpu->R[15] += (SIGNEEXT_IMM11(i)<<1); + cpu->next_instruction = cpu->R[15]; + return 1; +} + +TEMPLATE static u32 FASTCALL OP_BLX(const u32 i) +{ + cpu->R[15] = (cpu->R[14] + ((i&0x7FF)<<1))&0xFFFFFFFC; + cpu->R[14] = cpu->next_instruction | 1; + cpu->next_instruction = cpu->R[15]; + cpu->CPSR.bits.T = 0; + return 3; +} + +TEMPLATE static u32 FASTCALL OP_BL_10(const u32 i) +{ + cpu->R[14] = cpu->R[15] + (SIGNEEXT_IMM11(i)<<12); + return 1; +} + +TEMPLATE static u32 FASTCALL OP_BL_11(const u32 i) +{ + cpu->R[15] = (cpu->R[14] + ((i&0x7FF)<<1)); + cpu->R[14] = cpu->next_instruction | 1; + cpu->next_instruction = cpu->R[15]; + return 4; +} + +TEMPLATE static u32 FASTCALL OP_BX_THUMB(const u32 i) +{ + // When using PC as operand with BX opcode, switch to ARM state and jump to (instruct_adr+4) + // Reference: http://nocash.emubase.de/gbatek.htm#thumb5hiregisteroperationsbranchexchange + +#if 0 + if (REG_POS(i, 3) == 15) + { + cpu->CPSR.bits.T = 0; + cpu->R[15] &= 0xFFFFFFFC; + cpu->next_instruction = cpu->R[15]; + } + else + { + u32 Rm = cpu->R[REG_POS(i, 3)]; + + cpu->CPSR.bits.T = BIT0(Rm); + cpu->R[15] = (Rm & 0xFFFFFFFE); + cpu->next_instruction = cpu->R[15]; + } +#else + u32 Rm = cpu->R[REG_POS(i, 3)]; + //----- ARM_REF: + //----- Register 15 can be specified for <Rm>. If this is done, R15 is read as normal for Thumb code, + //----- that is, it is the address of the BX instruction itself plus 4. If the BX instruction is at a + //----- word-aligned address, this results in a branch to the next word, executing in ARM state. + //----- However, if the BX instruction is not at a word-aligned address, this means that the results of + //----- the instruction are UNPREDICTABLE (because the value read for R15 has bits[1:0]==0b10). + if (Rm == 15) + { + //printf("THUMB%c: BX using PC as operand\n", PROCNUM?'7':'9'); + //emu_halt(); + } + cpu->CPSR.bits.T = BIT0(Rm); + cpu->R[15] = (Rm & (0xFFFFFFFC|(1<<cpu->CPSR.bits.T))); + cpu->next_instruction = cpu->R[15]; +#endif + return 3; +} + +TEMPLATE static u32 FASTCALL OP_BLX_THUMB(const u32 i) +{ + u32 Rm = cpu->R[REG_POS(i, 3)]; + + cpu->CPSR.bits.T = BIT0(Rm); + //cpu->R[15] = (Rm & (0xFFFFFFFC|(1<<cpu->CPSR.bits.T))); + cpu->R[15] = Rm & 0xFFFFFFFE; + cpu->R[14] = cpu->next_instruction | 1; + cpu->next_instruction = cpu->R[15]; + + return 4; +} + +//----------------------------------------------------------------------------- +// The End +//----------------------------------------------------------------------------- + +#define TABDECL(x) x<0> +const ThumbOpFunc thumb_instructions_set_0[1024] = { +#include "thumb_tabdef.inc" +}; +#undef TABDECL + +#define TABDECL(x) x<1> +const ThumbOpFunc thumb_instructions_set_1[1024] = { +#include "thumb_tabdef.inc" +}; +#undef TABDECL + +#define TABDECL(x) #x +const char* thumb_instruction_names[1024] = { +#include "thumb_tabdef.inc" +}; +#undef TABDECL diff --git a/jni/desmume/src/thumb_instructions.h b/jni/desmume/src/thumb_instructions.h new file mode 100755 index 0000000..393a5e8 --- /dev/null +++ b/jni/desmume/src/thumb_instructions.h @@ -0,0 +1,32 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2006-2009 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef THUMB_INSTRUCTIONS_H +#define THUMB_INSTRUCTIONS_H + +#include "armcpu.h" + +typedef u32 (FASTCALL* ThumbOpFunc)(const u32 i); + +extern const ThumbOpFunc thumb_instructions_set_0[1024]; +extern const ThumbOpFunc thumb_instructions_set_1[1024]; + +extern const char* thumb_instruction_names[1024]; + +#endif + diff --git a/jni/desmume/src/thumb_tabdef.inc b/jni/desmume/src/thumb_tabdef.inc new file mode 100755 index 0000000..21077b0 --- /dev/null +++ b/jni/desmume/src/thumb_tabdef.inc @@ -0,0 +1,1105 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2006-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +TABDECL( OP_LSL_0), //00 0000 0000 +TABDECL( OP_LSL), //00 0000 0001 +TABDECL( OP_LSL), //00 0000 0010 +TABDECL( OP_LSL), //00 0000 0011 +TABDECL( OP_LSL), //00 0000 0100 +TABDECL( OP_LSL), //00 0000 0101 +TABDECL( OP_LSL), //00 0000 0110 +TABDECL( OP_LSL), //00 0000 0111 +TABDECL( OP_LSL), //00 0000 1000 +TABDECL( OP_LSL), //00 0000 1001 +TABDECL( OP_LSL), //00 0000 1010 +TABDECL( OP_LSL), //00 0000 1011 +TABDECL( OP_LSL), //00 0000 1100 +TABDECL( OP_LSL), //00 0000 1101 +TABDECL( OP_LSL), //00 0000 1110 +TABDECL( OP_LSL), //00 0000 1111 + +TABDECL( OP_LSL), //00 0001 0000 +TABDECL( OP_LSL), //00 0001 0001 +TABDECL( OP_LSL), //00 0001 0010 +TABDECL( OP_LSL), //00 0001 0011 +TABDECL( OP_LSL), //00 0001 0100 +TABDECL( OP_LSL), //00 0001 0101 +TABDECL( OP_LSL), //00 0001 0110 +TABDECL( OP_LSL), //00 0001 0111 +TABDECL( OP_LSL), //00 0001 1000 +TABDECL( OP_LSL), //00 0001 1001 +TABDECL( OP_LSL), //00 0001 1010 +TABDECL( OP_LSL), //00 0001 1011 +TABDECL( OP_LSL), //00 0001 1100 +TABDECL( OP_LSL), //00 0001 1101 +TABDECL( OP_LSL), //00 0001 1110 +TABDECL( OP_LSL), //00 0001 1111 + +TABDECL( OP_LSR_0), //00 0010 0000 +TABDECL( OP_LSR), //00 0010 0001 +TABDECL( OP_LSR), //00 0010 0010 +TABDECL( OP_LSR), //00 0010 0011 +TABDECL( OP_LSR), //00 0010 0100 +TABDECL( OP_LSR), //00 0010 0101 +TABDECL( OP_LSR), //00 0010 0110 +TABDECL( OP_LSR), //00 0010 0111 +TABDECL( OP_LSR), //00 0010 1000 +TABDECL( OP_LSR), //00 0010 1001 +TABDECL( OP_LSR), //00 0010 1010 +TABDECL( OP_LSR), //00 0010 1011 +TABDECL( OP_LSR), //00 0010 1100 +TABDECL( OP_LSR), //00 0010 1101 +TABDECL( OP_LSR), //00 0010 1110 +TABDECL( OP_LSR), //00 0010 1111 + +TABDECL( OP_LSR), //00 0011 0000 +TABDECL( OP_LSR), //00 0011 0001 +TABDECL( OP_LSR), //00 0011 0010 +TABDECL( OP_LSR), //00 0011 0011 +TABDECL( OP_LSR), //00 0011 0100 +TABDECL( OP_LSR), //00 0011 0101 +TABDECL( OP_LSR), //00 0011 0110 +TABDECL( OP_LSR), //00 0011 0111 +TABDECL( OP_LSR), //00 0011 1000 +TABDECL( OP_LSR), //00 0011 1001 +TABDECL( OP_LSR), //00 0011 1010 +TABDECL( OP_LSR), //00 0011 1011 +TABDECL( OP_LSR), //00 0011 1100 +TABDECL( OP_LSR), //00 0011 1101 +TABDECL( OP_LSR), //00 0011 1110 +TABDECL( OP_LSR), //00 0011 1111 + +TABDECL( OP_ASR_0), //00 0100 0000 +TABDECL( OP_ASR), //00 0100 0001 +TABDECL( OP_ASR), //00 0100 0010 +TABDECL( OP_ASR), //00 0100 0011 +TABDECL( OP_ASR), //00 0100 0100 +TABDECL( OP_ASR), //00 0100 0101 +TABDECL( OP_ASR), //00 0100 0110 +TABDECL( OP_ASR), //00 0100 0111 +TABDECL( OP_ASR), //00 0100 1000 +TABDECL( OP_ASR), //00 0100 1001 +TABDECL( OP_ASR), //00 0100 1010 +TABDECL( OP_ASR), //00 0100 1011 +TABDECL( OP_ASR), //00 0100 1100 +TABDECL( OP_ASR), //00 0100 1101 +TABDECL( OP_ASR), //00 0100 1110 +TABDECL( OP_ASR), //00 0100 1111 + +TABDECL( OP_ASR), //00 0101 0000 +TABDECL( OP_ASR), //00 0101 0001 +TABDECL( OP_ASR), //00 0101 0010 +TABDECL( OP_ASR), //00 0101 0011 +TABDECL( OP_ASR), //00 0101 0100 +TABDECL( OP_ASR), //00 0101 0101 +TABDECL( OP_ASR), //00 0101 0110 +TABDECL( OP_ASR), //00 0101 0111 +TABDECL( OP_ASR), //00 0101 1000 +TABDECL( OP_ASR), //00 0101 1001 +TABDECL( OP_ASR), //00 0101 1010 +TABDECL( OP_ASR), //00 0101 1011 +TABDECL( OP_ASR), //00 0101 1100 +TABDECL( OP_ASR), //00 0101 1101 +TABDECL( OP_ASR), //00 0101 1110 +TABDECL( OP_ASR), //00 0101 1111 + +TABDECL( OP_ADD_REG), //00 0110 0000 +TABDECL( OP_ADD_REG), //00 0110 0001 +TABDECL( OP_ADD_REG), //00 0110 0010 +TABDECL( OP_ADD_REG), //00 0110 0011 +TABDECL( OP_ADD_REG), //00 0110 0100 +TABDECL( OP_ADD_REG), //00 0110 0101 +TABDECL( OP_ADD_REG), //00 0110 0110 +TABDECL( OP_ADD_REG), //00 0110 0111 +TABDECL( OP_SUB_REG), //00 0110 1000 +TABDECL( OP_SUB_REG), //00 0110 1001 +TABDECL( OP_SUB_REG), //00 0110 1010 +TABDECL( OP_SUB_REG), //00 0110 1011 +TABDECL( OP_SUB_REG), //00 0110 1100 +TABDECL( OP_SUB_REG), //00 0110 1101 +TABDECL( OP_SUB_REG), //00 0110 1110 +TABDECL( OP_SUB_REG), //00 0110 1111 + +TABDECL( OP_ADD_IMM3), //00 0111 0000 +TABDECL( OP_ADD_IMM3), //00 0111 0001 +TABDECL( OP_ADD_IMM3), //00 0111 0010 +TABDECL( OP_ADD_IMM3), //00 0111 0011 +TABDECL( OP_ADD_IMM3), //00 0111 0100 +TABDECL( OP_ADD_IMM3), //00 0111 0101 +TABDECL( OP_ADD_IMM3), //00 0111 0110 +TABDECL( OP_ADD_IMM3), //00 0111 0111 +TABDECL( OP_SUB_IMM3), //00 0111 1000 +TABDECL( OP_SUB_IMM3), //00 0111 1001 +TABDECL( OP_SUB_IMM3), //00 0111 1010 +TABDECL( OP_SUB_IMM3), //00 0111 1011 +TABDECL( OP_SUB_IMM3), //00 0111 1100 +TABDECL( OP_SUB_IMM3), //00 0111 1101 +TABDECL( OP_SUB_IMM3), //00 0111 1110 +TABDECL( OP_SUB_IMM3), //00 0111 1111 + +TABDECL( OP_MOV_IMM8), //00 1000 0000 +TABDECL( OP_MOV_IMM8), //00 1000 0001 +TABDECL( OP_MOV_IMM8), //00 1000 0010 +TABDECL( OP_MOV_IMM8), //00 1000 0011 +TABDECL( OP_MOV_IMM8), //00 1000 0100 +TABDECL( OP_MOV_IMM8), //00 1000 0101 +TABDECL( OP_MOV_IMM8), //00 1000 0110 +TABDECL( OP_MOV_IMM8), //00 1000 0111 +TABDECL( OP_MOV_IMM8), //00 1000 1000 +TABDECL( OP_MOV_IMM8), //00 1000 1001 +TABDECL( OP_MOV_IMM8), //00 1000 1010 +TABDECL( OP_MOV_IMM8), //00 1000 1011 +TABDECL( OP_MOV_IMM8), //00 1000 1100 +TABDECL( OP_MOV_IMM8), //00 1000 1101 +TABDECL( OP_MOV_IMM8), //00 1000 1110 +TABDECL( OP_MOV_IMM8), //00 1000 1111 + +TABDECL( OP_MOV_IMM8), //00 1001 0000 +TABDECL( OP_MOV_IMM8), //00 1001 0001 +TABDECL( OP_MOV_IMM8), //00 1001 0010 +TABDECL( OP_MOV_IMM8), //00 1001 0011 +TABDECL( OP_MOV_IMM8), //00 1001 0100 +TABDECL( OP_MOV_IMM8), //00 1001 0101 +TABDECL( OP_MOV_IMM8), //00 1001 0110 +TABDECL( OP_MOV_IMM8), //00 1001 0111 +TABDECL( OP_MOV_IMM8), //00 1001 1000 +TABDECL( OP_MOV_IMM8), //00 1001 1001 +TABDECL( OP_MOV_IMM8), //00 1001 1010 +TABDECL( OP_MOV_IMM8), //00 1001 1011 +TABDECL( OP_MOV_IMM8), //00 1001 1100 +TABDECL( OP_MOV_IMM8), //00 1001 1101 +TABDECL( OP_MOV_IMM8), //00 1001 1110 +TABDECL( OP_MOV_IMM8), //00 1001 1111 + +TABDECL( OP_CMP_IMM8), //00 1010 0000 +TABDECL( OP_CMP_IMM8), //00 1010 0001 +TABDECL( OP_CMP_IMM8), //00 1010 0010 +TABDECL( OP_CMP_IMM8), //00 1010 0011 +TABDECL( OP_CMP_IMM8), //00 1010 0100 +TABDECL( OP_CMP_IMM8), //00 1010 0101 +TABDECL( OP_CMP_IMM8), //00 1010 0110 +TABDECL( OP_CMP_IMM8), //00 1010 0111 +TABDECL( OP_CMP_IMM8), //00 1010 1000 +TABDECL( OP_CMP_IMM8), //00 1010 1001 +TABDECL( OP_CMP_IMM8), //00 1010 1010 +TABDECL( OP_CMP_IMM8), //00 1010 1011 +TABDECL( OP_CMP_IMM8), //00 1010 1100 +TABDECL( OP_CMP_IMM8), //00 1010 1101 +TABDECL( OP_CMP_IMM8), //00 1010 1110 +TABDECL( OP_CMP_IMM8), //00 1010 1111 + +TABDECL( OP_CMP_IMM8), //00 1011 0000 +TABDECL( OP_CMP_IMM8), //00 1011 0001 +TABDECL( OP_CMP_IMM8), //00 1011 0010 +TABDECL( OP_CMP_IMM8), //00 1011 0011 +TABDECL( OP_CMP_IMM8), //00 1011 0100 +TABDECL( OP_CMP_IMM8), //00 1011 0101 +TABDECL( OP_CMP_IMM8), //00 1011 0110 +TABDECL( OP_CMP_IMM8), //00 1011 0111 +TABDECL( OP_CMP_IMM8), //00 1011 1000 +TABDECL( OP_CMP_IMM8), //00 1011 1001 +TABDECL( OP_CMP_IMM8), //00 1011 1010 +TABDECL( OP_CMP_IMM8), //00 1011 1011 +TABDECL( OP_CMP_IMM8), //00 1011 1100 +TABDECL( OP_CMP_IMM8), //00 1011 1101 +TABDECL( OP_CMP_IMM8), //00 1011 1110 +TABDECL( OP_CMP_IMM8), //00 1011 1111 + +TABDECL( OP_ADD_IMM8), //00 1100 0000 +TABDECL( OP_ADD_IMM8), //00 1100 0001 +TABDECL( OP_ADD_IMM8), //00 1100 0010 +TABDECL( OP_ADD_IMM8), //00 1100 0011 +TABDECL( OP_ADD_IMM8), //00 1100 0100 +TABDECL( OP_ADD_IMM8), //00 1100 0101 +TABDECL( OP_ADD_IMM8), //00 1100 0110 +TABDECL( OP_ADD_IMM8), //00 1100 0111 +TABDECL( OP_ADD_IMM8), //00 1100 1000 +TABDECL( OP_ADD_IMM8), //00 1100 1001 +TABDECL( OP_ADD_IMM8), //00 1100 1010 +TABDECL( OP_ADD_IMM8), //00 1100 1011 +TABDECL( OP_ADD_IMM8), //00 1100 1100 +TABDECL( OP_ADD_IMM8), //00 1100 1101 +TABDECL( OP_ADD_IMM8), //00 1100 1110 +TABDECL( OP_ADD_IMM8), //00 1100 1111 + +TABDECL( OP_ADD_IMM8), //00 1101 0000 +TABDECL( OP_ADD_IMM8), //00 1101 0001 +TABDECL( OP_ADD_IMM8), //00 1101 0010 +TABDECL( OP_ADD_IMM8), //00 1101 0011 +TABDECL( OP_ADD_IMM8), //00 1101 0100 +TABDECL( OP_ADD_IMM8), //00 1101 0101 +TABDECL( OP_ADD_IMM8), //00 1101 0110 +TABDECL( OP_ADD_IMM8), //00 1101 0111 +TABDECL( OP_ADD_IMM8), //00 1101 1000 +TABDECL( OP_ADD_IMM8), //00 1101 1001 +TABDECL( OP_ADD_IMM8), //00 1101 1010 +TABDECL( OP_ADD_IMM8), //00 1101 1011 +TABDECL( OP_ADD_IMM8), //00 1101 1100 +TABDECL( OP_ADD_IMM8), //00 1101 1101 +TABDECL( OP_ADD_IMM8), //00 1101 1110 +TABDECL( OP_ADD_IMM8), //00 1101 1111 + +TABDECL( OP_SUB_IMM8), //00 1110 0000 +TABDECL( OP_SUB_IMM8), //00 1110 0001 +TABDECL( OP_SUB_IMM8), //00 1110 0010 +TABDECL( OP_SUB_IMM8), //00 1110 0011 +TABDECL( OP_SUB_IMM8), //00 1110 0100 +TABDECL( OP_SUB_IMM8), //00 1110 0101 +TABDECL( OP_SUB_IMM8), //00 1110 0110 +TABDECL( OP_SUB_IMM8), //00 1110 0111 +TABDECL( OP_SUB_IMM8), //00 1110 1000 +TABDECL( OP_SUB_IMM8), //00 1110 1001 +TABDECL( OP_SUB_IMM8), //00 1110 1010 +TABDECL( OP_SUB_IMM8), //00 1110 1011 +TABDECL( OP_SUB_IMM8), //00 1110 1100 +TABDECL( OP_SUB_IMM8), //00 1110 1101 +TABDECL( OP_SUB_IMM8), //00 1110 1110 +TABDECL( OP_SUB_IMM8), //00 1110 1111 + +TABDECL( OP_SUB_IMM8), //00 1111 0000 +TABDECL( OP_SUB_IMM8), //00 1111 0001 +TABDECL( OP_SUB_IMM8), //00 1111 0010 +TABDECL( OP_SUB_IMM8), //00 1111 0011 +TABDECL( OP_SUB_IMM8), //00 1111 0100 +TABDECL( OP_SUB_IMM8), //00 1111 0101 +TABDECL( OP_SUB_IMM8), //00 1111 0110 +TABDECL( OP_SUB_IMM8), //00 1111 0111 +TABDECL( OP_SUB_IMM8), //00 1111 1000 +TABDECL( OP_SUB_IMM8), //00 1111 1001 +TABDECL( OP_SUB_IMM8), //00 1111 1010 +TABDECL( OP_SUB_IMM8), //00 1111 1011 +TABDECL( OP_SUB_IMM8), //00 1111 1100 +TABDECL( OP_SUB_IMM8), //00 1111 1101 +TABDECL( OP_SUB_IMM8), //00 1111 1110 +TABDECL( OP_SUB_IMM8), //00 1111 1111 + +TABDECL( OP_AND), //01 0000 0000 +TABDECL( OP_EOR), //01 0000 0001 +TABDECL( OP_LSL_REG), //01 0000 0010 +TABDECL( OP_LSR_REG), //01 0000 0011 +TABDECL( OP_ASR_REG), //01 0000 0100 +TABDECL( OP_ADC_REG), //01 0000 0101 +TABDECL( OP_SBC_REG), //01 0000 0110 +TABDECL( OP_ROR_REG), //01 0000 0111 +TABDECL( OP_TST), //01 0000 1000 +TABDECL( OP_NEG), //01 0000 1001 +TABDECL( OP_CMP), //01 0000 1010 +TABDECL( OP_CMN), //01 0000 1011 +TABDECL( OP_ORR), //01 0000 1100 +TABDECL( OP_MUL_REG), //01 0000 1101 +TABDECL( OP_BIC), //01 0000 1110 +TABDECL( OP_MVN), //01 0000 1111 + +TABDECL( OP_ADD_SPE), //01 0001 0000 +TABDECL( OP_ADD_SPE), //01 0001 0001 +TABDECL( OP_ADD_SPE), //01 0001 0010 +TABDECL( OP_ADD_SPE), //01 0001 0011 +TABDECL( OP_CMP_SPE), //01 0001 0100 +TABDECL( OP_CMP_SPE), //01 0001 0101 +TABDECL( OP_CMP_SPE), //01 0001 0110 +TABDECL( OP_CMP_SPE), //01 0001 0111 +TABDECL( OP_MOV_SPE), //01 0001 1000 +TABDECL( OP_MOV_SPE), //01 0001 1001 +TABDECL( OP_MOV_SPE), //01 0001 1010 +TABDECL( OP_MOV_SPE), //01 0001 1011 +TABDECL( OP_BX_THUMB), //01 0001 1100 +TABDECL( OP_BX_THUMB), //01 0001 1101 +TABDECL( OP_BLX_THUMB), //01 0001 1110 +TABDECL( OP_BLX_THUMB), //01 0001 1111 + +TABDECL( OP_LDR_PCREL), //01 0010 0000 +TABDECL( OP_LDR_PCREL), //01 0010 0001 +TABDECL( OP_LDR_PCREL), //01 0010 0010 +TABDECL( OP_LDR_PCREL), //01 0010 0011 +TABDECL( OP_LDR_PCREL), //01 0010 0100 +TABDECL( OP_LDR_PCREL), //01 0010 0101 +TABDECL( OP_LDR_PCREL), //01 0010 0110 +TABDECL( OP_LDR_PCREL), //01 0010 0111 +TABDECL( OP_LDR_PCREL), //01 0010 1000 +TABDECL( OP_LDR_PCREL), //01 0010 1001 +TABDECL( OP_LDR_PCREL), //01 0010 1010 +TABDECL( OP_LDR_PCREL), //01 0010 1011 +TABDECL( OP_LDR_PCREL), //01 0010 1100 +TABDECL( OP_LDR_PCREL), //01 0010 1101 +TABDECL( OP_LDR_PCREL), //01 0010 1110 +TABDECL( OP_LDR_PCREL), //01 0010 1111 + +TABDECL( OP_LDR_PCREL), //01 0011 0000 +TABDECL( OP_LDR_PCREL), //01 0011 0001 +TABDECL( OP_LDR_PCREL), //01 0011 0010 +TABDECL( OP_LDR_PCREL), //01 0011 0011 +TABDECL( OP_LDR_PCREL), //01 0011 0100 +TABDECL( OP_LDR_PCREL), //01 0011 0101 +TABDECL( OP_LDR_PCREL), //01 0011 0110 +TABDECL( OP_LDR_PCREL), //01 0011 0111 +TABDECL( OP_LDR_PCREL), //01 0011 1000 +TABDECL( OP_LDR_PCREL), //01 0011 1001 +TABDECL( OP_LDR_PCREL), //01 0011 1010 +TABDECL( OP_LDR_PCREL), //01 0011 1011 +TABDECL( OP_LDR_PCREL), //01 0011 1100 +TABDECL( OP_LDR_PCREL), //01 0011 1101 +TABDECL( OP_LDR_PCREL), //01 0011 1110 +TABDECL( OP_LDR_PCREL), //01 0011 1111 + +TABDECL( OP_STR_REG_OFF), //01 0100 0000 +TABDECL( OP_STR_REG_OFF), //01 0100 0001 +TABDECL( OP_STR_REG_OFF), //01 0100 0010 +TABDECL( OP_STR_REG_OFF), //01 0100 0011 +TABDECL( OP_STR_REG_OFF), //01 0100 0100 +TABDECL( OP_STR_REG_OFF), //01 0100 0101 +TABDECL( OP_STR_REG_OFF), //01 0100 0110 +TABDECL( OP_STR_REG_OFF), //01 0100 0111 +TABDECL( OP_STRH_REG_OFF), //01 0100 1000 +TABDECL( OP_STRH_REG_OFF), //01 0100 1001 +TABDECL( OP_STRH_REG_OFF), //01 0100 1010 +TABDECL( OP_STRH_REG_OFF), //01 0100 1011 +TABDECL( OP_STRH_REG_OFF), //01 0100 1100 +TABDECL( OP_STRH_REG_OFF), //01 0100 1101 +TABDECL( OP_STRH_REG_OFF), //01 0100 1110 +TABDECL( OP_STRH_REG_OFF), //01 0100 1111 + +TABDECL( OP_STRB_REG_OFF), //01 0101 0000 +TABDECL( OP_STRB_REG_OFF), //01 0101 0001 +TABDECL( OP_STRB_REG_OFF), //01 0101 0010 +TABDECL( OP_STRB_REG_OFF), //01 0101 0011 +TABDECL( OP_STRB_REG_OFF), //01 0101 0100 +TABDECL( OP_STRB_REG_OFF), //01 0101 0101 +TABDECL( OP_STRB_REG_OFF), //01 0101 0110 +TABDECL( OP_STRB_REG_OFF), //01 0101 0111 +TABDECL( OP_LDRSB_REG_OFF), //01 0101 1000 +TABDECL( OP_LDRSB_REG_OFF), //01 0101 1001 +TABDECL( OP_LDRSB_REG_OFF), //01 0101 1010 +TABDECL( OP_LDRSB_REG_OFF), //01 0101 1011 +TABDECL( OP_LDRSB_REG_OFF), //01 0101 1100 +TABDECL( OP_LDRSB_REG_OFF), //01 0101 1101 +TABDECL( OP_LDRSB_REG_OFF), //01 0101 1110 +TABDECL( OP_LDRSB_REG_OFF), //01 0101 1111 + +TABDECL( OP_LDR_REG_OFF), //01 0110 0000 +TABDECL( OP_LDR_REG_OFF), //01 0110 0001 +TABDECL( OP_LDR_REG_OFF), //01 0110 0010 +TABDECL( OP_LDR_REG_OFF), //01 0110 0011 +TABDECL( OP_LDR_REG_OFF), //01 0110 0100 +TABDECL( OP_LDR_REG_OFF), //01 0110 0101 +TABDECL( OP_LDR_REG_OFF), //01 0110 0110 +TABDECL( OP_LDR_REG_OFF), //01 0110 0111 +TABDECL( OP_LDRH_REG_OFF), //01 0110 1000 +TABDECL( OP_LDRH_REG_OFF), //01 0110 1001 +TABDECL( OP_LDRH_REG_OFF), //01 0110 1010 +TABDECL( OP_LDRH_REG_OFF), //01 0110 1011 +TABDECL( OP_LDRH_REG_OFF), //01 0110 1100 +TABDECL( OP_LDRH_REG_OFF), //01 0110 1101 +TABDECL( OP_LDRH_REG_OFF), //01 0110 1110 +TABDECL( OP_LDRH_REG_OFF), //01 0110 1111 + +TABDECL( OP_LDRB_REG_OFF), //01 0111 0000 +TABDECL( OP_LDRB_REG_OFF), //01 0111 0001 +TABDECL( OP_LDRB_REG_OFF), //01 0111 0010 +TABDECL( OP_LDRB_REG_OFF), //01 0111 0011 +TABDECL( OP_LDRB_REG_OFF), //01 0111 0100 +TABDECL( OP_LDRB_REG_OFF), //01 0111 0101 +TABDECL( OP_LDRB_REG_OFF), //01 0111 0110 +TABDECL( OP_LDRB_REG_OFF), //01 0111 0111 +TABDECL( OP_LDRSH_REG_OFF), //01 0111 1000 +TABDECL( OP_LDRSH_REG_OFF), //01 0111 1001 +TABDECL( OP_LDRSH_REG_OFF), //01 0111 1010 +TABDECL( OP_LDRSH_REG_OFF), //01 0111 1011 +TABDECL( OP_LDRSH_REG_OFF), //01 0111 1100 +TABDECL( OP_LDRSH_REG_OFF), //01 0111 1101 +TABDECL( OP_LDRSH_REG_OFF), //01 0111 1110 +TABDECL( OP_LDRSH_REG_OFF), //01 0111 1111 + +TABDECL( OP_STR_IMM_OFF), //01 1000 0000 +TABDECL( OP_STR_IMM_OFF), //01 1000 0001 +TABDECL( OP_STR_IMM_OFF), //01 1000 0010 +TABDECL( OP_STR_IMM_OFF), //01 1000 0011 +TABDECL( OP_STR_IMM_OFF), //01 1000 0100 +TABDECL( OP_STR_IMM_OFF), //01 1000 0101 +TABDECL( OP_STR_IMM_OFF), //01 1000 0110 +TABDECL( OP_STR_IMM_OFF), //01 1000 0111 +TABDECL( OP_STR_IMM_OFF), //01 1000 1000 +TABDECL( OP_STR_IMM_OFF), //01 1000 1001 +TABDECL( OP_STR_IMM_OFF), //01 1000 1010 +TABDECL( OP_STR_IMM_OFF), //01 1000 1011 +TABDECL( OP_STR_IMM_OFF), //01 1000 1100 +TABDECL( OP_STR_IMM_OFF), //01 1000 1101 +TABDECL( OP_STR_IMM_OFF), //01 1000 1110 +TABDECL( OP_STR_IMM_OFF), //01 1000 1111 + +TABDECL( OP_STR_IMM_OFF), //01 1001 0000 +TABDECL( OP_STR_IMM_OFF), //01 1001 0001 +TABDECL( OP_STR_IMM_OFF), //01 1001 0010 +TABDECL( OP_STR_IMM_OFF), //01 1001 0011 +TABDECL( OP_STR_IMM_OFF), //01 1001 0100 +TABDECL( OP_STR_IMM_OFF), //01 1001 0101 +TABDECL( OP_STR_IMM_OFF), //01 1001 0110 +TABDECL( OP_STR_IMM_OFF), //01 1001 0111 +TABDECL( OP_STR_IMM_OFF), //01 1001 1000 +TABDECL( OP_STR_IMM_OFF), //01 1001 1001 +TABDECL( OP_STR_IMM_OFF), //01 1001 1010 +TABDECL( OP_STR_IMM_OFF), //01 1001 1011 +TABDECL( OP_STR_IMM_OFF), //01 1001 1100 +TABDECL( OP_STR_IMM_OFF), //01 1001 1101 +TABDECL( OP_STR_IMM_OFF), //01 1001 1110 +TABDECL( OP_STR_IMM_OFF), //01 1001 1111 + +TABDECL( OP_LDR_IMM_OFF), //01 1010 0000 +TABDECL( OP_LDR_IMM_OFF), //01 1010 0001 +TABDECL( OP_LDR_IMM_OFF), //01 1010 0010 +TABDECL( OP_LDR_IMM_OFF), //01 1010 0011 +TABDECL( OP_LDR_IMM_OFF), //01 1010 0100 +TABDECL( OP_LDR_IMM_OFF), //01 1010 0101 +TABDECL( OP_LDR_IMM_OFF), //01 1010 0110 +TABDECL( OP_LDR_IMM_OFF), //01 1010 0111 +TABDECL( OP_LDR_IMM_OFF), //01 1010 1000 +TABDECL( OP_LDR_IMM_OFF), //01 1010 1001 +TABDECL( OP_LDR_IMM_OFF), //01 1010 1010 +TABDECL( OP_LDR_IMM_OFF), //01 1010 1011 +TABDECL( OP_LDR_IMM_OFF), //01 1010 1100 +TABDECL( OP_LDR_IMM_OFF), //01 1010 1101 +TABDECL( OP_LDR_IMM_OFF), //01 1010 1110 +TABDECL( OP_LDR_IMM_OFF), //01 1010 1111 + +TABDECL( OP_LDR_IMM_OFF), //01 1011 0000 +TABDECL( OP_LDR_IMM_OFF), //01 1011 0001 +TABDECL( OP_LDR_IMM_OFF), //01 1011 0010 +TABDECL( OP_LDR_IMM_OFF), //01 1011 0011 +TABDECL( OP_LDR_IMM_OFF), //01 1011 0100 +TABDECL( OP_LDR_IMM_OFF), //01 1011 0101 +TABDECL( OP_LDR_IMM_OFF), //01 1011 0110 +TABDECL( OP_LDR_IMM_OFF), //01 1011 0111 +TABDECL( OP_LDR_IMM_OFF), //01 1011 1000 +TABDECL( OP_LDR_IMM_OFF), //01 1011 1001 +TABDECL( OP_LDR_IMM_OFF), //01 1011 1010 +TABDECL( OP_LDR_IMM_OFF), //01 1011 1011 +TABDECL( OP_LDR_IMM_OFF), //01 1011 1100 +TABDECL( OP_LDR_IMM_OFF), //01 1011 1101 +TABDECL( OP_LDR_IMM_OFF), //01 1011 1110 +TABDECL( OP_LDR_IMM_OFF), //01 1011 1111 + +TABDECL( OP_STRB_IMM_OFF), //01 1100 0000 +TABDECL( OP_STRB_IMM_OFF), //01 1100 0001 +TABDECL( OP_STRB_IMM_OFF), //01 1100 0010 +TABDECL( OP_STRB_IMM_OFF), //01 1100 0011 +TABDECL( OP_STRB_IMM_OFF), //01 1100 0100 +TABDECL( OP_STRB_IMM_OFF), //01 1100 0101 +TABDECL( OP_STRB_IMM_OFF), //01 1100 0110 +TABDECL( OP_STRB_IMM_OFF), //01 1100 0111 +TABDECL( OP_STRB_IMM_OFF), //01 1100 1000 +TABDECL( OP_STRB_IMM_OFF), //01 1100 1001 +TABDECL( OP_STRB_IMM_OFF), //01 1100 1010 +TABDECL( OP_STRB_IMM_OFF), //01 1100 1011 +TABDECL( OP_STRB_IMM_OFF), //01 1100 1100 +TABDECL( OP_STRB_IMM_OFF), //01 1100 1101 +TABDECL( OP_STRB_IMM_OFF), //01 1100 1110 +TABDECL( OP_STRB_IMM_OFF), //01 1100 1111 + +TABDECL( OP_STRB_IMM_OFF), //01 1101 0000 +TABDECL( OP_STRB_IMM_OFF), //01 1101 0001 +TABDECL( OP_STRB_IMM_OFF), //01 1101 0010 +TABDECL( OP_STRB_IMM_OFF), //01 1101 0011 +TABDECL( OP_STRB_IMM_OFF), //01 1101 0100 +TABDECL( OP_STRB_IMM_OFF), //01 1101 0101 +TABDECL( OP_STRB_IMM_OFF), //01 1101 0110 +TABDECL( OP_STRB_IMM_OFF), //01 1101 0111 +TABDECL( OP_STRB_IMM_OFF), //01 1101 1000 +TABDECL( OP_STRB_IMM_OFF), //01 1101 1001 +TABDECL( OP_STRB_IMM_OFF), //01 1101 1010 +TABDECL( OP_STRB_IMM_OFF), //01 1101 1011 +TABDECL( OP_STRB_IMM_OFF), //01 1101 1100 +TABDECL( OP_STRB_IMM_OFF), //01 1101 1101 +TABDECL( OP_STRB_IMM_OFF), //01 1101 1110 +TABDECL( OP_STRB_IMM_OFF), //01 1101 1111 + +TABDECL( OP_LDRB_IMM_OFF), //01 1110 0000 +TABDECL( OP_LDRB_IMM_OFF), //01 1110 0001 +TABDECL( OP_LDRB_IMM_OFF), //01 1110 0010 +TABDECL( OP_LDRB_IMM_OFF), //01 1110 0011 +TABDECL( OP_LDRB_IMM_OFF), //01 1110 0100 +TABDECL( OP_LDRB_IMM_OFF), //01 1110 0101 +TABDECL( OP_LDRB_IMM_OFF), //01 1110 0110 +TABDECL( OP_LDRB_IMM_OFF), //01 1110 0111 +TABDECL( OP_LDRB_IMM_OFF), //01 1110 1000 +TABDECL( OP_LDRB_IMM_OFF), //01 1110 1001 +TABDECL( OP_LDRB_IMM_OFF), //01 1110 1010 +TABDECL( OP_LDRB_IMM_OFF), //01 1110 1011 +TABDECL( OP_LDRB_IMM_OFF), //01 1110 1100 +TABDECL( OP_LDRB_IMM_OFF), //01 1110 1101 +TABDECL( OP_LDRB_IMM_OFF), //01 1110 1110 +TABDECL( OP_LDRB_IMM_OFF), //01 1110 1111 + +TABDECL( OP_LDRB_IMM_OFF), //01 1111 0000 +TABDECL( OP_LDRB_IMM_OFF), //01 1111 0001 +TABDECL( OP_LDRB_IMM_OFF), //01 1111 0010 +TABDECL( OP_LDRB_IMM_OFF), //01 1111 0011 +TABDECL( OP_LDRB_IMM_OFF), //01 1111 0100 +TABDECL( OP_LDRB_IMM_OFF), //01 1111 0101 +TABDECL( OP_LDRB_IMM_OFF), //01 1111 0110 +TABDECL( OP_LDRB_IMM_OFF), //01 1111 0111 +TABDECL( OP_LDRB_IMM_OFF), //01 1111 1000 +TABDECL( OP_LDRB_IMM_OFF), //01 1111 1001 +TABDECL( OP_LDRB_IMM_OFF), //01 1111 1010 +TABDECL( OP_LDRB_IMM_OFF), //01 1111 1011 +TABDECL( OP_LDRB_IMM_OFF), //01 1111 1100 +TABDECL( OP_LDRB_IMM_OFF), //01 1111 1101 +TABDECL( OP_LDRB_IMM_OFF), //01 1111 1110 +TABDECL( OP_LDRB_IMM_OFF), //01 1111 1111 + +TABDECL( OP_STRH_IMM_OFF), //10 0000 0000 +TABDECL( OP_STRH_IMM_OFF), //10 0000 0001 +TABDECL( OP_STRH_IMM_OFF), //10 0000 0010 +TABDECL( OP_STRH_IMM_OFF), //10 0000 0011 +TABDECL( OP_STRH_IMM_OFF), //10 0000 0100 +TABDECL( OP_STRH_IMM_OFF), //10 0000 0101 +TABDECL( OP_STRH_IMM_OFF), //10 0000 0110 +TABDECL( OP_STRH_IMM_OFF), //10 0000 0111 +TABDECL( OP_STRH_IMM_OFF), //10 0000 1000 +TABDECL( OP_STRH_IMM_OFF), //10 0000 1001 +TABDECL( OP_STRH_IMM_OFF), //10 0000 1010 +TABDECL( OP_STRH_IMM_OFF), //10 0000 1011 +TABDECL( OP_STRH_IMM_OFF), //10 0000 1100 +TABDECL( OP_STRH_IMM_OFF), //10 0000 1101 +TABDECL( OP_STRH_IMM_OFF), //10 0000 1110 +TABDECL( OP_STRH_IMM_OFF), //10 0000 1111 + +TABDECL( OP_STRH_IMM_OFF), //10 0001 0000 +TABDECL( OP_STRH_IMM_OFF), //10 0001 0001 +TABDECL( OP_STRH_IMM_OFF), //10 0001 0010 +TABDECL( OP_STRH_IMM_OFF), //10 0001 0011 +TABDECL( OP_STRH_IMM_OFF), //10 0001 0100 +TABDECL( OP_STRH_IMM_OFF), //10 0001 0101 +TABDECL( OP_STRH_IMM_OFF), //10 0001 0110 +TABDECL( OP_STRH_IMM_OFF), //10 0001 0111 +TABDECL( OP_STRH_IMM_OFF), //10 0001 1000 +TABDECL( OP_STRH_IMM_OFF), //10 0001 1001 +TABDECL( OP_STRH_IMM_OFF), //10 0001 1010 +TABDECL( OP_STRH_IMM_OFF), //10 0001 1011 +TABDECL( OP_STRH_IMM_OFF), //10 0001 1100 +TABDECL( OP_STRH_IMM_OFF), //10 0001 1101 +TABDECL( OP_STRH_IMM_OFF), //10 0001 1110 +TABDECL( OP_STRH_IMM_OFF), //10 0001 1111 + +TABDECL( OP_LDRH_IMM_OFF), //10 0010 0000 +TABDECL( OP_LDRH_IMM_OFF), //10 0010 0001 +TABDECL( OP_LDRH_IMM_OFF), //10 0010 0010 +TABDECL( OP_LDRH_IMM_OFF), //10 0010 0011 +TABDECL( OP_LDRH_IMM_OFF), //10 0010 0100 +TABDECL( OP_LDRH_IMM_OFF), //10 0010 0101 +TABDECL( OP_LDRH_IMM_OFF), //10 0010 0110 +TABDECL( OP_LDRH_IMM_OFF), //10 0010 0111 +TABDECL( OP_LDRH_IMM_OFF), //10 0010 1000 +TABDECL( OP_LDRH_IMM_OFF), //10 0010 1001 +TABDECL( OP_LDRH_IMM_OFF), //10 0010 1010 +TABDECL( OP_LDRH_IMM_OFF), //10 0010 1011 +TABDECL( OP_LDRH_IMM_OFF), //10 0010 1100 +TABDECL( OP_LDRH_IMM_OFF), //10 0010 1101 +TABDECL( OP_LDRH_IMM_OFF), //10 0010 1110 +TABDECL( OP_LDRH_IMM_OFF), //10 0010 1111 + +TABDECL( OP_LDRH_IMM_OFF), //10 0011 0000 +TABDECL( OP_LDRH_IMM_OFF), //10 0011 0001 +TABDECL( OP_LDRH_IMM_OFF), //10 0011 0010 +TABDECL( OP_LDRH_IMM_OFF), //10 0011 0011 +TABDECL( OP_LDRH_IMM_OFF), //10 0011 0100 +TABDECL( OP_LDRH_IMM_OFF), //10 0011 0101 +TABDECL( OP_LDRH_IMM_OFF), //10 0011 0110 +TABDECL( OP_LDRH_IMM_OFF), //10 0011 0111 +TABDECL( OP_LDRH_IMM_OFF), //10 0011 1000 +TABDECL( OP_LDRH_IMM_OFF), //10 0011 1001 +TABDECL( OP_LDRH_IMM_OFF), //10 0011 1010 +TABDECL( OP_LDRH_IMM_OFF), //10 0011 1011 +TABDECL( OP_LDRH_IMM_OFF), //10 0011 1100 +TABDECL( OP_LDRH_IMM_OFF), //10 0011 1101 +TABDECL( OP_LDRH_IMM_OFF), //10 0011 1110 +TABDECL( OP_LDRH_IMM_OFF), //10 0011 1111 + +TABDECL( OP_STR_SPREL), //10 0100 0000 +TABDECL( OP_STR_SPREL), //10 0100 0001 +TABDECL( OP_STR_SPREL), //10 0100 0010 +TABDECL( OP_STR_SPREL), //10 0100 0011 +TABDECL( OP_STR_SPREL), //10 0100 0100 +TABDECL( OP_STR_SPREL), //10 0100 0101 +TABDECL( OP_STR_SPREL), //10 0100 0110 +TABDECL( OP_STR_SPREL), //10 0100 0111 +TABDECL( OP_STR_SPREL), //10 0100 1000 +TABDECL( OP_STR_SPREL), //10 0100 1001 +TABDECL( OP_STR_SPREL), //10 0100 1010 +TABDECL( OP_STR_SPREL), //10 0100 1011 +TABDECL( OP_STR_SPREL), //10 0100 1100 +TABDECL( OP_STR_SPREL), //10 0100 1101 +TABDECL( OP_STR_SPREL), //10 0100 1110 +TABDECL( OP_STR_SPREL), //10 0100 1111 + +TABDECL( OP_STR_SPREL), //10 0101 0000 +TABDECL( OP_STR_SPREL), //10 0101 0001 +TABDECL( OP_STR_SPREL), //10 0101 0010 +TABDECL( OP_STR_SPREL), //10 0101 0011 +TABDECL( OP_STR_SPREL), //10 0101 0100 +TABDECL( OP_STR_SPREL), //10 0101 0101 +TABDECL( OP_STR_SPREL), //10 0101 0110 +TABDECL( OP_STR_SPREL), //10 0101 0111 +TABDECL( OP_STR_SPREL), //10 0101 1000 +TABDECL( OP_STR_SPREL), //10 0101 1001 +TABDECL( OP_STR_SPREL), //10 0101 1010 +TABDECL( OP_STR_SPREL), //10 0101 1011 +TABDECL( OP_STR_SPREL), //10 0101 1100 +TABDECL( OP_STR_SPREL), //10 0101 1101 +TABDECL( OP_STR_SPREL), //10 0101 1110 +TABDECL( OP_STR_SPREL), //10 0101 1111 + +TABDECL( OP_LDR_SPREL), //10 0110 0000 +TABDECL( OP_LDR_SPREL), //10 0110 0001 +TABDECL( OP_LDR_SPREL), //10 0110 0010 +TABDECL( OP_LDR_SPREL), //10 0110 0011 +TABDECL( OP_LDR_SPREL), //10 0110 0100 +TABDECL( OP_LDR_SPREL), //10 0110 0101 +TABDECL( OP_LDR_SPREL), //10 0110 0110 +TABDECL( OP_LDR_SPREL), //10 0110 0111 +TABDECL( OP_LDR_SPREL), //10 0110 1000 +TABDECL( OP_LDR_SPREL), //10 0110 1001 +TABDECL( OP_LDR_SPREL), //10 0110 1010 +TABDECL( OP_LDR_SPREL), //10 0110 1011 +TABDECL( OP_LDR_SPREL), //10 0110 1100 +TABDECL( OP_LDR_SPREL), //10 0110 1101 +TABDECL( OP_LDR_SPREL), //10 0110 1110 +TABDECL( OP_LDR_SPREL), //10 0110 1111 + +TABDECL( OP_LDR_SPREL), //10 0111 0000 +TABDECL( OP_LDR_SPREL), //10 0111 0001 +TABDECL( OP_LDR_SPREL), //10 0111 0010 +TABDECL( OP_LDR_SPREL), //10 0111 0011 +TABDECL( OP_LDR_SPREL), //10 0111 0100 +TABDECL( OP_LDR_SPREL), //10 0111 0101 +TABDECL( OP_LDR_SPREL), //10 0111 0110 +TABDECL( OP_LDR_SPREL), //10 0111 0111 +TABDECL( OP_LDR_SPREL), //10 0111 1000 +TABDECL( OP_LDR_SPREL), //10 0111 1001 +TABDECL( OP_LDR_SPREL), //10 0111 1010 +TABDECL( OP_LDR_SPREL), //10 0111 1011 +TABDECL( OP_LDR_SPREL), //10 0111 1100 +TABDECL( OP_LDR_SPREL), //10 0111 1101 +TABDECL( OP_LDR_SPREL), //10 0111 1110 +TABDECL( OP_LDR_SPREL), //10 0111 1111 + +TABDECL( OP_ADD_2PC), //10 1000 0000 +TABDECL( OP_ADD_2PC), //10 1000 0001 +TABDECL( OP_ADD_2PC), //10 1000 0010 +TABDECL( OP_ADD_2PC), //10 1000 0011 +TABDECL( OP_ADD_2PC), //10 1000 0100 +TABDECL( OP_ADD_2PC), //10 1000 0101 +TABDECL( OP_ADD_2PC), //10 1000 0110 +TABDECL( OP_ADD_2PC), //10 1000 0111 +TABDECL( OP_ADD_2PC), //10 1000 1000 +TABDECL( OP_ADD_2PC), //10 1000 1001 +TABDECL( OP_ADD_2PC), //10 1000 1010 +TABDECL( OP_ADD_2PC), //10 1000 1011 +TABDECL( OP_ADD_2PC), //10 1000 1100 +TABDECL( OP_ADD_2PC), //10 1000 1101 +TABDECL( OP_ADD_2PC), //10 1000 1110 +TABDECL( OP_ADD_2PC), //10 1000 1111 + +TABDECL( OP_ADD_2PC), //10 1001 0000 +TABDECL( OP_ADD_2PC), //10 1001 0001 +TABDECL( OP_ADD_2PC), //10 1001 0010 +TABDECL( OP_ADD_2PC), //10 1001 0011 +TABDECL( OP_ADD_2PC), //10 1001 0100 +TABDECL( OP_ADD_2PC), //10 1001 0101 +TABDECL( OP_ADD_2PC), //10 1001 0110 +TABDECL( OP_ADD_2PC), //10 1001 0111 +TABDECL( OP_ADD_2PC), //10 1001 1000 +TABDECL( OP_ADD_2PC), //10 1001 1001 +TABDECL( OP_ADD_2PC), //10 1001 1010 +TABDECL( OP_ADD_2PC), //10 1001 1011 +TABDECL( OP_ADD_2PC), //10 1001 1100 +TABDECL( OP_ADD_2PC), //10 1001 1101 +TABDECL( OP_ADD_2PC), //10 1001 1110 +TABDECL( OP_ADD_2PC), //10 1001 1111 + +TABDECL( OP_ADD_2SP), //10 1010 0000 +TABDECL( OP_ADD_2SP), //10 1010 0001 +TABDECL( OP_ADD_2SP), //10 1010 0010 +TABDECL( OP_ADD_2SP), //10 1010 0011 +TABDECL( OP_ADD_2SP), //10 1010 0100 +TABDECL( OP_ADD_2SP), //10 1010 0101 +TABDECL( OP_ADD_2SP), //10 1010 0110 +TABDECL( OP_ADD_2SP), //10 1010 0111 +TABDECL( OP_ADD_2SP), //10 1010 1000 +TABDECL( OP_ADD_2SP), //10 1010 1001 +TABDECL( OP_ADD_2SP), //10 1010 1010 +TABDECL( OP_ADD_2SP), //10 1010 1011 +TABDECL( OP_ADD_2SP), //10 1010 1100 +TABDECL( OP_ADD_2SP), //10 1010 1101 +TABDECL( OP_ADD_2SP), //10 1010 1110 +TABDECL( OP_ADD_2SP), //10 1010 1111 + +TABDECL( OP_ADD_2SP), //10 1011 0000 +TABDECL( OP_ADD_2SP), //10 1011 0001 +TABDECL( OP_ADD_2SP), //10 1011 0010 +TABDECL( OP_ADD_2SP), //10 1011 0011 +TABDECL( OP_ADD_2SP), //10 1011 0100 +TABDECL( OP_ADD_2SP), //10 1011 0101 +TABDECL( OP_ADD_2SP), //10 1011 0110 +TABDECL( OP_ADD_2SP), //10 1011 0111 +TABDECL( OP_ADD_2SP), //10 1011 1000 +TABDECL( OP_ADD_2SP), //10 1011 1001 +TABDECL( OP_ADD_2SP), //10 1011 1010 +TABDECL( OP_ADD_2SP), //10 1011 1011 +TABDECL( OP_ADD_2SP), //10 1011 1100 +TABDECL( OP_ADD_2SP), //10 1011 1101 +TABDECL( OP_ADD_2SP), //10 1011 1110 +TABDECL( OP_ADD_2SP), //10 1011 1111 + +TABDECL( OP_ADJUST_P_SP), //10 1100 0000 +TABDECL( OP_ADJUST_P_SP), //10 1100 0001 +TABDECL( OP_ADJUST_M_SP), //10 1100 0010 +TABDECL( OP_ADJUST_M_SP), //10 1100 0011 +TABDECL( OP_UND_THUMB), //10 1100 0100 +TABDECL( OP_UND_THUMB), //10 1100 0101 +TABDECL( OP_UND_THUMB), //10 1100 0110 +TABDECL( OP_UND_THUMB), //10 1100 0111 +TABDECL( OP_UND_THUMB), //10 1100 1000 +TABDECL( OP_UND_THUMB), //10 1100 1001 +TABDECL( OP_UND_THUMB), //10 1100 1010 +TABDECL( OP_UND_THUMB), //10 1100 1011 +TABDECL( OP_UND_THUMB), //10 1100 1100 +TABDECL( OP_UND_THUMB), //10 1100 1101 +TABDECL( OP_UND_THUMB), //10 1100 1110 +TABDECL( OP_UND_THUMB), //10 1100 1111 + +TABDECL( OP_PUSH), //10 1101 0000 +TABDECL( OP_PUSH), //10 1101 0001 +TABDECL( OP_PUSH), //10 1101 0010 +TABDECL( OP_PUSH), //10 1101 0011 +TABDECL( OP_PUSH_LR), //10 1101 0100 +TABDECL( OP_PUSH_LR), //10 1101 0101 +TABDECL( OP_PUSH_LR), //10 1101 0110 +TABDECL( OP_PUSH_LR), //10 1101 0111 +TABDECL( OP_UND_THUMB), //10 1101 1000 +TABDECL( OP_UND_THUMB), //10 1101 1001 +TABDECL( OP_UND_THUMB), //10 1101 1010 +TABDECL( OP_UND_THUMB), //10 1101 1011 +TABDECL( OP_UND_THUMB), //10 1101 1100 +TABDECL( OP_UND_THUMB), //10 1101 1101 +TABDECL( OP_UND_THUMB), //10 1101 1110 +TABDECL( OP_UND_THUMB), //10 1101 1111 + +TABDECL( OP_UND_THUMB), //10 1110 0000 +TABDECL( OP_UND_THUMB), //10 1110 0001 +TABDECL( OP_UND_THUMB), //10 1110 0010 +TABDECL( OP_UND_THUMB), //10 1110 0011 +TABDECL( OP_UND_THUMB), //10 1110 0100 +TABDECL( OP_UND_THUMB), //10 1110 0101 +TABDECL( OP_UND_THUMB), //10 1110 0110 +TABDECL( OP_UND_THUMB), //10 1110 0111 +TABDECL( OP_UND_THUMB), //10 1110 1000 +TABDECL( OP_UND_THUMB), //10 1110 1001 +TABDECL( OP_UND_THUMB), //10 1110 1010 +TABDECL( OP_UND_THUMB), //10 1110 1011 +TABDECL( OP_UND_THUMB), //10 1110 1100 +TABDECL( OP_UND_THUMB), //10 1110 1101 +TABDECL( OP_UND_THUMB), //10 1110 1110 +TABDECL( OP_UND_THUMB), //10 1110 1111 + +TABDECL( OP_POP), //10 1111 0000 +TABDECL( OP_POP), //10 1111 0001 +TABDECL( OP_POP), //10 1111 0010 +TABDECL( OP_POP), //10 1111 0011 +TABDECL( OP_POP_PC), //10 1111 0100 +TABDECL( OP_POP_PC), //10 1111 0101 +TABDECL( OP_POP_PC), //10 1111 0110 +TABDECL( OP_POP_PC), //10 1111 0111 +TABDECL( OP_BKPT_THUMB), //10 1111 1000 +TABDECL( OP_BKPT_THUMB), //10 1111 1001 +TABDECL( OP_BKPT_THUMB), //10 1111 1010 +TABDECL( OP_BKPT_THUMB), //10 1111 1011 +TABDECL( OP_UND_THUMB), //10 1111 1100 +TABDECL( OP_UND_THUMB), //10 1111 1101 +TABDECL( OP_UND_THUMB), //10 1111 1110 +TABDECL( OP_UND_THUMB), //10 1111 1111 + +TABDECL( OP_STMIA_THUMB), //11 0000 0000 +TABDECL( OP_STMIA_THUMB), //11 0000 0001 +TABDECL( OP_STMIA_THUMB), //11 0000 0010 +TABDECL( OP_STMIA_THUMB), //11 0000 0011 +TABDECL( OP_STMIA_THUMB), //11 0000 0100 +TABDECL( OP_STMIA_THUMB), //11 0000 0101 +TABDECL( OP_STMIA_THUMB), //11 0000 0110 +TABDECL( OP_STMIA_THUMB), //11 0000 0111 +TABDECL( OP_STMIA_THUMB), //11 0000 1000 +TABDECL( OP_STMIA_THUMB), //11 0000 1001 +TABDECL( OP_STMIA_THUMB), //11 0000 1010 +TABDECL( OP_STMIA_THUMB), //11 0000 1011 +TABDECL( OP_STMIA_THUMB), //11 0000 1100 +TABDECL( OP_STMIA_THUMB), //11 0000 1101 +TABDECL( OP_STMIA_THUMB), //11 0000 1110 +TABDECL( OP_STMIA_THUMB), //11 0000 1111 + +TABDECL( OP_STMIA_THUMB), //11 0001 0000 +TABDECL( OP_STMIA_THUMB), //11 0001 0001 +TABDECL( OP_STMIA_THUMB), //11 0001 0010 +TABDECL( OP_STMIA_THUMB), //11 0001 0011 +TABDECL( OP_STMIA_THUMB), //11 0001 0100 +TABDECL( OP_STMIA_THUMB), //11 0001 0101 +TABDECL( OP_STMIA_THUMB), //11 0001 0110 +TABDECL( OP_STMIA_THUMB), //11 0001 0111 +TABDECL( OP_STMIA_THUMB), //11 0001 1000 +TABDECL( OP_STMIA_THUMB), //11 0001 1001 +TABDECL( OP_STMIA_THUMB), //11 0001 1010 +TABDECL( OP_STMIA_THUMB), //11 0001 1011 +TABDECL( OP_STMIA_THUMB), //11 0001 1100 +TABDECL( OP_STMIA_THUMB), //11 0001 1101 +TABDECL( OP_STMIA_THUMB), //11 0001 1110 +TABDECL( OP_STMIA_THUMB), //11 0001 1111 + +TABDECL( OP_LDMIA_THUMB), //11 0010 0000 +TABDECL( OP_LDMIA_THUMB), //11 0010 0001 +TABDECL( OP_LDMIA_THUMB), //11 0010 0010 +TABDECL( OP_LDMIA_THUMB), //11 0010 0011 +TABDECL( OP_LDMIA_THUMB), //11 0010 0100 +TABDECL( OP_LDMIA_THUMB), //11 0010 0101 +TABDECL( OP_LDMIA_THUMB), //11 0010 0110 +TABDECL( OP_LDMIA_THUMB), //11 0010 0111 +TABDECL( OP_LDMIA_THUMB), //11 0010 1000 +TABDECL( OP_LDMIA_THUMB), //11 0010 1001 +TABDECL( OP_LDMIA_THUMB), //11 0010 1010 +TABDECL( OP_LDMIA_THUMB), //11 0010 1011 +TABDECL( OP_LDMIA_THUMB), //11 0010 1100 +TABDECL( OP_LDMIA_THUMB), //11 0010 1101 +TABDECL( OP_LDMIA_THUMB), //11 0010 1110 +TABDECL( OP_LDMIA_THUMB), //11 0010 1111 + +TABDECL( OP_LDMIA_THUMB), //11 0011 0000 +TABDECL( OP_LDMIA_THUMB), //11 0011 0001 +TABDECL( OP_LDMIA_THUMB), //11 0011 0010 +TABDECL( OP_LDMIA_THUMB), //11 0011 0011 +TABDECL( OP_LDMIA_THUMB), //11 0011 0100 +TABDECL( OP_LDMIA_THUMB), //11 0011 0101 +TABDECL( OP_LDMIA_THUMB), //11 0011 0110 +TABDECL( OP_LDMIA_THUMB), //11 0011 0111 +TABDECL( OP_LDMIA_THUMB), //11 0011 1000 +TABDECL( OP_LDMIA_THUMB), //11 0011 1001 +TABDECL( OP_LDMIA_THUMB), //11 0011 1010 +TABDECL( OP_LDMIA_THUMB), //11 0011 1011 +TABDECL( OP_LDMIA_THUMB), //11 0011 1100 +TABDECL( OP_LDMIA_THUMB), //11 0011 1101 +TABDECL( OP_LDMIA_THUMB), //11 0011 1110 +TABDECL( OP_LDMIA_THUMB), //11 0011 1111 + +TABDECL( OP_B_COND), //11 0100 0000 +TABDECL( OP_B_COND), //11 0100 0001 +TABDECL( OP_B_COND), //11 0100 0010 +TABDECL( OP_B_COND), //11 0100 0011 +TABDECL( OP_B_COND), //11 0100 0100 +TABDECL( OP_B_COND), //11 0100 0101 +TABDECL( OP_B_COND), //11 0100 0110 +TABDECL( OP_B_COND), //11 0100 0111 +TABDECL( OP_B_COND), //11 0100 1000 +TABDECL( OP_B_COND), //11 0100 1001 +TABDECL( OP_B_COND), //11 0100 1010 +TABDECL( OP_B_COND), //11 0100 1011 +TABDECL( OP_B_COND), //11 0100 1100 +TABDECL( OP_B_COND), //11 0100 1101 +TABDECL( OP_B_COND), //11 0100 1110 +TABDECL( OP_B_COND), //11 0100 1111 + +TABDECL( OP_B_COND), //11 0101 0000 +TABDECL( OP_B_COND), //11 0101 0001 +TABDECL( OP_B_COND), //11 0101 0010 +TABDECL( OP_B_COND), //11 0101 0011 +TABDECL( OP_B_COND), //11 0101 0100 +TABDECL( OP_B_COND), //11 0101 0101 +TABDECL( OP_B_COND), //11 0101 0110 +TABDECL( OP_B_COND), //11 0101 0111 +TABDECL( OP_B_COND), //11 0101 1000 +TABDECL( OP_B_COND), //11 0101 1001 +TABDECL( OP_B_COND), //11 0101 1010 +TABDECL( OP_B_COND), //11 0101 1011 +TABDECL( OP_B_COND), //11 0101 1100 +TABDECL( OP_B_COND), //11 0101 1101 +TABDECL( OP_B_COND), //11 0101 1110 +TABDECL( OP_B_COND), //11 0101 1111 + +TABDECL( OP_B_COND), //11 0110 0000 +TABDECL( OP_B_COND), //11 0110 0001 +TABDECL( OP_B_COND), //11 0110 0010 +TABDECL( OP_B_COND), //11 0110 0011 +TABDECL( OP_B_COND), //11 0110 0100 +TABDECL( OP_B_COND), //11 0110 0101 +TABDECL( OP_B_COND), //11 0110 0110 +TABDECL( OP_B_COND), //11 0110 0111 +TABDECL( OP_B_COND), //11 0110 1000 +TABDECL( OP_B_COND), //11 0110 1001 +TABDECL( OP_B_COND), //11 0110 1010 +TABDECL( OP_B_COND), //11 0110 1011 +TABDECL( OP_B_COND), //11 0110 1100 +TABDECL( OP_B_COND), //11 0110 1101 +TABDECL( OP_B_COND), //11 0110 1110 +TABDECL( OP_B_COND), //11 0110 1111 + +TABDECL( OP_B_COND), //11 0111 0000 +TABDECL( OP_B_COND), //11 0111 0001 +TABDECL( OP_B_COND), //11 0111 0010 +TABDECL( OP_B_COND), //11 0111 0011 +TABDECL( OP_B_COND), //11 0111 0100 +TABDECL( OP_B_COND), //11 0111 0101 +TABDECL( OP_B_COND), //11 0111 0110 +TABDECL( OP_B_COND), //11 0111 0111 +TABDECL( OP_B_COND), //11 0111 1000 +TABDECL( OP_B_COND), //11 0111 1001 +TABDECL( OP_B_COND), //11 0111 1010 +TABDECL( OP_B_COND), //11 0111 1011 +TABDECL( OP_SWI_THUMB), //11 0111 1100 +TABDECL( OP_SWI_THUMB), //11 0111 1101 +TABDECL( OP_SWI_THUMB), //11 0111 1110 +TABDECL( OP_SWI_THUMB), //11 0111 1111 + +TABDECL( OP_B_UNCOND), //11 1000 0000 +TABDECL( OP_B_UNCOND), //11 1000 0001 +TABDECL( OP_B_UNCOND), //11 1000 0010 +TABDECL( OP_B_UNCOND), //11 1000 0011 +TABDECL( OP_B_UNCOND), //11 1000 0100 +TABDECL( OP_B_UNCOND), //11 1000 0101 +TABDECL( OP_B_UNCOND), //11 1000 0110 +TABDECL( OP_B_UNCOND), //11 1000 0111 +TABDECL( OP_B_UNCOND), //11 1000 1000 +TABDECL( OP_B_UNCOND), //11 1000 1001 +TABDECL( OP_B_UNCOND), //11 1000 1010 +TABDECL( OP_B_UNCOND), //11 1000 1011 +TABDECL( OP_B_UNCOND), //11 1000 1100 +TABDECL( OP_B_UNCOND), //11 1000 1101 +TABDECL( OP_B_UNCOND), //11 1000 1110 +TABDECL( OP_B_UNCOND), //11 1000 1111 + +TABDECL( OP_B_UNCOND), //11 1001 0000 +TABDECL( OP_B_UNCOND), //11 1001 0001 +TABDECL( OP_B_UNCOND), //11 1001 0010 +TABDECL( OP_B_UNCOND), //11 1001 0011 +TABDECL( OP_B_UNCOND), //11 1001 0100 +TABDECL( OP_B_UNCOND), //11 1001 0101 +TABDECL( OP_B_UNCOND), //11 1001 0110 +TABDECL( OP_B_UNCOND), //11 1001 0111 +TABDECL( OP_B_UNCOND), //11 1001 1000 +TABDECL( OP_B_UNCOND), //11 1001 1001 +TABDECL( OP_B_UNCOND), //11 1001 1010 +TABDECL( OP_B_UNCOND), //11 1001 1011 +TABDECL( OP_B_UNCOND), //11 1001 1100 +TABDECL( OP_B_UNCOND), //11 1001 1101 +TABDECL( OP_B_UNCOND), //11 1001 1110 +TABDECL( OP_B_UNCOND), //11 1001 1111 + +TABDECL( OP_BLX), //11 1010 0000 +TABDECL( OP_BLX), //11 1010 0001 +TABDECL( OP_BLX), //11 1010 0010 +TABDECL( OP_BLX), //11 1010 0011 +TABDECL( OP_BLX), //11 1010 0100 +TABDECL( OP_BLX), //11 1010 0101 +TABDECL( OP_BLX), //11 1010 0110 +TABDECL( OP_BLX), //11 1010 0111 +TABDECL( OP_BLX), //11 1010 1000 +TABDECL( OP_BLX), //11 1010 1001 +TABDECL( OP_BLX), //11 1010 1010 +TABDECL( OP_BLX), //11 1010 1011 +TABDECL( OP_BLX), //11 1010 1100 +TABDECL( OP_BLX), //11 1010 1101 +TABDECL( OP_BLX), //11 1010 1110 +TABDECL( OP_BLX), //11 1010 1111 + +TABDECL( OP_BLX), //11 1011 0000 +TABDECL( OP_BLX), //11 1011 0001 +TABDECL( OP_BLX), //11 1011 0010 +TABDECL( OP_BLX), //11 1011 0011 +TABDECL( OP_BLX), //11 1011 0100 +TABDECL( OP_BLX), //11 1011 0101 +TABDECL( OP_BLX), //11 1011 0110 +TABDECL( OP_BLX), //11 1011 0111 +TABDECL( OP_BLX), //11 1011 1000 +TABDECL( OP_BLX), //11 1011 1001 +TABDECL( OP_BLX), //11 1011 1010 +TABDECL( OP_BLX), //11 1011 1011 +TABDECL( OP_BLX), //11 1011 1100 +TABDECL( OP_BLX), //11 1011 1101 +TABDECL( OP_BLX), //11 1011 1110 +TABDECL( OP_BLX), //11 1011 1111 + +TABDECL( OP_BL_10), //11 1100 0000 +TABDECL( OP_BL_10), //11 1100 0001 +TABDECL( OP_BL_10), //11 1100 0010 +TABDECL( OP_BL_10), //11 1100 0011 +TABDECL( OP_BL_10), //11 1100 0100 +TABDECL( OP_BL_10), //11 1100 0101 +TABDECL( OP_BL_10), //11 1100 0110 +TABDECL( OP_BL_10), //11 1100 0111 +TABDECL( OP_BL_10), //11 1100 1000 +TABDECL( OP_BL_10), //11 1100 1001 +TABDECL( OP_BL_10), //11 1100 1010 +TABDECL( OP_BL_10), //11 1100 1011 +TABDECL( OP_BL_10), //11 1100 1100 +TABDECL( OP_BL_10), //11 1100 1101 +TABDECL( OP_BL_10), //11 1100 1110 +TABDECL( OP_BL_10), //11 1100 1111 + +TABDECL( OP_BL_10), //11 1101 0000 +TABDECL( OP_BL_10), //11 1101 0001 +TABDECL( OP_BL_10), //11 1101 0010 +TABDECL( OP_BL_10), //11 1101 0011 +TABDECL( OP_BL_10), //11 1101 0100 +TABDECL( OP_BL_10), //11 1101 0101 +TABDECL( OP_BL_10), //11 1101 0110 +TABDECL( OP_BL_10), //11 1101 0111 +TABDECL( OP_BL_10), //11 1101 1000 +TABDECL( OP_BL_10), //11 1101 1001 +TABDECL( OP_BL_10), //11 1101 1010 +TABDECL( OP_BL_10), //11 1101 1011 +TABDECL( OP_BL_10), //11 1101 1100 +TABDECL( OP_BL_10), //11 1101 1101 +TABDECL( OP_BL_10), //11 1101 1110 +TABDECL( OP_BL_10), //11 1101 1111 + +TABDECL( OP_BL_11), //11 1110 0000 +TABDECL( OP_BL_11), //11 1110 0001 +TABDECL( OP_BL_11), //11 1110 0010 +TABDECL( OP_BL_11), //11 1110 0011 +TABDECL( OP_BL_11), //11 1110 0100 +TABDECL( OP_BL_11), //11 1110 0101 +TABDECL( OP_BL_11), //11 1110 0110 +TABDECL( OP_BL_11), //11 1110 0111 +TABDECL( OP_BL_11), //11 1110 1000 +TABDECL( OP_BL_11), //11 1110 1001 +TABDECL( OP_BL_11), //11 1110 1010 +TABDECL( OP_BL_11), //11 1110 1011 +TABDECL( OP_BL_11), //11 1110 1100 +TABDECL( OP_BL_11), //11 1110 1101 +TABDECL( OP_BL_11), //11 1110 1110 +TABDECL( OP_BL_11), //11 1110 1111 + +TABDECL( OP_BL_11), //11 1111 0000 +TABDECL( OP_BL_11), //11 1111 0001 +TABDECL( OP_BL_11), //11 1111 0010 +TABDECL( OP_BL_11), //11 1111 0011 +TABDECL( OP_BL_11), //11 1111 0100 +TABDECL( OP_BL_11), //11 1111 0101 +TABDECL( OP_BL_11), //11 1111 0110 +TABDECL( OP_BL_11), //11 1111 0111 +TABDECL( OP_BL_11), //11 1111 1000 +TABDECL( OP_BL_11), //11 1111 1001 +TABDECL( OP_BL_11), //11 1111 1010 +TABDECL( OP_BL_11), //11 1111 1011 +TABDECL( OP_BL_11), //11 1111 1100 +TABDECL( OP_BL_11), //11 1111 1101 +TABDECL( OP_BL_11), //11 1111 1110 +TABDECL( OP_BL_11), //11 1111 1111 diff --git a/jni/desmume/src/types.h b/jni/desmume/src/types.h new file mode 100755 index 0000000..b33383e --- /dev/null +++ b/jni/desmume/src/types.h @@ -0,0 +1,470 @@ +/* + Copyright (C) 2005 Guillaume Duhamel + Copyright (C) 2008-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef TYPES_HPP +#define TYPES_HPP + +//analyze microsoft compilers +#ifdef _MSC_VER +#define _WINDOWS +//todo - everyone will want to support this eventually, i suppose +#include "config.h" +#endif + +//enforce a constraint: gdb stub requires developer +#if defined(GDB_STUB) && !defined(DEVELOPER) +#define DEVELOPER +#endif + +#ifdef DEVELOPER +#define IF_DEVELOPER(X) X +#else +#define IF_DEVELOPER(X) +#endif + +#ifdef _WINDOWS + //#define HAVE_WX //not useful yet.... + #define HAVE_LIBAGG + #define ENABLE_SSE + #define ENABLE_SSE2 + #ifdef DEVELOPER + #define HAVE_LUA + #endif +#endif + +#ifdef __GNUC__ +#ifdef __SSE__ +#define ENABLE_SSE +#endif +#ifdef __SSE2__ +#define ENABLE_SSE2 +#endif +#endif + +#ifdef NOSSE +#undef ENABLE_SSE +#endif + +#ifdef NOSSE2 +#undef ENABLE_SSE2 +#endif + +#ifdef _MSC_VER +#define strcasecmp(x,y) _stricmp(x,y) +#define strncasecmp(x, y, l) strnicmp(x, y, l) +#define snprintf _snprintf +#else +#define WINAPI +#endif + +#ifdef __GNUC__ +#include <limits.h> +#ifndef PATH_MAX +#define MAX_PATH 1024 +#else +#define MAX_PATH PATH_MAX +#endif +#endif + + +#if defined(_MSC_VER) || defined(__INTEL_COMPILER) +#define DS_ALIGN(X) __declspec(align(X)) +#elif defined(__GNUC__) +#define DS_ALIGN(X) __attribute__ ((aligned (X))) +#else +#define DS_ALIGN(X) +#endif + +#define CACHE_ALIGN DS_ALIGN(32) + +//use this for example when you want a byte value to be better-aligned +#define FAST_ALIGN DS_ALIGN(4) + +#ifndef FASTCALL +#ifdef __MINGW32__ +#define FASTCALL __attribute__((fastcall)) +#elif defined (__i386__) && !defined(__clang__) +#define FASTCALL __attribute__((regparm(3))) +#elif defined(_MSC_VER) || defined(__INTEL_COMPILER) +#define FASTCALL +#else +#define FASTCALL +#endif +#endif + +#ifdef _MSC_VER +#define _CDECL_ __cdecl +#else +#define _CDECL_ +#endif + +#ifndef INLINE +#if defined(_MSC_VER) || defined(__INTEL_COMPILER) +#define INLINE _inline +#else +#define INLINE inline +#endif +#endif + +#ifndef FORCEINLINE +#if defined(_MSC_VER) || defined(__INTEL_COMPILER) +#define FORCEINLINE __forceinline +#define MSC_FORCEINLINE __forceinline +#else +#define FORCEINLINE inline __attribute__((always_inline)) +#define MSC_FORCEINLINE +#endif +#endif + +#if defined(__LP64__) +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +typedef signed char s8; +typedef signed short s16; +typedef signed int s32; +typedef signed long long s64; +#else +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +#if defined(_MSC_VER) || defined(__INTEL_COMPILER) +typedef unsigned __int64 u64; +#else +typedef unsigned long long u64; +#endif + +typedef signed char s8; +typedef signed short s16; +typedef signed int s32; +#if defined(_MSC_VER) || defined(__INTEL_COMPILER) +typedef __int64 s64; +#else +typedef signed long long s64; +#endif +#endif + +typedef u8 uint8; +typedef u16 uint16; + +#ifndef OBJ_C +typedef u32 uint32; +#else +#define uint32 u32 //uint32 is defined in Leopard somewhere, avoid conflicts +#endif + +/*---------- GPU3D fixed-points types -----------*/ + +typedef s32 f32; +#define inttof32(n) ((n) << 12) +#define f32toint(n) ((n) >> 12) +#define floattof32(n) ((int32)((n) * (1 << 12))) +#define f32tofloat(n) (((float)(n)) / (float)(1<<12)) + +typedef s16 t16; +#define f32tot16(n) ((t16)(n >> 8)) +#define inttot16(n) ((n) << 4) +#define t16toint(n) ((n) >> 4) +#define floattot16(n) ((t16)((n) * (1 << 4))) +#define t16ofloat(n) (((float)(n)) / (float)(1<<4)) + +typedef s16 v16; +#define inttov16(n) ((n) << 12) +#define f32tov16(n) (n) +#define floattov16(n) ((v16)((n) * (1 << 12))) +#define v16toint(n) ((n) >> 12) +#define v16tofloat(n) (((float)(n)) / (float)(1<<12)) + +typedef s16 v10; +#define inttov10(n) ((n) << 9) +#define f32tov10(n) ((v10)(n >> 3)) +#define v10toint(n) ((n) >> 9) +#define floattov10(n) ((v10)((n) * (1 << 9))) +#define v10tofloat(n) (((float)(n)) / (float)(1<<9)) + +/*----------------------*/ + +#ifndef OBJ_C +typedef int BOOL; +#else +//apple also defines BOOL +typedef int desmume_BOOL; +#define BOOL desmume_BOOL +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifdef __BIG_ENDIAN__ +#ifndef WORDS_BIGENDIAN +#define WORDS_BIGENDIAN +#endif +#endif + +#ifdef WORDS_BIGENDIAN +# define LOCAL_BE +#else +# define LOCAL_LE +#endif + +/* little endian (ds' endianess) to local endianess convert macros */ +#ifdef LOCAL_BE /* local arch is big endian */ +# define LE_TO_LOCAL_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff)) +# define LE_TO_LOCAL_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff)) +# define LE_TO_LOCAL_64(x) ((((x)&0xff)<<56)|(((x)&0xff00)<<40)|(((x)&0xff0000)<<24)|(((x)&0xff000000)<<8)|(((x)>>8)&0xff000000)|(((x)>>24)&0xff00)|(((x)>>40)&0xff00)|(((x)>>56)&0xff)) +# define LOCAL_TO_LE_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff)) +# define LOCAL_TO_LE_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff)) +# define LOCAL_TO_LE_64(x) ((((x)&0xff)<<56)|(((x)&0xff00)<<40)|(((x)&0xff0000)<<24)|(((x)&0xff000000)<<8)|(((x)>>8)&0xff000000)|(((x)>>24)&0xff00)|(((x)>>40)&0xff00)|(((x)>>56)&0xff)) +#else /* local arch is little endian */ +# define LE_TO_LOCAL_16(x) (x) +# define LE_TO_LOCAL_32(x) (x) +# define LE_TO_LOCAL_64(x) (x) +# define LOCAL_TO_LE_16(x) (x) +# define LOCAL_TO_LE_32(x) (x) +# define LOCAL_TO_LE_64(x) (x) +#endif + +// kilobytes and megabytes macro +#define MB(x) ((x)*1024*1024) +#define KB(x) ((x)*1024) + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +#define CPU_STR(c) ((c==ARM9)?"ARM9":"ARM7") +typedef enum +{ + ARM9 = 0, + ARM7 = 1 +} cpu_id_t; + +///endian-flips count bytes. count should be even and nonzero. +inline void FlipByteOrder(u8 *src, u32 count) +{ + u8 *start=src; + u8 *end=src+count-1; + + if((count&1) || !count) return; /* This shouldn't happen. */ + + while(count--) + { + u8 tmp; + + tmp=*end; + *end=*start; + *start=tmp; + end--; + start++; + } +} + + + +inline u64 double_to_u64(double d) { + union { + u64 a; + double b; + } fuxor; + fuxor.b = d; + return fuxor.a; +} + +inline double u64_to_double(u64 u) { + union { + u64 a; + double b; + } fuxor; + fuxor.a = u; + return fuxor.b; +} + +inline u32 float_to_u32(float f) { + union { + u32 a; + float b; + } fuxor; + fuxor.b = f; + return fuxor.a; +} + +inline float u32_to_float(u32 u) { + union { + u32 a; + float b; + } fuxor; + fuxor.a = u; + return fuxor.b; +} + + +///stores a 32bit value into the provided byte array in guaranteed little endian form +inline void en32lsb(u8 *buf, u32 morp) +{ + buf[0]=(u8)(morp); + buf[1]=(u8)(morp>>8); + buf[2]=(u8)(morp>>16); + buf[3]=(u8)(morp>>24); +} + +inline void en16lsb(u8* buf, u16 morp) +{ + buf[0]=(u8)morp; + buf[1]=(u8)(morp>>8); +} + +///unpacks a 64bit little endian value from the provided byte array into host byte order +inline u64 de64lsb(u8 *morp) +{ + return morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24)|((u64)morp[4]<<32)|((u64)morp[5]<<40)|((u64)morp[6]<<48)|((u64)morp[7]<<56); +} + +///unpacks a 32bit little endian value from the provided byte array into host byte order +inline u32 de32lsb(u8 *morp) +{ + return morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24); +} + +///unpacks a 16bit little endian value from the provided byte array into host byte order +inline u16 de16lsb(u8 *morp) +{ + return morp[0]|(morp[1]<<8); +} + +#ifndef ARRAY_SIZE +//taken from winnt.h +extern "C++" // templates cannot be declared to have 'C' linkage +template <typename T, size_t N> +char (*BLAHBLAHBLAH( UNALIGNED T (&)[N] ))[N]; + +#define ARRAY_SIZE(A) (sizeof(*BLAHBLAHBLAH(A))) +#endif + + +//fairly standard for loop macros +#define MACRODO1(TRICK,TODO) { const int X = TRICK; TODO; } +#define MACRODO2(X,TODO) { MACRODO1((X),TODO) MACRODO1(((X)+1),TODO) } +#define MACRODO4(X,TODO) { MACRODO2((X),TODO) MACRODO2(((X)+2),TODO) } +#define MACRODO8(X,TODO) { MACRODO4((X),TODO) MACRODO4(((X)+4),TODO) } +#define MACRODO16(X,TODO) { MACRODO8((X),TODO) MACRODO8(((X)+8),TODO) } +#define MACRODO32(X,TODO) { MACRODO16((X),TODO) MACRODO16(((X)+16),TODO) } +#define MACRODO64(X,TODO) { MACRODO32((X),TODO) MACRODO32(((X)+32),TODO) } +#define MACRODO128(X,TODO) { MACRODO64((X),TODO) MACRODO64(((X)+64),TODO) } +#define MACRODO256(X,TODO) { MACRODO128((X),TODO) MACRODO128(((X)+128),TODO) } + +//this one lets you loop any number of times (as long as N<256) +#define MACRODO_N(N,TODO) {\ + if((N)&0x100) MACRODO256(0,TODO); \ + if((N)&0x080) MACRODO128((N)&(0x100),TODO); \ + if((N)&0x040) MACRODO64((N)&(0x100|0x080),TODO); \ + if((N)&0x020) MACRODO32((N)&(0x100|0x080|0x040),TODO); \ + if((N)&0x010) MACRODO16((N)&(0x100|0x080|0x040|0x020),TODO); \ + if((N)&0x008) MACRODO8((N)&(0x100|0x080|0x040|0x020|0x010),TODO); \ + if((N)&0x004) MACRODO4((N)&(0x100|0x080|0x040|0x020|0x010|0x008),TODO); \ + if((N)&0x002) MACRODO2((N)&(0x100|0x080|0x040|0x020|0x010|0x008|0x004),TODO); \ + if((N)&0x001) MACRODO1((N)&(0x100|0x080|0x040|0x020|0x010|0x008|0x004|0x002),TODO); \ +} + +//--------------------------- +//Binary constant generator macro By Tom Torfs - donated to the public domain + +//turn a numeric literal into a hex constant +//(avoids problems with leading zeroes) +//8-bit constants max value 0x11111111, always fits in unsigned long +#define HEX__(n) 0x##n##LU + +//8-bit conversion function +#define B8__(x) ((x&0x0000000FLU)?1:0) \ ++((x&0x000000F0LU)?2:0) \ ++((x&0x00000F00LU)?4:0) \ ++((x&0x0000F000LU)?8:0) \ ++((x&0x000F0000LU)?16:0) \ ++((x&0x00F00000LU)?32:0) \ ++((x&0x0F000000LU)?64:0) \ ++((x&0xF0000000LU)?128:0) + +//for upto 8-bit binary constants +#define B8(d) ((unsigned char)B8__(HEX__(d))) + +// for upto 16-bit binary constants, MSB first +#define B16(dmsb,dlsb) (((unsigned short)B8(dmsb)<<8) \ ++ B8(dlsb)) + +// for upto 32-bit binary constants, MSB first */ +#define B32(dmsb,db2,db3,dlsb) (((unsigned long)B8(dmsb)<<24) \ ++ ((unsigned long)B8(db2)<<16) \ ++ ((unsigned long)B8(db3)<<8) \ ++ B8(dlsb)) + +//Sample usage: +//B8(01010101) = 85 +//B16(10101010,01010101) = 43605 +//B32(10000000,11111111,10101010,01010101) = 2164238933 +//--------------------------- + +#ifndef CTASSERT +#define CTASSERT(x) typedef char __assert ## y[(x) ? 1 : -1] +#endif + +static const char hexValid[23] = {"0123456789ABCDEFabcdef"}; + + +template<typename T> inline void reconstruct(T* t) { + t->~T(); + new(t) T(); +} + +//-------------fixed point speedup macros + +#ifdef _WIN32 +#include <intrin.h> +#endif + +FORCEINLINE s64 fx32_mul(const s32 a, const s32 b) +{ +#ifdef _WIN32 + return __emul(a,b); +#else + return ((s64)a)*((s64)b); +#endif +} + +FORCEINLINE s32 fx32_shiftdown(const s64 a) +{ +#ifdef _WIN32 + return (s32)__ll_rshift(a,12); +#else + return (s32)(a>>12); +#endif +} + +FORCEINLINE s64 fx32_shiftup(const s32 a) +{ +#ifdef _WIN32 + return __ll_lshift(a,12); +#else + return ((s64)a)<<12; +#endif +} + +#endif diff --git a/jni/desmume/src/utils/ConvertUTF.c b/jni/desmume/src/utils/ConvertUTF.c new file mode 100755 index 0000000..9b3deeb --- /dev/null +++ b/jni/desmume/src/utils/ConvertUTF.c @@ -0,0 +1,539 @@ +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* --------------------------------------------------------------------- + + Conversions between UTF32, UTF-16, and UTF-8. Source code file. + Author: Mark E. Davis, 1994. + Rev History: Rick McGowan, fixes & updates May 2001. + Sept 2001: fixed const & error conditions per + mods suggested by S. Parent & A. Lillich. + June 2002: Tim Dodd added detection and handling of incomplete + source sequences, enhanced error detection, added casts + to eliminate compiler warnings. + July 2003: slight mods to back out aggressive FFFE detection. + Jan 2004: updated switches in from-UTF8 conversions. + Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions. + + See the header file "ConvertUTF.h" for complete documentation. + +------------------------------------------------------------------------ */ + + +#include "ConvertUTF.h" +#ifdef CVTUTF_DEBUG +#include <stdio.h> +#endif + +static const int halfShift = 10; /* used for shifting by 10 bits */ + +static const UTF32 halfBase = 0x0010000UL; +static const UTF32 halfMask = 0x3FFUL; + +#define UNI_SUR_HIGH_START (UTF32)0xD800 +#define UNI_SUR_HIGH_END (UTF32)0xDBFF +#define UNI_SUR_LOW_START (UTF32)0xDC00 +#define UNI_SUR_LOW_END (UTF32)0xDFFF +#define false 0 +#define true 1 + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF32toUTF16 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF32* source = *sourceStart; + UTF16* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + if (target >= targetEnd) { + result = targetExhausted; break; + } + ch = *source++; + if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = (UTF16)ch; /* normal case */ + } + } else if (ch > UNI_MAX_LEGAL_UTF32) { + if (flags == strictConversion) { + result = sourceIllegal; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if (target + 1 >= targetEnd) { + --source; /* Back up source pointer! */ + result = targetExhausted; break; + } + ch -= halfBase; + *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF16toUTF32 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF16* source = *sourceStart; + UTF32* target = *targetStart; + UTF32 ch, ch2; + while (source < sourceEnd) { + const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) { + ch2 = *source; + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } else { /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } else if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + if (target >= targetEnd) { + source = oldSource; /* Back up source pointer! */ + result = targetExhausted; break; + } + *target++ = ch; + } + *sourceStart = source; + *targetStart = target; +#ifdef CVTUTF_DEBUG +if (result == sourceIllegal) { + fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2); + fflush(stderr); +} +#endif + return result; +} + +/* --------------------------------------------------------------------- */ + +/* + * Index into the table below with the first byte of a UTF-8 sequence to + * get the number of trailing bytes that are supposed to follow it. + * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is + * left as-is for anyone who may want to do such conversion, which was + * allowed in earlier algorithms. + */ +static const char trailingBytesForUTF8[256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 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, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 +}; + +/* + * Magic values subtracted from a buffer value during UTF8 conversion. + * This table contains as many values as there might be trailing bytes + * in a UTF-8 sequence. + */ +static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, + 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; + +/* + * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed + * into the first byte, depending on how many bytes follow. There are + * as many entries in this table as there are UTF-8 sequence types. + * (I.e., one byte sequence, two byte... etc.). Remember that sequencs + * for *legal* UTF-8 will be 4 or fewer bytes total. + */ +static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + +/* --------------------------------------------------------------------- */ + +/* The interface converts a whole buffer to avoid function-call overhead. + * Constants have been gathered. Loops & conditionals have been removed as + * much as possible for efficiency, in favor of drop-through switches. + * (See "Note A" at the bottom of the file for equivalent code.) + * If your compiler supports it, the "isLegalUTF8" call can be turned + * into an inline function. + */ + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF16toUTF8 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF16* source = *sourceStart; + UTF8* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + unsigned short bytesToWrite = 0; + const UTF32 byteMask = 0xBF; + const UTF32 byteMark = 0x80; + const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) { + UTF32 ch2 = *source; + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } else { /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } else if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + /* Figure out how many bytes the result will require */ + if (ch < (UTF32)0x80) { bytesToWrite = 1; + } else if (ch < (UTF32)0x800) { bytesToWrite = 2; + } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; + } else if (ch < (UTF32)0x110000) { bytesToWrite = 4; + } else { bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + } + + target += bytesToWrite; + if (target > targetEnd) { + source = oldSource; /* Back up source pointer! */ + target -= bytesToWrite; result = targetExhausted; break; + } + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); + } + target += bytesToWrite; + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +/* + * Utility routine to tell whether a sequence of bytes is legal UTF-8. + * This must be called with the length pre-determined by the first byte. + * If not calling this from ConvertUTF8to*, then the length can be set by: + * length = trailingBytesForUTF8[*source]+1; + * and the sequence is illegal right away if there aren't that many bytes + * available. + * If presented with a length > 4, this returns false. The Unicode + * definition of UTF-8 goes up to 4-byte sequences. + */ + +static Boolean isLegalUTF8(const UTF8 *source, int length) { + UTF8 a; + const UTF8 *srcptr = source+length; + switch (length) { + default: return false; + /* Everything else falls through when "true"... */ + case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 2: if ((a = (*--srcptr)) > 0xBF) return false; + + switch (*source) { + /* no fall-through in this inner switch */ + case 0xE0: if (a < 0xA0) return false; break; + case 0xED: if (a > 0x9F) return false; break; + case 0xF0: if (a < 0x90) return false; break; + case 0xF4: if (a > 0x8F) return false; break; + default: if (a < 0x80) return false; + } + + case 1: if (*source >= 0x80 && *source < 0xC2) return false; + } + if (*source > 0xF4) return false; + return true; +} + +/* --------------------------------------------------------------------- */ + +/* + * Exported function to return whether a UTF-8 sequence is legal or not. + * This is not used here; it's just exported. + */ +Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { + int length = trailingBytesForUTF8[*source]+1; + if (source+length > sourceEnd) { + return false; + } + return isLegalUTF8(source, length); +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF8toUTF16 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF8* source = *sourceStart; + UTF16* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + if (source + extraBytesToRead >= sourceEnd) { + result = sourceExhausted; break; + } + /* Do this check whether lenient or strict */ + if (! isLegalUTF8(source, extraBytesToRead+1)) { + result = sourceIllegal; + break; + } + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) { + case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ + case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ + case 3: ch += *source++; ch <<= 6; + case 2: ch += *source++; ch <<= 6; + case 1: ch += *source++; ch <<= 6; + case 0: ch += *source++; + } + ch -= offsetsFromUTF8[extraBytesToRead]; + + if (target >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up source pointer! */ + result = targetExhausted; break; + } + if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + source -= (extraBytesToRead+1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = (UTF16)ch; /* normal case */ + } + } else if (ch > UNI_MAX_UTF16) { + if (flags == strictConversion) { + result = sourceIllegal; + source -= (extraBytesToRead+1); /* return to the start */ + break; /* Bail out; shouldn't continue */ + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if (target + 1 >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up source pointer! */ + result = targetExhausted; break; + } + ch -= halfBase; + *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF32toUTF8 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF32* source = *sourceStart; + UTF8* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + unsigned short bytesToWrite = 0; + const UTF32 byteMask = 0xBF; + const UTF32 byteMark = 0x80; + ch = *source++; + if (flags == strictConversion ) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + /* + * Figure out how many bytes the result will require. Turn any + * illegally large UTF32 things (> Plane 17) into replacement chars. + */ + if (ch < (UTF32)0x80) { bytesToWrite = 1; + } else if (ch < (UTF32)0x800) { bytesToWrite = 2; + } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; + } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4; + } else { bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + result = sourceIllegal; + } + + target += bytesToWrite; + if (target > targetEnd) { + --source; /* Back up source pointer! */ + target -= bytesToWrite; result = targetExhausted; break; + } + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; + case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]); + } + target += bytesToWrite; + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF8toUTF32 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF8* source = *sourceStart; + UTF32* target = *targetStart; + while (source < sourceEnd) { + UTF32 ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + if (source + extraBytesToRead >= sourceEnd) { + result = sourceExhausted; break; + } + /* Do this check whether lenient or strict */ + if (! isLegalUTF8(source, extraBytesToRead+1)) { + result = sourceIllegal; + break; + } + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) { + case 5: ch += *source++; ch <<= 6; + case 4: ch += *source++; ch <<= 6; + case 3: ch += *source++; ch <<= 6; + case 2: ch += *source++; ch <<= 6; + case 1: ch += *source++; ch <<= 6; + case 0: ch += *source++; + } + ch -= offsetsFromUTF8[extraBytesToRead]; + + if (target >= targetEnd) { + source -= (extraBytesToRead+1); /* Back up the source pointer! */ + result = targetExhausted; break; + } + if (ch <= UNI_MAX_LEGAL_UTF32) { + /* + * UTF-16 surrogate values are illegal in UTF-32, and anything + * over Plane 17 (> 0x10FFFF) is illegal. + */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + source -= (extraBytesToRead+1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = ch; + } + } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */ + result = sourceIllegal; + *target++ = UNI_REPLACEMENT_CHAR; + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- + + Note A. + The fall-through switches in UTF-8 reading code save a + temp variable, some decrements & conditionals. The switches + are equivalent to the following loop: + { + int tmpBytesToRead = extraBytesToRead+1; + do { + ch += *source++; + --tmpBytesToRead; + if (tmpBytesToRead) ch <<= 6; + } while (tmpBytesToRead > 0); + } + In UTF-8 writing code, the switches on "bytesToWrite" are + similarly unrolled loops. + + --------------------------------------------------------------------- */ diff --git a/jni/desmume/src/utils/ConvertUTF.h b/jni/desmume/src/utils/ConvertUTF.h new file mode 100755 index 0000000..e264915 --- /dev/null +++ b/jni/desmume/src/utils/ConvertUTF.h @@ -0,0 +1,149 @@ +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* --------------------------------------------------------------------- + + Conversions between UTF32, UTF-16, and UTF-8. Header file. + + Several funtions are included here, forming a complete set of + conversions between the three formats. UTF-7 is not included + here, but is handled in a separate source file. + + Each of these routines takes pointers to input buffers and output + buffers. The input buffers are const. + + Each routine converts the text between *sourceStart and sourceEnd, + putting the result into the buffer between *targetStart and + targetEnd. Note: the end pointers are *after* the last item: e.g. + *(sourceEnd - 1) is the last item. + + The return result indicates whether the conversion was successful, + and if not, whether the problem was in the source or target buffers. + (Only the first encountered problem is indicated.) + + After the conversion, *sourceStart and *targetStart are both + updated to point to the end of last text successfully converted in + the respective buffers. + + Input parameters: + sourceStart - pointer to a pointer to the source buffer. + The contents of this are modified on return so that + it points at the next thing to be converted. + targetStart - similarly, pointer to pointer to the target buffer. + sourceEnd, targetEnd - respectively pointers to the ends of the + two buffers, for overflow checking only. + + These conversion functions take a ConversionFlags argument. When this + flag is set to strict, both irregular sequences and isolated surrogates + will cause an error. When the flag is set to lenient, both irregular + sequences and isolated surrogates are converted. + + Whether the flag is strict or lenient, all illegal sequences will cause + an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>, + or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code + must check for illegal sequences. + + When the flag is set to lenient, characters over 0x10FFFF are converted + to the replacement character; otherwise (when the flag is set to strict) + they constitute an error. + + Output parameters: + The value "sourceIllegal" is returned from some routines if the input + sequence is malformed. When "sourceIllegal" is returned, the source + value will point to the illegal value that caused the problem. E.g., + in UTF-8 when a sequence is malformed, it points to the start of the + malformed sequence. + + Author: Mark E. Davis, 1994. + Rev History: Rick McGowan, fixes & updates May 2001. + Fixes & updates, Sept 2001. + +------------------------------------------------------------------------ */ + +/* --------------------------------------------------------------------- + The following 4 definitions are compiler-specific. + The C standard does not guarantee that wchar_t has at least + 16 bits, so wchar_t is no less portable than unsigned short! + All should be unsigned values to avoid sign extension during + bit mask & shift operations. +------------------------------------------------------------------------ */ + +typedef unsigned long UTF32; /* at least 32 bits */ +typedef unsigned short UTF16; /* at least 16 bits */ +typedef unsigned char UTF8; /* typically 8 bits */ +typedef unsigned char Boolean; /* 0 or 1 */ + +/* Some fundamental constants */ +#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD +#define UNI_MAX_BMP (UTF32)0x0000FFFF +#define UNI_MAX_UTF16 (UTF32)0x0010FFFF +#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF +#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF + +typedef enum { + conversionOK, /* conversion successful */ + sourceExhausted, /* partial character in source, but hit end */ + targetExhausted, /* insuff. room in target for conversion */ + sourceIllegal /* source sequence is illegal/malformed */ +} ConversionResult; + +typedef enum { + strictConversion = 0, + lenientConversion +} ConversionFlags; + +/* This is for C++ and does no harm in C */ +#ifdef __cplusplus +extern "C" { +#endif + +ConversionResult ConvertUTF8toUTF16 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF16toUTF8 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF8toUTF32 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF32toUTF8 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF16toUTF32 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF32toUTF16 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); + +Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); + +#ifdef __cplusplus +} +#endif + +/* --------------------------------------------------------------------- */ diff --git a/jni/desmume/src/utils/datetime.cpp b/jni/desmume/src/utils/datetime.cpp new file mode 100755 index 0000000..f68eea0 --- /dev/null +++ b/jni/desmume/src/utils/datetime.cpp @@ -0,0 +1,5 @@ +#include "datetime.h" + +const char* DateTime::monthnames[] = { NULL, "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" }; +const int DateTime::daysmonth[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +const int DateTime::daysmonthleap[] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; diff --git a/jni/desmume/src/utils/datetime.h b/jni/desmume/src/utils/datetime.h new file mode 100755 index 0000000..0fa50fa --- /dev/null +++ b/jni/desmume/src/utils/datetime.h @@ -0,0 +1,816 @@ +/* + Copyright (C) 2010 DeSmuME team + + This file is based on System.DateTime.cs and System.TimeSpan.cs from mono-2.6.7 + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +// +// System.DateTime.cs +// +// author: +// Marcel Narings (marcel@narings.nl) +// Martin Baulig (martin@gnome.org) +// Atsushi Enomoto (atsushi@ximian.com) +// +// (C) 2001 Marcel Narings +// Copyright (C) 2004-2006 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// +// System.TimeSpan.cs +// +// Authors: +// Duco Fijma (duco@lorentz.xs4all.nl) +// Andreas Nahr (ClassDevelopment@A-SoftTech.com) +// Sebastien Pouliot <sebastien@ximian.com> +// +// (C) 2001 Duco Fijma +// (C) 2004 Andreas Nahr +// Copyright (C) 2004 Novell (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +#ifndef _DATETIME_H_ +#define _DATETIME_H_ + +#include <math.h> +#include <time.h> +#include <string.h> +#include <stdio.h> + +#include <string> + +#include "../types.h" + +enum DayOfWeek { + DayOfWeek_Sunday=0, + DayOfWeek_Monday=1, + DayOfWeek_Tuesday=2, + DayOfWeek_Wednesday=3, + DayOfWeek_Thursday=4, + DayOfWeek_Friday=5, + DayOfWeek_Saturday=6 +}; + +class TimeSpan +{ + friend class DateTime; + +public: + static const TimeSpan& get_MaxValue() + { + static TimeSpan val(0x7FFFFFFFFFFFFFFFLL); + return val; + } + + static const TimeSpan& get_MinValue() + { + static TimeSpan val(0x8000000000000000LL); + return val; + } + + static const TimeSpan& get_Zero() + { + static TimeSpan val(0); + return val; + } + + static const s64 TicksPerDay = 864000000000LL; + static const s64 TicksPerHour = 36000000000LL; + static const s64 TicksPerMillisecond = 10000LL; + static const s64 TicksPerMinute = 600000000LL; + static const s64 TicksPerSecond = 10000000LL; + + TimeSpan () + { + } + + TimeSpan (s64 ticks) + : _ticks(ticks) + { + } + + TimeSpan (int hours, int minutes, int seconds) + { + _ticks = CalculateTicks (0, hours, minutes, seconds, 0); + } + + TimeSpan (int days, int hours, int minutes, int seconds) + { + _ticks = CalculateTicks (days, hours, minutes, seconds, 0); + } + + TimeSpan (int days, int hours, int minutes, int seconds, int milliseconds) + { + _ticks = CalculateTicks (days, hours, minutes, seconds, milliseconds); + } + + int get_Days() const { return (int) (_ticks / TicksPerDay); } + int get_Hours() const { return (int) (_ticks % TicksPerDay / TicksPerHour); } + int get_Milliseconds() const { return (int) (_ticks % TicksPerSecond / TicksPerMillisecond); } + int get_Minutes() const { return (int) (_ticks % TicksPerHour / TicksPerMinute); } + int get_Seconds() const { return (int) (_ticks % TicksPerMinute / TicksPerSecond); } + s64 get_Ticks() const { return _ticks; } + double get_TotalDays() const { return (double) _ticks / TicksPerDay; } + double get_TotalHours() const { return (double) _ticks / TicksPerHour; } + double get_TotalMilliseconds() const { return (double) _ticks / TicksPerMillisecond; } + double get_TotalMinutes() const { return (double) _ticks / TicksPerMinute; } + double get_TotalSeconds() const { return (double) _ticks / TicksPerSecond; } + + TimeSpan Add (const TimeSpan &ts) + { + return TimeSpan (_ticks + ts._ticks); + //removed: + //catch (OverflowException) throw new OverflowException (Locale.GetText ("Resulting timespan is too big.")); + } + + static int Compare (const TimeSpan& t1, const TimeSpan& t2) + { + if (t1._ticks < t2._ticks) + return -1; + if (t1._ticks > t2._ticks) + return 1; + return 0; + } + + int CompareTo (const TimeSpan& value) + { + return Compare (*this, value); + } + + TimeSpan Duration () + { + return TimeSpan(_ticks<0?-_ticks:_ticks); + //removed: + //catch (OverflowException) throw new OverflowException (Locale.GetText ("This TimeSpan value is MinValue so you cannot get the duration.")); + } + + static TimeSpan FromDays (double value) + { + return From (value, TicksPerDay); + } + + static TimeSpan FromHours (double value) + { + return From (value, TicksPerHour); + } + + static TimeSpan FromMinutes (double value) + { + return From (value, TicksPerMinute); + } + + static TimeSpan FromSeconds (double value) + { + return From (value, TicksPerSecond); + } + + static TimeSpan FromMilliseconds (double value) + { + return From (value, TicksPerMillisecond); + } + + static TimeSpan FromTicks (s64 value) + { + return TimeSpan (value); + } + + TimeSpan Negate () + { + //removed error handling + //if (_ticks == MinValue()._ticks) throw new OverflowException (Locale.GetText ( "This TimeSpan value is MinValue and cannot be negated.")); + return TimeSpan (-_ticks); + } + + TimeSpan Subtract (const TimeSpan& ts) + { + //removed error handling + //try { checked { + return TimeSpan (_ticks - ts._ticks); + // } + //} + //catch (OverflowException) { + // throw new OverflowException (Locale.GetText ("Resulting timespan is too big.")); + //} + } + + TimeSpan operator + (const TimeSpan& t2) const + { + TimeSpan temp = *this; + temp.Add (t2); + return temp; + } + + bool operator == (const TimeSpan& t2) const + { + return _ticks == t2._ticks; + } + + bool operator > (const TimeSpan& t2) const + { + return _ticks > t2._ticks; + } + + bool operator >= (const TimeSpan& t2) const + { + return _ticks >= t2._ticks; + } + + bool operator != (const TimeSpan& t2) const + { + return _ticks != t2._ticks; + } + + bool operator < (const TimeSpan& t2) const + { + return _ticks < t2._ticks; + } + + bool operator <= (const TimeSpan& t2) const + { + return _ticks <= t2._ticks; + } + + TimeSpan operator - (const TimeSpan& t2) const + { + TimeSpan temp = *this; + return temp.Subtract (t2); + } + + TimeSpan operator - () + { + return Negate (); + } + + +private: + s64 _ticks; + + static s64 CalculateTicks (int days, int hours, int minutes, int seconds, int milliseconds) + { + // there's no overflow checks for hours, minutes, ... + // so big hours/minutes values can overflow at some point and change expected values + int hrssec = (hours * 3600); // break point at (Int32.MaxValue - 596523) + int minsec = (minutes * 60); + s64 t = ((s64)(hrssec + minsec + seconds) * 1000L + (s64)milliseconds); + t *= 10000; + + bool overflow = false; + // days is problematic because it can overflow but that overflow can be + // "legal" (i.e. temporary) (e.g. if other parameters are negative) or + // illegal (e.g. sign change). + if (days > 0) { + s64 td = TicksPerDay * days; + if (t < 0) { + s64 ticks = t; + t += td; + // positive days -> total ticks should be lower + overflow = (ticks > t); + } + else { + t += td; + // positive + positive != negative result + overflow = (t < 0); + } + } + else if (days < 0) { + s64 td = TicksPerDay * days; + if (t <= 0) { + t += td; + // negative + negative != positive result + overflow = (t > 0); + } + else { + s64 ticks = t; + t += td; + // negative days -> total ticks should be lower + overflow = (t > ticks); + } + } + + //removed: + //if (overflow) throw ArgumentOutOfRangeException ("The timespan is too big or too small."); + + return t; + } + + static TimeSpan From (double value, s64 tickMultiplicator) + { + //a bunch of error handling removed + + //if (Double.IsNaN (value)) throw new ArgumentException (Locale.GetText ("Value cannot be NaN."), "value"); + //if (Double.IsNegativeInfinity (value) || Double.IsPositiveInfinity (value) || + // (value < MinValue.Ticks) || (value > MaxValue.Ticks)) + // throw new OverflowException (Locale.GetText ("Outside range [MinValue,MaxValue]")); + + //try { + value = (value * (tickMultiplicator / TicksPerMillisecond)); + + // checked { + // long val = (long) Math.Round(value); + // return new TimeSpan (val * TicksPerMillisecond); + // } + //} + //catch (OverflowException) { + // throw new OverflowException (Locale.GetText ("Resulting timespan is too big.")); + //} + //} + } + +}; + +class DateTime +{ +private: + TimeSpan ticks; + + static inline double round(const double x) { return floor(x + 0.5); } + + static const int dp400 = 146097; + static const int dp100 = 36524; + static const int dp4 = 1461; + + // w32 file time starts counting from 1/1/1601 00:00 GMT + // which is the constant ticks from the .NET epoch + static const s64 w32file_epoch = 504911232000000000LL; + + //private const long MAX_VALUE_TICKS = 3155378975400000000L; + // -- Microsoft .NET has this value. + static const s64 MAX_VALUE_TICKS = 3155378975999999999LL; + + // + // The UnixEpoch, it begins on Jan 1, 1970 at 0:0:0, expressed + // in Ticks + // + static const s64 UnixEpoch = 621355968000000000LL; + + + static const int daysmonth[13]; + static const int daysmonthleap[13]; + static const char* monthnames[13]; + + void init (int year, int month, int day, int hour, int minute, int second, int millisecond) + { + //removed error handling + /* if ( year < 1 || year > 9999 || + month < 1 || month >12 || + day < 1 || day > DaysInMonth(year, month) || + hour < 0 || hour > 23 || + minute < 0 || minute > 59 || + second < 0 || second > 59 || + millisecond < 0 || millisecond > 999) + throw new ArgumentOutOfRangeException ("Parameters describe an " + + "unrepresentable DateTime.");*/ + + ticks = TimeSpan (AbsoluteDays(year,month,day), hour, minute, second, millisecond); + } + + + + static int AbsoluteDays (int year, int month, int day) + { + const int* days; + int temp = 0, m=1 ; + + days = (IsLeapYear(year) ? daysmonthleap : daysmonth); + + while (m < month) + temp += days[m++]; + return ((day-1) + temp + (365* (year-1)) + ((year-1)/4) - ((year-1)/100) + ((year-1)/400)); + } + + + enum Which + { + Which_Day, + Which_DayYear, + Which_Month, + Which_Year + }; + + int FromTicks(Which what) const + { + int num400, num100, num4, numyears; + int M =1; + + const int* days = daysmonth; + int totaldays = ticks.get_Days(); + + num400 = (totaldays / dp400); + totaldays -= num400 * dp400; + + num100 = (totaldays / dp100); + if (num100 == 4) // leap + num100 = 3; + totaldays -= (num100 * dp100); + + num4 = totaldays / dp4; + totaldays -= (num4 * dp4); + + numyears = totaldays / 365 ; + + if (numyears == 4) //leap + numyears =3 ; + if (what == Which_Year ) + return num400*400 + num100*100 + num4*4 + numyears + 1; + + totaldays -= (numyears * 365) ; + if (what == Which_DayYear ) + return totaldays + 1; + + if ((numyears==3) && ((num100 == 3) || !(num4 == 24)) ) //31 dec leapyear + days = daysmonthleap; + + while (totaldays >= days[M]) + totaldays -= days[M++]; + + if (what == Which_Month ) + return M; + + return totaldays +1; + } + +public: + DateTime() + : ticks(0) + { + } + + static const char* GetNameOfMonth(int month) { return monthnames[month]; } + + DateTime (s64 ticks) + { + this->ticks = TimeSpan (ticks); + //removed error handling + //if (ticks < get_MinValue().get_Ticks() || ticks > get_MaxValue().get_Ticks()) { + // string msg = Locale.GetText ("Value {0} is outside the valid range [{1},{2}].", + // ticks, MinValue.Ticks, MaxValue.Ticks); + // throw new ArgumentOutOfRangeException ("ticks", msg); + //} + } + + static const DateTime& get_MaxValue() { + static DateTime val(false, TimeSpan (MAX_VALUE_TICKS)); + return val; + } + + static const DateTime& get_MinValue() { + static DateTime val(false, TimeSpan (0)); + return val; + } + + DateTime (int year, int month, int day) + { + init(year,month,day,0,0,0,0); + } + + DateTime (int year, int month, int day, int hour, int minute, int second) + { + init(year, month, day, hour, minute, second, 0); + } + + DateTime (int year, int month, int day, int hour, int minute, int second, int millisecond) + { + init(year,month,day,hour,minute,second,millisecond); + } + + + DateTime (bool check, const TimeSpan& value) + { + //removed error handling + //if (check && (value.Ticks < MinValue.Ticks || value.Ticks > MaxValue.Ticks)) + // throw new ArgumentOutOfRangeException (); + + ticks = value; + } + + DateTime get_Date () const + { + return DateTime (get_Year(), get_Month(), get_Day()); + } + + int get_Month () const { + return FromTicks(Which_Month); + } + + int get_Day() const + { + return FromTicks(Which_Day); + } + + DayOfWeek get_DayOfWeek () const + { + return ( (DayOfWeek) ((ticks.get_Days()+1) % 7) ); + } + + int get_DayOfYear () const + { + return FromTicks(Which_DayYear); + } + + TimeSpan get_TimeOfDay () const + { + return TimeSpan(ticks.get_Ticks() % TimeSpan::TicksPerDay ); + } + + int get_Hour () const + { + return ticks.get_Hours(); + } + + int get_Minute () const + { + return ticks.get_Minutes(); + } + + int get_Second () const + { + return ticks.get_Seconds(); + } + + int get_Millisecond () const + { + return ticks.get_Milliseconds(); + } + + //internal static extern s64 GetTimeMonotonic (); + //internal static extern s64 GetNow (); + + static DateTime get_Now () + { + time_t timer; + time(&timer); + struct tm *tm = localtime(&timer); + return DateTime(tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec); + } + + s64 get_Ticks()const + { + return ticks.get_Ticks(); + } + + static DateTime get_Today () + { + DateTime now = get_Now(); + DateTime today = DateTime (now.get_Year(), now.get_Month(), now.get_Day()); + return today; + } + + int get_Year () const + { + return FromTicks(Which_Year); + } + + DateTime Add (const TimeSpan& value) const + { + DateTime ret = AddTicks (value.get_Ticks()); + return ret; + } + + DateTime AddDays (double value) const + { + return AddMilliseconds (round(value * 86400000)); + } + + DateTime AddTicks (const s64 value) const + { + //removed error handling + //if ((value + ticks.Ticks) > MAX_VALUE_TICKS || (value + ticks.Ticks) < 0) { + // throw new ArgumentOutOfRangeException(); + //} + return DateTime (value + ticks.get_Ticks()); + } + + DateTime AddHours (double value) const + { + return AddMilliseconds (value * 3600000); + } + + DateTime AddMilliseconds (double value) const + { + //removed error handling + /* if ((value * TimeSpan.TicksPerMillisecond) > long.MaxValue || + (value * TimeSpan.TicksPerMillisecond) < long.MinValue) { + throw new ArgumentOutOfRangeException(); + } + */ + s64 msticks = (s64) round(value * TimeSpan::TicksPerMillisecond); + return AddTicks (msticks); + } + + DateTime AddMinutes (double value) const + { + return AddMilliseconds (value * 60000); + } + + DateTime AddMonths (int months) const + { + int day, month, year, maxday ; + DateTime temp; + + day = get_Day(); + month = get_Month() + (months % 12); + year = get_Year() + months/12 ; + + if (month < 1) + { + month = 12 + month ; + year -- ; + } + else if (month>12) + { + month = month -12; + year ++; + } + maxday = DaysInMonth(year, month); + if (day > maxday) + day = maxday; + + temp = (year, month, day); + return temp.Add (get_TimeOfDay()); + } + + DateTime AddSeconds (double value) const + { + return AddMilliseconds (value * 1000); + } + + DateTime AddYears (int value) const + { + return AddMonths (value * 12); + } + + static int Compare (const DateTime& t1, const DateTime& t2) + { + if (t1.ticks < t2.ticks) + return -1; + else if (t1.ticks > t2.ticks) + return 1; + else + return 0; + } + + static int DaysInMonth (int year, int month) + { + const int* days ; + + //removed error handling + //if (month < 1 || month >12)throw new ArgumentOutOfRangeException (); + //if (year < 1 || year > 9999)throw new ArgumentOutOfRangeException (); + + days = (IsLeapYear(year) ? daysmonthleap : daysmonth); + return days[month]; + } + static bool IsLeapYear (int year) + { + //removed error handling + /* if (year < 1 || year > 9999) + throw new ArgumentOutOfRangeException ();*/ + return ( (year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ; + } + + TimeSpan Subtract (const DateTime& value) const + { + return TimeSpan (ticks.get_Ticks()) - value.ticks; + } + + DateTime Subtract(const TimeSpan& value) const + { + TimeSpan newticks; + + newticks = (TimeSpan (ticks.get_Ticks())) - value; + DateTime ret = DateTime (true,newticks); + return ret; + } + + DateTime operator +(const TimeSpan& t) const + { + return DateTime (true, ticks + t); + } + + bool operator ==(const DateTime& d2) const + { + return (ticks == d2.ticks); + } + + bool operator >(const DateTime& t2) const + { + return (ticks > t2.ticks); + } + + bool operator >=(const DateTime &t2) const + { + return (ticks >= t2.ticks); + } + + bool operator !=(const DateTime& d2) const + { + return (ticks != d2.ticks); + } + + bool operator <(const DateTime& t2) const + { + return (ticks < t2.ticks ); + } + + bool operator <=(const DateTime& t2) const + { + return (ticks <= t2.ticks); + } + + TimeSpan operator -(const DateTime& d2) const + { + return TimeSpan((ticks - d2.ticks).get_Ticks()); + } + + DateTime operator -(const TimeSpan& t) const + { + return DateTime (true, ticks - t); + } + + //try to have a canonical format here. this was comment was typed at 2010-oct-04 02:16:44:000 + + std::string ToString() const + { + char tmp[32]; + sprintf(tmp,"%04d-%s-%02d %02d:%02d:%02d:%03d",get_Year(),monthnames[get_Month()],get_Day(),get_Hour(),get_Minute(),get_Second(),get_Millisecond()); + return tmp; + } + + static bool TryParse(const char* str, DateTime& out) + { + int year,mon=-1,day,hour,min,sec,ms; + char strmon[4]; + int done = sscanf(str,"%04d-%3s-%02d %02d:%02d:%02d:%03d",&year,strmon,&day,&hour,&min,&sec,&ms); + if(done != 7) return false; + for(int i=1;i<12;i++) + if(!strncasecmp(monthnames[i],strmon,3)) + { + mon=i; + break; + } + if(mon==-1) return false; + out = DateTime(year,mon,day,hour,min,sec); + return true; + } + + static DateTime Parse(const char* str) + { + DateTime ret; + TryParse(str,ret); + return ret; + } + +}; + + +#endif //_DATETIME_H_ diff --git a/jni/desmume/src/utils/decrypt/crc.cpp b/jni/desmume/src/utils/decrypt/crc.cpp new file mode 100755 index 0000000..52f3fd3 --- /dev/null +++ b/jni/desmume/src/utils/decrypt/crc.cpp @@ -0,0 +1,167 @@ +//taken from ndstool +//http://devkitpro.svn.sourceforge.net/viewvc/devkitpro/trunk/tools/nds/ndstool/source/crc.cpp?revision=1587 + +/* crc.cpp - this file is part of DeSmuME + * + * Copyright (C) 2005-2006 Rafael Vuijk + * + * This file 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, or (at your option) + * any later version. + * + * This file 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; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + Cyclic Redundancy Code (CRC) functions + by Rafael Vuijk (aka DarkFader) +*/ + +unsigned short ccitt16tab[] = +{ + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 +}; + +unsigned short crc16tab[] = +{ + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 +}; + +unsigned long crc32tab[] = +{ + 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, + 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, + 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, + 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L, + 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, + 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, + 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, + 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L, + 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, + 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, + 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, + 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, + 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, + 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL, + 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, + 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL, + 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, + 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, + 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, + 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, + 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, + 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, + 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, + 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, + 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, + 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, + 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, + 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L, + 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, + 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, + 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, + 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL, + 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, + 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L, + 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, + 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, + 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, + 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, + 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, + 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, + 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, + 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, + 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, + 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L, + 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, + 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, + 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, + 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, + 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, + 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, + 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, + 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L, + 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, + 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, + 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, + 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, + 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, + 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, + 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, + 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, + 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, + 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, + 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, + 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL +}; diff --git a/jni/desmume/src/utils/decrypt/crc.h b/jni/desmume/src/utils/decrypt/crc.h new file mode 100755 index 0000000..e7ca577 --- /dev/null +++ b/jni/desmume/src/utils/decrypt/crc.h @@ -0,0 +1,198 @@ +//taken from ndstool +//http://devkitpro.svn.sourceforge.net/viewvc/devkitpro/trunk/tools/nds/ndstool/include/crc.h?revision=2447 + +/* crc.h - this file is part of DeSmuME + * + * Copyright (C) 2005-2006 Rafael Vuijk + * + * This file 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, or (at your option) + * any later version. + * + * This file 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; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + Cyclic Redundancy Code (CRC) functions + by Rafael Vuijk (aka DarkFader) +*/ + +#ifndef __CRC_H +#define __CRC_H + +//#include "little.h" // FixCrc is not yet big endian compatible + +/* + * Data + */ +extern unsigned short ccitt16tab[]; +extern unsigned short crc16tab[]; +extern unsigned long crc32tab[]; + +/* + * Defines + */ +#define CRC_TEMPLATE template <typename CrcType, CrcType *crcTable> + +/* + * CalcCcitt + * Does not perform final inversion. + */ +#define CalcCcitt_ CalcCcitt<CrcType, crcTable> +#define CalcCcitt16 CalcCcitt<typeof(*ccitt16tab), ccitt16tab> +CRC_TEMPLATE inline CrcType CalcCcitt(unsigned char *data, unsigned int length, CrcType crc = (CrcType)0) +{ + for (unsigned int i=0; i<length; i++) + { + crc = (crc << 8) ^ crcTable[(crc >> 8) ^ data[i]]; + } + return crc; +} + +/* + * CalcCrc + * Does not perform final inversion. + */ +#define CalcCrc_ CalcCrc<CrcType, crcTable> +#define CalcCrc16 CalcCrc<typeof(*crc16tab), crc16tab> +#define CalcCrc32 CalcCrc<typeof(*crc32tab), crc32tab> +CRC_TEMPLATE inline CrcType CalcCrc(unsigned char *data, unsigned int length, CrcType crc = (CrcType)~0) +{ + for (unsigned int i=0; i<length; i++) + { + crc = (crc >> 8) ^ crcTable[(crc ^ data[i]) & 0xFF]; + } + return crc; +} + +/* + * FCalcCrc + * Does not perform final inversion. + */ +#define FCalcCrc_ FCalcCrc<CrcType, crcTable> +#define FCalcCrc16 FCalcCrc<typeof(*crc16tab), crc16tab> +#define FCalcCrc32 FCalcCrc<typeof(*crc32tab), crc32tab> +CRC_TEMPLATE inline CrcType FCalcCrc(FILE *f, unsigned int offset, unsigned int length, CrcType crc = (CrcType)~0) +{ + fseek(f, offset, SEEK_SET); + for (unsigned int i=0; i<length; i++) + { + crc = (crc >> 8) ^ crcTable[(crc ^ fgetc(f)) & 0xFF]; + } + return crc; +} + +/* + * RevCrc + * Reverse table lookup. + */ +#define RevCrc_ RevCrc<CrcType, crcTable> +CRC_TEMPLATE inline unsigned char RevCrc(unsigned char x, CrcType *value = 0) +{ + for (int y=0; y<256; y++) + { + if ((crcTable[y] >> (8*sizeof(CrcType)-8)) == x) + { + if (value) *value = crcTable[y]; + return y; + } + } + return 0; +} + +/* + * FixCrc + */ +#define FixCrc_ FixCrc<CrcType, crcTable> +#define FixCrc16 FixCrc<typeof(*crc16tab), crc16tab> +#define FixCrc32 FixCrc<typeof(*crc32tab), crc32tab> +CRC_TEMPLATE void FixCrc +( + unsigned char *data, // data to be patched + unsigned int patch_offset, unsigned char *patch_data, unsigned int patch_length, // patch data + unsigned int fix_offset = 0, // position to write the fix. by default, it is immediately after the patched data + CrcType initial_crc = (CrcType)~0 // useful when manually calculating leading data +) +{ + if (!fix_offset) fix_offset = patch_offset + patch_length; + + // calculate CRC after leading data + initial_crc = CalcCrc_(data, patch_offset, initial_crc); + + // calculate CRC before fix + unsigned char buf[2*sizeof(CrcType)]; + CrcType crc_before_fix = CalcCrc_(data + patch_offset, fix_offset - patch_offset); + *(CrcType *)(buf + 0) = crc_before_fix; + + // patch + memcpy(data + patch_offset, patch_data, patch_length); + + // calculate CRC after unfixed + CrcType crc_after_unfix = CalcCrc_(data + patch_offset, fix_offset - patch_offset + sizeof(CrcType)); + *(CrcType *)(buf + sizeof(CrcType)) = crc_after_unfix; + + // fix it + for (int i=sizeof(CrcType); i>=1; i--) + { + CrcType value; + unsigned char index = RevCrc_(buf[i + sizeof(CrcType) - 1], &value); + *(CrcType *)(buf + i) ^= value; + buf[i - 1] ^= index; + } + memcpy(data + fix_offset, buf, sizeof(CrcType)); +} + +/* + * FFixCrc + */ +#define FFixCrc_ FFixCrc<CrcType, crcTable> +#define FFixCrc16 FFixCrc<typeof(*crc16tab), crc16tab> +#define FFixCrc32 FFixCrc<typeof(*crc32tab), crc32tab> +CRC_TEMPLATE void FFixCrc +( + FILE *f, // file to be patched + unsigned int patch_offset, unsigned char *patch_data, unsigned int patch_length, // patch data + unsigned int fix_offset = 0, // position to write the fix. by default, it is immediately after the patched data + CrcType initial_crc = (CrcType)~0 // useful when manually calculating leading data +) +{ + if (!fix_offset) fix_offset = patch_offset + patch_length; + + // calculate CRC after leading data + initial_crc = FCalcCrc_(f, 0, patch_offset, initial_crc); + + // calculate CRC before fix + unsigned char buf[2*sizeof(CrcType)]; + CrcType crc_before_fix = FCalcCrc_(f, patch_offset, fix_offset - patch_offset); + *(CrcType *)(buf + 0) = crc_before_fix; + + // patch + fseek(f, patch_offset, SEEK_SET); + fwrite(patch_data, 1, patch_length, f); + + // calculate CRC after unfixed + CrcType crc_after_unfix = FCalcCrc_(f, patch_offset, fix_offset - patch_offset + sizeof(CrcType)); + *(CrcType *)(buf + sizeof(CrcType)) = crc_after_unfix; + + // fix it + for (int i=sizeof(CrcType); i>=1; i--) + { + CrcType value=0; + unsigned char index = RevCrc_(buf[i + sizeof(CrcType) - 1], &value); + *(CrcType *)(buf + i) ^= value; + buf[i - 1] ^= index; + } + fseek(f, fix_offset, SEEK_SET); + fwrite(buf, sizeof(CrcType), 1, f); +} + +#endif // __CRC_H diff --git a/jni/desmume/src/utils/decrypt/decrypt.cpp b/jni/desmume/src/utils/decrypt/decrypt.cpp new file mode 100755 index 0000000..00c83f0 --- /dev/null +++ b/jni/desmume/src/utils/decrypt/decrypt.cpp @@ -0,0 +1,506 @@ +//taken from ndstool +//http://devkitpro.svn.sourceforge.net/viewvc/devkitpro/trunk/tools/nds/ndstool/source/encryption.cpp?revision=1565 + +/* decrypt.cpp - this file is part of DeSmuME + * + * Copyright (C) 2006 Rafael Vuijk + * + * This file 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, or (at your option) + * any later version. + * + * This file 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; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../../types.h" +#include "crc.h" +#include "header.h" +#include "decrypt.h" + +const unsigned char encr_data[] = +{ + 0x99,0xD5,0x20,0x5F,0x57,0x44,0xF5,0xB9,0x6E,0x19,0xA4,0xD9,0x9E,0x6A,0x5A,0x94, + 0xD8,0xAE,0xF1,0xEB,0x41,0x75,0xE2,0x3A,0x93,0x82,0xD0,0x32,0x33,0xEE,0x31,0xD5, + 0xCC,0x57,0x61,0x9A,0x37,0x06,0xA2,0x1B,0x79,0x39,0x72,0xF5,0x55,0xAE,0xF6,0xBE, + 0x5F,0x1B,0x69,0xFB,0xE5,0x9D,0xF1,0xE9,0xCE,0x2C,0xD9,0xA1,0x5E,0x32,0x05,0xE6, + 0xFE,0xD3,0xFE,0xCF,0xD4,0x62,0x04,0x0D,0x8B,0xF5,0xEC,0xB7,0x2B,0x60,0x79,0xBB, + 0x12,0x95,0x31,0x0D,0x6E,0x3F,0xDA,0x2B,0x88,0x84,0xF0,0xF1,0x3D,0x12,0x7E,0x25, + 0x45,0x22,0xF1,0xBB,0x24,0x06,0x1A,0x06,0x11,0xAD,0xDF,0x28,0x8B,0x64,0x81,0x34, + 0x2B,0xEB,0x33,0x29,0x99,0xAA,0xF2,0xBD,0x9C,0x14,0x95,0x9D,0x9F,0xF7,0xF5,0x8C, + 0x72,0x97,0xA1,0x29,0x9D,0xD1,0x5F,0xCF,0x66,0x4D,0x07,0x1A,0xDE,0xD3,0x4A,0x4B, + 0x85,0xC9,0xA7,0xA3,0x17,0x95,0x05,0x3A,0x3D,0x49,0x0A,0xBF,0x0A,0x89,0x8B,0xA2, + 0x4A,0x82,0x49,0xDD,0x27,0x90,0xF1,0x0B,0xE9,0xEB,0x1C,0x6A,0x83,0x76,0x45,0x05, + 0xBA,0x81,0x70,0x61,0x17,0x3F,0x4B,0xDE,0xAE,0xCF,0xAB,0x39,0x57,0xF2,0x3A,0x56, + 0x48,0x11,0xAD,0x8A,0x40,0xE1,0x45,0x3F,0xFA,0x9B,0x02,0x54,0xCA,0xA6,0x93,0xFB, + 0xEF,0x4D,0xFE,0x6F,0xA3,0xD8,0x87,0x9C,0x08,0xBA,0xD5,0x48,0x6A,0x8D,0x2D,0xFD, + 0x6E,0x15,0xF8,0x74,0xBD,0xBE,0x52,0x8B,0x18,0x22,0x8A,0x9E,0xFB,0x74,0x37,0x07, + 0x1B,0x36,0x6C,0x4A,0x19,0xBA,0x42,0x62,0xB9,0x79,0x91,0x10,0x7B,0x67,0x65,0x96, + 0xFE,0x02,0x23,0xE8,0xEE,0x99,0x8C,0x77,0x3E,0x5C,0x86,0x64,0x4D,0x6D,0x78,0x86, + 0xA5,0x4F,0x65,0xE2,0x1E,0xB2,0xDF,0x5A,0x0A,0xD0,0x7E,0x08,0x14,0xB0,0x71,0xAC, + 0xBD,0xDB,0x83,0x1C,0xB9,0xD7,0xA1,0x62,0xCD,0xC6,0x63,0x7C,0x52,0x69,0xC3,0xE6, + 0xBF,0x75,0xCE,0x12,0x44,0x5D,0x21,0x04,0xFA,0xFB,0xD3,0x3C,0x38,0x11,0x63,0xD4, + 0x95,0x85,0x41,0x49,0x46,0x09,0xF2,0x08,0x43,0x11,0xDC,0x1F,0x76,0xC0,0x15,0x6D, + 0x1F,0x3C,0x63,0x70,0xEA,0x87,0x80,0x6C,0xC3,0xBD,0x63,0x8B,0xC2,0x37,0x21,0x37, + 0xDC,0xEE,0x09,0x23,0x2E,0x37,0x6A,0x4D,0x73,0x90,0xF7,0x50,0x30,0xAC,0x1C,0x92, + 0x04,0x10,0x23,0x91,0x4F,0xD2,0x07,0xAA,0x68,0x3E,0x4F,0x9A,0xC9,0x64,0x60,0x6A, + 0xC8,0x14,0x21,0xF3,0xD6,0x22,0x41,0x12,0x44,0x24,0xCF,0xE6,0x8A,0x56,0xDD,0x0D, + 0x53,0x4D,0xE1,0x85,0x1E,0x8C,0x52,0x5A,0x9C,0x19,0x84,0xC2,0x03,0x57,0xF1,0x6F, + 0xE3,0x00,0xBE,0x58,0xF6,0x4C,0xED,0xD5,0x21,0x64,0x9C,0x1F,0xBE,0x55,0x03,0x3C, + 0x4A,0xDC,0xFF,0xAA,0xC9,0xDA,0xE0,0x5D,0x5E,0xBF,0xE6,0xDE,0xF5,0xD8,0xB1,0xF8, + 0xFF,0x36,0xB3,0xB9,0x62,0x67,0x95,0xDB,0x31,0x5F,0x37,0xED,0x4C,0x70,0x67,0x99, + 0x90,0xB5,0x18,0x31,0x6C,0x3D,0x99,0x99,0xE4,0x42,0xDA,0xD3,0x25,0x42,0x13,0xA0, + 0xAE,0xD7,0x70,0x6C,0xB1,0x55,0xCF,0xC7,0xD7,0x46,0xD5,0x43,0x61,0x17,0x3D,0x44, + 0x28,0xE9,0x33,0x85,0xD5,0xD0,0xA2,0x93,0xAA,0x25,0x12,0x1F,0xFB,0xC5,0x0B,0x46, + 0xF5,0x97,0x76,0x56,0x45,0xA6,0xBE,0x87,0xB1,0x94,0x6B,0xE8,0xB1,0xFE,0x33,0x99, + 0xAE,0x1F,0x3E,0x6C,0x39,0x71,0x1D,0x09,0x00,0x90,0x37,0xE4,0x10,0x3E,0x75,0x74, + 0xFF,0x8C,0x83,0x3B,0xB0,0xF1,0xB0,0xF9,0x01,0x05,0x47,0x42,0x95,0xF1,0xD6,0xAC, + 0x7E,0x38,0xE6,0x9E,0x95,0x74,0x26,0x3F,0xB4,0x68,0x50,0x18,0xD0,0x43,0x30,0xB4, + 0x4C,0x4B,0xE3,0x68,0xBF,0xE5,0x4D,0xB6,0x95,0x8B,0x0A,0xA0,0x74,0x25,0x32,0x77, + 0xCF,0xA1,0xF7,0x2C,0xD8,0x71,0x13,0x5A,0xAB,0xEA,0xC9,0x51,0xE8,0x0D,0xEE,0xEF, + 0xE9,0x93,0x7E,0x19,0xA7,0x1E,0x43,0x38,0x81,0x16,0x2C,0xA1,0x48,0xE3,0x73,0xCC, + 0x29,0x21,0x6C,0xD3,0x5D,0xCE,0xA0,0xD9,0x61,0x71,0x43,0xA0,0x15,0x13,0xB5,0x64, + 0x92,0xCF,0x2A,0x19,0xDC,0xAD,0xB7,0xA5,0x9F,0x86,0x65,0xF8,0x1A,0x9F,0xE7,0xFB, + 0xF7,0xFD,0xB8,0x13,0x6C,0x27,0xDB,0x6F,0xDF,0x35,0x1C,0xF7,0x8D,0x2C,0x5B,0x9B, + 0x12,0xAB,0x38,0x64,0x06,0xCC,0xDE,0x31,0xE8,0x4E,0x75,0x11,0x64,0xE3,0xFA,0xEA, + 0xEB,0x34,0x54,0xC2,0xAD,0x3F,0x34,0xEB,0x93,0x2C,0x7D,0x26,0x36,0x9D,0x56,0xF3, + 0x5A,0xE1,0xF6,0xB3,0x98,0x63,0x4A,0x9E,0x32,0x83,0xE4,0x9A,0x84,0x60,0x7D,0x90, + 0x2E,0x13,0x0E,0xEE,0x93,0x4B,0x36,0xA2,0x85,0xEC,0x16,0x38,0xE8,0x88,0x06,0x02, + 0xBF,0xF0,0xA0,0x3A,0xED,0xD7,0x6A,0x9A,0x73,0xE1,0x57,0xCF,0xF8,0x44,0xB8,0xDC, + 0x2E,0x23,0x59,0xD1,0xDF,0x95,0x52,0x71,0x99,0x61,0xA0,0x4B,0xD5,0x7F,0x6E,0x78, + 0xBA,0xA9,0xC5,0x30,0xD3,0x40,0x86,0x32,0x9D,0x32,0x0C,0x9C,0x37,0xB7,0x02,0x2F, + 0xBA,0x54,0x98,0xA9,0xC4,0x13,0x04,0xC9,0x8D,0xBE,0xC8,0xE7,0x5D,0x97,0x50,0x2E, + 0x93,0xD6,0x22,0x59,0x0C,0x27,0xBC,0x22,0x92,0xE0,0xA7,0x20,0x0F,0x93,0x6F,0x7F, + 0x4C,0x9F,0xD3,0xB5,0xA6,0x2A,0x0B,0x74,0x67,0x49,0x7D,0x10,0x26,0xCB,0xD1,0xC5, + 0x86,0x71,0xE7,0x8C,0xA0,0x9C,0xE9,0x5B,0xB2,0x1A,0xF6,0x01,0xEE,0x8C,0x9E,0x5E, + 0x83,0xF2,0x1A,0xDB,0xE6,0xE5,0xEA,0x84,0x59,0x76,0xD2,0x7C,0xF6,0x8D,0xA5,0x49, + 0x36,0x48,0xC2,0x16,0x52,0xBB,0x83,0xA3,0x74,0xB9,0x07,0x0C,0x3B,0xFF,0x61,0x28, + 0xE1,0x61,0xE9,0xE4,0xEF,0x6E,0x15,0xAA,0x4E,0xBA,0xE8,0x5D,0x05,0x96,0xBB,0x32, + 0x56,0xB0,0xFB,0x72,0x52,0x0F,0x0E,0xC8,0x42,0x25,0x65,0x76,0x89,0xAF,0xF2,0xDE, + 0x10,0x27,0xF0,0x01,0x4B,0x74,0xA7,0x97,0x07,0xD5,0x26,0x54,0x54,0x09,0x1F,0x82, + 0x0A,0x86,0x7D,0x30,0x39,0x0E,0xB3,0x26,0x9B,0x0B,0x57,0xBB,0x36,0x06,0x31,0xAF, + 0xFD,0x79,0xFC,0xD9,0x30,0x10,0x2B,0x0C,0xB3,0xE1,0x9B,0xD7,0x7B,0xDC,0x5F,0xEF, + 0xD2,0xF8,0x13,0x45,0x4D,0x47,0x75,0xBD,0x46,0x96,0x3C,0x7E,0x75,0xF3,0x3E,0xB5, + 0x67,0xC5,0x9A,0x3B,0xB0,0x5B,0x29,0x6B,0xDE,0x80,0x5B,0xC8,0x15,0x05,0xB1,0x31, + 0xB6,0xCE,0x49,0xDD,0xAD,0x84,0xB5,0xAE,0x60,0xDC,0x67,0x31,0x34,0x30,0xFE,0x4E, + 0xBD,0x80,0x2F,0xA6,0xBF,0x63,0x39,0x21,0x86,0xD9,0x35,0x7F,0x16,0x68,0x22,0x05, + 0x54,0xE9,0x90,0x26,0x8C,0x07,0x6C,0x51,0xA4,0x31,0x55,0xD7,0x09,0x07,0xA8,0x3E, + 0x2E,0x53,0x66,0xC1,0xF8,0xF2,0x7B,0xC4,0xF2,0x58,0xCF,0xF1,0x87,0xC5,0xA2,0xE7, + 0x27,0x8F,0x30,0x87,0x58,0xA0,0x64,0x62,0x23,0x18,0xB9,0x88,0x7C,0xFA,0xCE,0xC4, + 0x98,0xAE,0xAD,0x17,0xCC,0x4A,0x5B,0xF3,0xE9,0x48,0xD5,0x56,0xD3,0x0D,0xF2,0xC8, + 0x92,0x73,0x8C,0xDB,0xD7,0x2F,0x56,0xAC,0x81,0xF9,0x92,0x69,0x4D,0xC6,0x32,0xF6, + 0xE6,0xC0,0x8D,0x21,0xE2,0x76,0x80,0x61,0x11,0xBC,0xDC,0x6C,0x93,0xAF,0x19,0x69, + 0x9B,0xD0,0xBF,0xB9,0x31,0x9F,0x02,0x67,0xA3,0x51,0xEE,0x83,0x06,0x22,0x7B,0x0C, + 0xAB,0x49,0x42,0x40,0xB8,0xD5,0x01,0x7D,0xCE,0x5E,0xF7,0x55,0x53,0x39,0xC5,0x99, + 0x46,0xD8,0x87,0x9F,0xBA,0xF7,0x64,0xB4,0xE3,0x9A,0xFA,0xA1,0x6D,0x90,0x68,0x10, + 0x30,0xCA,0x8A,0x54,0xA7,0x9F,0x60,0xC3,0x19,0xF5,0x6B,0x0D,0x7A,0x51,0x98,0xE6, + 0x98,0x43,0x51,0xB4,0xD6,0x35,0xE9,0x4F,0xC3,0xDF,0x0F,0x7B,0xD6,0x2F,0x5C,0xBD, + 0x3A,0x15,0x61,0x19,0xF1,0x4B,0xCB,0xAA,0xDC,0x6D,0x64,0xC9,0xD3,0xC6,0x1E,0x56, + 0xEF,0x38,0x4C,0x50,0x71,0x86,0x75,0xCC,0x0D,0x0D,0x4E,0xE9,0x28,0xF6,0x06,0x5D, + 0x70,0x1B,0xAA,0xD3,0x45,0xCF,0xA8,0x39,0xAC,0x95,0xA6,0x2E,0xB4,0xE4,0x22,0xD4, + 0x74,0xA8,0x37,0x5F,0x48,0x7A,0x04,0xCC,0xA5,0x4C,0x40,0xD8,0x28,0xB4,0x28,0x08, + 0x0D,0x1C,0x72,0x52,0x41,0xF0,0x7D,0x47,0x19,0x3A,0x53,0x4E,0x58,0x84,0x62,0x6B, + 0x93,0xB5,0x8A,0x81,0x21,0x4E,0x0D,0xDC,0xB4,0x3F,0xA2,0xC6,0xFC,0xC9,0x2B,0x40, + 0xDA,0x38,0x04,0xE9,0x5E,0x5A,0x86,0x6B,0x0C,0x22,0x25,0x85,0x68,0x11,0x8D,0x7C, + 0x92,0x1D,0x95,0x55,0x4D,0xAB,0x8E,0xBB,0xDA,0xA6,0xE6,0xB7,0x51,0xB6,0x32,0x5A, + 0x05,0x41,0xDD,0x05,0x2A,0x0A,0x56,0x50,0x91,0x17,0x47,0xCC,0xC9,0xE6,0x7E,0xB5, + 0x61,0x4A,0xDB,0x73,0x67,0x51,0xC8,0x33,0xF5,0xDA,0x6E,0x74,0x2E,0x54,0xC3,0x37, + 0x0D,0x6D,0xAF,0x08,0xE8,0x15,0x8A,0x5F,0xE2,0x59,0x21,0xCD,0xA8,0xDE,0x0C,0x06, + 0x5A,0x77,0x6B,0x5F,0xDB,0x18,0x65,0x3E,0xC8,0x50,0xDE,0x78,0xE0,0xB8,0x82,0xB3, + 0x5D,0x4E,0x72,0x32,0x07,0x4F,0xC1,0x34,0x23,0xBA,0x96,0xB7,0x67,0x4E,0xA4,0x28, + 0x1E,0x34,0x62,0xEB,0x2D,0x6A,0x70,0xE9,0x2F,0x42,0xC4,0x70,0x4E,0x5A,0x31,0x9C, + 0xF9,0x5B,0x47,0x28,0xAA,0xDA,0x71,0x6F,0x38,0x1F,0xB3,0x78,0xC4,0x92,0x6B,0x1C, + 0x9E,0xF6,0x35,0x9A,0xB7,0x4D,0x0E,0xBF,0xCC,0x18,0x29,0x41,0x03,0x48,0x35,0x5D, + 0x55,0xD0,0x2B,0xC6,0x29,0xAF,0x5C,0x60,0x74,0x69,0x8E,0x5E,0x9B,0x7C,0xD4,0xBD, + 0x7B,0x44,0x64,0x7D,0x3F,0x92,0x5D,0x69,0xB6,0x1F,0x00,0x4B,0xD4,0x83,0x35,0xCF, + 0x7E,0x64,0x4E,0x17,0xAE,0x8D,0xD5,0x2E,0x9A,0x28,0x12,0x4E,0x2E,0x2B,0x49,0x08, + 0x5C,0xAE,0xC6,0x46,0x85,0xAE,0x41,0x61,0x1E,0x6F,0x82,0xD2,0x51,0x37,0x16,0x1F, + 0x0B,0xF6,0x59,0xA4,0x9A,0xCA,0x5A,0xAF,0x0D,0xD4,0x33,0x8B,0x20,0x63,0xF1,0x84, + 0x80,0x5C,0xCB,0xCF,0x08,0xB4,0xB9,0xD3,0x16,0x05,0xBD,0x62,0x83,0x31,0x9B,0x56, + 0x51,0x98,0x9F,0xBA,0xB2,0x5B,0xAA,0xB2,0x22,0x6B,0x2C,0xB5,0xD4,0x48,0xFA,0x63, + 0x2B,0x5F,0x58,0xFA,0x61,0xFA,0x64,0x09,0xBB,0x38,0xE0,0xB8,0x9D,0x92,0x60,0xA8, + 0x0D,0x67,0x6F,0x0E,0x37,0xF5,0x0D,0x01,0x9F,0xC2,0x77,0xD4,0xFE,0xEC,0xF1,0x73, + 0x30,0x39,0xE0,0x7D,0xF5,0x61,0x98,0xE4,0x2C,0x28,0x55,0x04,0x56,0x55,0xDB,0x2F, + 0x6B,0xEC,0xE5,0x58,0x06,0xB6,0x64,0x80,0x6A,0x2A,0x1A,0x4E,0x5B,0x0F,0xD8,0xC4, + 0x0A,0x2E,0x52,0x19,0xD9,0x62,0xF5,0x30,0x48,0xBE,0x8C,0x7B,0x4F,0x38,0x9B,0xA2, + 0xC3,0xAF,0xC9,0xD3,0xC7,0xC1,0x62,0x41,0x86,0xB9,0x61,0x21,0x57,0x6F,0x99,0x4F, + 0xC1,0xBA,0xCE,0x7B,0xB5,0x3B,0x4D,0x5E,0x8A,0x8B,0x44,0x57,0x5F,0x13,0x5F,0x70, + 0x6D,0x5B,0x29,0x47,0xDC,0x38,0xE2,0xEC,0x04,0x55,0x65,0x12,0x2A,0xE8,0x17,0x43, + 0xE1,0x8E,0xDD,0x2A,0xB3,0xE2,0x94,0xF7,0x09,0x6E,0x5C,0xE6,0xEB,0x8A,0xF8,0x6D, + 0x89,0x49,0x54,0x48,0xF5,0x2F,0xAD,0xBF,0xEA,0x94,0x4B,0xCA,0xFC,0x39,0x87,0x82, + 0x5F,0x8A,0x01,0xF2,0x75,0xF2,0xE6,0x71,0xD6,0xD8,0x42,0xDE,0xF1,0x2D,0x1D,0x28, + 0xA6,0x88,0x7E,0xA3,0xA0,0x47,0x1D,0x30,0xD9,0xA3,0x71,0xDF,0x49,0x1C,0xCB,0x01, + 0xF8,0x36,0xB1,0xF2,0xF0,0x22,0x58,0x5D,0x45,0x6B,0xBD,0xA0,0xBB,0xB2,0x88,0x42, + 0xC7,0x8C,0x28,0xCE,0x93,0xE8,0x90,0x63,0x08,0x90,0x7C,0x89,0x3C,0xF5,0x7D,0xB7, + 0x04,0x2D,0x4F,0x55,0x51,0x16,0xFD,0x7E,0x79,0xE8,0xBE,0xC1,0xF2,0x12,0xD4,0xF8, + 0xB4,0x84,0x05,0x23,0xA0,0xCC,0xD2,0x2B,0xFD,0xE1,0xAB,0xAD,0x0D,0xD1,0x55,0x6C, + 0x23,0x41,0x94,0x4D,0x77,0x37,0x4F,0x05,0x28,0x0C,0xBF,0x17,0xB3,0x12,0x67,0x6C, + 0x8C,0xC3,0x5A,0xF7,0x41,0x84,0x2A,0x6D,0xD0,0x94,0x12,0x27,0x2C,0xB4,0xED,0x9C, + 0x4D,0xEC,0x47,0x82,0x97,0xD5,0x67,0xB9,0x1B,0x9D,0xC0,0x55,0x07,0x7E,0xE5,0x8E, + 0xE2,0xA8,0xE7,0x3E,0x12,0xE4,0x0E,0x3A,0x2A,0x45,0x55,0x34,0xA2,0xF9,0x2D,0x5A, + 0x1B,0xAB,0x52,0x7C,0x83,0x10,0x5F,0x55,0xD2,0xF1,0x5A,0x43,0x2B,0xC6,0xA7,0xA4, + 0x89,0x15,0x95,0xE8,0xB4,0x4B,0x9D,0xF8,0x75,0xE3,0x9F,0x60,0x78,0x5B,0xD6,0xE6, + 0x0D,0x44,0xE6,0x21,0x06,0xBD,0x47,0x22,0x53,0xA4,0x00,0xAD,0x8D,0x43,0x13,0x85, + 0x39,0xF7,0xAA,0xFC,0x38,0xAF,0x7B,0xED,0xFC,0xE4,0x2B,0x54,0x50,0x98,0x4C,0xFC, + 0x85,0x80,0xF7,0xDF,0x3C,0x80,0x22,0xE1,0x94,0xDA,0xDE,0x24,0xC6,0xB0,0x7A,0x39, + 0x38,0xDC,0x0F,0xA1,0xA7,0xF4,0xF9,0x6F,0x63,0x18,0x57,0x8B,0x84,0x41,0x2A,0x2E, + 0xD4,0x53,0xF2,0xD9,0x00,0x0F,0xD0,0xDD,0x99,0x6E,0x19,0xA6,0x0A,0xD0,0xEC,0x5B, + 0x58,0x24,0xAB,0xC0,0xCB,0x06,0x65,0xEC,0x1A,0x13,0x38,0x94,0x0A,0x67,0x03,0x2F, + 0x3F,0xF7,0xE3,0x77,0x44,0x77,0x33,0xC6,0x14,0x39,0xD0,0xE3,0xC0,0xA2,0x08,0x79, + 0xBB,0x40,0x99,0x57,0x41,0x0B,0x01,0x90,0xCD,0xE1,0xCC,0x48,0x67,0xDB,0xB3,0xAF, + 0x88,0x74,0xF3,0x4C,0x82,0x8F,0x72,0xB1,0xB5,0x23,0x29,0xC4,0x12,0x6C,0x19,0xFC, + 0x8E,0x46,0xA4,0x9C,0xC4,0x25,0x65,0x87,0xD3,0x6D,0xBE,0x8A,0x93,0x11,0x03,0x38, + 0xED,0x83,0x2B,0xF3,0x46,0xA4,0x93,0xEA,0x3B,0x53,0x85,0x1D,0xCE,0xD4,0xF1,0x08, + 0x83,0x27,0xED,0xFC,0x9B,0x1A,0x18,0xBC,0xF9,0x8B,0xAE,0xDC,0x24,0xAB,0x50,0x38, + 0xE9,0x72,0x4B,0x10,0x22,0x17,0x7B,0x46,0x5D,0xAB,0x59,0x64,0xF3,0x40,0xAE,0xF8, + 0xBB,0xE5,0xC8,0xF9,0x26,0x03,0x4E,0x55,0x7D,0xEB,0xEB,0xFE,0xF7,0x39,0xE6,0xE0, + 0x0A,0x11,0xBE,0x2E,0x28,0xFF,0x98,0xED,0xC0,0xC9,0x42,0x56,0x42,0xC3,0xFD,0x00, + 0xF6,0xAF,0x87,0xA2,0x5B,0x01,0x3F,0x32,0x92,0x47,0x95,0x9A,0x72,0xA5,0x32,0x3D, + 0xAE,0x6B,0xD0,0x9B,0x07,0xD2,0x49,0x92,0xE3,0x78,0x4A,0xFA,0xA1,0x06,0x7D,0xF2, + 0x41,0xCF,0x77,0x74,0x04,0x14,0xB2,0x0C,0x86,0x84,0x64,0x16,0xD5,0xBB,0x51,0xA1, + 0xE5,0x6F,0xF1,0xD1,0xF2,0xE2,0xF7,0x5F,0x58,0x20,0x4D,0xB8,0x57,0xC7,0xCF,0xDD, + 0xC5,0xD8,0xBE,0x76,0x3D,0xF6,0x5F,0x7E,0xE7,0x2A,0x8B,0x88,0x24,0x1B,0x38,0x3F, + 0x0E,0x41,0x23,0x77,0xF5,0xF0,0x4B,0xD4,0x0C,0x1F,0xFA,0xA4,0x0B,0x80,0x5F,0xCF, + 0x45,0xF6,0xE0,0xDA,0x2F,0x34,0x59,0x53,0xFB,0x20,0x3C,0x52,0x62,0x5E,0x35,0xB5, + 0x62,0xFE,0x8B,0x60,0x63,0xE3,0x86,0x5A,0x15,0x1A,0x6E,0xD1,0x47,0x45,0xBC,0x32, + 0xB4,0xEB,0x67,0x38,0xAB,0xE4,0x6E,0x33,0x3A,0xB5,0xED,0xA3,0xAD,0x67,0xE0,0x4E, + 0x41,0x95,0xEE,0x62,0x62,0x71,0x26,0x1D,0x31,0xEF,0x62,0x30,0xAF,0xD7,0x82,0xAC, + 0xC2,0xDC,0x05,0x04,0xF5,0x97,0x07,0xBF,0x11,0x59,0x23,0x07,0xC0,0x64,0x02,0xE8, + 0x97,0xE5,0x3E,0xAF,0x18,0xAC,0x59,0xA6,0x8B,0x4A,0x33,0x90,0x1C,0x6E,0x7C,0x9C, + 0x20,0x7E,0x4C,0x3C,0x3E,0x61,0x64,0xBB,0xC5,0x6B,0x7C,0x7E,0x3E,0x9F,0xC5,0x4C, + 0x9F,0xEA,0x73,0xF5,0xD7,0x89,0xC0,0x4C,0xF4,0xFB,0xF4,0x2D,0xEC,0x14,0x1B,0x51, + 0xD5,0xC1,0x12,0xC8,0x10,0xDF,0x0B,0x4A,0x8B,0x9C,0xBC,0x93,0x45,0x6A,0x3E,0x3E, + 0x7D,0xC1,0xA9,0xBA,0xCD,0xC1,0xB4,0x07,0xE4,0xE1,0x68,0x86,0x43,0xB2,0x6D,0x38, + 0xF3,0xFB,0x0C,0x5C,0x66,0x37,0x71,0xDE,0x56,0xEF,0x6E,0xA0,0x10,0x40,0x65,0xA7, + 0x98,0xF7,0xD0,0xBE,0x0E,0xC8,0x37,0x36,0xEC,0x10,0xCA,0x7C,0x9C,0xAB,0x84,0x1E, + 0x05,0x17,0x76,0x02,0x1C,0x4F,0x52,0xAA,0x5F,0xC1,0xC6,0xA0,0x56,0xB9,0xD8,0x04, + 0x84,0x44,0x4D,0xA7,0x59,0xD8,0xDE,0x60,0xE6,0x38,0x0E,0x05,0x8F,0x03,0xE1,0x3B, + 0x6D,0x81,0x04,0x33,0x6F,0x30,0x0B,0xCE,0x69,0x05,0x21,0x33,0xFB,0x26,0xBB,0x89, + 0x7D,0xB6,0xAE,0x87,0x7E,0x51,0x07,0xE0,0xAC,0xF7,0x96,0x0A,0x6B,0xF9,0xC4,0x5C, + 0x1D,0xE4,0x44,0x47,0xB8,0x5E,0xFA,0xE3,0x78,0x84,0x55,0x42,0x4B,0x48,0x5E,0xF7, + 0x7D,0x47,0x35,0x86,0x1D,0x2B,0x43,0x05,0x03,0xEC,0x8A,0xB8,0x1E,0x06,0x3C,0x76, + 0x0C,0x48,0x1A,0x43,0xA7,0xB7,0x8A,0xED,0x1E,0x13,0xC6,0x43,0xEE,0x10,0xEF,0xDB, + 0xEC,0xFB,0x3C,0x83,0xB2,0x95,0x44,0xEF,0xD8,0x54,0x51,0x4E,0x2D,0x11,0x44,0x1D, + 0xFB,0x36,0x59,0x1E,0x7A,0x34,0xC1,0xC3,0xCA,0x57,0x00,0x61,0xEA,0x67,0xA5,0x16, + 0x9B,0x55,0xD0,0x55,0xE1,0x7F,0xD9,0x36,0xD2,0x40,0x76,0xAE,0xDC,0x01,0xCE,0xB0, + 0x7A,0x83,0xD5,0xCB,0x20,0x98,0xEC,0x6B,0xC1,0x72,0x92,0x34,0xF3,0x82,0x57,0x37, + 0x62,0x8A,0x32,0x36,0x0C,0x90,0x43,0xAE,0xAE,0x5C,0x9B,0x78,0x8E,0x13,0x65,0x02, + 0xFD,0x68,0x71,0xC1,0xFE,0xB0,0x31,0xA0,0x24,0x82,0xB0,0xC3,0xB1,0x79,0x69,0xA7, + 0xF5,0xD2,0xEB,0xD0,0x82,0xC0,0x32,0xDC,0x9E,0xC7,0x26,0x3C,0x6D,0x8D,0x98,0xC1, + 0xBB,0x22,0xD4,0xD0,0x0F,0x33,0xEC,0x3E,0xB9,0xCC,0xE1,0xDC,0x6A,0x4C,0x77,0x36, + 0x14,0x1C,0xF9,0xBF,0x81,0x9F,0x28,0x5F,0x71,0x85,0x32,0x29,0x90,0x75,0x48,0xC4, + 0xB3,0x4A,0xCE,0xD8,0x44,0x8F,0x14,0x2F,0xFD,0x40,0x57,0xEF,0xAA,0x08,0x75,0xD9, + 0x46,0xD1,0xD6,0x6E,0x32,0x55,0x1F,0xC3,0x18,0xFE,0x84,0x1F,0xFC,0x84,0xD5,0xFF, + 0x71,0x5E,0x1B,0x48,0xC3,0x86,0x95,0x0E,0x28,0x08,0x27,0xD3,0x38,0x83,0x71,0x7B, + 0x4C,0x80,0x63,0x54,0x9A,0x56,0xB0,0xAC,0xCF,0x80,0xCA,0x31,0x09,0xEF,0xFE,0xF3, + 0xBE,0xAF,0x24,0x7E,0xA6,0xFE,0x53,0x3F,0xC2,0x8D,0x4A,0x33,0x68,0xD1,0x22,0xA6, + 0x66,0xAD,0x7B,0xEA,0xDE,0xB6,0x43,0xB0,0xA1,0x25,0x95,0x00,0xA3,0x3F,0x75,0x46, + 0x14,0x11,0x44,0xEC,0xD7,0x95,0xBC,0x92,0xF0,0x4F,0xA9,0x16,0x53,0x62,0x97,0x60, + 0x2A,0x0F,0x41,0xF1,0x71,0x24,0xBE,0xEE,0x94,0x7F,0x08,0xCD,0x60,0x93,0xB3,0x85, + 0x5B,0x07,0x00,0x3F,0xD8,0x0F,0x28,0x83,0x9A,0xD1,0x69,0x9F,0xD1,0xDA,0x2E,0xC3, + 0x90,0x01,0xA2,0xB9,0x6B,0x4E,0x2A,0x66,0x9D,0xDA,0xAE,0xA6,0xEA,0x2A,0xD3,0x68, + 0x2F,0x0C,0x0C,0x9C,0xD2,0x8C,0x4A,0xED,0xE2,0x9E,0x57,0x65,0x9D,0x09,0x87,0xA3, + 0xB4,0xC4,0x32,0x5D,0xC9,0xD4,0x32,0x2B,0xB1,0xE0,0x71,0x1E,0x64,0x4D,0xE6,0x90, + 0x71,0xE3,0x1E,0x40,0xED,0x7D,0xF3,0x84,0x0E,0xED,0xC8,0x78,0x76,0xAE,0xC0,0x71, + 0x27,0x72,0xBB,0x05,0xEA,0x02,0x64,0xFB,0xF3,0x48,0x6B,0xB5,0x42,0x93,0x3F,0xED, + 0x9F,0x13,0x53,0xD2,0xF7,0xFE,0x2A,0xEC,0x1D,0x47,0x25,0xDB,0x3C,0x91,0x86,0xC6, + 0x8E,0xF0,0x11,0xFD,0x23,0x74,0x36,0xF7,0xA4,0xF5,0x9E,0x7A,0x7E,0x53,0x50,0x44, + 0xD4,0x47,0xCA,0xD3,0xEB,0x38,0x6D,0xE6,0xD9,0x71,0x94,0x7F,0x4A,0xC6,0x69,0x4B, + 0x11,0xF4,0x52,0xEA,0x22,0xFE,0x8A,0xB0,0x36,0x67,0x8B,0x59,0xE8,0xE6,0x80,0x2A, + 0xEB,0x65,0x04,0x13,0xEE,0xEC,0xDC,0x9E,0x5F,0xB1,0xEC,0x05,0x6A,0x59,0xE6,0x9F, + 0x5E,0x59,0x6B,0x89,0xBF,0xF7,0x1A,0xCA,0x44,0xF9,0x5B,0x6A,0x71,0x85,0x03,0xE4, + 0x29,0x62,0xE0,0x70,0x6F,0x41,0xC4,0xCF,0xB2,0xB1,0xCC,0xE3,0x7E,0xA6,0x07,0xA8, + 0x87,0xE7,0x7F,0x84,0x93,0xDB,0x52,0x4B,0x6C,0xEC,0x7E,0xDD,0xD4,0x24,0x48,0x10, + 0x69,0x9F,0x04,0x60,0x74,0xE6,0x48,0x18,0xF3,0xE4,0x2C,0xB9,0x4F,0x2E,0x50,0x7A, + 0xDF,0xD4,0x54,0x69,0x2B,0x8B,0xA7,0xF3,0xCE,0xFF,0x1F,0xF3,0x3E,0x26,0x01,0x39, + 0x17,0x95,0x84,0x89,0xB0,0xF0,0x4C,0x4B,0x82,0x91,0x9F,0xC4,0x4B,0xAC,0x9D,0xA5, + 0x74,0xAF,0x17,0x25,0xC9,0xCA,0x32,0xD3,0xBC,0x89,0x8A,0x84,0x89,0xCC,0x0D,0xAE, + 0x7C,0xA2,0xDB,0x9C,0x6A,0x78,0x91,0xEE,0xEA,0x76,0x5D,0x4E,0x87,0x60,0xF5,0x69, + 0x15,0x67,0xD4,0x02,0xCF,0xAF,0x48,0x36,0x07,0xEA,0xBF,0x6F,0x66,0x2D,0x06,0x8F, + 0xC4,0x9A,0xFE,0xF9,0xF6,0x90,0x87,0x75,0xB8,0xF7,0xAD,0x0F,0x76,0x10,0x5A,0x3D, + 0x59,0xB0,0x2E,0xB3,0xC7,0x35,0x2C,0xCC,0x70,0x56,0x2B,0xCB,0xE3,0x37,0x96,0xC5, + 0x2F,0x46,0x1B,0x8A,0x22,0x46,0xC7,0x88,0xA7,0x26,0x32,0x98,0x61,0xDF,0x86,0x22, + 0x8A,0xF4,0x1C,0x2F,0x87,0xA1,0x09,0xAA,0xCC,0xA9,0xAE,0xD3,0xBD,0x00,0x45,0x1C, + 0x9A,0x54,0x87,0x86,0x52,0x87,0xEF,0xFF,0x1E,0x8F,0xA1,0x8F,0xC1,0x89,0x5C,0x35, + 0x1B,0xDA,0x2D,0x3A,0x2C,0x16,0xB2,0xC2,0xF1,0x56,0xE2,0x78,0xC1,0x6B,0x63,0x97, + 0xC5,0x56,0x8F,0xC9,0x32,0x7F,0x2C,0xAA,0xAF,0xA6,0xA8,0xAC,0x20,0x91,0x22,0x88, + 0xDE,0xE4,0x60,0x8B,0xF9,0x4B,0x42,0x25,0x1A,0xE3,0x7F,0x9C,0x2C,0x19,0x89,0x3A, + 0x7E,0x05,0xD4,0x36,0xCC,0x69,0x58,0xC2,0xC1,0x32,0x8B,0x2F,0x90,0x85,0xEB,0x7A, + 0x39,0x50,0xA5,0xA1,0x27,0x92,0xC5,0x66,0xB0,0x20,0x4F,0x58,0x7E,0x55,0x83,0x43, + 0x2B,0x45,0xE2,0x9C,0xE4,0xD8,0x12,0x90,0x2C,0x16,0x83,0x56,0x16,0x79,0x03,0xB3, + 0xAD,0x2D,0x61,0x18,0x1A,0x13,0x1F,0x37,0xE2,0xE1,0x9C,0x73,0x7B,0x80,0xD5,0xFD, + 0x2D,0x51,0x87,0xFC,0x7B,0xAA,0xD7,0x1F,0x2C,0x7A,0x8E,0xAF,0xF4,0x8D,0xBB,0xCD, + 0x95,0x11,0x7C,0x72,0x0B,0xEE,0x6F,0xE2,0xB9,0xAF,0xDE,0x37,0x83,0xDE,0x8C,0x8D, + 0x62,0x05,0x67,0xB7,0x96,0xC6,0x8D,0x56,0xB6,0x0D,0xD7,0x62,0xBA,0xD6,0x46,0x36, + 0xBD,0x8E,0xC8,0xE6,0xEA,0x2A,0x6C,0x10,0x14,0xFF,0x6B,0x5B,0xFA,0x82,0x3C,0x46, + 0xB1,0x30,0x43,0x46,0x51,0x8A,0x7D,0x9B,0x92,0x3E,0x83,0x79,0x5B,0x55,0x5D,0xB2, + 0x6C,0x5E,0xCE,0x90,0x62,0x8E,0x53,0x98,0xC9,0x0D,0x6D,0xE5,0x2D,0x57,0xCD,0xC5, + 0x81,0x57,0xBA,0xE1,0xE8,0xB8,0x8F,0x72,0xE5,0x4F,0x13,0xDC,0xEA,0x9D,0x71,0x15, + 0x10,0xB2,0x11,0x88,0xD5,0x09,0xD4,0x7F,0x5B,0x65,0x7F,0x2C,0x3B,0x38,0x4C,0x11, + 0x68,0x50,0x8D,0xFB,0x9E,0xB0,0x59,0xBF,0x94,0x80,0x89,0x4A,0xC5,0x1A,0x18,0x12, + 0x89,0x53,0xD1,0x4A,0x10,0x29,0xE8,0x8C,0x1C,0xEC,0xB6,0xEA,0x46,0xC7,0x17,0x8B, + 0x25,0x15,0x31,0xA8,0xA2,0x6B,0x43,0xB1,0x9D,0xE2,0xDB,0x0B,0x87,0x9B,0xB0,0x11, + 0x04,0x0E,0x71,0xD2,0x29,0x77,0x89,0x82,0x0A,0x66,0x41,0x7F,0x1D,0x0B,0x48,0xFF, + 0x72,0xBB,0x24,0xFD,0xC2,0x48,0xA1,0x9B,0xFE,0x7B,0x7F,0xCE,0x88,0xDB,0x86,0xD9, + 0x85,0x3B,0x1C,0xB0,0xDC,0xA8,0x33,0x07,0xBF,0x51,0x2E,0xE3,0x0E,0x9A,0x00,0x97, + 0x1E,0x06,0xC0,0x97,0x43,0x9D,0xD8,0xB6,0x45,0xC4,0x86,0x67,0x5F,0x00,0xF8,0x88, + 0x9A,0xA4,0x52,0x9E,0xC7,0xAA,0x8A,0x83,0x75,0xEC,0xC5,0x18,0xAE,0xCE,0xC3,0x2F, + 0x1A,0x2B,0xF9,0x18,0xFF,0xAE,0x1A,0xF5,0x53,0x0B,0xB5,0x33,0x51,0xA7,0xFD,0xE8, + 0xA8,0xE1,0xA2,0x64,0xB6,0x22,0x17,0x43,0x80,0xCC,0x0A,0xD8,0xAE,0x3B,0xBA,0x40, + 0xD7,0xD9,0x92,0x4A,0x89,0xDF,0x04,0x10,0xEE,0x9B,0x18,0x2B,0x6A,0x77,0x69,0x8A, + 0x68,0xF4,0xF9,0xB9,0xA2,0x21,0x15,0x6E,0xE6,0x1E,0x3B,0x03,0x62,0x30,0x9B,0x60, + 0x41,0x7E,0x25,0x9B,0x9E,0x8F,0xC5,0x52,0x10,0x08,0xF8,0xC2,0x69,0xA1,0x21,0x11, + 0x88,0x37,0x5E,0x79,0x35,0x66,0xFF,0x10,0x42,0x18,0x6E,0xED,0x97,0xB6,0x6B,0x1C, + 0x4E,0x36,0xE5,0x6D,0x7D,0xB4,0xE4,0xBF,0x20,0xB9,0xE0,0x05,0x3A,0x69,0xD5,0xB8, + 0xE3,0xD5,0xDC,0xE0,0xB9,0xAC,0x53,0x3E,0x07,0xA4,0x57,0xAD,0x77,0xFF,0x48,0x18, + 0x76,0x2A,0xAC,0x49,0x2A,0x8E,0x47,0x75,0x6D,0x9F,0x67,0x63,0x30,0x35,0x8C,0x39, + 0x05,0x39,0xD5,0x6F,0x64,0x3A,0x5B,0xAD,0xCA,0x0B,0xBB,0x82,0x52,0x99,0x45,0xB1, + 0x93,0x36,0x36,0x99,0xAF,0x13,0x20,0x44,0x36,0xD8,0x02,0x44,0x09,0x39,0x92,0x85, + 0xFF,0x4A,0x4A,0x97,0x87,0xA6,0x63,0xD7,0xC7,0xB5,0xB5,0x24,0xED,0x0F,0xB4,0x6F, + 0x0C,0x58,0x52,0x14,0xD9,0xA6,0x7B,0xD3,0x79,0xBC,0x38,0x58,0xA1,0xBD,0x3B,0x84, + 0x06,0xD8,0x1A,0x06,0xFD,0x6B,0xA8,0xEA,0x4B,0x69,0x28,0x04,0x37,0xAD,0x82,0x99, + 0xFB,0x0E,0x1B,0x85,0xBD,0xA8,0x5D,0x73,0xCD,0xDC,0x58,0x75,0x0A,0xBE,0x63,0x6C, + 0x48,0xE7,0x4C,0xE4,0x30,0x2B,0x04,0x60,0xB9,0x15,0xD8,0xDA,0x86,0x81,0x75,0x8F, + 0x96,0xD4,0x8D,0x1C,0x5D,0x70,0x85,0x7C,0x1C,0x67,0x7B,0xD5,0x08,0x67,0xA6,0xCE, + 0x4B,0x0A,0x66,0x70,0xB7,0xE5,0x63,0xD4,0x5B,0x8A,0x82,0xEA,0x10,0x67,0xCA,0xE2, + 0xF4,0xEF,0x17,0x85,0x2F,0x2A,0x5F,0x8A,0x97,0x82,0xF8,0x6A,0xD6,0x34,0x10,0xEA, + 0xEB,0xC9,0x5C,0x3C,0xE1,0x49,0xF8,0x46,0xEB,0xDE,0xBD,0xF6,0xA9,0x92,0xF1,0xAA, + 0xA6,0xA0,0x18,0xB0,0x3A,0xD3,0x0F,0x1F,0xF3,0x6F,0xFF,0x31,0x45,0x43,0x44,0xD3, + 0x50,0x9A,0xF7,0x88,0x09,0x96,0xC1,0xCE,0x76,0xCC,0xF2,0x2C,0x2C,0xBA,0xAD,0x82, + 0x77,0x8F,0x18,0x84,0xC0,0xD2,0x07,0x9C,0x36,0x90,0x83,0x4E,0x0B,0xA5,0x4F,0x43, + 0x3E,0x04,0xAB,0x78,0x4F,0xD6,0xFB,0x09,0x01,0x24,0x90,0xDA,0x6F,0x3C,0x3A,0x61, + 0x0D,0x7F,0x69,0x4A,0xEB,0x2B,0x30,0x02,0xB4,0xDB,0xE0,0x84,0xA9,0xEC,0xD7,0x35, + 0xBF,0x37,0x7D,0x85,0x58,0xCE,0xA9,0x4E,0xE4,0x80,0xC7,0xA8,0xD3,0x30,0x67,0x48, + 0xEB,0x29,0xAF,0x2F,0x74,0x6A,0xB4,0xA7,0x3F,0x0F,0x3F,0x92,0xAF,0xF3,0xCA,0xAC, + 0xAF,0x4B,0xD9,0x94,0xC0,0x43,0xCA,0x81,0x0D,0x2F,0x48,0xA1,0xB0,0x27,0xD5,0xD2, + 0xEF,0x4B,0x05,0x85,0xA3,0xDE,0x4D,0x93,0x30,0x3C,0xF0,0xBB,0x4A,0x8F,0x30,0x27, + 0x4C,0xEB,0xE3,0x3E,0x64,0xED,0x9A,0x2F,0x3B,0xF1,0x82,0xF0,0xBA,0xF4,0xCF,0x7F, + 0x40,0xCB,0xB0,0xE1,0x7F,0xBC,0xAA,0x57,0xD3,0xC9,0x74,0xF2,0xFA,0x43,0x0D,0x22, + 0xD0,0xF4,0x77,0x4E,0x93,0xD7,0x85,0x70,0x1F,0x99,0xBF,0xB6,0xDE,0x35,0xF1,0x30, + 0xA7,0x5E,0x71,0xF0,0x6B,0x01,0x2D,0x7B,0x64,0xF0,0x33,0x53,0x0A,0x39,0x88,0xF3, + 0x6B,0x3A,0xA6,0x6B,0x35,0xD2,0x2F,0x43,0xCD,0x02,0xFD,0xB5,0xE9,0xBC,0x5B,0xAA, + 0xD8,0xA4,0x19,0x7E,0x0E,0x5D,0x94,0x81,0x9E,0x6F,0x77,0xAD,0xD6,0x0E,0x74,0x93, + 0x96,0xE7,0xC4,0x18,0x5F,0xAD,0xF5,0x19, +}; + +u32 card_hash[0x412]; +int cardheader_devicetype = 0; +u32 global3_x00, global3_x04; // RTC value +u32 global3_rand1; +u32 global3_rand3; + +static u32 lookup(u32 *magic, u32 v) +{ + u32 a = (v >> 24) & 0xFF; + u32 b = (v >> 16) & 0xFF; + u32 c = (v >> 8) & 0xFF; + u32 d = (v >> 0) & 0xFF; + + a = magic[a+18+0]; + b = magic[b+18+256]; + c = magic[c+18+512]; + d = magic[d+18+768]; + + return d + (c ^ (b + a)); +} + +static void encrypt(u32 *magic, u32 *arg1, u32 *arg2) +{ + u32 a,b,c; + a = *arg1; + b = *arg2; + for (int i=0; i<16; i++) + { + c = magic[i] ^ a; + a = b ^ lookup(magic, c); + b = c; + } + *arg2 = a ^ magic[16]; + *arg1 = b ^ magic[17]; +} + +static void decrypt(u32 *magic, u32 *arg1, u32 *arg2) +{ + u32 a,b,c; + a = *arg1; + b = *arg2; + for (int i=17; i>1; i--) + { + c = magic[i] ^ a; + a = b ^ lookup(magic, c); + b = c; + } + *arg1 = b ^ magic[0]; + *arg2 = a ^ magic[1]; +} + +static void encrypt(u32 *magic, u64 &cmd) +{ + encrypt(magic, (u32 *)&cmd + 1, (u32 *)&cmd + 0); +} + +static void decrypt(u32 *magic, u64 &cmd) +{ + decrypt(magic, (u32 *)&cmd + 1, (u32 *)&cmd + 0); +} + +static void update_hashtable(u32* magic, u8 arg1[8]) +{ + for (int j=0;j<18;j++) + { + u32 r3=0; + for (int i=0;i<4;i++) + { + r3 <<= 8; + r3 |= arg1[(j*4 + i) & 7]; + } + magic[j] ^= r3; + } + + u32 tmp1 = 0; + u32 tmp2 = 0; + for (int i=0; i<18; i+=2) + { + encrypt(magic,&tmp1,&tmp2); + magic[i+0] = tmp1; + magic[i+1] = tmp2; + } + for (int i=0; i<0x400; i+=2) + { + encrypt(magic,&tmp1,&tmp2); + magic[i+18+0] = tmp1; + magic[i+18+1] = tmp2; + } +} + +u32 arg2[3]; + +static void init2(u32 *magic, u32 a[3]) +{ + encrypt(magic, a+2, a+1); + encrypt(magic, a+1, a+0); + update_hashtable(magic, (u8*)a); +} + +static void init1(u32 cardheader_gamecode) +{ + memcpy(card_hash, &encr_data, 4*(1024 + 18)); + arg2[0] = *(u32 *)&cardheader_gamecode; + arg2[1] = (*(u32 *)&cardheader_gamecode) >> 1; + arg2[2] = (*(u32 *)&cardheader_gamecode) << 1; + init2(card_hash, arg2); + init2(card_hash, arg2); +} + +static void init0(u32 cardheader_gamecode) +{ + init1(cardheader_gamecode); + encrypt(card_hash, (u32*)&global3_x04, (u32*)&global3_x00); + global3_rand1 = global3_x00 ^ global3_x04; // more RTC + global3_rand3 = global3_x04 ^ 0x0380FEB2; + encrypt(card_hash, (u32*)&global3_rand3, (u32*)&global3_rand1); +} + +// ARM9 decryption check values +#define MAGIC30 0x72636E65 +#define MAGIC34 0x6A624F79 + +/* + * decrypt_arm9 + */ +static void decrypt_arm9(u32 cardheader_gamecode, unsigned char *data) +{ + u32 *p = (u32*)data; + + init1(cardheader_gamecode); + decrypt(card_hash, p+1, p); + arg2[1] <<= 1; + arg2[2] >>= 1; + init2(card_hash, arg2); + decrypt(card_hash, p+1, p); + + if (p[0] != MAGIC30 || p[1] != MAGIC34) + { + fprintf(stderr, "Decryption failed!\n"); + exit(1); + } + + *p++ = 0xE7FFDEFF; + *p++ = 0xE7FFDEFF; + u32 size = 0x800 - 8; + while (size > 0) + { + decrypt(card_hash, p+1, p); + p += 2; + size -= 8; + } +} + + +bool DecryptSecureArea(u8 *romdata, long romlen) +{ + //this looks like it will only work on little endian hosts + Header* header = (Header*)romdata; + + int romType = DetectRomType(*header,(char*)romdata); + + /*bool do_decrypt = (endecrypt_option == 'd'); + bool do_encrypt = (endecrypt_option == 'e') || (endecrypt_option == 'E'); + unsigned int rounds_offsets = (endecrypt_option == 'E') ? 0x2000 : 0x1600; + unsigned int sbox_offsets = (endecrypt_option == 'E') ? 0x2400 : 0x2800;*/ +#if 0 + unsigned int rounds_offsets = 0x1600; + unsigned int sbox_offsets = 0x2800; +#endif + + if(romType == ROMTYPE_INVALID) + return false; + + // check if ROM is already encrypted + if (romType == ROMTYPE_NDSDUMPED) + { + printf("Already decrypted.\n"); + } + else if (romType >= ROMTYPE_ENCRSECURE) // includes ROMTYPE_MASKROM + { + unsigned char data[0x4000]; + memcpy(data,romdata+0x4000,0x4000); + + decrypt_arm9(*(u32 *)header->gamecode, data); + + // clear data after header + //fseek(fNDS, 0x200, SEEK_SET); + //for (unsigned int i=0x200; i<0x4000; i++) fputc(0, fNDS); + memset(romdata+0x200,0,(0x4000-0x200)); + + // write secure 0x800 + //fseek(fNDS, 0x4000, SEEK_SET); + //fwrite(data, 1, 0x800, fNDS); + memcpy(romdata+0x4000,data,0x800); + + // write header + //(already poked directly) + //fseek(fNDS, 0, SEEK_SET); + //fwrite(&header, 512, 1, fNDS); + + printf("Decrypted.\n"); + } + else + { + printf("File doesn't appear to have a secure area.\n"); + } + + return true; +} diff --git a/jni/desmume/src/utils/decrypt/decrypt.h b/jni/desmume/src/utils/decrypt/decrypt.h new file mode 100755 index 0000000..d279d56 --- /dev/null +++ b/jni/desmume/src/utils/decrypt/decrypt.h @@ -0,0 +1,26 @@ +/* decrypt.h - this file is part of DeSmuME + * + * Copyright (C) 2006 Rafael Vuijk + * + * This file 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, or (at your option) + * any later version. + * + * This file 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; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _DECRYPT_H_ +#define _DECRYPT_H_ + +bool DecryptSecureArea(u8 *romdata, long romlen); + +#endif diff --git a/jni/desmume/src/utils/decrypt/header.cpp b/jni/desmume/src/utils/decrypt/header.cpp new file mode 100755 index 0000000..d3dd6e6 --- /dev/null +++ b/jni/desmume/src/utils/decrypt/header.cpp @@ -0,0 +1,656 @@ +//taken from ndstool +//http://devkitpro.svn.sourceforge.net/viewvc/devkitpro/trunk/tools/nds/ndstool/source/header.cpp?revision=3063 + +/* header.cpp - this file is part of DeSmuME + * + * Copyright (C) 2005-2006 Rafael Vuijk + * + * This file 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, or (at your option) + * any later version. + * + * This file 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; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "header.h" + +//#include "ndstool.h" +//#include "banner.h" +//#include "sha1.h" +//#include "crc.h" +//#include "bigint.h" +//#include "arm7_sha1_homebrew.h" +//#include "arm7_sha1_nintendo.h" +//#include "encryption.h" +// +///* +// * Data +// */ +//unsigned char publicKeyNintendo[] = +//{ +// 0x9E, 0xC1, 0xCC, 0xC0, 0x4A, 0x6B, 0xD0, 0xA0, 0x6D, 0x62, 0xED, 0x5F, 0x15, 0x67, 0x87, 0x12, +// 0xE6, 0xF4, 0x77, 0x1F, 0xD8, 0x5C, 0x81, 0xCE, 0x0C, 0xD0, 0x22, 0x31, 0xF5, 0x89, 0x08, 0xF5, +// 0xBE, 0x04, 0xCB, 0xC1, 0x4F, 0x63, 0xD9, 0x5A, 0x98, 0xFF, 0xEB, 0x36, 0x0F, 0x9C, 0x5D, 0xAD, +// 0x15, 0xB9, 0x99, 0xFB, 0xC6, 0x86, 0x2C, 0x0A, 0x0C, 0xFC, 0xE6, 0x86, 0x03, 0x60, 0xD4, 0x87, +// 0x28, 0xD5, 0x66, 0x42, 0x9C, 0xF7, 0x04, 0x14, 0x4E, 0x6F, 0x73, 0x20, 0xC3, 0x3E, 0x3F, 0xF5, +// 0x82, 0x2E, 0x78, 0x18, 0xD6, 0xCD, 0xD5, 0xC2, 0xDC, 0xAA, 0x1D, 0x34, 0x91, 0xEC, 0x99, 0xC9, +// 0xF7, 0xBF, 0xBF, 0xA0, 0x0E, 0x1E, 0xF0, 0x25, 0xF8, 0x66, 0x17, 0x54, 0x34, 0x28, 0x2D, 0x28, +// 0xA3, 0xAE, 0xF0, 0xA9, 0xFA, 0x3A, 0x70, 0x56, 0xD2, 0x34, 0xA9, 0xC5, 0x9E, 0x5D, 0xF5, 0xE1, +//}; +// +///* +// * CalcHeaderCRC +// */ +//unsigned short CalcHeaderCRC(Header &header) +//{ +// return CalcCrc16((unsigned char *)&header, 0x15E); +//} +// +///* +// * CalcLogoCRC +// */ +//unsigned short CalcLogoCRC(Header &header) +//{ +// return CalcCrc16((unsigned char *)&header + 0xC0, 156); +//} +// +/* + * DetectRomType + */ +int DetectRomType(const Header& header, char* romdata) +{ + unsigned int * data = (unsigned int*)(romdata + 0x4000); + + //this is attempting to check for an utterly invalid nds header + if(header.unitcode < 0 && header.unitcode > 3) return ROMTYPE_INVALID; + + if (header.arm9_rom_offset < 0x4000) return ROMTYPE_HOMEBREW; + if (data[0] == 0x00000000 && data[1] == 0x00000000) return ROMTYPE_MULTIBOOT; + if (data[0] == 0xE7FFDEFF && data[1] == 0xE7FFDEFF) return ROMTYPE_NDSDUMPED; + for (int i=0x200; i<0x4000; i++) + if (romdata[i]) return ROMTYPE_MASKROM; // found something odd ;) + return ROMTYPE_ENCRSECURE; +} + +///* +// * CalcSecureAreaCRC +// */ +//unsigned short CalcSecureAreaCRC(bool encrypt) +//{ +// fseek(fNDS, 0x4000, SEEK_SET); +// unsigned char data[0x4000]; +// fread(data, 1, 0x4000, fNDS); +// if (encrypt) encrypt_arm9(*(u32 *)header.gamecode, data); +// return CalcCrc16(data, 0x4000); +//} +// +///* +// * CalcSecurityDataCRC +// */ +//unsigned short CalcSecurityDataCRC() +//{ +// fseek(fNDS, 0x1000, SEEK_SET); +// unsigned char data[0x2000]; +// fread(data, 1, 0x2000, fNDS); +// return CalcCrc16(data, 0x2000); +//} +// +///* +// * CalcSegment3CRC +// */ +//unsigned short CalcSegment3CRC() +//{ +// fseek(fNDS, 0x3000, SEEK_SET); +// unsigned char data[0x1000]; +// fread(data, 1, 0x1000, fNDS); +// for (int i=0; i<0x1000; i+=2) // swap bytes +// { +// unsigned char t = data[i+1]; data[i+1] = data[i]; data[i] = t; +// } +// return CalcCcitt16(data, 0x1000); // why would they use CRC16-CCITT ? +//} +// +///* +// * FixHeaderCRC +// */ +//void FixHeaderCRC(char *ndsfilename) +//{ +// fNDS = fopen(ndsfilename, "r+b"); +// if (!fNDS) { fprintf(stderr, "Cannot open file '%s'.\n", ndsfilename); exit(1); } +// fread(&header, 512, 1, fNDS); +// header.header_crc = CalcHeaderCRC(header); +// fseek(fNDS, 0, SEEK_SET); +// fwrite(&header, 512, 1, fNDS); +// fclose(fNDS); +//} +// +///* +// * ShowHeaderInfo +// */ +//void ShowHeaderInfo(Header &header, int romType, unsigned int length = 0x200) +//{ +// printf("0x00\t%-25s\t", "Game title"); +// +// for (unsigned int i=0; i<sizeof(header.title); i++) +// if (header.title[i]) putchar(header.title[i]); printf("\n"); +// +// printf("0x0C\t%-25s\t", "Game code"); +// for (unsigned int i=0; i<sizeof(header.gamecode); i++) +// if (header.gamecode[i]) putchar(header.gamecode[i]); +// for (int i=0; i<NumCountries; i++) +// { +// if (countries[i].countrycode == header.gamecode[3]) +// { +// printf(" (NTR-"); +// for (unsigned int j=0; j<sizeof(header.gamecode); j++) +// if (header.gamecode[j]) putchar(header.gamecode[j]); +// printf("-%s)", countries[i].name); +// break; +// } +// } +// printf("\n"); +// +// printf("0x10\t%-25s\t", "Maker code"); for (unsigned int i=0; i<sizeof(header.makercode); i++) +// if (header.makercode[i]) putchar(header.makercode[i]); +// for (int j=0; j<NumMakers; j++) +// { +// if ((makers[j].makercode[0] == header.makercode[0]) && (makers[j].makercode[1] == header.makercode[1])) +// { +// printf(" (%s)", makers[j].name); +// break; +// } +// } +// printf("\n"); +// +// printf("0x12\t%-25s\t0x%02X\n", "Unit code", header.unitcode); +// printf("0x13\t%-25s\t0x%02X\n", "Device type", header.devicetype); +// printf("0x14\t%-25s\t0x%02X (%d Mbit)\n", "Device capacity", header.devicecap, 1<<header.devicecap); +// printf("0x15\t%-25s\t", "reserved 1"); for (unsigned int i=0; i<sizeof(header.reserved1); i++) printf("%02X", header.reserved1[i]); printf("\n"); +// printf("0x1E\t%-25s\t0x%02X\n", "ROM version", header.romversion); +// printf("0x1F\t%-25s\t0x%02X\n", "reserved 2", header.reserved2); +// printf("0x20\t%-25s\t0x%X\n", "ARM9 ROM offset", (int)header.arm9_rom_offset); +// printf("0x24\t%-25s\t0x%X\n", "ARM9 entry address", (int)header.arm9_entry_address); +// printf("0x28\t%-25s\t0x%X\n", "ARM9 RAM address", (int)header.arm9_ram_address); +// printf("0x2C\t%-25s\t0x%X\n", "ARM9 code size", (int)header.arm9_size); +// printf("0x30\t%-25s\t0x%X\n", "ARM7 ROM offset", (int)header.arm7_rom_offset); +// printf("0x34\t%-25s\t0x%X\n", "ARM7 entry address", (int)header.arm7_entry_address); +// printf("0x38\t%-25s\t0x%X\n", "ARM7 RAM address", (int)header.arm7_ram_address); +// printf("0x3C\t%-25s\t0x%X\n", "ARM7 code size", (int)header.arm7_size); +// printf("0x40\t%-25s\t0x%X\n", "File name table offset", (int)header.fnt_offset); +// printf("0x44\t%-25s\t0x%X\n", "File name table size", (int)header.fnt_size); +// printf("0x48\t%-25s\t0x%X\n", "FAT offset", (int)header.fat_offset); +// printf("0x4C\t%-25s\t0x%X\n", "FAT size", (int)header.fat_size); +// printf("0x50\t%-25s\t0x%X\n", "ARM9 overlay offset", (int)header.arm9_overlay_offset); +// printf("0x54\t%-25s\t0x%X\n", "ARM9 overlay size", (int)header.arm9_overlay_size); +// printf("0x58\t%-25s\t0x%X\n", "ARM7 overlay offset", (int)header.arm7_overlay_offset); +// printf("0x5C\t%-25s\t0x%X\n", "ARM7 overlay size", (int)header.arm7_overlay_size); +// printf("0x60\t%-25s\t0x%08X\n", "ROM control info 1", (int)header.rom_control_info1); +// printf("0x64\t%-25s\t0x%08X\n", "ROM control info 2", (int)header.rom_control_info2); +// printf("0x68\t%-25s\t0x%X\n", "Icon/title offset", (int)header.banner_offset); +// unsigned short secure_area_crc = CalcSecureAreaCRC((romType == ROMTYPE_NDSDUMPED)); +// const char *s1, *s2 = ""; +// if (romType == ROMTYPE_HOMEBREW) s1 = "-"; +// else if (secure_area_crc == header.secure_area_crc) s1 = "OK"; +// else +// { +// s1 = "INVALID"; +// } +// switch (romType) +// { +// case ROMTYPE_HOMEBREW: s2 = "homebrew"; break; +// case ROMTYPE_MULTIBOOT: s2 = "multiboot"; break; +// case ROMTYPE_NDSDUMPED: s2 = "decrypted"; break; +// case ROMTYPE_ENCRSECURE: s2 = "encrypted"; break; +// case ROMTYPE_MASKROM: s2 = "mask ROM"; break; +// } +// printf("0x6C\t%-25s\t0x%04X (%s, %s)\n", "Secure area CRC", (int)header.secure_area_crc, s1, s2); +// printf("0x6E\t%-25s\t0x%04X\n", "ROM control info 3", (int)header.rom_control_info3); +// printf("0x70\t%-25s\t0x%X\n", "ARM9 ?", (int)header.offset_0x70); +// printf("0x74\t%-25s\t0x%X\n", "ARM7 ?", (int)header.offset_0x74); +// printf("0x78\t%-25s\t0x%08X\n", "Magic 1", (int)header.offset_0x78); +// printf("0x7C\t%-25s\t0x%08X\n", "Magic 2", (int)header.offset_0x7C); +// printf("0x80\t%-25s\t0x%08X\n", "Application end offset", (int)header.application_end_offset); +// printf("0x84\t%-25s\t0x%08X\n", "ROM header size", (int)header.rom_header_size); +// for (unsigned int i=0x88; i<0xC0; i+=4) +// { +// unsigned_int &x = ((unsigned_int *)&header)[i/4]; +// if (x != 0) printf("0x%02X\t%-25s\t0x%08X\n", i, "?", (int)x); +// } +// unsigned short logo_crc = CalcLogoCRC(header); +// printf("0x15C\t%-25s\t0x%04X (%s)\n", "Logo CRC", (int)header.logo_crc, (logo_crc == header.logo_crc) ? "OK" : "INVALID"); +// unsigned short header_crc = CalcHeaderCRC(header); +// printf("0x15E\t%-25s\t0x%04X (%s)\n", "Header CRC", (int)header.header_crc, (header_crc == header.header_crc) ? "OK" : "INVALID"); +// for (unsigned int i=0x160; i<length; i+=4) +// { +// unsigned_int &x = ((unsigned_int *)&header)[i/4]; +// if (x != 0) printf("0x%02X\t%-25s\t0x%08X\n", i, "?", (int)x); +// } +//} +// +///* +// * HeaderSha1 +// */ +//void HeaderSha1(FILE *fNDS, unsigned char *header_sha1, int romType) +//{ +// sha1_ctx m_sha1; +// sha1_begin(&m_sha1); +// unsigned char buf[32 + 0x200]; +// fseek(fNDS, 0x200, SEEK_SET); // check for 32 bytes text + alternate header +// fread(buf, 1, sizeof(buf), fNDS); +// if (!memcmp(buf, "DS DOWNLOAD PLAY", 16)) // found? +// { +// sha1_hash(buf + 0x20, 0x160, &m_sha1); // alternate header +// if (verbose >= 2) +// { +// printf("{ DS Download Play(TM) / Wireless MultiBoot header information:\n"); +// ShowHeaderInfo(*(Header *)(buf + 0x20), romType, 0x160); +// printf("}\n"); +// } +// } +// else +// { +// fseek(fNDS, 0, SEEK_SET); +// fread(buf, 1, sizeof(buf), fNDS); +// sha1_hash(buf, 0x160, &m_sha1); +// } +// sha1_end(header_sha1, &m_sha1); +//} +// +///* +// * Arm9Sha1Multiboot +// */ +//void Arm9Sha1Multiboot(FILE *fNDS, unsigned char *arm9_sha1) +//{ +// sha1_ctx m_sha1; +// sha1_begin(&m_sha1); +// fseek(fNDS, header.arm9_rom_offset, SEEK_SET); +// unsigned int len = header.arm9_size; +// unsigned char *buf = new unsigned char [len]; +// fread(buf, 1, len, fNDS); +// //printf("%u\n", len); +// sha1_hash(buf, len, &m_sha1); +// delete [] buf; +// sha1_end(arm9_sha1, &m_sha1); +//} +// +///* +// * Arm9Sha1ClearedOutArea +// */ +//void Arm9Sha1ClearedOutArea(FILE *fNDS, unsigned char *arm9_sha1) +//{ +// sha1_ctx m_sha1; +// sha1_begin(&m_sha1); +// fseek(fNDS, header.arm9_rom_offset, SEEK_SET); +// unsigned int len = header.arm9_size; +// unsigned char *buf = new unsigned char [len]; +// +// int len1 = (0x5000 - header.arm9_rom_offset); // e.g. 0x5000 - 0x4000 = 0x1000 +// int len3 = header.arm9_size - (0x7000 - header.arm9_rom_offset); // e.g. 0x10000 - (0x7000 - 0x4000) = 0xD000 +// int len2 = header.arm9_size - len1 - len3; // e.g. 0x10000 - 0x1000 - 0xD000 = 0x2000 +// if (len1 > 0) fread(buf, 1, len1, fNDS); +// if (len2 > 0) { memset(buf + len1, 0, len2); fseek(fNDS, len2, SEEK_CUR); } // gets cleared for security? +// if (len3 > 0) fread(buf + len1 + len2, 1, len3, fNDS); +//// printf("%X %X %X\n", len1, len2, len3); +// +//// memset(buf, 0, 0x800); // clear "secure area" too +// +// sha1_hash(buf, len, &m_sha1); +// delete [] buf; +// sha1_end(arm9_sha1, &m_sha1); +//} +// +///* +// * Arm7Sha1 +// */ +//void Arm7Sha1(FILE *fNDS, unsigned char *arm7_sha1) +//{ +// sha1_ctx m_sha1; +// sha1_begin(&m_sha1); +// fseek(fNDS, header.arm7_rom_offset, SEEK_SET); +// unsigned int len = header.arm7_size; +// unsigned char *buf = new unsigned char [len]; +// fread(buf, 1, len, fNDS); +// //printf("%u\n", len); +// sha1_hash(buf, len, &m_sha1); +// delete [] buf; +// sha1_end(arm7_sha1, &m_sha1); +//} +// +///* +// * CompareSha1WithList +// */ +//int CompareSha1WithList(unsigned char *arm7_sha1, const unsigned char *text, unsigned int textSize) +//{ +// while (1) +// { +// //printf("\n"); +// for (int i=0; i<SHA1_DIGEST_SIZE; i++) +// { +// unsigned char b = 0; +// for (int n=0; n<2; n++) +// { +// //printf("%c", *text); +// if (!*text) return -1; +// b = b << 4 | ((*text > '9') ? ((*text - 'A') & 7) + 10 : *text - '0'); +// text++; +// } +// //printf("%02X", b); +// if (b != arm7_sha1[i]) break; else if (i == 19) return 0; +// } +// while (*text && (*text >= ' ')) text++; // line end +// while (*text && (*text < ' ')) text++; // new line +// } +//} +// +///* +// * HashAndCompareWithList +// * -1=error, 0=match, 1=no match +// */ +//int HashAndCompareWithList(char *filename, unsigned char sha1[]) +//{ +// FILE *f = fopen(filename, "rb"); +// if (!f) return -1; +// sha1_ctx m_sha1; +// sha1_begin(&m_sha1); +// unsigned char buf[1024]; +// unsigned int r; +// do +// { +// r = fread(buf, 1, 1024, f); +// sha1_hash(buf, r, &m_sha1); +// } while (r > 0); +// fclose(f); +// sha1_end(sha1, &m_sha1); +// if (CompareSha1WithList(sha1, arm7_sha1_homebrew, arm7_sha1_homebrew_size)) return 1; // not yet in list +// return 0; +//} +// +///* +// * strsepc +// */ +//char *strsepc(char **s, char d) +//{ +// char *r = *s; +// for (char *p = *s; ; p++) +// { +// if (*p == 0) { *s = p; break; } +// if (*p == d) { *s = p+1; *p = 0; break; } +// } +// return r; +//} +// +///* +// * RomListInfo +// */ +//void RomListInfo(unsigned int crc32_match) +//{ +// if (!romlistfilename) return; +// FILE *fRomList = fopen(romlistfilename, "rt"); +// if (!fRomList) { fprintf(stderr, "Cannot open file '%s'.\n", romlistfilename); exit(1); } +// char s[1024]; +// while (fgets(s, 1024, fRomList)) // empty, title, title, title, title, filename, CRC32 +// { +// char *p = s; +// if (strlen(strsepc(&p, '\xAC')) == 0) +// { +// char *title = strsepc(&p, '\xAC'); +// unsigned int index = strtoul(title, 0, 10); +// title += 7; +// char *b1 = strchr(title, '('); +// char *b2 = b1 ? strchr(b1+1, ')') : 0; +// char *b3 = b2 ? strchr(b2+1, '(') : 0; +// char *b4 = b3 ? strchr(b3+1, ')') : 0; +// char *group = 0; +// if (b1 + 2 == b2) if (b3 && b4) { *b3 = 0; *b4 = 0; group = b3+1; } // remove release group name +// strsepc(&p, '\xAC'); strsepc(&p, '\xAC'); +// strsepc(&p, '\xAC'); strsepc(&p, '\xAC'); +// unsigned long crc32 = strtoul(strsepc(&p, '\xAC'), 0, 16); +// if (crc32 == crc32_match) +// { +// printf("Release index: \t%u\n", index); +// printf("Release title: \t%s\n", title); +// printf("Release group: \t%s\n", group ? group : ""); +// } +// //for (int i=0; i<10; i++) printf("%d %s\n", i, strsepc(&p, '\xAC')); +// } +// } +//} +// +///* +// * ShowVerboseInfo +// */ +//void ShowVerboseInfo(FILE *fNDS, Header &header, int romType) +//{ +// // calculate SHA1 of ARM7 binary +// unsigned char arm7_sha1[SHA1_DIGEST_SIZE]; +// Arm7Sha1(fNDS, arm7_sha1); +// +// // find signature data +// unsigned_int signature_id = 0; +// fseek(fNDS, header.application_end_offset, SEEK_SET); +// fread(&signature_id, sizeof(signature_id), 1, fNDS); +// if (signature_id != 0x00016361) +// { +// fseek(fNDS, header.application_end_offset - 136, SEEK_SET); // try again +// fread(&signature_id, sizeof(signature_id), 1, fNDS); +// } +// if (signature_id == 0x00016361) +// { +// printf("\n"); +// +// unsigned char signature[128]; +// fread(signature, 1, sizeof(signature), fNDS); +// +// unsigned char sha_parts[3*SHA1_DIGEST_SIZE + 4]; +// fread(sha_parts + 3*SHA1_DIGEST_SIZE, 4, 1, fNDS); // some number +// +// //printf("%08X\n", *(unsigned int *)(sha_parts + 3*SHA1_DIGEST_SIZE)); +// +// unsigned char header_sha1[SHA1_DIGEST_SIZE]; +// HeaderSha1(fNDS, header_sha1, romType); +// memcpy(sha_parts + 0*SHA1_DIGEST_SIZE, header_sha1, SHA1_DIGEST_SIZE); +// +// unsigned char arm9_sha1[SHA1_DIGEST_SIZE]; +// if (romType == ROMTYPE_MULTIBOOT) +// { +// Arm9Sha1Multiboot(fNDS, arm9_sha1); +// } +// else +// { +// Arm9Sha1ClearedOutArea(fNDS, arm9_sha1); +// } +// memcpy(sha_parts + 1*SHA1_DIGEST_SIZE, arm9_sha1, SHA1_DIGEST_SIZE); +// +// memcpy(sha_parts + 2*SHA1_DIGEST_SIZE, arm7_sha1, SHA1_DIGEST_SIZE); +// +// unsigned char sha_final[SHA1_DIGEST_SIZE]; +// { +// sha1_ctx m_sha1; +// sha1_begin(&m_sha1); +// unsigned int len = sizeof(sha_parts); +// unsigned char *buf = sha_parts; +// sha1_hash(buf, len, &m_sha1); +// sha1_end(sha_final, &m_sha1); +// } +// +// // calculate SHA1 from signature +// unsigned char sha1_from_sig[SHA1_DIGEST_SIZE]; +// { +// BigInt _signature; +// _signature.Set(signature, sizeof(signature)); +// //printf("signature: "); _signature.print(); +// +// BigInt _publicKey; +// _publicKey.Set(publicKeyNintendo, sizeof(publicKeyNintendo)); +// //printf("public key: "); _publicKey.print(); +// +// BigInt big_sha1; +// big_sha1.PowMod(_signature, _publicKey); +// //printf("big_sha1: "); big_sha1.print(); +// big_sha1.Get(sha1_from_sig, sizeof(sha1_from_sig)); +// } +// +// bool ok = (memcmp(sha_final, sha1_from_sig, SHA1_DIGEST_SIZE) == 0); +// printf("DS Download Play(TM) / Wireless MultiBoot signature: %s\n", ok ? "OK" : "INVALID"); +// if (!ok) +// { +// printf("header hash: \t"); for (int i=0; i<SHA1_DIGEST_SIZE; i++) printf("%02X", (sha_parts + 0*SHA1_DIGEST_SIZE)[i]); printf("\n"); +// printf("ARM9 hash: \t"); for (int i=0; i<SHA1_DIGEST_SIZE; i++) printf("%02X", (sha_parts + 1*SHA1_DIGEST_SIZE)[i]); printf("\n"); +// printf("ARM7 hash: \t"); for (int i=0; i<SHA1_DIGEST_SIZE; i++) printf("%02X", (sha_parts + 2*SHA1_DIGEST_SIZE)[i]); printf("\n"); +// printf("combined hash: \t"); for (int i=0; i<SHA1_DIGEST_SIZE; i++) printf("%02X", sha_final[i]); printf("\n"); +// printf("signature hash: \t"); for (int i=0; i<SHA1_DIGEST_SIZE; i++) printf("%02X", sha1_from_sig[i]); printf("\n"); +// } +// } +// +// // CRC32 +// { +// unsigned char *buf = new unsigned char [0x10000]; +// fseek(fNDS, 0, SEEK_SET); +// unsigned long crc32 = ~0; +// int r; +// while ((r = fread(buf, 1, 0x10000, fNDS)) > 0) +// { +// crc32 = CalcCrc32(buf, r, crc32); +// } +// crc32 = ~crc32; +// delete [] buf; +// +// printf("\nFile CRC32: \t%08X\n", (unsigned int)crc32); +// RomListInfo(crc32); +// } +// +// // ROM dumper 1.0 bad data +// { +// unsigned char buf[0x200]; +// fseek(fNDS, 0x7E00, SEEK_SET); +// fread(buf, 1, 0x200, fNDS); +// unsigned long crc32 = ~CalcCrc32(buf, 0x200); +// printf("\nSMT dumper v1.0 corruption check: \t%s\n", (crc32 == 0x7E8B456F) ? "CORRUPTED" : "OK"); +// } +// +// // Verify ARM7 SHA1 hash against known default binaries +// int bKnownArm7 = 0; +// { +// printf("\nARM7 binary hash : \t"); for (int i=0; i<SHA1_DIGEST_SIZE; i++) printf("%02X", arm7_sha1[i]); printf("\n"); +// +// if (CompareSha1WithList(arm7_sha1, arm7_sha1_homebrew, arm7_sha1_homebrew_size) == 0) +// { +// bKnownArm7 = 1; printf("ARM7 binary is homebrew verified.\n"); +// } +// if (CompareSha1WithList(arm7_sha1, arm7_sha1_nintendo, arm7_sha1_nintendo_size) == 0) +// { +// bKnownArm7 = 2; printf("ARM7 binary is Nintendo verified.\n"); +// } +// if (!bKnownArm7) printf("WARNING! ARM7 binary is NOT verified!\n"); +// } +// +// // check ARM7 RAM address +// if (bKnownArm7 != 2) +// if ((header.arm7_ram_address < 0x03000000) || (header.arm7_ram_address >= 0x04000000)) +// { +// printf("\nWARNING! ARM7 RAM address does not point to shared memory!\n"); +// } +// +// // check ARM7 entry address +// if ((header.arm7_entry_address < header.arm7_ram_address) || +// (header.arm7_entry_address > header.arm7_ram_address + header.arm7_size)) +// { +// printf("\nWARNING! ARM7 entry address points outside of ARM7 binary!\n"); +// } +//} +// +///* +// * ShowInfo +// */ +//void ShowInfo(char *ndsfilename) +//{ +// fNDS = fopen(ndsfilename, "rb"); +// if (!fNDS) { fprintf(stderr, "Cannot open file '%s'.\n", ndsfilename); exit(1); } +// fread(&header, 512, 1, fNDS); +// +// int romType = DetectRomType(); +// +// printf("Header information:\n"); +// ShowHeaderInfo(header, romType); +// +// // banner info +// if (header.banner_offset) +// { +// Banner banner; +// fseek(fNDS, header.banner_offset, SEEK_SET); +// if (fread(&banner, 1, sizeof(banner), fNDS)) +// { +// unsigned short banner_crc = CalcBannerCRC(banner); +// printf("\n"); +// printf("Banner CRC: \t0x%04X (%s)\n", (int)banner.crc, (banner_crc == banner.crc) ? "OK" : "INVALID"); +// +// for (int language=1; language<=1; language++) +// { +// int line = 1; +// bool nextline = true; +// for (int i=0; i<128; i++) +// { +// unsigned short c = banner.title[language][i]; +// if (c >= 128) c = '_'; +// if (c == 0x00) { printf("\n"); break; } +// if (c == 0x0A) +// { +// nextline = true; +// } +// else +// { +// if (nextline) +// { +// if (line != 1) printf("\n"); +// printf("%s banner text, line %d:", bannerLanguages[language], line); +// for (unsigned int i=0; i<11 - strlen(bannerLanguages[language]); i++) putchar(' '); +// printf("\t"); +// nextline = false; +// line++; +// } +// putchar(c); +// } +// } +// } +// } +// } +// +// // ARM9 footer +// fseek(fNDS, header.arm9_rom_offset + header.arm9_size, SEEK_SET); +// unsigned_int nitrocode; +// if (fread(&nitrocode, sizeof(nitrocode), 1, fNDS) && (nitrocode == 0xDEC00621)) +// { +// printf("\n"); +// printf("ARM9 footer found.\n"); +// unsigned_int x; +// fread(&x, sizeof(x), 1, fNDS); +// fread(&x, sizeof(x), 1, fNDS); +// } +// +// // show security CRCs +// if (romType >= ROMTYPE_NDSDUMPED) +// { +// printf("\n"); +// unsigned short securitydata_crc = CalcSecurityDataCRC(); +// printf("Security data CRC (0x1000-0x2FFF) 0x%04X\n", (int)securitydata_crc); +// unsigned short segment3_crc = CalcSegment3CRC(); +// printf("Segment3 CRC (0x3000-0x3FFF) 0x%04X (%s)\n", (int)segment3_crc, (segment3_crc == 0x0254) ? "OK" : "INVALID"); +// } +// +// // more information +// if (verbose >= 1) +// { +// ShowVerboseInfo(fNDS, header, romType); +// } +// +// fclose(fNDS); +//} diff --git a/jni/desmume/src/utils/decrypt/header.h b/jni/desmume/src/utils/decrypt/header.h new file mode 100755 index 0000000..bca8ee5 --- /dev/null +++ b/jni/desmume/src/utils/decrypt/header.h @@ -0,0 +1,134 @@ +//taken from ndstool +//http://devkitpro.svn.sourceforge.net/viewvc/devkitpro/trunk/tools/nds/ndstool/include/header.h?revision=2447 + +/* header.h - this file is part of DeSmuME + * + * Copyright (C) 2005-2006 Rafael Vuijk + * + * This file 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, or (at your option) + * any later version. + * + * This file 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; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _HEADER_H_ +#define _HEADER_H_ + + +#include "../../types.h" + +#include "../../PACKED.h" +struct __PACKED Header +{ + char title[0xC]; + char gamecode[0x4]; + char makercode[2]; + unsigned char unitcode; // product code. 0 = Nintendo DS + unsigned char devicetype; // device code. 0 = normal + unsigned char devicecap; // device size. (1<<n Mbit) + unsigned char reserved1[0x9]; // 0x015..0x01D + unsigned char romversion; + unsigned char reserved2; // 0x01F + u32 arm9_rom_offset; // points to libsyscall and rest of ARM9 binary + u32 arm9_entry_address; + u32 arm9_ram_address; + u32 arm9_size; + u32 arm7_rom_offset; + u32 arm7_entry_address; + u32 arm7_ram_address; + u32 arm7_size; + u32 fnt_offset; + u32 fnt_size; + u32 fat_offset; + u32 fat_size; + u32 arm9_overlay_offset; + u32 arm9_overlay_size; + u32 arm7_overlay_offset; + u32 arm7_overlay_size; + u32 rom_control_info1; // 0x00416657 for OneTimePROM + u32 rom_control_info2; // 0x081808F8 for OneTimePROM + u32 banner_offset; + u16 secure_area_crc; + u16 rom_control_info3; // 0x0D7E for OneTimePROM + u32 offset_0x70; // magic1 (64 bit encrypted magic code to disable LFSR) + u32 offset_0x74; // magic2 + u32 offset_0x78; // unique ID for homebrew + u32 offset_0x7C; // unique ID for homebrew + u32 application_end_offset; // rom size + u32 rom_header_size; + u32 offset_0x88; // reserved... ? + u32 offset_0x8C; + + // reserved + u32 offset_0x90; + u32 offset_0x94; + u32 offset_0x98; + u32 offset_0x9C; + u32 offset_0xA0; + u32 offset_0xA4; + u32 offset_0xA8; + u32 offset_0xAC; + u32 offset_0xB0; + u32 offset_0xB4; + u32 offset_0xB8; + u32 offset_0xBC; + + unsigned char logo[156]; // character data + u16 logo_crc; + u16 header_crc; + + // 0x160..0x17F reserved + u32 offset_0x160; + u32 offset_0x164; + u32 offset_0x168; + u32 offset_0x16C; + unsigned char zero[0x90]; +}; +#include "../../PACKED_END.h" + + + +struct Country +{ + const char countrycode; + const char *name; +}; + +struct Maker +{ + const char *makercode; + const char *name; +}; + +extern Country countries[]; +extern int NumCountries; + +extern Maker makers[]; +extern int NumMakers; + +unsigned short CalcHeaderCRC(Header &header); +unsigned short CalcLogoCRC(Header &header); +void FixHeaderCRC(char *ndsfilename); +void ShowInfo(char *ndsfilename); +int HashAndCompareWithList(char *filename, unsigned char sha1[]); +int DetectRomType(const Header& header, char* romdata); +unsigned short CalcSecureAreaCRC(bool encrypt); + +#define ROMTYPE_HOMEBREW 0 +#define ROMTYPE_MULTIBOOT 1 +#define ROMTYPE_NDSDUMPED 2 // decrypted secure area +#define ROMTYPE_ENCRSECURE 3 +#define ROMTYPE_MASKROM 4 // unknown layout +#define ROMTYPE_INVALID 5 // rejected; can't be a supported rom + +#endif diff --git a/jni/desmume/src/utils/dlditool.cpp b/jni/desmume/src/utils/dlditool.cpp new file mode 100755 index 0000000..fd694a4 --- /dev/null +++ b/jni/desmume/src/utils/dlditool.cpp @@ -0,0 +1,748 @@ +/* + dlditool - Dynamically Linked Disk Interface patch tool + Copyright (C) 2006 Michael Chisholm (Chishm) + + Send all queries to chishm@hotmail.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + * v1.24d - 2010-06-14 - zeromus + * Modified for inclusion in desmume + + * v1.24 - 2007-08-02 - SmileyDude + * Now using EXIT_SUCCESS and EXIT_FAILURE at the suggestion of MachinShin. + * Defined EXIT_NO_DLDI_SECTION for when there is no DLDI section in a file. + * Added cast to strcmp() call to appease the compiler. + + * v1.23 - 2007-01-23 - Chishm + * Fixed bug when DLDI section doesn't exist + * addr_t is now a signed int + + * v1.22 - 2007-01-12 - WinterMute + * add search paths for dldi files + + * v1.21 - 2007-01-12 - Chishm + * Improved error messages + + * v1.20 - 2007-01-11 - Chishm + * Changed offset calculation method + + * v1.10 - 2007-01-07 - Chishm + * Removed assumptions about endianess of computer + * Word size shouldn't matter now either, except that an int type must be at least 32 bits long + * Added *.sc.nds and *.gba.nds file extensions + * Improved command line argument parsing + + * v1.01 - 2006-12-30 - Chishm + * Minor bugfix parsing 3 arguments + + * v1.00 - 2006-12-25 - Chishm + * Original release +*/ +#define VERSION "v1.24" + +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#include <stdlib.h> +#include <stdarg.h> + +#ifndef _MSC_VER +#include <stdint.h> +#include <unistd.h> +#include <sys/param.h> +#else +typedef int int32_t; +#define MAXPATHLEN 1024 +#endif + +#include <sys/stat.h> + +namespace DLDI +{ + +//#ifndef bool +// typedef enum {false = 0, true = !0} bool; +//#endif + +typedef int32_t addr_t; +typedef unsigned char data_t; + +#define FEATURE_MEDIUM_CANREAD 0x00000001 +#define FEATURE_MEDIUM_CANWRITE 0x00000002 +#define FEATURE_SLOT_GBA 0x00000010 +#define FEATURE_SLOT_NDS 0x00000020 + +#define MAGIC_TOKEN 0xBF8DA5ED + +#define FIX_ALL 0x01 +#define FIX_GLUE 0x02 +#define FIX_GOT 0x04 +#define FIX_BSS 0x08 + +#define DLDI_VERSION 1 + +#define EXIT_NO_DLDI_SECTION 2 + +enum DldiOffsets { + DO_magicString = 0x00, // "\xED\xA5\x8D\xBF Chishm" + DO_magicToken = 0x00, // 0xBF8DA5ED + DO_magicShortString = 0x04, // " Chishm" + DO_version = 0x0C, + DO_driverSize = 0x0D, + DO_fixSections = 0x0E, + DO_allocatedSpace = 0x0F, + + DO_friendlyName = 0x10, + + DO_text_start = 0x40, // Data start + DO_data_end = 0x44, // Data end + DO_glue_start = 0x48, // Interworking glue start -- Needs address fixing + DO_glue_end = 0x4C, // Interworking glue end + DO_got_start = 0x50, // GOT start -- Needs address fixing + DO_got_end = 0x54, // GOT end + DO_bss_start = 0x58, // bss start -- Needs setting to zero + DO_bss_end = 0x5C, // bss end + + // IO_INTERFACE data + DO_ioType = 0x60, + DO_features = 0x64, + DO_startup = 0x68, + DO_isInserted = 0x6C, + DO_readSectors = 0x70, + DO_writeSectors = 0x74, + DO_clearStatus = 0x78, + DO_shutdown = 0x7C, + DO_code = 0x80 +}; + +const data_t dldiMagicString[] = "\xED\xA5\x8D\xBF Chishm"; +const char dldiFileExtension[] = ".dldi"; + + +void printUsage (char* programName) { + printf ("Usage:\n"); + printf ("%s <dldi> <app>\n", programName); + printf (" <dldi> the dldi patch file to apply\n"); + printf (" <app> the application binary to apply the patch to\n"); + return; +} + +addr_t readAddr (data_t *mem, addr_t offset) { + return (addr_t)( + (mem[offset + 0] << 0) | + (mem[offset + 1] << 8) | + (mem[offset + 2] << 16) | + (mem[offset + 3] << 24) + ); +} + +void writeAddr (data_t *mem, addr_t offset, addr_t value) { + mem[offset + 0] = (data_t)(value >> 0); + mem[offset + 1] = (data_t)(value >> 8); + mem[offset + 2] = (data_t)(value >> 16); + mem[offset + 3] = (data_t)(value >> 24); +} + +int stringCaseInsensitiveCompare (const char *str1, const char *str2) { + while (tolower(*str1) == tolower(*str2)) { + if (*str1 == '\0') { + return 0; + } + str1++; + str2++; + } + return (tolower(*str1) - tolower(*str2)); +} + +bool stringEndsWith (const char *str, const char *end) { + const char* strEnd; + if (strlen (str) < strlen(end)) { + return false; + } + strEnd = &str[strlen (str) - strlen(end)]; + return (stringCaseInsensitiveCompare (strEnd, end) == 0); +} + +bool stringStartsWith (const char *str, const char *start) { + return (strstr (str, start) == str); +} + +addr_t quickFind (const data_t* data, const data_t* search, size_t dataLen, size_t searchLen) { + const int32_t* dataChunk = (const int32_t*) data; + int searchChunk = ((const int32_t*)search)[0]; + addr_t i; + addr_t dataChunkEnd = (addr_t)(dataLen / sizeof(int32_t)); + + for ( i = 0; i < dataChunkEnd; i++) { + if (dataChunk[i] == searchChunk) { + if ((i*sizeof(int32_t) + searchLen) > dataLen) { + return -1; + } + if (memcmp (&data[i*sizeof(int32_t)], search, searchLen) == 0) { + return i*sizeof(int32_t); + } + } + } + + return -1; +} + +FILE *openDLDIFile(const char *argv0, char *dldiFileName ) { + + + FILE *dldiFile; + char *dldiPATH; + char appPath[MAXPATHLEN]; + char appName[MAXPATHLEN]; + char appPathName[MAXPATHLEN]; + + char *ptr, *lastSlash; + struct stat buf; + + // add .dldi extension to filename + if (!stringEndsWith (dldiFileName, dldiFileExtension)) { + strcat (dldiFileName, dldiFileExtension); + } + + printf ("Trying \"%s\"\n", dldiFileName); + // try opening from current directory + dldiFile = fopen(dldiFileName,"rb"); + + if ( NULL != dldiFile ) return dldiFile; + + // check if the filename has a path component + // check both slash varieties, win32 understands both + // if we have a directory separator don't bother with search paths + if ( NULL != strstr(dldiFileName,"\\") ) return NULL; + if ( NULL != strstr(dldiFileName,"/") ) return NULL; + + // check for DLDIPATH in environment + dldiPATH = getenv("DLDIPATH"); + + + if ( NULL != dldiPATH ) { + strcpy(appPath,dldiPATH); + if ( appPath[strlen(appPath)] != '\\' && appPath[strlen(appPath)] != '/' ) + strcat(appPath,"/"); + strcat ( appPath, dldiFileName ); + + printf ("Trying \"%s\"\n", appPath); + dldiFile = fopen(appPath,"rb"); + + if ( NULL != dldiFile ) return dldiFile; + + } + + + lastSlash = NULL; + ptr = (char *)argv0; + + while ( *(ptr++) != 0 ) { + if ( *ptr == '\\' || * ptr == '/' ) + lastSlash = ptr; + } + + if ( NULL != lastSlash ) { + *(lastSlash++) = '\0'; + strcpy(appPath, argv0); + strcpy(appName, lastSlash); + strcat(appPath, "/"); + } else { + strcpy(appPath, ""); + strcpy(appName, argv0); + } + + + // finally try in the application path + // if argv0 contains a directory separator we have a path component + + if ( NULL == strstr(appPath,"\\") && NULL == strstr(appPath,"/") ) { + + // no path in argv0 so search system path + char *sysPATH = getenv("PATH"); + char *nextPATH; + char *thisPATH = sysPATH; + printf("Searching system path\n%s\n",sysPATH); + + while(1) { + nextPATH = strstr(thisPATH, ":" ); // find next PATH separator + + if ( NULL != nextPATH ) + *(nextPATH++) = '\0'; // terminate string, point to next component + + strcpy(appPath,thisPATH); + strcat(appPath,"/"); + strcpy(appPathName,appPath); + strcat(appPathName,appName); // add application name + + if ( stat(appPathName,&buf) == 0 ) // if it exists we found the path + break; + + thisPATH = nextPATH; + strcpy(appPath,""); // empty path + if ( thisPATH == NULL) break; + } + } + + strcat(appPath,"dldi/"); // add dldi folder + strcat(appPath,dldiFileName); // add dldi filename to path + printf ("Trying \"%s\"\n", appPath); + + return fopen(appPath,"rb"); // no more places to check, just return this handle +} + +//int main(int argc, char* argv[]) +//{ +// +// char *dldiFileName = NULL; +// char *appFileName = NULL; +// +// addr_t memOffset; // Offset of DLDI after the file is loaded into memory +// addr_t patchOffset; // Position of patch destination in the file +// addr_t relocationOffset; // Value added to all offsets within the patch to fix it properly +// addr_t ddmemOffset; // Original offset used in the DLDI file +// addr_t ddmemStart; // Start of range that offsets can be in the DLDI file +// addr_t ddmemEnd; // End of range that offsets can be in the DLDI file +// addr_t ddmemSize; // Size of range that offsets can be in the DLDI file +// +// addr_t addrIter; +// +// FILE* dldiFile; +// FILE* appFile; +// +// data_t *pDH; +// data_t *pAH; +// +// data_t *appFileData = NULL; +// size_t appFileSize = 0; +// data_t *dldiFileData = NULL; +// size_t dldiFileSize = 0; +// +// int i; +// +// printf ("Dynamically Linked Disk Interface patch tool " VERSION " by Michael Chisholm (Chishm)\n\n"); +// +// for (i = 1; i < argc; i++) { +// if (dldiFileName == NULL) { +// dldiFileName = (char*) malloc (strlen (argv[i]) + 1 + sizeof(dldiFileExtension)); +// if (!dldiFileName) { +// return EXIT_FAILURE; +// } +// strcpy (dldiFileName, argv[i]); +// } else if (appFileName == NULL) { +// appFileName = (char*) malloc (strlen (argv[i]) + 1); +// if (!appFileName) { +// return EXIT_FAILURE; +// } +// strcpy (appFileName, argv[i]); +// } else { +// printUsage (argv[0]); +// return EXIT_FAILURE; +// } +// } +// +// if ((dldiFileName == NULL) || (appFileName == NULL)) { +// printUsage (argv[0]); +// return EXIT_FAILURE; +// } +// +// if (!(dldiFile = openDLDIFile(argv[0],dldiFileName))) { +// printf ("Cannot open \"%s\" - %s\n", dldiFileName, strerror(errno)); +// return EXIT_FAILURE; +// } +// +// if (!(appFile = fopen (appFileName, "rb+"))) { +// printf ("Cannot open \"%s\" - %s\n", appFileName, strerror(errno)); +// return EXIT_FAILURE; +// } +// +// // Load the app file and the DLDI patch file +// fseek (appFile, 0, SEEK_END); +// appFileSize = ftell(appFile); +// appFileData = (data_t*) malloc (appFileSize); +// fseek (appFile, 0, SEEK_SET); +// +// fseek (dldiFile, 0, SEEK_END); +// dldiFileSize = ftell(dldiFile); +// dldiFileData = (data_t*) malloc (dldiFileSize); +// fseek (dldiFile, 0, SEEK_SET); +// +// if (!appFileData || !dldiFileData) { +// fclose (appFile); +// fclose (dldiFile); +// if (appFileData) free (appFileData); +// if (dldiFileData) free (dldiFileData); +// printf ("Out of memory\n"); +// return EXIT_FAILURE; +// } +// +// fread (appFileData, 1, appFileSize, appFile); +// fread (dldiFileData, 1, dldiFileSize, dldiFile); +// fclose (dldiFile); +// +// // Find the DSDI reserved space in the file +// patchOffset = quickFind (appFileData, dldiMagicString, appFileSize, sizeof(dldiMagicString)/sizeof(char)); +// +// if (patchOffset < 0) { +// printf ("%s does not have a DLDI section\n", appFileName); +// return EXIT_NO_DLDI_SECTION; +// } +// +// pDH = dldiFileData; +// pAH = &appFileData[patchOffset]; +// +// // Make sure the DLDI file is valid and usable +// if (strcmp ((char*)dldiMagicString, (char*)&pDH[DO_magicString]) != 0) { +// printf ("Invalid DLDI file\n"); +// return EXIT_FAILURE; +// } +// if (pDH[DO_version] != DLDI_VERSION) { +// printf ("Incorrect DLDI file version. Expected %d, found %d.\n", DLDI_VERSION, pDH[DO_version]); +// return EXIT_FAILURE; +// } +// if (pDH[DO_driverSize] > pAH[DO_allocatedSpace]) { +// printf ("Not enough space for patch. Available %d bytes, need %d bytes\n", ( 1 << pAH[DO_allocatedSpace]), ( 1 << pDH[DO_driverSize]) ); +// return EXIT_FAILURE; +// } +// +// memOffset = readAddr (pAH, DO_text_start); +// if (memOffset == 0) { +// memOffset = readAddr (pAH, DO_startup) - DO_code; +// } +// ddmemOffset = readAddr (pDH, DO_text_start); +// relocationOffset = memOffset - ddmemOffset; +// +// printf ("Old driver: %s\n", &pAH[DO_friendlyName]); +// printf ("New driver: %s\n", &pDH[DO_friendlyName]); +// printf ("\n"); +// printf ("Position in file: 0x%08X\n", patchOffset); +// printf ("Position in memory: 0x%08X\n", memOffset); +// printf ("Patch base address: 0x%08X\n", ddmemOffset); +// printf ("Relocation offset: 0x%08X\n", relocationOffset); +// printf ("\n"); +// +// ddmemStart = readAddr (pDH, DO_text_start); +// ddmemSize = (1 << pDH[DO_driverSize]); +// ddmemEnd = ddmemStart + ddmemSize; +// +// // Remember how much space is actually reserved +// pDH[DO_allocatedSpace] = pAH[DO_allocatedSpace]; +// // Copy the DLDI patch into the application +// memcpy (pAH, pDH, dldiFileSize); +// +// // Fix the section pointers in the header +// writeAddr (pAH, DO_text_start, readAddr (pAH, DO_text_start) + relocationOffset); +// writeAddr (pAH, DO_data_end, readAddr (pAH, DO_data_end) + relocationOffset); +// writeAddr (pAH, DO_glue_start, readAddr (pAH, DO_glue_start) + relocationOffset); +// writeAddr (pAH, DO_glue_end, readAddr (pAH, DO_glue_end) + relocationOffset); +// writeAddr (pAH, DO_got_start, readAddr (pAH, DO_got_start) + relocationOffset); +// writeAddr (pAH, DO_got_end, readAddr (pAH, DO_got_end) + relocationOffset); +// writeAddr (pAH, DO_bss_start, readAddr (pAH, DO_bss_start) + relocationOffset); +// writeAddr (pAH, DO_bss_end, readAddr (pAH, DO_bss_end) + relocationOffset); +// // Fix the function pointers in the header +// writeAddr (pAH, DO_startup, readAddr (pAH, DO_startup) + relocationOffset); +// writeAddr (pAH, DO_isInserted, readAddr (pAH, DO_isInserted) + relocationOffset); +// writeAddr (pAH, DO_readSectors, readAddr (pAH, DO_readSectors) + relocationOffset); +// writeAddr (pAH, DO_writeSectors, readAddr (pAH, DO_writeSectors) + relocationOffset); +// writeAddr (pAH, DO_clearStatus, readAddr (pAH, DO_clearStatus) + relocationOffset); +// writeAddr (pAH, DO_shutdown, readAddr (pAH, DO_shutdown) + relocationOffset); +// +// if (pDH[DO_fixSections] & FIX_ALL) { +// // Search through and fix pointers within the data section of the file +// for (addrIter = (readAddr(pDH, DO_text_start) - ddmemStart); addrIter < (readAddr(pDH, DO_data_end) - ddmemStart); addrIter++) { +// if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { +// writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); +// } +// } +// } +// +// if (pDH[DO_fixSections] & FIX_GLUE) { +// // Search through and fix pointers within the glue section of the file +// for (addrIter = (readAddr(pDH, DO_glue_start) - ddmemStart); addrIter < (readAddr(pDH, DO_glue_end) - ddmemStart); addrIter++) { +// if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { +// writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); +// } +// } +// } +// +// if (pDH[DO_fixSections] & FIX_GOT) { +// // Search through and fix pointers within the Global Offset Table section of the file +// for (addrIter = (readAddr(pDH, DO_got_start) - ddmemStart); addrIter < (readAddr(pDH, DO_got_end) - ddmemStart); addrIter++) { +// if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { +// writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); +// } +// } +// } +// +// if (pDH[DO_fixSections] & FIX_BSS) { +// // Initialise the BSS to 0 +// memset (&pAH[readAddr(pDH, DO_bss_start) - ddmemStart] , 0, readAddr(pDH, DO_bss_end) - readAddr(pDH, DO_bss_start)); +// } +// +// // Write the patch back to the file +// fseek (appFile, patchOffset, SEEK_SET); +// fwrite (pAH, 1, ddmemSize, appFile); +// fclose (appFile); +// +// free (appFileData); +// free (dldiFileData); +// +// printf ("Patched successfully\n"); +// +// return EXIT_SUCCESS; +//} + +// Source File: mpcf.dldi +// Time: 6/14/2010 9:38 PM +// Orig. Offset: 0 / 0x00000000 +// Length: 1876 / 0x00000754 (bytes) +data_t mpcf_dldi[1876] = +{ + 0xED, 0xA5, 0x8D, 0xBF, 0x20, 0x43, 0x68, 0x69, 0x73, 0x68, 0x6D, 0x00, 0x01, 0x0B, 0x0C, 0x00, + 0x47, 0x42, 0x41, 0x20, 0x4D, 0x6F, 0x76, 0x69, 0x65, 0x20, 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72, + 0x20, 0x28, 0x43, 0x6F, 0x6D, 0x70, 0x61, 0x63, 0x74, 0x20, 0x46, 0x6C, 0x61, 0x73, 0x68, 0x29, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xBF, 0x54, 0x07, 0x80, 0xBF, 0x98, 0x00, 0x80, 0xBF, 0x98, 0x00, 0x80, 0xBF, + 0x50, 0x07, 0x80, 0xBF, 0x50, 0x07, 0x80, 0xBF, 0x54, 0x07, 0x80, 0xBF, 0x70, 0x07, 0x80, 0xBF, + 0x4D, 0x50, 0x43, 0x46, 0x13, 0x00, 0x00, 0x00, 0x3C, 0x01, 0x80, 0xBF, 0x98, 0x01, 0x80, 0xBF, + 0x78, 0x02, 0x80, 0xBF, 0xC8, 0x04, 0x80, 0xBF, 0xC8, 0x01, 0x80, 0xBF, 0x10, 0x07, 0x80, 0xBF, + 0x0D, 0xC0, 0xA0, 0xE1, 0xF8, 0xDF, 0x2D, 0xE9, 0x04, 0xB0, 0x4C, 0xE2, 0x28, 0xD0, 0x4B, 0xE2, + 0xF0, 0x6F, 0x9D, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0x10, 0x40, 0x2D, 0xE9, 0x2C, 0x40, 0x9F, 0xE5, + 0x00, 0x30, 0xD4, 0xE5, 0x00, 0x00, 0x53, 0xE3, 0x24, 0x20, 0x9F, 0xE5, 0x05, 0x00, 0x00, 0x1A, + 0x00, 0x00, 0x52, 0xE3, 0x1C, 0x00, 0x9F, 0xE5, 0x0F, 0xE0, 0xA0, 0x11, 0x12, 0xFF, 0x2F, 0x11, + 0x01, 0x30, 0xA0, 0xE3, 0x00, 0x30, 0xC4, 0xE5, 0x10, 0x40, 0xBD, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, + 0x54, 0x07, 0x80, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x48, 0x07, 0x80, 0xBF, 0x04, 0xE0, 0x2D, 0xE5, + 0x40, 0x30, 0x9F, 0xE5, 0x00, 0x00, 0x53, 0xE3, 0x04, 0xD0, 0x4D, 0xE2, 0x38, 0x00, 0x9F, 0xE5, + 0x38, 0x10, 0x9F, 0xE5, 0x0F, 0xE0, 0xA0, 0x11, 0x13, 0xFF, 0x2F, 0x11, 0x30, 0x00, 0x9F, 0xE5, + 0x00, 0x30, 0x90, 0xE5, 0x00, 0x00, 0x53, 0xE3, 0x28, 0x30, 0x9F, 0xE5, 0x02, 0x00, 0x00, 0x0A, + 0x00, 0x00, 0x53, 0xE3, 0x0F, 0xE0, 0xA0, 0x11, 0x13, 0xFF, 0x2F, 0x11, 0x04, 0xD0, 0x8D, 0xE2, + 0x04, 0xE0, 0x9D, 0xE4, 0x1E, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x48, 0x07, 0x80, 0xBF, + 0x58, 0x07, 0x80, 0xBF, 0x4C, 0x07, 0x80, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x09, 0x14, 0xA0, 0xE3, + 0x06, 0x18, 0x81, 0xE2, 0xB0, 0x30, 0xD1, 0xE1, 0x03, 0x30, 0xE0, 0xE1, 0x03, 0x38, 0xA0, 0xE1, + 0x23, 0x38, 0xA0, 0xE1, 0xFF, 0x30, 0x03, 0xE2, 0xB0, 0x30, 0xC1, 0xE1, 0xB0, 0x20, 0xD1, 0xE1, + 0x04, 0xE0, 0x2D, 0xE5, 0xAA, 0xCC, 0xA0, 0xE3, 0x55, 0xEC, 0xE0, 0xE3, 0x03, 0x00, 0x52, 0xE1, + 0xAA, 0xE0, 0x4E, 0xE2, 0x55, 0xC0, 0x8C, 0xE2, 0x00, 0x00, 0xA0, 0xE3, 0x03, 0x00, 0x00, 0x1A, + 0xB0, 0xE0, 0xC1, 0xE1, 0xB0, 0x30, 0xD1, 0xE1, 0x0C, 0x00, 0x53, 0xE0, 0x01, 0x00, 0xA0, 0x13, + 0x04, 0xE0, 0x9D, 0xE4, 0x1E, 0xFF, 0x2F, 0xE1, 0x26, 0x35, 0xA0, 0xE3, 0x03, 0x37, 0x83, 0xE2, + 0x50, 0x20, 0xA0, 0xE3, 0xB0, 0x20, 0xC3, 0xE1, 0xB0, 0x00, 0xD3, 0xE1, 0x00, 0x08, 0xA0, 0xE1, + 0x20, 0x08, 0xA0, 0xE1, 0xFF, 0x00, 0x00, 0xE2, 0x50, 0x00, 0x50, 0xE3, 0x00, 0x00, 0xA0, 0x13, + 0x01, 0x00, 0xA0, 0x03, 0x1E, 0xFF, 0x2F, 0xE1, 0x09, 0x34, 0xA0, 0xE3, 0x0E, 0x38, 0x83, 0xE2, + 0xB0, 0x20, 0xD3, 0xE1, 0x80, 0x00, 0x12, 0xE3, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0xA0, 0xE3, + 0x01, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x50, 0xE1, 0x08, 0x00, 0x00, 0x0A, 0x09, 0x34, 0xA0, 0xE3, + 0x0E, 0x38, 0x83, 0xE2, 0xB0, 0x20, 0xD3, 0xE1, 0x26, 0x17, 0xA0, 0xE3, 0x96, 0x1C, 0x81, 0xE2, + 0x80, 0x00, 0x12, 0xE3, 0x01, 0x00, 0x80, 0xE2, 0x80, 0x10, 0x81, 0xE2, 0xF4, 0xFF, 0xFF, 0x1A, + 0x26, 0x15, 0xA0, 0xE3, 0x03, 0x17, 0x81, 0xE2, 0xB0, 0x30, 0xD1, 0xE1, 0x50, 0x30, 0x13, 0xE2, + 0x01, 0x00, 0xA0, 0x13, 0x1E, 0xFF, 0x2F, 0x11, 0x26, 0x27, 0xA0, 0xE3, 0x96, 0x2C, 0x82, 0xE2, + 0x03, 0x00, 0xA0, 0xE1, 0x80, 0x20, 0x82, 0xE2, 0x01, 0x00, 0x00, 0xEA, 0x02, 0x00, 0x50, 0xE1, + 0x0A, 0x00, 0x00, 0x0A, 0xB0, 0x30, 0xD1, 0xE1, 0x50, 0x30, 0x13, 0xE2, 0x01, 0x00, 0x80, 0xE2, + 0xF9, 0xFF, 0xFF, 0x0A, 0x26, 0x37, 0xA0, 0xE3, 0x96, 0x3C, 0x83, 0xE2, 0x7F, 0x30, 0x83, 0xE2, + 0x03, 0x00, 0x50, 0xE1, 0x00, 0x00, 0xA0, 0xC3, 0x01, 0x00, 0xA0, 0xD3, 0x1E, 0xFF, 0x2F, 0xE1, + 0x03, 0x00, 0xA0, 0xE1, 0x1E, 0xFF, 0x2F, 0xE1, 0xF0, 0x4B, 0x2D, 0xE9, 0x09, 0x34, 0xA0, 0xE3, + 0x0E, 0x38, 0x83, 0xE2, 0xB0, 0xC0, 0xD3, 0xE1, 0x80, 0x00, 0x1C, 0xE3, 0x10, 0xD0, 0x4D, 0xE2, + 0x01, 0x90, 0xA0, 0xE1, 0x02, 0xE0, 0xA0, 0xE1, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0xC0, 0xA0, 0xE3, + 0x01, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x5C, 0xE1, 0x08, 0x00, 0x00, 0x0A, 0x09, 0x34, 0xA0, 0xE3, + 0x0E, 0x38, 0x83, 0xE2, 0xB0, 0x20, 0xD3, 0xE1, 0x26, 0x17, 0xA0, 0xE3, 0x96, 0x1C, 0x81, 0xE2, + 0x80, 0x00, 0x12, 0xE3, 0x01, 0xC0, 0x8C, 0xE2, 0x80, 0x10, 0x81, 0xE2, 0xF4, 0xFF, 0xFF, 0x1A, + 0x26, 0xC5, 0xA0, 0xE3, 0x03, 0xC7, 0x8C, 0xE2, 0xB0, 0x30, 0xDC, 0xE1, 0x50, 0x30, 0x13, 0xE2, + 0x26, 0x17, 0xA0, 0x03, 0x96, 0x1C, 0x81, 0x02, 0x03, 0x20, 0xA0, 0x01, 0x80, 0x10, 0x81, 0x02, + 0x02, 0x00, 0x00, 0x0A, 0x0A, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x52, 0xE1, 0x67, 0x00, 0x00, 0x0A, + 0xB0, 0x30, 0xDC, 0xE1, 0x50, 0x00, 0x13, 0xE3, 0x01, 0x20, 0x82, 0xE2, 0xF9, 0xFF, 0xFF, 0x0A, + 0x26, 0x37, 0xA0, 0xE3, 0x96, 0x3C, 0x83, 0xE2, 0x7F, 0x30, 0x83, 0xE2, 0x03, 0x00, 0x52, 0xE1, + 0x5E, 0x00, 0x00, 0xCA, 0xFF, 0x00, 0x59, 0xE3, 0x00, 0x30, 0xA0, 0x83, 0x0C, 0x30, 0x8D, 0x85, + 0x5E, 0x00, 0x00, 0x9A, 0x00, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, 0xFF, 0x30, 0x03, 0xE2, + 0x09, 0x54, 0xA0, 0xE3, 0x04, 0x30, 0x8D, 0xE5, 0x0C, 0x30, 0x9D, 0xE5, 0x20, 0x4C, 0xA0, 0xE1, + 0x0E, 0xB0, 0xA0, 0xE1, 0x05, 0x60, 0xA0, 0xE1, 0x20, 0x74, 0xA0, 0xE1, 0x05, 0x20, 0xA0, 0xE1, + 0x20, 0x18, 0xA0, 0xE1, 0x05, 0xC0, 0xA0, 0xE1, 0x05, 0x00, 0xA0, 0xE1, 0x05, 0xE0, 0xA0, 0xE1, + 0x01, 0x57, 0x85, 0xE2, 0xB0, 0x30, 0xC5, 0xE1, 0x04, 0x30, 0x9D, 0xE5, 0x0F, 0x40, 0x04, 0xE2, + 0x06, 0x68, 0x86, 0xE2, 0xB0, 0x30, 0xC6, 0xE1, 0xFF, 0x70, 0x07, 0xE2, 0x02, 0x27, 0x82, 0xE2, + 0xFF, 0x10, 0x01, 0xE2, 0x0A, 0x08, 0x80, 0xE2, 0xE0, 0x40, 0x84, 0xE3, 0x03, 0xC7, 0x8C, 0xE2, + 0x0E, 0xE8, 0x8E, 0xE2, 0x20, 0x30, 0xA0, 0xE3, 0xB0, 0x70, 0xC2, 0xE1, 0xB0, 0x10, 0xC0, 0xE1, + 0xB0, 0x40, 0xCC, 0xE1, 0xB0, 0x30, 0xCE, 0xE1, 0x0B, 0x80, 0xA0, 0xE1, 0x01, 0x90, 0x59, 0xE2, + 0x3E, 0x00, 0x00, 0x3A, 0x26, 0x25, 0xA0, 0xE3, 0x03, 0x27, 0x82, 0xE2, 0xB0, 0x30, 0xD2, 0xE1, + 0x03, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, 0xFF, 0x30, 0x03, 0xE2, 0x58, 0x00, 0x53, 0xE3, + 0x26, 0x17, 0xA0, 0x13, 0x96, 0x1C, 0x81, 0x12, 0x02, 0x00, 0xA0, 0x11, 0x80, 0x10, 0x81, 0x12, + 0x00, 0x20, 0xA0, 0x13, 0x02, 0x00, 0x00, 0x1A, 0x0D, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x52, 0xE1, + 0x26, 0x00, 0x00, 0x0A, 0xB0, 0x30, 0xD0, 0xE1, 0x03, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, + 0xFF, 0x30, 0x03, 0xE2, 0x58, 0x00, 0x53, 0xE3, 0x01, 0x20, 0x82, 0xE2, 0xF6, 0xFF, 0xFF, 0x1A, + 0x26, 0x37, 0xA0, 0xE3, 0x96, 0x3C, 0x83, 0xE2, 0x7F, 0x30, 0x83, 0xE2, 0x03, 0x00, 0x52, 0xE1, + 0x1A, 0x00, 0x00, 0xCA, 0x01, 0x00, 0x18, 0xE3, 0x0B, 0x10, 0xA0, 0x01, 0xFF, 0x20, 0xA0, 0x03, + 0x09, 0x04, 0xA0, 0x03, 0x0E, 0x00, 0x00, 0x0A, 0x08, 0x10, 0xA0, 0xE1, 0xFF, 0x00, 0xA0, 0xE3, + 0x09, 0xC4, 0xA0, 0xE3, 0xB0, 0x30, 0xDC, 0xE1, 0x03, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, + 0x01, 0x00, 0x40, 0xE2, 0x43, 0x24, 0xA0, 0xE1, 0x01, 0x00, 0x70, 0xE3, 0x01, 0x20, 0xC1, 0xE5, + 0x00, 0x30, 0xC1, 0xE5, 0x02, 0x10, 0x81, 0xE2, 0xF5, 0xFF, 0xFF, 0x1A, 0x02, 0x8C, 0x88, 0xE2, + 0xCD, 0xFF, 0xFF, 0xEA, 0x01, 0x20, 0x42, 0xE2, 0xB0, 0x30, 0xD0, 0xE1, 0x01, 0x00, 0x72, 0xE3, + 0xB2, 0x30, 0xC1, 0xE0, 0xFA, 0xFF, 0xFF, 0x1A, 0x02, 0xBC, 0x8B, 0xE2, 0xC6, 0xFF, 0xFF, 0xEA, + 0x00, 0x00, 0xA0, 0xE3, 0x10, 0xD0, 0x8D, 0xE2, 0xF0, 0x4B, 0xBD, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, + 0x09, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, 0x0C, 0x30, 0x8D, 0xE5, 0x9C, 0xFF, 0xFF, 0xEA, + 0x01, 0x00, 0xA0, 0xE3, 0xF6, 0xFF, 0xFF, 0xEA, 0xF0, 0x4B, 0x2D, 0xE9, 0x09, 0x34, 0xA0, 0xE3, + 0x0E, 0x38, 0x83, 0xE2, 0xB0, 0xC0, 0xD3, 0xE1, 0x80, 0x00, 0x1C, 0xE3, 0x10, 0xD0, 0x4D, 0xE2, + 0x01, 0x90, 0xA0, 0xE1, 0x02, 0xE0, 0xA0, 0xE1, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0xC0, 0xA0, 0xE3, + 0x01, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x5C, 0xE1, 0x08, 0x00, 0x00, 0x0A, 0x09, 0x34, 0xA0, 0xE3, + 0x0E, 0x38, 0x83, 0xE2, 0xB0, 0x20, 0xD3, 0xE1, 0x26, 0x17, 0xA0, 0xE3, 0x96, 0x1C, 0x81, 0xE2, + 0x80, 0x00, 0x12, 0xE3, 0x01, 0xC0, 0x8C, 0xE2, 0x80, 0x10, 0x81, 0xE2, 0xF4, 0xFF, 0xFF, 0x1A, + 0x26, 0xC5, 0xA0, 0xE3, 0x03, 0xC7, 0x8C, 0xE2, 0xB0, 0x30, 0xDC, 0xE1, 0x50, 0x30, 0x13, 0xE2, + 0x26, 0x17, 0xA0, 0x03, 0x96, 0x1C, 0x81, 0x02, 0x03, 0x20, 0xA0, 0x01, 0x80, 0x10, 0x81, 0x02, + 0x02, 0x00, 0x00, 0x0A, 0x0A, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x52, 0xE1, 0x65, 0x00, 0x00, 0x0A, + 0xB0, 0x30, 0xDC, 0xE1, 0x50, 0x00, 0x13, 0xE3, 0x01, 0x20, 0x82, 0xE2, 0xF9, 0xFF, 0xFF, 0x0A, + 0x26, 0x37, 0xA0, 0xE3, 0x96, 0x3C, 0x83, 0xE2, 0x7F, 0x30, 0x83, 0xE2, 0x03, 0x00, 0x52, 0xE1, + 0x5C, 0x00, 0x00, 0xCA, 0xFF, 0x00, 0x59, 0xE3, 0x00, 0x30, 0xA0, 0x83, 0x0C, 0x30, 0x8D, 0x85, + 0x5C, 0x00, 0x00, 0x9A, 0x00, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, 0xFF, 0x30, 0x03, 0xE2, + 0x09, 0x54, 0xA0, 0xE3, 0x04, 0x30, 0x8D, 0xE5, 0x0C, 0x30, 0x9D, 0xE5, 0x20, 0x4C, 0xA0, 0xE1, + 0x0E, 0xB0, 0xA0, 0xE1, 0x05, 0x60, 0xA0, 0xE1, 0x20, 0x74, 0xA0, 0xE1, 0x05, 0x20, 0xA0, 0xE1, + 0x20, 0x18, 0xA0, 0xE1, 0x05, 0xC0, 0xA0, 0xE1, 0x05, 0x00, 0xA0, 0xE1, 0x05, 0xE0, 0xA0, 0xE1, + 0x01, 0x57, 0x85, 0xE2, 0xB0, 0x30, 0xC5, 0xE1, 0x04, 0x30, 0x9D, 0xE5, 0x0F, 0x40, 0x04, 0xE2, + 0x06, 0x68, 0x86, 0xE2, 0xB0, 0x30, 0xC6, 0xE1, 0xFF, 0x70, 0x07, 0xE2, 0x02, 0x27, 0x82, 0xE2, + 0xFF, 0x10, 0x01, 0xE2, 0x0A, 0x08, 0x80, 0xE2, 0xE0, 0x40, 0x84, 0xE3, 0x03, 0xC7, 0x8C, 0xE2, + 0x0E, 0xE8, 0x8E, 0xE2, 0x30, 0x30, 0xA0, 0xE3, 0xB0, 0x70, 0xC2, 0xE1, 0xB0, 0x10, 0xC0, 0xE1, + 0xB0, 0x40, 0xCC, 0xE1, 0xB0, 0x30, 0xCE, 0xE1, 0x0B, 0x80, 0xA0, 0xE1, 0x01, 0x90, 0x59, 0xE2, + 0x3C, 0x00, 0x00, 0x3A, 0x26, 0x25, 0xA0, 0xE3, 0x03, 0x27, 0x82, 0xE2, 0xB0, 0x30, 0xD2, 0xE1, + 0x03, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, 0xFF, 0x30, 0x03, 0xE2, 0x58, 0x00, 0x53, 0xE3, + 0x26, 0x17, 0xA0, 0x13, 0x96, 0x1C, 0x81, 0x12, 0x02, 0x00, 0xA0, 0x11, 0x80, 0x10, 0x81, 0x12, + 0x00, 0x20, 0xA0, 0x13, 0x02, 0x00, 0x00, 0x1A, 0x0D, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x52, 0xE1, + 0x24, 0x00, 0x00, 0x0A, 0xB0, 0x30, 0xD0, 0xE1, 0x03, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, + 0xFF, 0x30, 0x03, 0xE2, 0x58, 0x00, 0x53, 0xE3, 0x01, 0x20, 0x82, 0xE2, 0xF6, 0xFF, 0xFF, 0x1A, + 0x26, 0x37, 0xA0, 0xE3, 0x96, 0x3C, 0x83, 0xE2, 0x7F, 0x30, 0x83, 0xE2, 0x03, 0x00, 0x52, 0xE1, + 0x18, 0x00, 0x00, 0xCA, 0x01, 0x00, 0x18, 0xE3, 0x0B, 0x10, 0xA0, 0x01, 0xFF, 0x20, 0xA0, 0x03, + 0x09, 0x04, 0xA0, 0x03, 0x0C, 0x00, 0x00, 0x0A, 0x08, 0x10, 0xA0, 0xE1, 0xFF, 0x00, 0xA0, 0xE3, + 0x09, 0xC4, 0xA0, 0xE3, 0x00, 0x30, 0xD1, 0xE5, 0x01, 0x20, 0xD1, 0xE5, 0x01, 0x00, 0x40, 0xE2, + 0x02, 0x34, 0x83, 0xE1, 0x01, 0x00, 0x70, 0xE3, 0xB0, 0x30, 0xCC, 0xE1, 0x02, 0x10, 0x81, 0xE2, + 0xF7, 0xFF, 0xFF, 0x1A, 0x02, 0x8C, 0x88, 0xE2, 0xCF, 0xFF, 0xFF, 0xEA, 0x01, 0x20, 0x42, 0xE2, + 0xB2, 0x30, 0xD1, 0xE0, 0x01, 0x00, 0x72, 0xE3, 0xB0, 0x30, 0xC0, 0xE1, 0xFA, 0xFF, 0xFF, 0x1A, + 0x02, 0xBC, 0x8B, 0xE2, 0xC8, 0xFF, 0xFF, 0xEA, 0x00, 0x00, 0xA0, 0xE3, 0x10, 0xD0, 0x8D, 0xE2, + 0xF0, 0x4B, 0xBD, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0x09, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, + 0x0C, 0x30, 0x8D, 0xE5, 0x9E, 0xFF, 0xFF, 0xEA, 0x01, 0x00, 0xA0, 0xE3, 0xF6, 0xFF, 0xFF, 0xEA, + 0x04, 0xE0, 0x2D, 0xE5, 0x04, 0xD0, 0x4D, 0xE2, 0xAA, 0xFE, 0xFF, 0xEB, 0x04, 0xD0, 0x8D, 0xE2, + 0x04, 0xE0, 0x9D, 0xE4, 0x1E, 0xFF, 0x2F, 0xE1, 0x0D, 0xC0, 0xA0, 0xE1, 0xF8, 0xDF, 0x2D, 0xE9, + 0x04, 0xB0, 0x4C, 0xE2, 0x28, 0xD0, 0x4B, 0xE2, 0xF0, 0x6F, 0x9D, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, + 0xDC, 0x00, 0x80, 0xBF, 0x98, 0x00, 0x80, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; //unsigned char mpcf_dldi[1876] + +bool tryPatch(void* data, size_t size) +{ + // Find the DSDI reserved space in the file + addr_t patchOffset = quickFind ((data_t*)data, dldiMagicString, size, sizeof(dldiMagicString)/sizeof(char)); + + //no DLDI section + if (patchOffset < 0) + return false; + + data_t *pDH = mpcf_dldi; + data_t *pAH = (data_t*)data + patchOffset; + + if (pDH[DO_driverSize] > pAH[DO_allocatedSpace]) { + printf ("Not enough space for patch. Available %d bytes, need %d bytes\n", ( 1 << pAH[DO_allocatedSpace]), ( 1 << pDH[DO_driverSize]) ); + return false; + } + + if(memcmp(&pAH[DO_friendlyName],"Default (No interface)",22)) + { + printf("Would have been a candidate for auto-patch DLDI, but there was already a patch installed."); + return false; + } + + //----should be able to patch OK----- + + addr_t memOffset; // Offset of DLDI after the file is loaded into memory + addr_t relocationOffset; // Value added to all offsets within the patch to fix it properly + addr_t ddmemOffset; // Original offset used in the DLDI file + addr_t ddmemStart; // Start of range that offsets can be in the DLDI file + addr_t ddmemEnd; // End of range that offsets can be in the DLDI file + addr_t ddmemSize; // Size of range that offsets can be in the DLDI file + + addr_t addrIter; + + + memOffset = readAddr (pAH, DO_text_start); + if (memOffset == 0) { + memOffset = readAddr (pAH, DO_startup) - DO_code; + } + ddmemOffset = readAddr (pDH, DO_text_start); + relocationOffset = memOffset - ddmemOffset; + + printf ("AUTO-PATCHING DLDI to MPCF! Lucky you!\n\n"); + printf ("Old driver: %s\n", &pAH[DO_friendlyName]); + printf ("New driver: %s\n", &pDH[DO_friendlyName]); + printf ("\n"); + printf ("Position in file: 0x%08X\n", patchOffset); + printf ("Position in memory: 0x%08X\n", memOffset); + printf ("Patch base address: 0x%08X\n", ddmemOffset); + printf ("Relocation offset: 0x%08X\n", relocationOffset); + printf ("\n"); + + ddmemStart = readAddr (pDH, DO_text_start); + ddmemSize = (1 << pDH[DO_driverSize]); + ddmemEnd = ddmemStart + ddmemSize; + + // Remember how much space is actually reserved + pDH[DO_allocatedSpace] = pAH[DO_allocatedSpace]; + // Copy the DLDI patch into the application + memcpy (pAH, pDH, sizeof(mpcf_dldi)); + + // Fix the section pointers in the header + writeAddr (pAH, DO_text_start, readAddr (pAH, DO_text_start) + relocationOffset); + writeAddr (pAH, DO_data_end, readAddr (pAH, DO_data_end) + relocationOffset); + writeAddr (pAH, DO_glue_start, readAddr (pAH, DO_glue_start) + relocationOffset); + writeAddr (pAH, DO_glue_end, readAddr (pAH, DO_glue_end) + relocationOffset); + writeAddr (pAH, DO_got_start, readAddr (pAH, DO_got_start) + relocationOffset); + writeAddr (pAH, DO_got_end, readAddr (pAH, DO_got_end) + relocationOffset); + writeAddr (pAH, DO_bss_start, readAddr (pAH, DO_bss_start) + relocationOffset); + writeAddr (pAH, DO_bss_end, readAddr (pAH, DO_bss_end) + relocationOffset); + // Fix the function pointers in the header + writeAddr (pAH, DO_startup, readAddr (pAH, DO_startup) + relocationOffset); + writeAddr (pAH, DO_isInserted, readAddr (pAH, DO_isInserted) + relocationOffset); + writeAddr (pAH, DO_readSectors, readAddr (pAH, DO_readSectors) + relocationOffset); + writeAddr (pAH, DO_writeSectors, readAddr (pAH, DO_writeSectors) + relocationOffset); + writeAddr (pAH, DO_clearStatus, readAddr (pAH, DO_clearStatus) + relocationOffset); + writeAddr (pAH, DO_shutdown, readAddr (pAH, DO_shutdown) + relocationOffset); + + if (pDH[DO_fixSections] & FIX_ALL) { + // Search through and fix pointers within the data section of the file + for (addrIter = (readAddr(pDH, DO_text_start) - ddmemStart); addrIter < (readAddr(pDH, DO_data_end) - ddmemStart); addrIter++) { + if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { + writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); + } + } + } + + if (pDH[DO_fixSections] & FIX_GLUE) { + // Search through and fix pointers within the glue section of the file + for (addrIter = (readAddr(pDH, DO_glue_start) - ddmemStart); addrIter < (readAddr(pDH, DO_glue_end) - ddmemStart); addrIter++) { + if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { + writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); + } + } + } + + if (pDH[DO_fixSections] & FIX_GOT) { + // Search through and fix pointers within the Global Offset Table section of the file + for (addrIter = (readAddr(pDH, DO_got_start) - ddmemStart); addrIter < (readAddr(pDH, DO_got_end) - ddmemStart); addrIter++) { + if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { + writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); + } + } + } + + if (pDH[DO_fixSections] & FIX_BSS) { + // Initialise the BSS to 0 + memset (&pAH[readAddr(pDH, DO_bss_start) - ddmemStart] , 0, readAddr(pDH, DO_bss_end) - readAddr(pDH, DO_bss_start)); + } + + return true; +} + +} //namespace DLDI diff --git a/jni/desmume/src/utils/emufat.cpp b/jni/desmume/src/utils/emufat.cpp new file mode 100755 index 0000000..cd3d774 --- /dev/null +++ b/jni/desmume/src/utils/emufat.cpp @@ -0,0 +1,1937 @@ +/* + Copyright 2009-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +//based on Arduino SdFat Library ( http://code.google.com/p/sdfatlib/ ) +//Copyright (C) 2009 by William Greiman + +//based on mkdosfs - utility to create FAT/MS-DOS filesystems +//Copyright (C) 1991 Linus Torvalds <torvalds@klaava.helsinki.fi> +//Copyright (C) 1992-1993 Remy Card <card@masi.ibp.fr> +//Copyright (C) 1993-1994 David Hudson <dave@humbug.demon.co.uk> +//Copyright (C) 1998 H. Peter Anvin <hpa@zytor.com> +//Copyright (C) 1998-2005 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> + +#include "emufat.h" +#include <ctype.h> +#include <wchar.h> +#include <wctype.h> +#include <string.h> + + +#define LE16(x) (x) +#define LE32(x) (x) + + +#define MAX_CLUST_12 ((1 << 12) - 16) +#define MAX_CLUST_16 ((1 << 16) - 16) +#define MIN_CLUST_32 65529 +/* M$ says the high 4 bits of a FAT32 FAT entry are reserved and don't belong +* to the cluster number. So the max. cluster# is based on 2^28 */ +#define MAX_CLUST_32 ((1 << 28) - 16) +#define FAT12_THRESHOLD 4085 +#define MSDOS_EXT_SIGN 0x29 /* extended boot sector signature */ +#define MSDOS_FAT12_SIGN "FAT12 " /* FAT12 filesystem signature */ +#define MSDOS_FAT16_SIGN "FAT16 " /* FAT16 filesystem signature */ +#define MSDOS_FAT32_SIGN "FAT32 " /* FAT32 filesystem signature */ +static const int sector_size = 512; +#define BLOCK_SIZE 512 +#define HARD_SECTOR_SIZE 512 +#define SECTORS_PER_BLOCK ( BLOCK_SIZE / HARD_SECTOR_SIZE ) +#define FAT_EOF (0x0ffffff8) +#define BOOT_SIGN 0xAA55 /* Boot sector magic number */ + +struct __PACKED fat32_fsinfo { + u32 reserved1; /* Nothing as far as I can tell */ + u32 signature; /* 0x61417272L */ + u32 free_clusters; /* Free cluster count. -1 if unknown */ + u32 next_cluster; /* Most recently allocated cluster. + * Unused under Linux. */ + u32 reserved2[4]; +}; + +//see mkdosfs for the disassembly +static const u8 mkdosfs_bootcode_fat32[420] = +{ + 0x0E, 0x1F, 0xBE, 0x77, 0x7C, 0xAC, 0x22, 0xC0, 0x74, 0x0B, 0x56, 0xB4, 0x0E, 0xBB, 0x07, 0x00, + 0xCD, 0x10, 0x5E, 0xEB, 0xF0, 0x32, 0xE4, 0xCD, 0x16, 0xCD, 0x19, 0xEB, 0xFE, 0x54, 0x68, 0x69, + 0x73, 0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x20, 0x62, 0x6F, 0x6F, 0x74, 0x61, + 0x62, 0x6C, 0x65, 0x20, 0x64, 0x69, 0x73, 0x6B, 0x2E, 0x20, 0x20, 0x50, 0x6C, 0x65, 0x61, 0x73, + 0x65, 0x20, 0x69, 0x6E, 0x73, 0x65, 0x72, 0x74, 0x20, 0x61, 0x20, 0x62, 0x6F, 0x6F, 0x74, 0x61, + 0x62, 0x6C, 0x65, 0x20, 0x66, 0x6C, 0x6F, 0x70, 0x70, 0x79, 0x20, 0x61, 0x6E, 0x64, 0x0D, 0x0A, + 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x74, 0x6F, + 0x20, 0x74, 0x72, 0x79, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6E, 0x20, 0x2E, 0x2E, 0x2E, 0x20, 0x0D, + 0x0A, 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, 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 +}; + + + +EmuFat::EmuFat(const char* fname, bool readonly) + : m_readonly(readonly) + , m_owns(true) +{ + m_pFile = new EMUFILE_FILE(fname,readonly?"rb":"rb+"); +} + +EmuFat::EmuFat() + : m_readonly(false) + , m_owns(true) +{ + m_pFile = new EMUFILE_MEMORY(); +} + +EmuFat::EmuFat(EMUFILE* fileNotToDelete) + : m_pFile(fileNotToDelete) + , m_owns(false) + , m_readonly(false) +{ +} + +EmuFat::~EmuFat() +{ + cacheFlush(); + if(m_owns) + delete m_pFile; +} + +u8 EmuFat::cacheRawBlock(u32 blockNumber, u8 action) +{ + if (cache_.cacheBlockNumber_ != blockNumber) { + if (!cacheFlush()) return false; + if (!readBlock(blockNumber, cache_.cacheBuffer_.data)) return false; + cache_.cacheBlockNumber_ = blockNumber; + } + cache_.cacheDirty_ |= action; + return true; +} + +u8 EmuFat::cacheZeroBlock(u32 blockNumber) +{ + if (!cacheFlush()) return false; + + // loop take less flash than memset(cacheBuffer_.data, 0, 512); + for (u16 i = 0; i < 512; i++) { + cache_.cacheBuffer_.data[i] = 0; + } + cache_.cacheBlockNumber_ = blockNumber; + cacheSetDirty(); + return true; +} + +void EmuFat::cacheReset() +{ + reconstruct(&cache_); +} + +u8 EmuFat::cacheFlush() { + if (cache_.cacheDirty_) { + if (!writeBlock(cache_.cacheBlockNumber_, cache_.cacheBuffer_.data)) { + return false; + } + // mirror FAT tables + if (cache_.cacheMirrorBlock_) { + if (!writeBlock(cache_.cacheMirrorBlock_, cache_.cacheBuffer_.data)) { + return false; + } + cache_.cacheMirrorBlock_ = 0; + } + cache_.cacheDirty_ = 0; + } + return true; +} + +u8 EmuFat::readBlock(u32 block, u8* dst) +{ + m_pFile->fseek(block*512,SEEK_SET); + m_pFile->fread(dst,512); + if(m_pFile->fail()) + { + m_pFile->unfail(); + return 0; + } + return 1; +} + +u8 EmuFat::writeBlock(u32 blockNumber, const u8* src) +{ + m_pFile->fseek(blockNumber*512,SEEK_SET); + m_pFile->fwrite(src,512); + if(m_pFile->fail()) + { + m_pFile->unfail(); + return 0; + } + return 1; +} + +u8 EmuFat::readData(u32 block, u16 offset, u16 count, u8* dst) +{ + m_pFile->fseek(block*512+offset,SEEK_SET); + m_pFile->fread(dst,count); + if(m_pFile->fail()) + { + m_pFile->unfail(); + return 0; + } + return 1; +} + +void EmuFat::truncate(u32 size) +{ + m_pFile->truncate(size); +} + +//------------------------------------------------------------------------------------- + +inline int cdiv (int a, int b) +{ + return (a + b - 1) / b; +} + +bool calculateClusterSize(TFat32BootSector* bsp, u32 avail_sectors, u32& cluster_count, u32& fat_length, int size_fat_by_user, int &size_fat) +{ + TFat32BootSector &bs = *bsp; + const u32 fatdata = avail_sectors; + int maxclustsize = bsp->sectorsPerCluster; + + u32 fatlength12, fatlength16, fatlength32; + u32 maxclust12, maxclust16, maxclust32; + u32 clust12, clust16, clust32; +do { + printf( "Trying with %d sectors/cluster:\n", bs.sectorsPerCluster ); + + /* The factor 2 below avoids cut-off errors for nr_fats == 1. + * The "nr_fats*3" is for the reserved first two FAT entries */ + clust12 = 2*((u64) fatdata *sector_size + bs.fatCount*3) / + (2*(int) bs.sectorsPerCluster * sector_size + bs.fatCount*3); + fatlength12 = cdiv (((clust12+2) * 3 + 1) >> 1, sector_size); + /* Need to recalculate number of clusters, since the unused parts of the + * FATS and data area together could make up space for an additional, + * not really present cluster. */ + clust12 = (fatdata - bs.fatCount*fatlength12)/bs.sectorsPerCluster; + maxclust12 = (fatlength12 * 2 * sector_size) / 3; + if (maxclust12 > MAX_CLUST_12) + maxclust12 = MAX_CLUST_12; + printf( "FAT12: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n", + clust12, fatlength12, maxclust12, MAX_CLUST_12 ); + if (clust12 > maxclust12-2) { + clust12 = 0; + printf( "FAT12: too much clusters\n" ); + } + + clust16 = ((u64) fatdata *sector_size + bs.fatCount*4) / + ((int) bs.sectorsPerCluster * sector_size + bs.fatCount*2); + fatlength16 = cdiv ((clust16+2) * 2, sector_size); + /* Need to recalculate number of clusters, since the unused parts of the + * FATS and data area together could make up space for an additional, + * not really present cluster. */ + clust16 = (fatdata - bs.fatCount*fatlength16)/bs.sectorsPerCluster; + maxclust16 = (fatlength16 * sector_size) / 2; + if (maxclust16 > MAX_CLUST_16) + maxclust16 = MAX_CLUST_16; + printf( "FAT16: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n", + clust16, fatlength16, maxclust16, MAX_CLUST_16 ); + if (clust16 > maxclust16-2) { + printf( "FAT16: too much clusters\n" ); + clust16 = 0; + } + /* The < 4078 avoids that the filesystem will be misdetected as having a + * 12 bit FAT. */ + if (clust16 < FAT12_THRESHOLD && !(size_fat_by_user && size_fat == 16)) { + printf( clust16 < FAT12_THRESHOLD ? + "FAT16: would be misdetected as FAT12\n" : + "FAT16: too much clusters\n" ); + clust16 = 0; + } + + clust32 = ((u64) fatdata *sector_size + bs.fatCount*8) / + ((int) bs.sectorsPerCluster * sector_size + bs.fatCount*4); + fatlength32 = cdiv ((clust32+2) * 4, sector_size); + /* Need to recalculate number of clusters, since the unused parts of the + * FATS and data area together could make up space for an additional, + * not really present cluster. */ + clust32 = (fatdata - bs.fatCount*fatlength32)/bs.sectorsPerCluster; + maxclust32 = (fatlength32 * sector_size) / 4; + if (maxclust32 > MAX_CLUST_32) + maxclust32 = MAX_CLUST_32; + if (clust32 && clust32 < MIN_CLUST_32 && !(size_fat_by_user && size_fat == 32)) { + clust32 = 0; + printf( "FAT32: not enough clusters (%d)\n", MIN_CLUST_32); + } + printf( "FAT32: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n", + clust32, fatlength32, maxclust32, MAX_CLUST_32 ); + if (clust32 > maxclust32) { + clust32 = 0; + printf( "FAT32: too much clusters\n" ); + } + + if ((clust12 && (size_fat == 0 || size_fat == 12)) || + (clust16 && (size_fat == 0 || size_fat == 16)) || + (clust32 && size_fat == 32)) + break; + + bs.sectorsPerCluster <<= 1; + } while (bs.sectorsPerCluster && bs.sectorsPerCluster <= maxclustsize); + + + /* Use the optimal FAT size if not specified; + * FAT32 is (not yet) choosen automatically */ + if (!size_fat) { + size_fat = (clust16 > clust12) ? 16 : 12; + printf( "Choosing %d bits for FAT\n", size_fat ); + } + + switch (size_fat) { + case 12: + cluster_count = clust12; + fat_length = fatlength12; + bs.sectorsPerFat16 = LE16(fatlength12); + break; + case 16: + if (clust16 < FAT12_THRESHOLD) { + if (size_fat_by_user) { + printf("WARNING: Not enough clusters for a " + "16 bit FAT! The filesystem will be\n" + "misinterpreted as having a 12 bit FAT without " + "mount option \"fat=16\".\n" ); + return false; + } + else { + printf("This filesystem has an unfortunate size. " + "A 12 bit FAT cannot provide\n" + "enough clusters, but a 16 bit FAT takes up a little " + "bit more space so that\n" + "the total number of clusters becomes less than the " + "threshold value for\n" + "distinction between 12 and 16 bit FATs.\n" ); + return false; + } + } + cluster_count = clust16; + fat_length = fatlength16; + bs.sectorsPerFat16 = LE16(fatlength16); + break; + +case 32: + if (clust32 < MIN_CLUST_32) + printf("WARNING: Not enough clusters for a 32 bit FAT!\n"); + cluster_count = clust32; + fat_length = fatlength32; + bs.sectorsPerFat16 = LE16(0); + bs.fat32.sectorsPerFat32 = LE32(fatlength32); + break; + + } + + return true; +} + +static void mark_FAT_cluster (int size_fat, u8* fat, int cluster, unsigned int value) +{ + switch( size_fat ) { +case 12: + value &= 0x0fff; + if (((cluster * 3) & 0x1) == 0) + { + fat[3 * cluster / 2] = (unsigned char) (value & 0x00ff); + fat[(3 * cluster / 2) + 1] = (unsigned char) ((fat[(3 * cluster / 2) + 1] & 0x00f0) + | ((value & 0x0f00) >> 8)); + } + else + { + fat[3 * cluster / 2] = (unsigned char) ((fat[3 * cluster / 2] & 0x000f) | ((value & 0x000f) << 4)); + fat[(3 * cluster / 2) + 1] = (unsigned char) ((value & 0x0ff0) >> 4); + } + break; + +case 16: + value &= 0xffff; + fat[2 * cluster] = (unsigned char) (value & 0x00ff); + fat[(2 * cluster) + 1] = (unsigned char) (value >> 8); + break; + +case 32: + value &= 0xfffffff; + fat[4 * cluster] = (unsigned char) (value & 0x000000ff); + fat[(4 * cluster) + 1] = (unsigned char) ((value & 0x0000ff00) >> 8); + fat[(4 * cluster) + 2] = (unsigned char) ((value & 0x00ff0000) >> 16); + fat[(4 * cluster) + 3] = (unsigned char) ((value & 0xff000000) >> 24); + break; + } +} + +//use 36M as minimum fat32 size (or else mkdosfs complains) +//this function assumes fat32. it could be redone to be intelligent by making another pass through mkdosfs and analyzing it again +//but we onnly targeted fat32 our first time through +bool EmuFatVolume::formatNew(u32 sectors) +{ + u32 volumeStartBlock = 0; + TFat32BootSector bsrec; + memset(&bsrec,0,sizeof(TFat32BootSector)); + TFat32BootSector *bs = &bsrec; + + //perform same analysis (we guess) as mkdosfs + + //"fake values" + bs->sectorsPerTrack = 32; + bs->headCount = 64; + //def_hd_params: + bs->mediaType = 0xF8; + bs->rootDirEntryCount = LE16(512); //Default to 512 entries - N.B. this is overwritten later + static const u32 BLOCK_SIZE_BITS = 9; + const u32 sz_mb = (sectors+(1<<(20-BLOCK_SIZE_BITS))-1) >> (20-BLOCK_SIZE_BITS); + bs->sectorsPerCluster = + sz_mb > 16*1024 ? 32 : + sz_mb > 8*1024 ? 16 : + sz_mb > 260 ? 8 : + 1; + //(fat16 and fat12 would start at 4 sectors per cluster) + + memcpy (bs->oemName, "mkdosfs", 8); + bs->rootDirEntryCount = 0; //Under FAT32, the root dir is in a cluster chain, and this is signalled by bs.dir_entries being 0 + bs->fat32.vi.volume_id = 0; //not generating a volume id.. just use 0 for determinism's sake + memcpy(bs->fat32.vi.volume_label," ",11); + bs->jmpToBootCode[0] = 0xEB; + bs->jmpToBootCode[1] = 0x58; //this value is only for fat32 //Patch in the correct offset to the boot code + bs->jmpToBootCode[2] = 0x90; + + memcpy(bs->fat32.boot_code,mkdosfs_bootcode_fat32,420); + bs->boot_sign[0] = 0x55; + bs->boot_sign[1] = 0xAA; + + bs->reservedSectorCount = LE16(32); + bs->fatCount = 2; + bs->hiddenSectors = LE32(0); + + u32 fatdata = sectors - cdiv (bs->rootDirEntryCount * 32, 512) - bs->reservedSectorCount; + + u32 cluster_count; + u32 fat_length; + int size_fat = 32; + if(!calculateClusterSize(bs, fatdata, cluster_count, fat_length, 1, size_fat)) + return false; + //TODO - this function whacks values we set earlier. gross. either mkdosfs is sloppy or i dont understand it. + //anyway, whack that dup code + switch(size_fat) + { + case 12: memcpy(bs->oldfat.vi.fs_type, MSDOS_FAT12_SIGN, 8); break; + case 16: memcpy(bs->oldfat.vi.fs_type, MSDOS_FAT16_SIGN, 8); break; + case 32: memcpy(bs->fat32.vi.fs_type, MSDOS_FAT32_SIGN, 8); break; + } + + bs->bytesPerSector = 512; + + //set up additional FAT32 fields + bs->fat32.fat32Flags = LE16(0); + bs->fat32.fat32Version = LE16(0); + bs->fat32.fat32RootCluster = LE32(2); + bs->fat32.fat32FSInfo = LE16(1); + u32 backup_boot = (bs->reservedSectorCount>= 7) ? 6 : (bs->reservedSectorCount >= 2) ? bs->reservedSectorCount-1 : 0; + printf( "Using sector %d as backup boot sector (0 = none)\n",backup_boot ); + bs->fat32.fat32BackBootBlock = LE16(backup_boot); + memset(bs->fat32.fat32Reserved,0,sizeof(bs->fat32.fat32Reserved)); + + if(sectors>= 65536) { + bs->totalSectors16 = LE16(0); + bs->totalSectors32 = LE32(sectors); + } else { + bs->totalSectors16 = LE16(sectors); + bs->totalSectors32 = LE32(0); + } + + if (!cluster_count) + { + //if (sectors_per_cluster) /* If yes, die if we'd spec'd sectors per cluster */ + // die ("Too many clusters for file system - try more sectors per cluster"); + //else + printf("Attempting to create a too large file system"); + return false; + } + + u32 start_data_sector = (bs->reservedSectorCount + bs->fatCount * fat_length) * (sector_size/512); + u32 start_data_block = (start_data_sector + SECTORS_PER_BLOCK - 1) / SECTORS_PER_BLOCK; + + if (sectors < start_data_block + 32) /* Arbitrary undersize file system! */ + { + printf("Too few blocks for viable file system"); + return false; + } + + bs->fat32.vi.ext_boot_sign = MSDOS_EXT_SIGN; + + //Make the file allocation tables! + u8* fat = new u8[fat_length * sector_size]; + memset( fat, 0, fat_length * sector_size ); + mark_FAT_cluster (size_fat, fat, 0, 0xffffffff); /* Initial fat entries */ + mark_FAT_cluster (size_fat, fat, 1, 0xffffffff); + fat[0] = bs->mediaType; /* Put media type in first byte! */ + if (size_fat == 32) { + /* Mark cluster 2 as EOF (used for root dir) */ + mark_FAT_cluster (size_fat, fat, 2, FAT_EOF); + } + + u32 size_root_dir = (size_fat == 32) ? bs->sectorsPerCluster*sector_size : + bs->rootDirEntryCount * sizeof (TDirectoryEntry); + //u8* root_dir = new u8[size_root_dir]; + //memset(root_dir, 0, size_root_dir); + u32 size_root_dir_in_sectors = size_root_dir/512; + + + u8* info_sector = NULL; + if (size_fat == 32) { + /* For FAT32, create an info sector */ + fat32_fsinfo *info; + + info_sector = new u8[sector_size]; + memset(info_sector, 0, sector_size); + /* fsinfo structure is at offset 0x1e0 in info sector by observation */ + info = (fat32_fsinfo *)(info_sector + 0x1e0); + + /* Info sector magic */ + info_sector[0] = 'R'; + info_sector[1] = 'R'; + info_sector[2] = 'a'; + info_sector[3] = 'A'; + + /* Magic for fsinfo structure */ + info->signature = LE32(0x61417272); + /* We've allocated cluster 2 for the root dir. */ + info->free_clusters = LE32(cluster_count - 1); + info->next_cluster = LE32(2); + + /* Info sector also must have boot sign */ + *(u16 *)(info_sector + 0x1fe) = LE16(BOOT_SIGN); + } + + //------------- + + //write_tables() + u8* blank_sector = new u8[512]; + memset(blank_sector,0,512); + + dev_->cacheReset(); + dev_->truncate(0); + dev_->truncate(sectors*512); + /* clear all reserved sectors */ + for(int i=0;i<bs->reservedSectorCount;i++) + dev_->writeBlock(0,blank_sector); + /* seek back to sector 0 and write the boot sector */ + dev_->writeBlock(0,(const u8*)bs); + /* on FAT32, write the info sector and backup boot sector */ + if (size_fat == 32) + { + dev_->writeBlock(bs->fat32.fat32FSInfo,info_sector); + if(bs->fat32.fat32BackBootBlock) + dev_->writeBlock(bs->fat32.fat32BackBootBlock,(const u8*)bs); + } + /* seek to start of FATS and write them all */ + int ctr=bs->reservedSectorCount; + for (int i=0;i<bs->fatCount;i++) + for(int j=0;j<fat_length;j++,ctr++) + dev_->writeBlock(ctr,fat+j*sector_size); + + /* Write the root directory directly after the last FAT. This is the root + * dir area on FAT12/16, and the first cluster on FAT32. */ + for(int i=0;i<size_root_dir_in_sectors;i++) + dev_->writeBlock(ctr,blank_sector); + + delete[] blank_sector; + delete[] info_sector; + delete[] fat; + + return init(dev_,0); + + //return true; +} + +//well, there are a lot of ways to format a disk. this is just a simple one. +//it would be nice if someone who understood fat better could modify the root +//directory setup to use reasonable code instead of magic arrays +bool EmuFatVolume::format(u32 sectors) +{ + //u32 volumeStartBlock = 0; + //dev_->truncate(0); + //dev_->truncate(sectors*512); + //if (!dev_->cacheRawBlock(volumeStartBlock, EmuFat::CACHE_FOR_WRITE)) return false; + //memset(&dev_->cache_.cacheBuffer_,0,sizeof(dev_->cache_.cacheBuffer_)); + //TFat32BootSector* bs = &dev_->cache_.cacheBuffer_.fbs; + //TBiosParmBlock* bpb = &bs->bpb; + + //bs->jmpToBootCode[0] = 0xEB; + //bs->jmpToBootCode[1] = 0x3C; + //bs->jmpToBootCode[2] = 0x90; + //memcpy(bs->oemName,"mkdosfs",8); + //bs->driveNumber = 0; + //bs->reserved1 = 0; + //bs->bootSignature = 0x29; + //bs->volumeSerialNumber = 0; + //memcpy(bs->volumeLabel," ",11); + //memcpy(bs->fileSystemType,"FAT16 ",8); + //memcpy(bs->bootCode,mkdosfs_bootcode,420); + //bs->bootSectorSig0 = 0x55; + //bs->bootSectorSig1 = 0xAA; + + //bpb->bytesPerSector = 512; + //bpb->sectorsPerCluster = 4; + //bpb->reservedSectorCount = 1; + //bpb->fatCount = 2; + //bpb->rootDirEntryCount = 512; + //bpb->totalSectors16 = 0; + //bpb->mediaType = 0xF8; + //bpb->sectorsPerFat16 = 32; + //bpb->sectorsPerTrack = 32; + //bpb->headCount = 64; + //bpb->hiddenSectors = 0; + //bpb->totalSectors32 = sectors; + //bpb->fat32Flags = 0xbe0d; + //bpb->fat32Version = 0x20Fd; + //bpb->fat32RootCluster = 0x20202020; + //bpb->fat32FSInfo = 0x2020; + //bpb->fat32BackBootBlock = 0x2020; + + //if(!dev_->cacheFlush()) + // return false; + + //if (!dev_->cacheRawBlock(1, EmuFat::CACHE_FOR_WRITE)) return false; + + //static const u8 rootEntry[8] = + //{ + // 0xF8, 0xFF, 0xFF, 0xFF, + //} ; + + //memcpy(dev_->cache_.cacheBuffer_.data,rootEntry,4); + + //if(!dev_->cacheFlush()) + // return false; + + //if (!dev_->cacheRawBlock(33, EmuFat::CACHE_FOR_WRITE)) return false; + + //memcpy(dev_->cache_.cacheBuffer_.data,rootEntry,4); + + //if(!dev_->cacheFlush()) + // return false; + + //return init(dev_,0); + + return false; +} + +bool EmuFatVolume::init(EmuFat* dev, u8 part) { + u32 volumeStartBlock = 0; + dev_ = dev; + // if part == 0 assume super floppy with FAT boot sector in block zero + // if part > 0 assume mbr volume with partition table + if (part) { + if (part > 4) return false; + if (!dev->cacheRawBlock(volumeStartBlock, EmuFat::CACHE_FOR_READ)) return false; + TPartitionRecord* p = &dev->cache_.cacheBuffer_.mbr.part[part-1]; + if ((p->boot & 0X7F) !=0 || + p->totalSectors < 100 || + p->firstSector == 0) { + // not a valid partition + return false; + } + volumeStartBlock = p->firstSector; + } + if (!dev->cacheRawBlock(volumeStartBlock, EmuFat::CACHE_FOR_READ)) return false; + TFat32BootSector* bs = &dev->cache_.cacheBuffer_.fbs; + if (bs->bytesPerSector != 512 || + bs->fatCount == 0 || + bs->reservedSectorCount == 0 || + bs->sectorsPerCluster == 0) { + // not valid FAT volume + return false; + } + fatCount_ = bs->fatCount; + blocksPerCluster_ = bs->sectorsPerCluster; + + // determine shift that is same as multiply by blocksPerCluster_ + clusterSizeShift_ = 0; + while (blocksPerCluster_ != (1 << clusterSizeShift_)) { + // error if not power of 2 + if (clusterSizeShift_++ > 7) return false; + } + blocksPerFat_ = bs->sectorsPerFat16 ? + bs->sectorsPerFat16 : bs->fat32.sectorsPerFat32; + + fatStartBlock_ = volumeStartBlock + bs->reservedSectorCount; + + // count for FAT16 zero for FAT32 + rootDirEntryCount_ = bs->rootDirEntryCount; + + // directory start for FAT16 dataStart for FAT32 + rootDirStart_ = fatStartBlock_ + bs->fatCount * blocksPerFat_; + + // data start for FAT16 and FAT32 + dataStartBlock_ = rootDirStart_ + ((32 * bs->rootDirEntryCount + 511)/512); + + // total blocks for FAT16 or FAT32 + u32 totalBlocks = bs->totalSectors16 ? + bs->totalSectors16 : bs->totalSectors32; + // total data blocks + clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock); + + // divide by cluster size to get cluster count + clusterCount_ >>= clusterSizeShift_; + + // FAT type is determined by cluster count + if (clusterCount_ < 4085) { + fatType_ = 12; + } else if (clusterCount_ < 65525) { + fatType_ = 16; + } else { + rootDirStart_ = bs->fat32.fat32RootCluster; + fatType_ = 32; + } + return true; +} + +u8 EmuFatVolume::allocContiguous(u32 count, u32* curCluster) { + // start of group + u32 bgnCluster; + + // flag to save place to start next search + u8 setStart; + + // set search start cluster + if (*curCluster) { + // try to make file contiguous + bgnCluster = *curCluster + 1; + + // don't save new start location + setStart = false; + } else { + // start at likely place for free cluster + bgnCluster = allocSearchStart_; + + // save next search start if one cluster + setStart = 1 == count; + } + // end of group + u32 endCluster = bgnCluster; + + // last cluster of FAT + u32 fatEnd = clusterCount_ + 1; + + // search the FAT for free clusters + for (u32 n = 0;; n++, endCluster++) { + // can't find space checked all clusters + if (n >= clusterCount_) return false; + + // past end - start from beginning of FAT + if (endCluster > fatEnd) { + bgnCluster = endCluster = 2; + } + u32 f; + if (!fatGet(endCluster, &f)) return false; + + if (f != 0) { + // cluster in use try next cluster as bgnCluster + bgnCluster = endCluster + 1; + } else if ((endCluster - bgnCluster + 1) == count) { + // done - found space + break; + } + } + // mark end of chain + if (!fatPutEOC(endCluster)) return false; + + // link clusters + while (endCluster > bgnCluster) { + if (!fatPut(endCluster - 1, endCluster)) return false; + endCluster--; + } + if (*curCluster != 0) { + // connect chains + if (!fatPut(*curCluster, bgnCluster)) return false; + } + // return first cluster number to caller + *curCluster = bgnCluster; + + // remember possible next free cluster + if (setStart) allocSearchStart_ = bgnCluster + 1; + + return true; +} + +u8 EmuFatVolume::fatGet(u32 cluster, u32* value) const { + if (cluster > (clusterCount_ + 1)) return false; + u32 lba = fatStartBlock_; + lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7; + if (lba != dev_->cache_.cacheBlockNumber_) { + if (!dev_->cacheRawBlock(lba, EmuFat::CACHE_FOR_READ)) return false; + } + if (fatType_ == 16) { + *value = dev_->cache_.cacheBuffer_.fat16[cluster & 0XFF]; + } else { + *value = dev_->cache_.cacheBuffer_.fat32[cluster & 0X7F] & FAT32MASK; + } + return true; +} +// Store a FAT entry +u8 EmuFatVolume::fatPut(u32 cluster, u32 value) { + // error if reserved cluster + if (cluster < 2) return false; + + // error if not in FAT + if (cluster > (clusterCount_ + 1)) return false; + + // calculate block address for entry + u32 lba = fatStartBlock_; + lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7; + + if (lba != dev_->cache_.cacheBlockNumber_) { + if (!dev_->cacheRawBlock(lba, EmuFat::CACHE_FOR_READ)) return false; + } + // store entry + if (fatType_ == 16) { + dev_->cache_.cacheBuffer_.fat16[cluster & 0xFF] = value; + } else { + dev_->cache_.cacheBuffer_.fat32[cluster & 0x7F] = value; + } + dev_->cacheSetDirty(); + + // mirror second FAT + if (fatCount_ > 1) dev_->cache_.cacheMirrorBlock_ = lba + blocksPerFat_; + return true; +} + +// return the size in bytes of a cluster chain +u8 EmuFatVolume::chainSize(u32 cluster, u32* size) const { + u32 s = 0; + do { + if (!fatGet(cluster, &cluster)) return false; + s += 512UL << clusterSizeShift_; + } while (!isEOC(cluster)); + *size = s; + return true; +} + +// free a cluster chain +u8 EmuFatVolume::freeChain(u32 cluster) { + // clear free cluster location + allocSearchStart_ = 2; + + do { + u32 next; + if (!fatGet(cluster, &next)) return false; + + // free cluster + if (!fatPut(cluster, 0)) return false; + + cluster = next; + } while (!isEOC(cluster)); + + return true; +} +u8 EmuFatVolume::readData(u32 block, u16 offset, u16 count, u8* dst) { + return dev_->readData(block, offset, count, dst); + } + +u8 EmuFatVolume::writeBlock(u32 block, const u8* dst) { + return dev_->writeBlock(block, dst); + } + +//----------------------------------------------------------------------------------- +//EmuFatFile: + +// add a cluster to a file +u8 EmuFatFile::addCluster() { + if (!vol_->allocContiguous(1, &curCluster_)) return false; + + // if first cluster of file link to directory entry + if (firstCluster_ == 0) { + firstCluster_ = curCluster_; + flags_ |= F_FILE_DIR_DIRTY; + } + return true; +} + + +// Add a cluster to a directory file and zero the cluster. +// return with first block of cluster in the cache +u8 EmuFatFile::addDirCluster(void) { + if (!addCluster()) return false; + + // zero data in cluster insure first cluster is in cache + u32 block = vol_->clusterStartBlock(curCluster_); + for (u8 i = vol_->blocksPerCluster_; i != 0; i--) { + if (!vol_->dev_->cacheZeroBlock(block + i - 1)) return false; + } + // Increase directory file size by cluster size + fileSize_ += 512UL << vol_->clusterSizeShift_; + return true; +} + + +// cache a file's directory entry +// return pointer to cached entry or null for failure +TDirectoryEntry* EmuFatFile::cacheDirEntry(u8 action) { + if (!vol_->dev_->cacheRawBlock(dirBlock_, action)) return NULL; + return vol_->dev_->cache_.cacheBuffer_.dir + dirIndex_; +} + + +/** + * Close a file and force cached data and directory information + * to be written to the storage device. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include no file is open or an I/O error. + */ +u8 EmuFatFile::close(void) { + if (!sync())return false; + type_ = FAT_FILE_TYPE_CLOSED; + return true; +} + + +/** + * Check for contiguous file and return its raw block range. + * + * \param[out] bgnBlock the first block address for the file. + * \param[out] endBlock the last block address for the file. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include file is not contiguous, file has zero length + * or an I/O error occurred. + */ +u8 EmuFatFile::contiguousRange(u32* bgnBlock, u32* endBlock) { + // error if no blocks + if (firstCluster_ == 0) return false; + + for (u32 c = firstCluster_; ; c++) { + u32 next; + if (!vol_->fatGet(c, &next)) return false; + + // check for contiguous + if (next != (c + 1)) { + // error if not end of chain + if (!vol_->isEOC(next)) return false; + *bgnBlock = vol_->clusterStartBlock(firstCluster_); + *endBlock = vol_->clusterStartBlock(c) + + vol_->blocksPerCluster_ - 1; + return true; + } + } +} + +//------------------------------------------------------------------------------ +/** + * Create and open a new contiguous file of a specified size. + * + * \note This function only supports short DOS 8.3 names. + * See open() for more information. + * + * \param[in] dirFile The directory where the file will be created. + * \param[in] fileName A valid DOS 8.3 file name. + * \param[in] size The desired file size. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include \a fileName contains + * an invalid DOS 8.3 file name, the FAT volume has not been initialized, + * a file is already open, the file already exists, the root + * directory is full or an I/O error. + * + */ +u8 EmuFatFile::createContiguous(EmuFatFile* dirFile, const char* fileName, u32 size) { + // don't allow zero length file + if (size == 0) return false; + if (!open(dirFile, fileName, EO_CREAT | EO_EXCL | EO_RDWR)) return false; + + // calculate number of clusters needed + u32 count = ((size - 1) >> (vol_->clusterSizeShift_ + 9)) + 1; + + // allocate clusters + if (!vol_->allocContiguous(count, &firstCluster_)) { + remove(); + return false; + } + fileSize_ = size; + + // insure sync() will update dir entry + flags_ |= F_FILE_DIR_DIRTY; + return sync(); +} + +/** + * Return a files directory entry + * + * \param[out] dir Location for return of the files directory entry. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +u8 EmuFatFile::dirEntry(TDirectoryEntry* dir) { + // make sure fields on SD are correct + if (!sync()) return false; + + // read entry + TDirectoryEntry* p = cacheDirEntry(EmuFat::CACHE_FOR_READ); + if (!p) return false; + + // copy to caller's struct + memcpy(dir, p, sizeof(TDirectoryEntry)); + return true; +} + +/** + * Format the name field of \a dir into the 13 byte array + * \a name in standard 8.3 short name format. + * + * \param[in] dir The directory structure containing the name. + * \param[out] name A 13 byte char array for the formatted name. + */ +void EmuFatFile::dirName(const TDirectoryEntry& dir, char* name) { + u8 j = 0; + for (u8 i = 0; i < 11; i++) { + if (dir.name[i] == ' ')continue; + if (i == 8) name[j++] = '.'; + name[j++] = dir.name[i]; + } + name[j] = 0; +} + +// format directory name field from a 8.3 name string +u8 EmuFatFile::make83Name(const char* str, u8* name) { + u8 c; + u8 n = 7; // max index for part before dot + u8 i = 0; + // blank fill name and extension + while (i < 11) name[i++] = ' '; + i = 0; + while ((c = *str++) != '\0') { + if (c == '.') { + if (n == 10) return false; // only one dot allowed + n = 10; // max index for full 8.3 name + i = 8; // place for extension + } else { + // illegal FAT characters + static const char* px = "\\/:*?\"<>"; + const char* p = px; + u8 b; + while ((b = *p++)) if (b == c) return false; + // check size and only allow ASCII printable characters + if (i > n || c < 0X21 || c > 0X7E)return false; + // only upper case allowed in 8.3 names - convert lower to upper + name[i++] = c < 'a' || c > 'z' ? c : c + ('A' - 'a'); + } + } + // must have a file name, extension is optional + return name[0] != ' '; +} + +/** Make a new directory. + * + * \param[in] dir An open SdFat instance for the directory that will containing + * the new directory. + * + * \param[in] dirName A valid 8.3 DOS name for the new directory. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include this SdFile is already open, \a dir is not a + * directory, \a dirName is invalid or already exists in \a dir. + */ +u8 EmuFatFile::makeDir(EmuFatFile* dir, const char* dirName) { + TDirectoryEntry d; + + // create a normal file + if (!open(dir, dirName, EO_CREAT | EO_EXCL | EO_RDWR)) return false; + + // convert SdFile to directory + flags_ = EO_READ; + type_ = FAT_FILE_TYPE_SUBDIR; + + // allocate and zero first cluster + if (!addDirCluster())return false; + + // force entry to SD + if (!sync()) return false; + + // cache entry - should already be in cache due to sync() call + TDirectoryEntry* p = cacheDirEntry(EmuFat::CACHE_FOR_WRITE); + if (!p) return false; + + // change directory entry attribute + p->attributes = DIR_ATT_DIRECTORY; + + // make entry for '.' + memcpy(&d, p, sizeof(d)); + for (u8 i = 1; i < 11; i++) d.name[i] = ' '; + d.name[0] = '.'; + + // cache block for '.' and '..' + u32 block = vol_->clusterStartBlock(firstCluster_); + if (!vol_->dev_->cacheRawBlock(block, EmuFat::CACHE_FOR_WRITE)) return false; + + // copy '.' to block + memcpy(&vol_->dev_->cache_.cacheBuffer_.dir[0], &d, sizeof(d)); + + // make entry for '..' + d.name[1] = '.'; + if (dir->isRoot()) { + d.firstClusterLow = 0; + d.firstClusterHigh = 0; + } else { + d.firstClusterLow = dir->firstCluster_ & 0XFFFF; + d.firstClusterHigh = dir->firstCluster_ >> 16; + } + // copy '..' to block + memcpy(&vol_->dev_->cache_.cacheBuffer_.dir[1], &d, sizeof(d)); + + // set position after '..' + curPosition_ = 2 * sizeof(d); + + // write first block + return vol_->dev_->cacheFlush(); +} + +/** + * Open a file or directory by name. + * + * \param[in] dirFile An open SdFat instance for the directory containing the + * file to be opened. + * + * \param[in] fileName A valid 8.3 DOS name for a file to be opened. + * + * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive + * OR of flags from the following list + * + * O_READ - Open for reading. + * + * O_RDONLY - Same as O_READ. + * + * O_WRITE - Open for writing. + * + * O_WRONLY - Same as O_WRITE. + * + * O_RDWR - Open for reading and writing. + * + * O_APPEND - If set, the file offset shall be set to the end of the + * file prior to each write. + * + * O_CREAT - If the file exists, this flag has no effect except as noted + * under O_EXCL below. Otherwise, the file shall be created + * + * O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file exists. + * + * O_SYNC - Call sync() after each write. This flag should not be used with + * write(uint8_t), write_P(PGM_P), writeln_P(PGM_P), or the Arduino Print class. + * These functions do character at a time writes so sync() will be called + * after each byte. + * + * O_TRUNC - If the file exists and is a regular file, and the file is + * successfully opened and is not read only, its length shall be truncated to 0. + * + * \note Directory files must be opened read only. Write and truncation is + * not allowed for directory files. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include this SdFile is already open, \a difFile is not + * a directory, \a fileName is invalid, the file does not exist + * or can't be opened in the access mode specified by oflag. + */ +u8 EmuFatFile::open(EmuFatFile* dirFile, const char* fileName, u8 oflag) { + u8 dname[11]; + TDirectoryEntry* p; + + // error if already open + if (isOpen())return false; + + if (!make83Name(fileName, dname)) return false; + vol_ = dirFile->vol_; + dirFile->rewind(); + + // bool for empty entry found + u8 emptyFound = false; + + // search for file + while (dirFile->curPosition_ < dirFile->fileSize_) { + u8 index = 0XF & (dirFile->curPosition_ >> 5); + p = dirFile->readDirCache(); + if (p == NULL) return false; + + if (p->name[0] == DIR_NAME_FREE || p->name[0] == DIR_NAME_DELETED) { + // remember first empty slot + if (!emptyFound) { + emptyFound = true; + dirIndex_ = index; + dirBlock_ = vol_->dev_->cache_.cacheBlockNumber_; + } + // done if no entries follow + if (p->name[0] == DIR_NAME_FREE) break; + } else if (!memcmp(dname, p->name, 11)) { + // don't open existing file if O_CREAT and O_EXCL + if ((oflag & (EO_CREAT | EO_EXCL)) == (EO_CREAT | EO_EXCL)) return false; + + // open found file + return openCachedEntry(0XF & index, oflag); + } + } + // only create file if O_CREAT and O_WRITE + if ((oflag & (EO_CREAT | EO_WRITE)) != (EO_CREAT | EO_WRITE)) return false; + + // cache found slot or add cluster if end of file + if (emptyFound) { + p = cacheDirEntry(EmuFat::CACHE_FOR_WRITE); + if (!p) return false; + } else { + if (dirFile->type_ == FAT_FILE_TYPE_ROOT16) return false; + + // add and zero cluster for dirFile - first cluster is in cache for write + if (!dirFile->addDirCluster()) return false; + + // use first entry in cluster + dirIndex_ = 0; + p = vol_->dev_->cache_.cacheBuffer_.dir; + } + // initialize as empty file + memset(p, 0, sizeof(TDirectoryEntry)); + memcpy(p->name, dname, 11); + + // set timestamps + if (dateTime_) { + // call user function + dateTime_(&p->creationDate, &p->creationTime); + } else { + // use default date/time + p->creationDate = FAT_DEFAULT_DATE; + p->creationTime = FAT_DEFAULT_TIME; + } + p->lastAccessDate = p->creationDate; + p->lastWriteDate = p->creationDate; + p->lastWriteTime = p->creationTime; + + // force write of entry to SD + if (!vol_->dev_->cacheFlush()) return false; + + // open entry in cache + return openCachedEntry(dirIndex_, oflag); +} + +/** + * Open a file by index. + * + * \param[in] dirFile An open SdFat instance for the directory. + * + * \param[in] index The \a index of the directory entry for the file to be + * opened. The value for \a index is (directory file position)/32. + * + * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive + * OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC. + * + * See open() by fileName for definition of flags and return values. + * + */ +u8 EmuFatFile::open(EmuFatFile* dirFile, u16 index, u8 oflag) { + // error if already open + if (isOpen())return false; + + // don't open existing file if O_CREAT and O_EXCL - user call error + if ((oflag & (EO_CREAT | EO_EXCL)) == (EO_CREAT | EO_EXCL)) return false; + + vol_ = dirFile->vol_; + + // seek to location of entry + if (!dirFile->seekSet(32 * index)) return false; + + // read entry into cache + TDirectoryEntry* p = dirFile->readDirCache(); + if (p == NULL) return false; + + // error if empty slot or '.' or '..' + if (p->name[0] == DIR_NAME_FREE || + p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') { + return false; + } + // open cached entry + return openCachedEntry(index & 0XF, oflag); +} + +//------------------------------------------------------------------------------ +// open a cached directory entry. Assumes vol_ is initializes +u8 EmuFatFile::openCachedEntry(u8 dirIndex, u8 oflag) { + // location of entry in cache + TDirectoryEntry* p = vol_->dev_->cache_.cacheBuffer_.dir + dirIndex; + + // write or truncate is an error for a directory or read-only file + if (p->attributes & (DIR_ATT_READ_ONLY | DIR_ATT_DIRECTORY)) { + if (oflag & (EO_WRITE | EO_TRUNC)) return false; + } + // remember location of directory entry on SD + dirIndex_ = dirIndex; + dirBlock_ = vol_->dev_->cache_.cacheBlockNumber_; + + // copy first cluster number for directory fields + firstCluster_ = (u32)p->firstClusterHigh << 16; + firstCluster_ |= p->firstClusterLow; + + // make sure it is a normal file or subdirectory + if (DIR_IS_FILE(p)) { + fileSize_ = p->fileSize; + type_ = FAT_FILE_TYPE_NORMAL; + } else if (DIR_IS_SUBDIR(p)) { + if (!vol_->chainSize(firstCluster_, &fileSize_)) return false; + type_ = FAT_FILE_TYPE_SUBDIR; + } else { + return false; + } + // save open flags for read/write + flags_ = oflag & (EO_ACCMODE | EO_SYNC | EO_APPEND); + + // set to start of file + curCluster_ = 0; + curPosition_ = 0; + + // truncate file to zero length if requested + if (oflag & EO_TRUNC) return truncate(0); + return true; +} + +//------------------------------------------------------------------------------ +/** + * Open a volume's root directory. + * + * \param[in] vol The FAT volume containing the root directory to be opened. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include the FAT volume has not been initialized + * or it a FAT12 volume. + */ +u8 EmuFatFile::openRoot(EmuFatVolume* vol) { + // error if file is already open + if (isOpen()) return false; + + if (vol->fatType() == 16) { + type_ = FAT_FILE_TYPE_ROOT16; + firstCluster_ = 0; + fileSize_ = 32 * vol->rootDirEntryCount(); + } else if (vol->fatType() == 32) { + type_ = FAT_FILE_TYPE_ROOT32; + firstCluster_ = vol->rootDirStart(); + if (!vol->chainSize(firstCluster_, &fileSize_)) return false; + } else { + // volume is not initialized or FAT12 + return false; + } + vol_ = vol; + // read only + flags_ = EO_READ; + + // set to start of file + curCluster_ = 0; + curPosition_ = 0; + + // root has no directory entry + dirBlock_ = 0; + dirIndex_ = 0; + return true; +} + +//------------------------------------------------------------------------------ +/** + * Read data from a file starting at the current position. + * + * \param[out] buf Pointer to the location that will receive the data. + * + * \param[in] nbyte Maximum number of bytes to read. + * + * \return For success read() returns the number of bytes read. + * A value less than \a nbyte, including zero, will be returned + * if end of file is reached. + * If an error occurs, read() returns -1. Possible errors include + * read() called before a file has been opened, corrupt file system + * or an I/O error occurred. + */ +s32 EmuFatFile::read(void* buf, u32 nbyte) { + u8* dst = reinterpret_cast<u8*>(buf); + + // error if not open or write only + if (!isOpen() || !(flags_ & EO_READ)) return -1; + + // max bytes left in file + if (nbyte > (fileSize_ - curPosition_)) nbyte = fileSize_ - curPosition_; + + // amount left to read + u32 toRead = nbyte; + while (toRead > 0) { + u32 block; // raw device block number + u16 offset = curPosition_ & 0x1FF; // offset in block + if (type_ == FAT_FILE_TYPE_ROOT16) { + block = vol_->rootDirStart() + (curPosition_ >> 9); + } else { + u8 blockOfCluster = vol_->blockOfCluster(curPosition_); + if (offset == 0 && blockOfCluster == 0) { + // start of new cluster + if (curPosition_ == 0) { + // use first cluster in file + curCluster_ = firstCluster_; + } else { + // get next cluster from FAT + if (!vol_->fatGet(curCluster_, &curCluster_)) return -1; + } + } + block = vol_->clusterStartBlock(curCluster_) + blockOfCluster; + } + u32 n = toRead; + + // amount to be read from current block + if (n > (512UL - offset)) n = 512 - offset; + + // no buffering needed if n == 512 or user requests no buffering + if ((unbufferedRead() || n == 512) && + block != vol_->dev_->cache_.cacheBlockNumber_) { + if (!vol_->readData(block, offset, n, dst)) return -1; + dst += n; + } else { + // read block to cache and copy data to caller + if (!vol_->dev_->cacheRawBlock(block, EmuFat::CACHE_FOR_READ)) return -1; + u8* src = vol_->dev_->cache_.cacheBuffer_.data + offset; + u8* end = src + n; + while (src != end) *dst++ = *src++; + } + curPosition_ += n; + toRead -= n; + } + return nbyte; +} + +//------------------------------------------------------------------------------ +/** + * Read the next directory entry from a directory file. + * + * \param[out] dir The dir_t struct that will receive the data. + * + * \return For success readDir() returns the number of bytes read. + * A value of zero will be returned if end of file is reached. + * If an error occurs, readDir() returns -1. Possible errors include + * readDir() called before a directory has been opened, this is not + * a directory file or an I/O error occurred. + */ +s8 EmuFatFile::readDir(TDirectoryEntry* dir) { + s16 n; + // if not a directory file or miss-positioned return an error + if (!isDir() || (0x1F & curPosition_)) return -1; + + while ((n = read(dir, sizeof(TDirectoryEntry))) == sizeof(TDirectoryEntry)) { + // last entry if DIR_NAME_FREE + if (dir->name[0] == DIR_NAME_FREE) break; + // skip empty entries and entry for . and .. + if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') continue; + // return if normal file or subdirectory + if (DIR_IS_FILE_OR_SUBDIR(dir)) return (s8)n; + } + // error, end of file, or past last entry + return n < 0 ? -1 : 0; +} + +// Read next directory entry into the cache +// Assumes file is correctly positioned +TDirectoryEntry* EmuFatFile::readDirCache(void) { + // error if not directory + if (!isDir()) return NULL; + + // index of entry in cache + u8 i = (curPosition_ >> 5) & 0XF; + + // use read to locate and cache block + if (read() < 0) return NULL; + + // advance to next entry + curPosition_ += 31; + + // return pointer to entry + return (vol_->dev_->cache_.cacheBuffer_.dir + i); +} + +//------------------------------------------------------------------------------ +/** + * Remove a file. + * + * The directory entry and all data for the file are deleted. + * + * \note This function should not be used to delete the 8.3 version of a + * file that has a long name. For example if a file has the long name + * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT". + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include the file read-only, is a directory, + * or an I/O error occurred. + */ +u8 EmuFatFile::remove(void) { + // free any clusters - will fail if read-only or directory + if (!truncate(0)) return false; + + // cache directory entry + TDirectoryEntry* d = cacheDirEntry(EmuFat::CACHE_FOR_WRITE); + if (!d) return false; + + // mark entry deleted + d->name[0] = DIR_NAME_DELETED; + + // set this SdFile closed + type_ = FAT_FILE_TYPE_CLOSED; + + // write entry to SD + return vol_->dev_->cacheFlush(); +} + +//------------------------------------------------------------------------------ +/** + * Remove a file. + * + * The directory entry and all data for the file are deleted. + * + * \param[in] dirFile The directory that contains the file. + * \param[in] fileName The name of the file to be removed. + * + * \note This function should not be used to delete the 8.3 version of a + * file that has a long name. For example if a file has the long name + * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT". + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include the file is a directory, is read only, + * \a dirFile is not a directory, \a fileName is not found + * or an I/O error occurred. + */ +u8 EmuFatFile::remove(EmuFatFile* dirFile, const char* fileName) { + EmuFatFile file; + if (!file.open(dirFile, fileName, EO_WRITE)) return false; + return file.remove(); +} + +//------------------------------------------------------------------------------ +/** Remove a directory file. + * + * The directory file will be removed only if it is empty and is not the + * root directory. rmDir() follows DOS and Windows and ignores the + * read-only attribute for the directory. + * + * \note This function should not be used to delete the 8.3 version of a + * directory that has a long name. For example if a directory has the + * long name "New folder" you should not delete the 8.3 name "NEWFOL~1". + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include the file is not a directory, is the root + * directory, is not empty, or an I/O error occurred. + */ +u8 EmuFatFile::rmDir(void) { + // must be open subdirectory + if (!isSubDir()) return false; + + rewind(); + + // make sure directory is empty + while (curPosition_ < fileSize_) { + TDirectoryEntry* p = readDirCache(); + if (p == NULL) return false; + // done if past last used entry + if (p->name[0] == DIR_NAME_FREE) break; + // skip empty slot or '.' or '..' + if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue; + // error not empty + if (DIR_IS_FILE_OR_SUBDIR(p)) return false; + } + // convert empty directory to normal file for remove + type_ = FAT_FILE_TYPE_NORMAL; + flags_ |= EO_WRITE; + return remove(); +} + +//------------------------------------------------------------------------------ +/** Recursively delete a directory and all contained files. + * + * This is like the Unix/Linux 'rm -rf *' if called with the root directory + * hence the name. + * + * Warning - This will remove all contents of the directory including + * subdirectories. The directory will then be removed if it is not root. + * The read-only attribute for files will be ignored. + * + * \note This function should not be used to delete the 8.3 version of + * a directory that has a long name. See remove() and rmDir(). + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +u8 EmuFatFile::rmRfStar(void) { + rewind(); + while (curPosition_ < fileSize_) { + EmuFatFile f; + + // remember position + u16 index = curPosition_/32; + + TDirectoryEntry* p = readDirCache(); + if (!p) return false; + + // done if past last entry + if (p->name[0] == DIR_NAME_FREE) break; + + // skip empty slot or '.' or '..' + if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue; + + // skip if part of long file name or volume label in root + if (!DIR_IS_FILE_OR_SUBDIR(p)) continue; + + if (!f.open(this, index, EO_READ)) return false; + if (f.isSubDir()) { + // recursively delete + return rmRfStar(); + } else { + // ignore read-only + f.flags_ |= EO_WRITE; + if (!f.remove()) return false; + } + // position to next entry if required + if (curPosition_ != (32*(index + 1))) { + if (!seekSet(32*(index + 1))) return false; + } + } + // don't try to delete root + if (isRoot()) return true; + return rmDir(); +} + +u8 EmuFatFile::seekSet(u32 pos) { + // error if file not open or seek past end of file + if (!isOpen() || pos > fileSize_) return false; + + if (type_ == FAT_FILE_TYPE_ROOT16) { + curPosition_ = pos; + return true; + } + if (pos == 0) { + // set position to start of file + curCluster_ = 0; + curPosition_ = 0; + return true; + } + // calculate cluster index for cur and new position + u32 nCur = (curPosition_ - 1) >> (vol_->clusterSizeShift_ + 9); + u32 nNew = (pos - 1) >> (vol_->clusterSizeShift_ + 9); + + if (nNew < nCur || curPosition_ == 0) { + // must follow chain from first cluster + curCluster_ = firstCluster_; + } else { + // advance from curPosition + nNew -= nCur; + } + while (nNew--) { + if (!vol_->fatGet(curCluster_, &curCluster_)) return false; + } + curPosition_ = pos; + return true; +} + +//------------------------------------------------------------------------------ +/** + * The sync() call causes all modified data and directory fields + * to be written to the storage device. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include a call to sync() before a file has been + * opened or an I/O error. + */ +u8 EmuFatFile::sync(void) { + // only allow open files and directories + if (!isOpen()) return false; + + if (flags_ & F_FILE_DIR_DIRTY) { + TDirectoryEntry* d = cacheDirEntry(EmuFat::CACHE_FOR_WRITE); + if (!d) return false; + + // do not set filesize for dir files + if (!isDir()) d->fileSize = fileSize_; + + // update first cluster fields + d->firstClusterLow = firstCluster_ & 0XFFFF; + d->firstClusterHigh = firstCluster_ >> 16; + + // set modify time if user supplied a callback date/time function + if (dateTime_) { + dateTime_(&d->lastWriteDate, &d->lastWriteTime); + d->lastAccessDate = d->lastWriteDate; + } + // clear directory dirty + flags_ &= ~F_FILE_DIR_DIRTY; + } + return vol_->dev_->cacheFlush(); +} + +//------------------------------------------------------------------------------ +/** + * Set a file's timestamps in its directory entry. + * + * \param[in] flags Values for \a flags are constructed by a bitwise-inclusive + * OR of flags from the following list + * + * T_ACCESS - Set the file's last access date. + * + * T_CREATE - Set the file's creation date and time. + * + * T_WRITE - Set the file's last write/modification date and time. + * + * \param[in] year Valid range 1980 - 2107 inclusive. + * + * \param[in] month Valid range 1 - 12 inclusive. + * + * \param[in] day Valid range 1 - 31 inclusive. + * + * \param[in] hour Valid range 0 - 23 inclusive. + * + * \param[in] minute Valid range 0 - 59 inclusive. + * + * \param[in] second Valid range 0 - 59 inclusive + * + * \note It is possible to set an invalid date since there is no check for + * the number of days in a month. + * + * \note + * Modify and access timestamps may be overwritten if a date time callback + * function has been set by dateTimeCallback(). + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + */ +u8 EmuFatFile::timestamp(u8 flags, u16 year, u8 month, u8 day, u8 hour, u8 minute, u8 second) { + if (!isOpen() + || year < 1980 + || year > 2107 + || month < 1 + || month > 12 + || day < 1 + || day > 31 + || hour > 23 + || minute > 59 + || second > 59) { + return false; + } + TDirectoryEntry* d = cacheDirEntry(EmuFat::CACHE_FOR_WRITE); + if (!d) return false; + + u16 dirDate = FAT_DATE(year, month, day); + u16 dirTime = FAT_TIME(hour, minute, second); + if (flags & T_ACCESS) { + d->lastAccessDate = dirDate; + } + if (flags & T_CREATE) { + d->creationDate = dirDate; + d->creationTime = dirTime; + // seems to be units of 1/100 second not 1/10 as Microsoft states + d->creationTimeTenths = second & 1 ? 100 : 0; + } + if (flags & T_WRITE) { + d->lastWriteDate = dirDate; + d->lastWriteTime = dirTime; + } + vol_->dev_->cacheSetDirty(); + return sync(); +} + +//------------------------------------------------------------------------------ +/** + * Truncate a file to a specified length. The current file position + * will be maintained if it is less than or equal to \a length otherwise + * it will be set to end of file. + * + * \param[in] length The desired length for the file. + * + * \return The value one, true, is returned for success and + * the value zero, false, is returned for failure. + * Reasons for failure include file is read only, file is a directory, + * \a length is greater than the current file size or an I/O error occurs. + */ +u8 EmuFatFile::truncate(u32 length) { +// error if not a normal file or read-only + if (!isFile() || !(flags_ & EO_WRITE)) return false; + + // error if length is greater than current size + if (length > fileSize_) return false; + + // fileSize and length are zero - nothing to do + if (fileSize_ == 0) return true; + + // remember position for seek after truncation + u32 newPos = curPosition_ > length ? length : curPosition_; + + // position to last cluster in truncated file + if (!seekSet(length)) return false; + + if (length == 0) { + // free all clusters + if (!vol_->freeChain(firstCluster_)) return false; + firstCluster_ = 0; + } else { + u32 toFree; + if (!vol_->fatGet(curCluster_, &toFree)) return false; + + if (!vol_->isEOC(toFree)) { + // free extra clusters + if (!vol_->freeChain(toFree)) return false; + + // current cluster is end of chain + if (!vol_->fatPutEOC(curCluster_)) return false; + } + } + fileSize_ = length; + + // need to update directory entry + flags_ |= F_FILE_DIR_DIRTY; + + if (!sync()) return false; + + // set file to correct position + return seekSet(newPos); +} + +/** + * Write data to an open file. + * + * \note Data is moved to the cache but may not be written to the + * storage device until sync() is called. + * + * \param[in] buf Pointer to the location of the data to be written. + * + * \param[in] nbyte Number of bytes to write. + * + * \return For success write() returns the number of bytes written, always + * \a nbyte. If an error occurs, write() returns -1. Possible errors + * include write() is called before a file has been opened, write is called + * for a read-only file, device is full, a corrupt file system or an I/O error. + * + */ +s32 EmuFatFile::write(const void* buf, u32 nbyte) { + // convert void* to uint8_t* - must be before goto statements + const u8* src = reinterpret_cast<const u8*>(buf); + + // number of bytes left to write - must be before goto statements + u32 nToWrite = nbyte; + + // error if not a normal file or is read-only + if (!isFile() || !(flags_ & EO_WRITE)) goto writeErrorReturn; + + // seek to end of file if append flag + if ((flags_ & EO_APPEND) && curPosition_ != fileSize_) { + if (!seekEnd()) goto writeErrorReturn; + } + + while (nToWrite > 0) { + u8 blockOfCluster = vol_->blockOfCluster(curPosition_); + u16 blockOffset = curPosition_ & 0X1FF; + if (blockOfCluster == 0 && blockOffset == 0) { + // start of new cluster + if (curCluster_ == 0) { + if (firstCluster_ == 0) { + // allocate first cluster of file + if (!addCluster()) goto writeErrorReturn; + } else { + curCluster_ = firstCluster_; + } + } else { + u32 next; + if (!vol_->fatGet(curCluster_, &next)) return false; + if (vol_->isEOC(next)) { + // add cluster if at end of chain + if (!addCluster()) goto writeErrorReturn; + } else { + curCluster_ = next; + } + } + } + // max space in block + u32 n = 512 - blockOffset; + + // lesser of space and amount to write + if (n > nToWrite) n = nToWrite; + + // block for data write + u32 block = vol_->clusterStartBlock(curCluster_) + blockOfCluster; + if (n == 512) { + // full block - don't need to use cache + // invalidate cache if block is in cache + if (vol_->dev_->cache_.cacheBlockNumber_ == block) { + vol_->dev_->cache_.cacheBlockNumber_ = 0XFFFFFFFF; + } + if (!vol_->writeBlock(block, src)) goto writeErrorReturn; + src += 512; + } else { + if (blockOffset == 0 && curPosition_ >= fileSize_) { + // start of new block don't need to read into cache + if (!vol_->dev_->cacheFlush()) goto writeErrorReturn; + vol_->dev_->cache_.cacheBlockNumber_ = block; + vol_->dev_->cacheSetDirty(); + } else { + // rewrite part of block + if (!vol_->dev_->cacheRawBlock(block, EmuFat::CACHE_FOR_WRITE)) { + goto writeErrorReturn; + } + } + u8* dst = vol_->dev_->cache_.cacheBuffer_.data + blockOffset; + u8* end = dst + n; + while (dst != end) *dst++ = *src++; + } + nToWrite -= n; + curPosition_ += n; + } + if (curPosition_ > fileSize_) { + // update fileSize and insure sync will update dir entry + fileSize_ = curPosition_; + flags_ |= F_FILE_DIR_DIRTY; + } else if (dateTime_ && nbyte) { + // insure sync will update modified date and time + flags_ |= F_FILE_DIR_DIRTY; + } + + if (flags_ & EO_SYNC) { + if (!sync()) goto writeErrorReturn; + } + return nbyte; + + writeErrorReturn: + // return for write error + writeError = true; + return -1; +} diff --git a/jni/desmume/src/utils/emufat.h b/jni/desmume/src/utils/emufat.h new file mode 100755 index 0000000..536d250 --- /dev/null +++ b/jni/desmume/src/utils/emufat.h @@ -0,0 +1,725 @@ +/* + Copyright 2009-2010 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +//based on Arduino SdFat Library ( http://code.google.com/p/sdfatlib/ ) +//Copyright (C) 2009 by William Greiman + +//based on mkdosfs - utility to create FAT/MS-DOS filesystems +//Copyright (C) 1991 Linus Torvalds <torvalds@klaava.helsinki.fi> +//Copyright (C) 1992-1993 Remy Card <card@masi.ibp.fr> +//Copyright (C) 1993-1994 David Hudson <dave@humbug.demon.co.uk> +//Copyright (C) 1998 H. Peter Anvin <hpa@zytor.com> +//Copyright (C) 1998-2005 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> + +//based on libfat +//Copyright (c) 2006 Michael "Chishm" Chisholm + +#ifndef EMUFAT_H +#define EMUFAT_H + +#include "emufat_types.h" +#include "emufile.h" +#include <stdio.h> + +#define BOOTCODE_SIZE 448 +#define BOOTCODE_FAT32_SIZE 420 + + +// use the gnu style oflag in open() +/** open() oflag for reading */ +static const u8 EO_READ = 0X01; +/** open() oflag - same as O_READ */ +static const u8 EO_RDONLY = EO_READ; +/** open() oflag for write */ +static const u8 EO_WRITE = 0X02; +/** open() oflag - same as O_WRITE */ +static const u8 EO_WRONLY = EO_WRITE; +/** open() oflag for reading and writing */ +static const u8 EO_RDWR = (EO_READ | EO_WRITE); +/** open() oflag mask for access modes */ +static const u8 EO_ACCMODE = (EO_READ | EO_WRITE); +/** The file offset shall be set to the end of the file prior to each write. */ +static const u8 EO_APPEND = 0X04; +/** synchronous writes - call sync() after each write */ +static const u8 EO_SYNC = 0X08; +/** create the file if nonexistent */ +static const u8 EO_CREAT = 0X10; +/** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */ +static const u8 EO_EXCL = 0X20; +/** truncate the file to zero length */ +static const u8 EO_TRUNC = 0X40; + + +//Value for byte 510 of boot block or MBR +static const u8 BOOTSIG0 = 0X55; +//Value for byte 511 of boot block or MBR +static const u8 BOOTSIG1 = 0XAA; + +static void (*dateTime_)(u16* date, u16* time) = NULL; + + +#include "PACKED.h" + +//A partition table entry for a MBR formatted storage device. +//The MBR partition table has four entries. +struct __PACKED TPartitionRecord { + //Boot Indicator . Indicates whether the volume is the active + //partition. Legal values include: 0X00. Do not use for booting. + //0X80 Active partition. + u8 boot; + + //Head part of Cylinder-head-sector address of the first block in + //the partition. Legal values are 0-255. Only used in old PC BIOS. + u8 beginHead; + + struct + { + //Sector part of Cylinder-head-sector address of the first block in + //the partition. Legal values are 1-63. Only used in old PC BIOS. + u32 beginSector : 6; + //High bits cylinder for first block in partition. + u32 beginCylinderHigh : 2; + }; + + //Combine beginCylinderLow with beginCylinderHigh. Legal values + //are 0-1023. Only used in old PC BIOS. + u8 beginCylinderLow; + //Partition type. See defines that begin with PART_TYPE_ for + //some Microsoft partition types. + u8 type; + + //head part of cylinder-head-sector address of the last sector in the + //partition. Legal values are 0-255. Only used in old PC BIOS. + u8 endHead; + + struct + { + //Sector part of cylinder-head-sector address of the last sector in + //the partition. Legal values are 1-63. Only used in old PC BIOS. + u32 endSector : 6; + // High bits of end cylinder + u32 endCylinderHigh : 2; + }; + + //Combine endCylinderLow with endCylinderHigh. Legal values + //are 0-1023. Only used in old PC BIOS. + u8 endCylinderLow; + + //Logical block address of the first block in the partition. + u32 firstSector; + + //Length of the partition, in blocks. + u32 totalSectors; +}; + +//Master Boot Record: +//The first block of a storage device that is formatted with a MBR. +struct __PACKED TMasterBootRecord { + //Code Area for master boot program. + u8 codeArea[440]; + //Optional WindowsNT disk signature. May contain more boot code. + u32 diskSignature; + //Usually zero but may be more boot code. + u16 usuallyZero; + //Partition tables. + TPartitionRecord part[4]; + //First MBR signature byte. Must be 0X55 + u8 mbrSig0; + //Second MBR signature byte. Must be 0XAA + u8 mbrSig1; +}; + +struct __PACKED msdos_volume_info { + u8 drive_number; /* BIOS drive number */ + u8 RESERVED; /* Unused */ + u8 ext_boot_sign; /* 0x29 if fields below exist (DOS 3.3+) */ + u32 volume_id; /* Volume ID number */ + u8 volume_label[11];/* Volume label */ + u8 fs_type[8]; /* Typically FAT12 or FAT16 */ +}; + +//Boot sector for a FAT16 or FAT32 volume. +struct __PACKED TFat32BootSector { + //X86 jmp to boot program + u8 jmpToBootCode[3]; + //informational only - don't depend on it + u8 oemName[8]; + + //Count of bytes per sector. This value may take on only the + //following values: 512, 1024, 2048 or 4096 + u16 bytesPerSector; + //Number of sectors per allocation unit. This value must be a + //power of 2 that is greater than 0. The legal values are + //1, 2, 4, 8, 16, 32, 64, and 128. + u8 sectorsPerCluster; //cluster_size + //Number of sectors before the first FAT. + //This value must not be zero. + u16 reservedSectorCount; + //The count of FAT data structures on the volume. This field should + //always contain the value 2 for any FAT volume of any type. + u8 fatCount; + //For FAT12 and FAT16 volumes, this field contains the count of + //32-byte directory entries in the root directory. For FAT32 volumes, + //this field must be set to 0. For FAT12 and FAT16 volumes, this + //value should always specify a count that when multiplied by 32 + //results in a multiple of bytesPerSector. FAT16 volumes should + //use the value 512. + u16 rootDirEntryCount; //dir_entries + //This field is the old 16-bit total count of sectors on the volume. + //This count includes the count of all sectors in all four regions + //of the volume. This field can be 0; if it is 0, then totalSectors32 + //must be non-zero. For FAT32 volumes, this field must be 0. For + //FAT12 and FAT16 volumes, this field contains the sector count, and + //totalSectors32 is 0 if the total sector count fits + //(is less than 0x10000). + u16 totalSectors16; + //This dates back to the old MS-DOS 1.x media determination and is + //no longer usually used for anything. 0xF8 is the standard value + //for fixed (non-removable) media. For removable media, 0xF0 is + //frequently used. Legal values are 0xF0 or 0xF8-0xFF. + u8 mediaType; + //Count of sectors occupied by one FAT on FAT12/FAT16 volumes. + //On FAT32 volumes this field must be 0, and sectorsPerFat32 + //contains the FAT size count. + u16 sectorsPerFat16; + //Sectors per track for interrupt 0x13. Not used otherwise. + u16 sectorsPerTrack; + //Number of heads for interrupt 0x13. Not used otherwise. + u16 headCount; + //Count of hidden sectors preceding the partition that contains this + //FAT volume. This field is generally only relevant for media + //visible on interrupt 0x13. + u32 hiddenSectors; + //This field is the new 32-bit total count of sectors on the volume. + //This count includes the count of all sectors in all four regions + //of the volume. This field can be 0; if it is 0, then + //totalSectors16 must be non-zero. + u32 totalSectors32; + + union { + struct __PACKED { + msdos_volume_info vi; + u8 boot_code[BOOTCODE_SIZE]; + } oldfat; + + struct __PACKED + { + //Count of sectors occupied by one FAT on FAT32 volumes. + u32 sectorsPerFat32; //fat32_length; /* sectors/FAT */ + + //This field is only defined for FAT32 media and does not exist on + //FAT12 and FAT16 media. + //Bits 0-3 -- Zero-based number of active FAT. + // Only valid if mirroring is disabled. + //Bits 4-6 -- Reserved. + //Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs. + // -- 1 means only one FAT is active; it is the one referenced in bits 0-3. + //Bits 8-15 -- Reserved. + u16 fat32Flags;// flags; /* bit 8: fat mirroring, low 4: active fat */ + + //FAT32 version. High byte is major revision number. + //Low byte is minor revision number. Only 0.0 define. + u16 fat32Version;//version[2]; /* major, minor filesystem version */ + + //Cluster number of the first cluster of the root directory for FAT32. + //This usually 2 but not required to be 2. + u32 fat32RootCluster; //root_cluster; /* first cluster in root directory */ + + //Sector number of FSINFO structure in the reserved area of the + //FAT32 volume. Usually 1. + u16 fat32FSInfo;// info_sector; /* filesystem info sector */ + + //If non-zero, indicates the sector number in the reserved area + //of the volume of a copy of the boot record. Usually 6. + //No value other than 6 is recommended. + u16 fat32BackBootBlock; //backup_boot; /* backup boot sector */ + + //Reserved for future expansion. Code that formats FAT32 volumes + //should always set all of the bytes of this field to 0. + u8 fat32Reserved[12]; //reserved2[6]; /* Unused */ + + msdos_volume_info vi; + + u8 boot_code[BOOTCODE_FAT32_SIZE]; + } fat32; + }; + + u8 boot_sign[2]; +}; + +#include "PACKED_END.h" + +// End Of Chain values for FAT entries +//FAT16 end of chain value used by Microsoft. +static const u16 FAT16EOC = 0XFFFF; +//Minimum value for FAT16 EOC. Use to test for EOC. +static const u16 FAT16EOC_MIN = 0XFFF8; +//FAT32 end of chain value used by Microsoft. +static const u32 FAT32EOC = 0X0FFFFFFF; +//Minimum value for FAT32 EOC. Use to test for EOC. +static const u32 FAT32EOC_MIN = 0X0FFFFFF8; +//Mask a for FAT32 entry. Entries are 28 bits. +static const u32 FAT32MASK = 0X0FFFFFFF; + +//------------------------------------------------------------------------------ + + +//\struct directoryEntry +//\brief FAT short directory entry +//Short means short 8.3 name, not the entry size. +// +//Date Format. A FAT directory entry date stamp is a 16-bit field that is +//basically a date relative to the MS-DOS epoch of 01/01/1980. Here is the +//format (bit 0 is the LSB of the 16-bit word, bit 15 is the MSB of the +//16-bit word): +// +//Bits 9-15: Count of years from 1980, valid value range 0-127 +//inclusive (1980-2107). +// +//Bits 5-8: Month of year, 1 = January, valid value range 1-12 inclusive. +//Bits 0-4: Day of month, valid value range 1-31 inclusive. +//Time Format. A FAT directory entry time stamp is a 16-bit field that has +//a granularity of 2 seconds. Here is the format (bit 0 is the LSB of the +//16-bit word, bit 15 is the MSB of the 16-bit word). +// +//Bits 11-15: Hours, valid value range 0-23 inclusive. +// +//Bits 5-10: Minutes, valid value range 0-59 inclusive. +// +//Bits 0-4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds). +// +//The valid time range is from Midnight 00:00:00 to 23:59:58. +struct TDirectoryEntry { + //Short 8.3 name. + //The first eight bytes contain the file name with blank fill. + //The last three bytes contain the file extension with blank fill. + + u8 name[11]; + //Entry attributes. + //The upper two bits of the attribute byte are reserved and should + //always be set to 0 when a file is created and never modified or + //looked at after that. See defines that begin with DIR_ATT_. + + u8 attributes; + + //Reserved for use by Windows NT. Set value to 0 when a file is + //created and never modify or look at it after that. + + u8 reservedNT; + + //The granularity of the seconds part of creationTime is 2 seconds + //so this field is a count of tenths of a second and its valid + //value range is 0-199 inclusive. (WHG note - seems to be hundredths) + + u8 creationTimeTenths; + //Time file was created. + u16 creationTime; + //Date file was created. + u16 creationDate; + + //Last access date. Note that there is no last access time, only + //a date. This is the date of last read or write. In the case of + //a write, this should be set to the same date as lastWriteDate. + + u16 lastAccessDate; + + //High word of this entry's first cluster number (always 0 for a + //FAT12 or FAT16 volume). + + u16 firstClusterHigh; + //Time of last write. File creation is considered a write. + u16 lastWriteTime; + // Date of last write. File creation is considered a write. + u16 lastWriteDate; + // Low word of this entry's first cluster number. + u16 firstClusterLow; + //32-bit unsigned holding this file's size in bytes. + u32 fileSize; +}; + +//escape for name[0] = 0xE5 +static const u8 DIR_NAME_0XE5 = 0x05; +//name[0] value for entry that is free after being "deleted" +static const u8 DIR_NAME_DELETED = 0xE5; +//name[0] value for entry that is free and no allocated entries follow +static const u8 DIR_NAME_FREE = 0x00; +//file is read-only +static const u8 DIR_ATT_READ_ONLY = 0x01; +//File should hidden in directory listings +static const u8 DIR_ATT_HIDDEN = 0x02; +//Entry is for a system file +static const u8 DIR_ATT_SYSTEM = 0x04; +//Directory entry contains the volume label +static const u8 DIR_ATT_VOLUME_ID = 0x08; +//Entry is for a directory +static const u8 DIR_ATT_DIRECTORY = 0x10; +//Old DOS archive bit for backup support +static const u8 DIR_ATT_ARCHIVE = 0x20; +//Test value for long name entry. Test is + //(d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. +static const u8 DIR_ATT_LONG_NAME = 0x0F; +//Test mask for long name entry +static const u8 DIR_ATT_LONG_NAME_MASK = 0x3F; +//defined attribute bits +static const u8 DIR_ATT_DEFINED_BITS = 0x3F; +//Directory entry is part of a long name +static inline u8 DIR_IS_LONG_NAME(const TDirectoryEntry* dir) { + return (dir->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME; +} +//Mask for file/subdirectory tests +static const u8 DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY); +//Directory entry is for a file +static inline u8 DIR_IS_FILE(const TDirectoryEntry* dir) { + return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0; +} +//Directory entry is for a subdirectory +static inline u8 DIR_IS_SUBDIR(const TDirectoryEntry* dir) { + return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY; +} +//Directory entry is for a file or subdirectory +static inline u8 DIR_IS_FILE_OR_SUBDIR(const TDirectoryEntry* dir) { + return (dir->attributes & DIR_ATT_VOLUME_ID) == 0; +} + +// flags for timestamp +/** set the file's last access date */ +static const u8 T_ACCESS = 1; +/** set the file's creation date and time */ +static const u8 T_CREATE = 2; +/** Set the file's write date and time */ +static const u8 T_WRITE = 4; +// values for type_ +/** This SdFile has not been opened. */ +static const u8 FAT_FILE_TYPE_CLOSED = 0; +/** SdFile for a file */ +static const u8 FAT_FILE_TYPE_NORMAL = 1; +/** SdFile for a FAT16 root directory */ +static const u8 FAT_FILE_TYPE_ROOT16 = 2; +/** SdFile for a FAT32 root directory */ +static const u8 FAT_FILE_TYPE_ROOT32 = 3; +/** SdFile for a subdirectory */ +static const u8 FAT_FILE_TYPE_SUBDIR = 4; +/** Test value for directory type */ +static const u8 FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT16; + +/** date field for FAT directory entry */ +static inline u16 FAT_DATE(u16 year, u8 month, u8 day) { + return (year - 1980) << 9 | month << 5 | day; +} +/** year part of FAT directory date field */ +static inline u16 FAT_YEAR(u16 fatDate) { + return 1980 + (fatDate >> 9); +} +/** month part of FAT directory date field */ +static inline u8 FAT_MONTH(u16 fatDate) { + return (fatDate >> 5) & 0XF; +} +/** day part of FAT directory date field */ +static inline u8 FAT_DAY(u16 fatDate) { + return fatDate & 0X1F; +} +/** time field for FAT directory entry */ +static inline u16 FAT_TIME(u8 hour, u8 minute, u8 second) { + return hour << 11 | minute << 5 | second >> 1; +} +/** hour part of FAT directory time field */ +static inline u8 FAT_HOUR(u16 fatTime) { + return fatTime >> 11; +} +/** minute part of FAT directory time field */ +static inline u8 FAT_MINUTE(u16 fatTime) { + return(fatTime >> 5) & 0X3F; +} +/** second part of FAT directory time field */ +static inline u8 FAT_SECOND(u16 fatTime) { + return 2*(fatTime & 0X1F); +} +/** Default date for file timestamps is 1 Jan 2000 */ +static const u16 FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1; +/** Default time for file timestamp is 1 am */ +static const u16 FAT_DEFAULT_TIME = (1 << 11); + +//------------------------------------------------------ + +class EmuFat; +class EmuFatVolume; +class EmuFatFile; + +union cache_t { + /** Used to access cached file data blocks. */ + u8 data[512]; + /** Used to access cached FAT16 entries. */ + u16 fat16[256]; + /** Used to access cached FAT32 entries. */ + u32 fat32[128]; + /** Used to access cached directory entries. */ + TDirectoryEntry dir[16]; + /** Used to access a cached MasterBoot Record. */ + TMasterBootRecord mbr; + /** Used to access to a cached FAT boot sector. */ + TFat32BootSector fbs; +}; + +class EmuFatFile +{ + public: + /** Create an instance of EmuFatFile. */ + EmuFatFile() : type_(FAT_FILE_TYPE_CLOSED) {} + + bool writeError; + void clearUnbufferedRead(void) { + flags_ &= ~F_FILE_UNBUFFERED_READ; + } + void setUnbufferedRead(void) { + if (isFile()) flags_ |= F_FILE_UNBUFFERED_READ; + } + u8 unbufferedRead(void) const { + return flags_ & F_FILE_UNBUFFERED_READ; + } + + u8 close(void); + u8 contiguousRange(u32* bgnBlock, u32* endBlock); + u8 createContiguous(EmuFatFile* dirFile, const char* fileName, u32 size); + /** \return The current cluster number for a file or directory. */ + u32 curCluster(void) const {return curCluster_;} + /** \return The current position for a file or directory. */ + u32 curPosition(void) const {return curPosition_;} + + u8 rmDir(void); + u8 rmRfStar(void); + s16 read(void) { + u8 b; + return read(&b, 1) == 1 ? b : -1; + } + s32 read(void* buf, u32 nbyte); + s8 readDir(TDirectoryEntry* dir); + s32 write(const void* buf, u32 nbyte); + + u8 openRoot(EmuFatVolume* vol); + u8 timestamp(u8 flag, u16 year, u8 month, u8 day, u8 hour, u8 minute, u8 second); + u8 sync(void); + u8 makeDir(EmuFatFile* dir, const char* dirName); + u8 open(EmuFatFile* dirFile, u16 index, u8 oflag); + u8 open(EmuFatFile* dirFile, const char* fileName, u8 oflag); + u8 remove(EmuFatFile* dirFile, const char* fileName); + u8 remove(void); + u8 dirEntry(TDirectoryEntry* dir); + u8 seekCur(u32 pos) { + return seekSet(curPosition_ + pos); + } + /** + * Set the files current position to end of file. Useful to position + * a file for append. See seekSet(). + */ + u8 seekEnd(void) {return seekSet(fileSize_);} + u8 seekSet(u32 pos); + + u8 type(void) const {return type_;} + u8 truncate(u32 size); + + u32 dirBlock(void) const {return dirBlock_;} + /** \return Index of this file's directory in the block dirBlock. */ + u8 dirIndex(void) const {return dirIndex_;} + static void dirName(const TDirectoryEntry& dir, char* name); + /** \return The total number of bytes in a file or directory. */ + u32 fileSize(void) const {return fileSize_;} + /** \return The first cluster number for a file or directory. */ + u32 firstCluster(void) const {return firstCluster_;} + /** \return True if this is a SdFile for a directory else false. */ + u8 isDir(void) const {return type_ >= FAT_FILE_TYPE_MIN_DIR;} + /** \return True if this is a SdFile for a file else false. */ + u8 isFile(void) const {return type_ == FAT_FILE_TYPE_NORMAL;} + /** \return True if this is a SdFile for an open file/directory else false. */ + u8 isOpen(void) const {return type_ != FAT_FILE_TYPE_CLOSED;} + /** \return True if this is a SdFile for a subdirectory else false. */ + u8 isSubDir(void) const {return type_ == FAT_FILE_TYPE_SUBDIR;} + /** \return True if this is a SdFile for the root directory. */ + u8 isRoot(void) const { + return type_ == FAT_FILE_TYPE_ROOT16 || type_ == FAT_FILE_TYPE_ROOT32; + } + + /** Set the file's current position to zero. */ + void rewind(void) { + curPosition_ = curCluster_ = 0; + } + + +private: + // bits defined in flags_ + // should be 0XF + static const u8 F_OFLAG = (EO_ACCMODE | EO_APPEND | EO_SYNC); + // available bits + static const u8 F_UNUSED = 0x30; + // use unbuffered SD read + static const u8 F_FILE_UNBUFFERED_READ = 0X40; + // sync of directory entry required + static const u8 F_FILE_DIR_DIRTY = 0x80; +// make sure F_OFLAG is ok + + void ctassert() + { + CTASSERT(!((F_UNUSED | F_FILE_UNBUFFERED_READ | F_FILE_DIR_DIRTY) & F_OFLAG)); + } + + // private data + u8 flags_; // See above for definition of flags_ bits + u8 type_; // type of file see above for values + u32 curCluster_; // cluster for current file position + u32 curPosition_; // current file position in bytes from beginning + u32 dirBlock_; // SD block that contains directory entry for file + u8 dirIndex_; // index of entry in dirBlock 0 <= dirIndex_ <= 0XF + u32 fileSize_; // file size in bytes + u32 firstCluster_; // first cluster of file + EmuFatVolume* vol_; // volume where file is located + + // private functions + u8 addCluster(void); + u8 addDirCluster(void); + TDirectoryEntry* cacheDirEntry(u8 action); + static u8 make83Name(const char* str, u8* name); + u8 openCachedEntry(u8 cacheIndex, u8 oflags); + TDirectoryEntry* readDirCache(void); +}; + +class EmuFatVolume +{ +public: + EmuFatVolume() :allocSearchStart_(2), fatType_(0) {} + + //Initialize a FAT volume. Try partition one first then try super floppy format. + //dev The Sd2Card where the volume is located. + //return The value one, true, is returned for success and + //the value zero, false, is returned for failure. Reasons for + //failure include not finding a valid partition, not finding a valid + //FAT file system or an I/O error. + bool init(EmuFat* dev) { return init(dev, 1) ? true : init(dev, 0);} + bool init(EmuFat* dev, u8 part); + + bool format(u32 sectors); + bool formatNew(u32 sectors); + + // inline functions that return volume info + //The volume's cluster size in blocks. + u8 blocksPerCluster(void) const {return blocksPerCluster_;} + //The number of blocks in one FAT. + u32 blocksPerFat(void) const {return blocksPerFat_;} + //The total number of clusters in the volume. // + u32 clusterCount(void) const {return clusterCount_;} + //The shift count required to multiply by blocksPerCluster. // + u8 clusterSizeShift(void) const {return clusterSizeShift_;} + //The logical block number for the start of file data. // + u32 dataStartBlock(void) const {return dataStartBlock_;} + //The number of FAT structures on the volume. // + u8 fatCount(void) const {return fatCount_;} + //The logical block number for the start of the first FAT. // + u32 fatStartBlock(void) const {return fatStartBlock_;} + //The FAT type of the volume. Values are 12, 16 or 32. // + u8 fatType(void) const {return fatType_;} + //The number of entries in the root directory for FAT16 volumes. // + u32 rootDirEntryCount(void) const {return rootDirEntryCount_;} + //The logical block number for the start of the root directory on FAT16 volumes or the first cluster number on FAT32 volumes. // + u32 rootDirStart(void) const {return rootDirStart_;} + + EmuFat* dev_; + + +private: + friend class EmuFatFile; + + u32 allocSearchStart_; // start cluster for alloc search + u8 blocksPerCluster_; // cluster size in blocks + u32 blocksPerFat_; // FAT size in blocks + u32 clusterCount_; // clusters in one FAT + u8 clusterSizeShift_; // shift to convert cluster count to block count + u32 dataStartBlock_; // first data block number + u8 fatCount_; // number of FATs on volume + u32 fatStartBlock_; // start block for first FAT + u8 fatType_; // volume type (12, 16, OR 32) + u16 rootDirEntryCount_; // number of entries in FAT16 root dir + u32 rootDirStart_; // root start block for FAT16, cluster for FAT32 + + u8 allocContiguous(u32 count, u32* curCluster); + u8 blockOfCluster(u32 position) const { + return (position >> 9) & (blocksPerCluster_ - 1);} + u32 clusterStartBlock(u32 cluster) const { + return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_);} + u32 blockNumber(u32 cluster, u32 position) const { + return clusterStartBlock(cluster) + blockOfCluster(position);} + u8 fatGet(u32 cluster, u32* value) const; + u8 fatPut(u32 cluster, u32 value); + u8 fatPutEOC(u32 cluster) { + return fatPut(cluster, 0x0FFFFFFF); + } + u8 chainSize(u32 beginCluster, u32* size) const; + u8 freeChain(u32 cluster); + u8 isEOC(u32 cluster) const { + return cluster >= (fatType_ == 16 ? FAT16EOC_MIN : FAT32EOC_MIN); + } + u8 readData(u32 block, u16 offset, u16 count, u8* dst); + u8 writeBlock(u32 block, const u8* dst); + +}; + +class EmuFat +{ +public: + EmuFat(const char* fname, bool readonly=false); + EmuFat(); + EmuFat(EMUFILE* fileNotToDelete); + virtual ~EmuFat(); + +private: + EMUFILE* m_pFile; + bool m_readonly, m_owns; + + friend class EmuFatVolume; + friend class EmuFatFile; + + // value for action argument in cacheRawBlock to indicate read from cache + static const u8 CACHE_FOR_READ = 0; + // value for action argument in cacheRawBlock to indicate cache dirty + static const u8 CACHE_FOR_WRITE = 1; + + struct Cache + { + Cache() + : cacheBlockNumber_(0xFFFFFFFF) + , cacheDirty_(0) // cacheFlush() will write block if true + , cacheMirrorBlock_(0) // mirror block for second FAT + {} + + cache_t cacheBuffer_; // 512 byte cache for device blocks + u32 cacheBlockNumber_; // Logical number of block in the cache + u8 cacheDirty_; // cacheFlush() will write block if true + u32 cacheMirrorBlock_; // block number for mirror FAT + } cache_; + + u8 cacheRawBlock(u32 blockNumber, u8 action); + void cacheSetDirty() {cache_.cacheDirty_ |= CACHE_FOR_WRITE;} + u8 cacheZeroBlock(u32 blockNumber); + u8 cacheFlush(); + void cacheReset(); + + //IO functions: + u8 readBlock(u32 block, u8* dst); + u8 writeBlock(u32 blockNumber, const u8* src); + u8 readData(u32 block, u16 offset, u16 count, u8* dst); + + void truncate(u32 size); +}; + +#endif //EMUFAT_H diff --git a/jni/desmume/src/utils/emufat_types.h b/jni/desmume/src/utils/emufat_types.h new file mode 100755 index 0000000..cd64dfd --- /dev/null +++ b/jni/desmume/src/utils/emufat_types.h @@ -0,0 +1,6 @@ +#ifndef EMUFAT_TYPES_H +#define EMUFAT_TYPES_H + +#include "types.h" + +#endif //EMUFAT_TYPES_H diff --git a/jni/desmume/src/utils/guid.cpp b/jni/desmume/src/utils/guid.cpp new file mode 100755 index 0000000..95b7650 --- /dev/null +++ b/jni/desmume/src/utils/guid.cpp @@ -0,0 +1,66 @@ +/* + Copyright (C) 2008-2009 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "guid.h" +#include "../types.h" + +void Desmume_Guid::newGuid() +{ + for(int i=0;i<size;i++) + data[i] = rand(); +} + +std::string Desmume_Guid::toString() +{ + char buf[37]; + sprintf(buf,"%08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X", + de32lsb(data),de16lsb(data+4),de16lsb(data+6),de16lsb(data+8),data[10],data[11],data[12],data[13],data[14],data[15]); + return std::string(buf); +} + +Desmume_Guid Desmume_Guid::fromString(std::string str) +{ + Desmume_Guid ret; + ret.scan(str); + return ret; +} + +uint8 Desmume_Guid::hexToByte(char** ptrptr) +{ + char a = toupper(**ptrptr); + (*ptrptr)++; + char b = toupper(**ptrptr); + (*ptrptr)++; + if(a>='A') a=a-'A'+10; + else a-='0'; + if(b>='A') b=b-'A'+10; + else b-='0'; + return ((unsigned char)a<<4)|(unsigned char)b; +} + +void Desmume_Guid::scan(std::string& str) +{ + char* endptr = (char*)str.c_str(); + en32lsb(data,strtoul(endptr,&endptr,16)); + en16lsb(data+4,(u16)strtoul(endptr+1,&endptr,16)); + en16lsb(data+6,(u16)strtoul(endptr+1,&endptr,16)); + en16lsb(data+8,(u16)strtoul(endptr+1,&endptr,16)); + endptr++; + for(int i=0;i<6;i++) + data[10+i] = hexToByte(&endptr); +} diff --git a/jni/desmume/src/utils/guid.h b/jni/desmume/src/utils/guid.h new file mode 100755 index 0000000..5e19e4b --- /dev/null +++ b/jni/desmume/src/utils/guid.h @@ -0,0 +1,36 @@ +/* + Copyright (C) 2008-2009 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _guid_h_ +#define _guid_h_ + +#include <string> +#include <cstdio> +#include "../types.h" +#include "valuearray.h" + +struct Desmume_Guid : public ValueArray<u8,16> +{ + void newGuid(); + std::string toString(); + static Desmume_Guid fromString(std::string str); + static uint8 hexToByte(char** ptrptr); + void scan(std::string& str); +}; + + +#endif diff --git a/jni/desmume/src/utils/libfat/bit_ops.h b/jni/desmume/src/utils/libfat/bit_ops.h new file mode 100755 index 0000000..f61cac6 --- /dev/null +++ b/jni/desmume/src/utils/libfat/bit_ops.h @@ -0,0 +1,59 @@ +/* + bit_ops.h + Functions for dealing with conversion of data between types + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _BIT_OPS_H +#define _BIT_OPS_H + +#ifndef _MSC_VER +#include <stdint.h> +#endif + +/*----------------------------------------------------------------- +Functions to deal with little endian values stored in uint8_t arrays +-----------------------------------------------------------------*/ +static inline uint16_t u8array_to_u16 (const uint8_t* item, int offset) { + return ( item[offset] | (item[offset + 1] << 8)); +} + +static inline uint32_t u8array_to_u32 (const uint8_t* item, int offset) { + return ( item[offset] | (item[offset + 1] << 8) | (item[offset + 2] << 16) | (item[offset + 3] << 24)); +} + +static inline void u16_to_u8array (uint8_t* item, int offset, uint16_t value) { + item[offset] = (uint8_t) value; + item[offset + 1] = (uint8_t)(value >> 8); +} + +static inline void u32_to_u8array (uint8_t* item, int offset, uint32_t value) { + item[offset] = (uint8_t) value; + item[offset + 1] = (uint8_t)(value >> 8); + item[offset + 2] = (uint8_t)(value >> 16); + item[offset + 3] = (uint8_t)(value >> 24); +} + +#endif // _BIT_OPS_H diff --git a/jni/desmume/src/utils/libfat/cache.cpp b/jni/desmume/src/utils/libfat/cache.cpp new file mode 100755 index 0000000..8429299 --- /dev/null +++ b/jni/desmume/src/utils/libfat/cache.cpp @@ -0,0 +1,366 @@ +/* + cache.c + The cache is not visible to the user. It should be flushed + when any file is closed or changes are made to the filesystem. + + This cache implements a least-used-page replacement policy. This will + distribute sectors evenly over the pages, so if less than the maximum + pages are used at once, they should all eventually remain in the cache. + This also has the benefit of throwing out old sectors, so as not to keep + too many stale pages around. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <string.h> +#include <limits.h> + +#include "common.h" +#include "cache.h" +#include "disc.h" + +#include "mem_allocate.h" +#include "bit_ops.h" +#include "file_allocation_table.h" + +#define CACHE_FREE UINT_MAX + +CACHE* _FAT_cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition) { + CACHE* cache; + unsigned int i; + CACHE_ENTRY* cacheEntries; + + if (numberOfPages < 2) { + numberOfPages = 2; + } + + if (sectorsPerPage < 8) { + sectorsPerPage = 8; + } + + cache = (CACHE*) _FAT_mem_allocate (sizeof(CACHE)); + if (cache == NULL) { + return NULL; + } + + cache->disc = discInterface; + cache->endOfPartition = endOfPartition; + cache->numberOfPages = numberOfPages; + cache->sectorsPerPage = sectorsPerPage; + + + cacheEntries = (CACHE_ENTRY*) _FAT_mem_allocate ( sizeof(CACHE_ENTRY) * numberOfPages); + if (cacheEntries == NULL) { + _FAT_mem_free (cache); + return NULL; + } + + for (i = 0; i < numberOfPages; i++) { + cacheEntries[i].sector = CACHE_FREE; + cacheEntries[i].count = 0; + cacheEntries[i].last_access = 0; + cacheEntries[i].dirty = false; + cacheEntries[i].cache = (uint8_t*) _FAT_mem_align ( sectorsPerPage * BYTES_PER_READ ); + } + + cache->cacheEntries = cacheEntries; + + return cache; +} + +void _FAT_cache_destructor (CACHE* cache) { + unsigned int i; + // Clear out cache before destroying it + _FAT_cache_flush(cache); + + // Free memory in reverse allocation order + for (i = 0; i < cache->numberOfPages; i++) { + _FAT_mem_free (cache->cacheEntries[i].cache); + } + _FAT_mem_free (cache->cacheEntries); + _FAT_mem_free (cache); +} + + +static u32 accessCounter = 0; + +static u32 accessTime(){ + accessCounter++; + return accessCounter; +} + + +static CACHE_ENTRY* _FAT_cache_getPage(CACHE *cache,sec_t sector) +{ + unsigned int i; + CACHE_ENTRY* cacheEntries = cache->cacheEntries; + unsigned int numberOfPages = cache->numberOfPages; + unsigned int sectorsPerPage = cache->sectorsPerPage; + + bool foundFree = false; + unsigned int oldUsed = 0; + unsigned int oldAccess = UINT_MAX; + + for(i=0;i<numberOfPages;i++) { + if(sector>=cacheEntries[i].sector && sector<(cacheEntries[i].sector + cacheEntries[i].count)) { + cacheEntries[i].last_access = accessTime(); + return &(cacheEntries[i]); + } + + if(foundFree==false && (cacheEntries[i].sector==CACHE_FREE || cacheEntries[i].last_access<oldAccess)) { + if(cacheEntries[i].sector==CACHE_FREE) foundFree = true; + oldUsed = i; + oldAccess = cacheEntries[i].last_access; + } + } + + if(foundFree==false && cacheEntries[oldUsed].dirty==true) { + if(!_FAT_disc_writeSectors(cache->disc,cacheEntries[oldUsed].sector,cacheEntries[oldUsed].count,cacheEntries[oldUsed].cache)) return NULL; + cacheEntries[oldUsed].dirty = false; + } + + sector = (sector/sectorsPerPage)*sectorsPerPage; // align base sector to page size + sec_t next_page = sector + sectorsPerPage; + if(next_page > cache->endOfPartition) next_page = cache->endOfPartition; + + if(!_FAT_disc_readSectors(cache->disc,sector,next_page-sector,cacheEntries[oldUsed].cache)) return NULL; + + cacheEntries[oldUsed].sector = sector; + cacheEntries[oldUsed].count = next_page-sector; + cacheEntries[oldUsed].last_access = accessTime(); + + return &(cacheEntries[oldUsed]); +} + +bool _FAT_cache_readSectors(CACHE *cache,sec_t sector,sec_t numSectors,void *buffer) +{ + sec_t sec; + sec_t secs_to_read; + CACHE_ENTRY *entry; + uint8_t *dest = (uint8_t *)buffer; + + while(numSectors>0) { + entry = _FAT_cache_getPage(cache,sector); + if(entry==NULL) return false; + + sec = sector - entry->sector; + secs_to_read = entry->count - sec; + if(secs_to_read>numSectors) secs_to_read = numSectors; + + memcpy(dest,entry->cache + (sec*BYTES_PER_READ),(secs_to_read*BYTES_PER_READ)); + + dest += (secs_to_read*BYTES_PER_READ); + sector += secs_to_read; + numSectors -= secs_to_read; + } + + return true; +} + +/* +Reads some data from a cache page, determined by the sector number +*/ +bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, sec_t sector, unsigned int offset, size_t size) +{ + sec_t sec; + CACHE_ENTRY *entry; + + if (offset + size > BYTES_PER_READ) return false; + + entry = _FAT_cache_getPage(cache,sector); + if(entry==NULL) return false; + + sec = sector - entry->sector; + memcpy(buffer,entry->cache + ((sec*BYTES_PER_READ) + offset),size); + + return true; +} + +bool _FAT_cache_readLittleEndianValue (CACHE* cache, uint32_t *value, sec_t sector, unsigned int offset, int num_bytes) { + uint8_t buf[4]; + if (!_FAT_cache_readPartialSector(cache, buf, sector, offset, num_bytes)) return false; + + switch(num_bytes) { + case 1: *value = buf[0]; break; + case 2: *value = u8array_to_u16(buf,0); break; + case 4: *value = u8array_to_u32(buf,0); break; + default: return false; + } + return true; +} + +/* +Writes some data to a cache page, making sure it is loaded into memory first. +*/ +bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size) +{ + sec_t sec; + CACHE_ENTRY *entry; + + if (offset + size > BYTES_PER_READ) return false; + + entry = _FAT_cache_getPage(cache,sector); + if(entry==NULL) return false; + + sec = sector - entry->sector; + memcpy(entry->cache + ((sec*BYTES_PER_READ) + offset),buffer,size); + + entry->dirty = true; + return true; +} + +bool _FAT_cache_writeLittleEndianValue (CACHE* cache, const uint32_t value, sec_t sector, unsigned int offset, int size) { + uint8_t buf[4] = {0, 0, 0, 0}; + + switch(size) { + case 1: buf[0] = value; break; + case 2: u16_to_u8array(buf, 0, value); break; + case 4: u32_to_u8array(buf, 0, value); break; + default: return false; + } + + return _FAT_cache_writePartialSector(cache, buf, sector, offset, size); +} + +/* +Writes some data to a cache page, zeroing out the page first +*/ +bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size) +{ + sec_t sec; + CACHE_ENTRY *entry; + + if (offset + size > BYTES_PER_READ) return false; + + entry = _FAT_cache_getPage(cache,sector); + if(entry==NULL) return false; + + sec = sector - entry->sector; + memset(entry->cache + (sec*BYTES_PER_READ),0,BYTES_PER_READ); + memcpy(entry->cache + ((sec*BYTES_PER_READ) + offset),buffer,size); + + entry->dirty = true; + return true; +} + + +static CACHE_ENTRY* _FAT_cache_findPage(CACHE *cache, sec_t sector, sec_t count) { + + unsigned int i; + CACHE_ENTRY* cacheEntries = cache->cacheEntries; + unsigned int numberOfPages = cache->numberOfPages; + CACHE_ENTRY *entry = NULL; + sec_t lowest = UINT_MAX; + + for(i=0;i<numberOfPages;i++) { + if (cacheEntries[i].sector != CACHE_FREE) { + bool intersect; + if (sector > cacheEntries[i].sector) { + intersect = sector - cacheEntries[i].sector < cacheEntries[i].count; + } else { + intersect = cacheEntries[i].sector - sector < count; + } + + if ( intersect && (cacheEntries[i].sector < lowest)) { + lowest = cacheEntries[i].sector; + entry = &cacheEntries[i]; + } + } + } + + return entry; +} + +bool _FAT_cache_writeSectors (CACHE* cache, sec_t sector, sec_t numSectors, const void* buffer) +{ + sec_t sec; + sec_t secs_to_write; + CACHE_ENTRY* entry; + const uint8_t *src = (const uint8_t *)buffer; + + while(numSectors>0) + { + entry = _FAT_cache_findPage(cache,sector,numSectors); + + if(entry!=NULL) { + + if ( entry->sector > sector) { + + secs_to_write = entry->sector - sector; + + _FAT_disc_writeSectors(cache->disc,sector,secs_to_write,src); + src += (secs_to_write*BYTES_PER_READ); + sector += secs_to_write; + numSectors -= secs_to_write; + } + + sec = sector - entry->sector; + secs_to_write = entry->count - sec; + + if(secs_to_write>numSectors) secs_to_write = numSectors; + + memcpy(entry->cache + (sec*BYTES_PER_READ),src,(secs_to_write*BYTES_PER_READ)); + + src += (secs_to_write*BYTES_PER_READ); + sector += secs_to_write; + numSectors -= secs_to_write; + + entry->dirty = true; + + } else { + _FAT_disc_writeSectors(cache->disc,sector,numSectors,src); + numSectors=0; + } + } + return true; +} + +/* +Flushes all dirty pages to disc, clearing the dirty flag. +*/ +bool _FAT_cache_flush (CACHE* cache) { + unsigned int i; + + for (i = 0; i < cache->numberOfPages; i++) { + if (cache->cacheEntries[i].dirty) { + if (!_FAT_disc_writeSectors (cache->disc, cache->cacheEntries[i].sector, cache->cacheEntries[i].count, cache->cacheEntries[i].cache)) { + return false; + } + } + cache->cacheEntries[i].dirty = false; + } + + return true; +} + +void _FAT_cache_invalidate (CACHE* cache) { + unsigned int i; + _FAT_cache_flush(cache); + for (i = 0; i < cache->numberOfPages; i++) { + cache->cacheEntries[i].sector = CACHE_FREE; + cache->cacheEntries[i].last_access = 0; + cache->cacheEntries[i].count = 0; + cache->cacheEntries[i].dirty = false; + } +} diff --git a/jni/desmume/src/utils/libfat/cache.h b/jni/desmume/src/utils/libfat/cache.h new file mode 100755 index 0000000..c6e48d0 --- /dev/null +++ b/jni/desmume/src/utils/libfat/cache.h @@ -0,0 +1,130 @@ +/* + cache.h + The cache is not visible to the user. It should be flushed + when any file is closed or changes are made to the filesystem. + + This cache implements a least-used-page replacement policy. This will + distribute sectors evenly over the pages, so if less than the maximum + pages are used at once, they should all eventually remain in the cache. + This also has the benefit of throwing out old sectors, so as not to keep + too many stale pages around. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _CACHE_H +#define _CACHE_H + +#include "common.h" +#include "disc.h" + +#define PAGE_SECTORS 64 +#define CACHE_PAGE_SIZE (BYTES_PER_READ * PAGE_SECTORS) + +typedef struct { + sec_t sector; + unsigned int count; + unsigned int last_access; + bool dirty; + uint8_t* cache; +} CACHE_ENTRY; + +typedef struct { + const DISC_INTERFACE* disc; + sec_t endOfPartition; + unsigned int numberOfPages; + unsigned int sectorsPerPage; + CACHE_ENTRY* cacheEntries; +} CACHE; + +/* +Read data from a sector in the cache +If the sector is not in the cache, it will be swapped in +offset is the position to start reading from +size is the amount of data to read +Precondition: offset + size <= BYTES_PER_READ +*/ +bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, sec_t sector, unsigned int offset, size_t size); + +bool _FAT_cache_readLittleEndianValue (CACHE* cache, uint32_t *value, sec_t sector, unsigned int offset, int num_bytes); + +/* +Write data to a sector in the cache +If the sector is not in the cache, it will be swapped in. +When the sector is swapped out, the data will be written to the disc +offset is the position to start writing to +size is the amount of data to write +Precondition: offset + size <= BYTES_PER_READ +*/ +bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size); + +bool _FAT_cache_writeLittleEndianValue (CACHE* cache, const uint32_t value, sec_t sector, unsigned int offset, int num_bytes); + +/* +Write data to a sector in the cache, zeroing the sector first +If the sector is not in the cache, it will be swapped in. +When the sector is swapped out, the data will be written to the disc +offset is the position to start writing to +size is the amount of data to write +Precondition: offset + size <= BYTES_PER_READ +*/ +bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size); + +/* +Read several sectors from the cache +*/ +bool _FAT_cache_readSectors (CACHE* cache, sec_t sector, sec_t numSectors, void* buffer); + +/* +Read a full sector from the cache +*/ +static inline bool _FAT_cache_readSector (CACHE* cache, void* buffer, sec_t sector) { + return _FAT_cache_readPartialSector (cache, buffer, sector, 0, BYTES_PER_READ); +} + +/* +Write a full sector to the cache +*/ +static inline bool _FAT_cache_writeSector (CACHE* cache, const void* buffer, sec_t sector) { + return _FAT_cache_writePartialSector (cache, buffer, sector, 0, BYTES_PER_READ); +} + +bool _FAT_cache_writeSectors (CACHE* cache, sec_t sector, sec_t numSectors, const void* buffer); + +/* +Write any dirty sectors back to disc and clear out the contents of the cache +*/ +bool _FAT_cache_flush (CACHE* cache); + +/* +Clear out the contents of the cache without writing any dirty sectors first +*/ +void _FAT_cache_invalidate (CACHE* cache); + +CACHE* _FAT_cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition); + +void _FAT_cache_destructor (CACHE* cache); + +#endif // _CACHE_H + diff --git a/jni/desmume/src/utils/libfat/common.h b/jni/desmume/src/utils/libfat/common.h new file mode 100755 index 0000000..fc5e486 --- /dev/null +++ b/jni/desmume/src/utils/libfat/common.h @@ -0,0 +1,90 @@ +/* + common.h + Common definitions and included files for the FATlib + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _COMMON_H +#define _COMMON_H + +#define BYTES_PER_READ 512 +#include <stddef.h> +#ifndef _MSC_VER +#include <stdint.h> +#endif + +// When compiling for NDS, make sure NDS is defined +#ifndef NDS + #if defined ARM9 || defined ARM7 + #define NDS + #endif +#endif + +// Platform specific includes +#if defined(__gamecube__) || defined (__wii__) + #include <gctypes.h> + #include <ogc/disc_io.h> + #include <gccore.h> +#elif defined(NDS) + #include <nds/ndstypes.h> + #include <nds/system.h> + #include <nds/disc_io.h> +#elif defined(GBA) + #include <gba_types.h> + #include <disc_io.h> +#endif + +// Platform specific options +#if defined (__wii__) + #define DEFAULT_CACHE_PAGES 4 + #define DEFAULT_SECTORS_PAGE 64 + #define USE_LWP_LOCK + #define USE_RTC_TIME +#elif defined (__gamecube__) + #define DEFAULT_CACHE_PAGES 4 + #define DEFAULT_SECTORS_PAGE 64 + #define USE_LWP_LOCK + #define USE_RTC_TIME +#elif defined (NDS) + #define DEFAULT_CACHE_PAGES 4 + #define DEFAULT_SECTORS_PAGE 8 + #define USE_RTC_TIME +#elif defined (GBA) + #define DEFAULT_CACHE_PAGES 2 + #define DEFAULT_SECTORS_PAGE 8 + #define LIMIT_SECTORS 128 +#else + #define LIBFAT_PC 1 + + //any particular reason for this? + #define DEFAULT_CACHE_PAGES 4 + #define DEFAULT_SECTORS_PAGE 8 +#endif + +#include "libfat_pc.h" + +#include "fat.h" + +#endif // _COMMON_H diff --git a/jni/desmume/src/utils/libfat/directory.cpp b/jni/desmume/src/utils/libfat/directory.cpp new file mode 100755 index 0000000..765d7ae --- /dev/null +++ b/jni/desmume/src/utils/libfat/directory.cpp @@ -0,0 +1,1139 @@ +/* + directory.c + Reading, writing and manipulation of the directory structure on + a FAT partition + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <string.h> +#include <ctype.h> +#include <wchar.h> +#include <wctype.h> +#include <stdlib.h> +#include <stdio.h> + +#include "directory.h" +#include "common.h" +#include "partition.h" +#include "file_allocation_table.h" +#include "bit_ops.h" +#include "filetime.h" + +#ifdef __APPLE__ +#include <AvailabilityMacros.h> + +#ifndef MAC_OS_X_VERSION_10_7 +// In Mac OS X, strnlen() is unsupported prior to v10.7, so define it here. +static size_t strnlen(const char *s, size_t n) +{ + const char *p = (const char *)memchr(s, 0, n); + return(p ? p-s : n); +} +#endif + +#endif // __APPLE__ + +// Directory entry codes +#define DIR_ENTRY_LAST 0x00 +#define DIR_ENTRY_FREE 0xE5 + +#define LAST_LFN_POS (19*13) +#define LAST_LFN_POS_CORRECTION (MAX_LFN_LENGTH-15) + +typedef unsigned short ucs2_t; + +// Long file name directory entry +enum LFN_offset { + LFN_offset_ordinal = 0x00, // Position within LFN + LFN_offset_char0 = 0x01, + LFN_offset_char1 = 0x03, + LFN_offset_char2 = 0x05, + LFN_offset_char3 = 0x07, + LFN_offset_char4 = 0x09, + LFN_offset_flag = 0x0B, // Should be equal to ATTRIB_LFN + LFN_offset_reserved1 = 0x0C, // Always 0x00 + LFN_offset_checkSum = 0x0D, // Checksum of short file name (alias) + LFN_offset_char5 = 0x0E, + LFN_offset_char6 = 0x10, + LFN_offset_char7 = 0x12, + LFN_offset_char8 = 0x14, + LFN_offset_char9 = 0x16, + LFN_offset_char10 = 0x18, + LFN_offset_reserved2 = 0x1A, // Always 0x0000 + LFN_offset_char11 = 0x1C, + LFN_offset_char12 = 0x1E +}; +static const int LFN_offset_table[13]={0x01,0x03,0x05,0x07,0x09,0x0E,0x10,0x12,0x14,0x16,0x18,0x1C,0x1E}; + +#define LFN_END 0x40 +#define LFN_DEL 0x80 + +static const char ILLEGAL_ALIAS_CHARACTERS[] = "\\/:;*?\"<>|&+,=[] "; +static const char ILLEGAL_LFN_CHARACTERS[] = "\\/:*?\"<>|"; + +/* +Returns number of UCS-2 characters needed to encode an LFN +Returns -1 if it is an invalid LFN +*/ +#define ABOVE_UCS_RANGE 0xF0 +static int _FAT_directory_lfnLength (const char* name) { + unsigned int i; + size_t nameLength; + int ucsLength; + const char* tempName = name; + + nameLength = strnlen(name, MAX_FILENAME_LENGTH); + // Make sure the name is short enough to be valid + if ( nameLength >= MAX_FILENAME_LENGTH) { + return -1; + } + // Make sure it doesn't contain any invalid characters + if (strpbrk (name, ILLEGAL_LFN_CHARACTERS) != NULL) { + return -1; + } + // Make sure the name doesn't contain any control codes or codes not representable in UCS-2 + for (i = 0; i < nameLength; i++) { + if (name[i] < 0x20 || name[i] >= ABOVE_UCS_RANGE) { + return -1; + } + } + // Convert to UCS-2 and get the resulting length + ucsLength = mbsrtowcs(NULL, &tempName, MAX_LFN_LENGTH, NULL); + if (ucsLength < 0 || ucsLength >= MAX_LFN_LENGTH) { + return -1; + } + + // Otherwise it is valid + return ucsLength; +} + +/* +Convert a multibyte encoded string into a NUL-terminated UCS-2 string, storing at most len characters +return number of characters stored +*/ +static size_t _FAT_directory_mbstoucs2 (ucs2_t* dst, const char* src, size_t len) { + mbstate_t ps = {0}; + wchar_t tempChar; + int bytes; + size_t count = 0; + + while (count < len-1 && src != '\0') { + bytes = mbrtowc (&tempChar, src, MB_CUR_MAX, &ps); + if (bytes > 0) { + *dst = (ucs2_t)tempChar; + src += bytes; + dst++; + count++; + } else if (bytes == 0) { + break; + } else { + return -1; + } + } + *dst = '\0'; + + return count; +} + +/* +Convert a UCS-2 string into a NUL-terminated multibyte string, storing at most len chars +return number of chars stored, or (size_t)-1 on error +*/ +static size_t _FAT_directory_ucs2tombs (char* dst, const ucs2_t* src, size_t len) { + mbstate_t ps = {0}; + size_t count = 0; + int bytes; + char* buff = (char*)alloca(MB_CUR_MAX); + int i; + + while (count < len - 1 && *src != '\0') { + bytes = wcrtomb (buff, *src, &ps); + if (bytes < 0) { + return -1; + } + if (count + bytes < len && bytes > 0) { + for (i = 0; i < bytes; i++) { + *dst++ = buff[i]; + } + src++; + count += bytes; + } else { + break; + } + } + *dst = L'\0'; + + return count; +} + +/* +Case-independent comparison of two multibyte encoded strings +*/ +static int _FAT_directory_mbsncasecmp (const char* s1, const char* s2, size_t len1) { + wchar_t wc1, wc2; + mbstate_t ps1 = {0}; + mbstate_t ps2 = {0}; + size_t b1 = 0; + size_t b2 = 0; + + if (len1 == 0) { + return 0; + } + + do { + s1 += b1; + s2 += b2; + b1 = mbrtowc(&wc1, s1, MB_CUR_MAX, &ps1); + b2 = mbrtowc(&wc2, s2, MB_CUR_MAX, &ps2); + if ((int)b1 < 0 || (int)b2 < 0) { + break; + } + len1 -= b1; + } while (len1 > 0 && towlower(wc1) == towlower(wc2) && wc1 != 0); + + return towlower(wc1) - towlower(wc2); +} + + +static bool _FAT_directory_entryGetAlias (const u8* entryData, char* destName) { + int i=0; + int j=0; + + destName[0] = '\0'; + if (entryData[0] != DIR_ENTRY_FREE) { + if (entryData[0] == '.') { + destName[0] = '.'; + if (entryData[1] == '.') { + destName[1] = '.'; + destName[2] = '\0'; + } else { + destName[1] = '\0'; + } + } else { + // Copy the filename from the dirEntry to the string + for (i = 0; (i < 8) && (entryData[DIR_ENTRY_name + i] != ' '); i++) { + destName[i] = entryData[DIR_ENTRY_name + i]; + } + // Copy the extension from the dirEntry to the string + if (entryData[DIR_ENTRY_extension] != ' ') { + destName[i++] = '.'; + for ( j = 0; (j < 3) && (entryData[DIR_ENTRY_extension + j] != ' '); j++) { + destName[i++] = entryData[DIR_ENTRY_extension + j]; + } + } + destName[i] = '\0'; + } + } + + return (destName[0] != '\0'); +} + +uint32_t _FAT_directory_entryGetCluster (PARTITION* partition, const uint8_t* entryData) { + if (partition->filesysType == FS_FAT32) { + // Only use high 16 bits of start cluster when we are certain they are correctly defined + return u8array_to_u16(entryData,DIR_ENTRY_cluster) | (u8array_to_u16(entryData, DIR_ENTRY_clusterHigh) << 16); + } else { + return u8array_to_u16(entryData,DIR_ENTRY_cluster); + } +} + +static bool _FAT_directory_incrementDirEntryPosition (PARTITION* partition, DIR_ENTRY_POSITION* entryPosition, bool extendDirectory) { + DIR_ENTRY_POSITION position = *entryPosition; + uint32_t tempCluster; + + // Increment offset, wrapping at the end of a sector + ++ position.offset; + if (position.offset == BYTES_PER_READ / DIR_ENTRY_DATA_SIZE) { + position.offset = 0; + // Increment sector when wrapping + ++ position.sector; + // But wrap at the end of a cluster + if ((position.sector == partition->sectorsPerCluster) && (position.cluster != FAT16_ROOT_DIR_CLUSTER)) { + position.sector = 0; + // Move onto the next cluster, making sure there is another cluster to go to + tempCluster = _FAT_fat_nextCluster(partition, position.cluster); + if (tempCluster == CLUSTER_EOF) { + if (extendDirectory) { + tempCluster = _FAT_fat_linkFreeClusterCleared (partition, position.cluster); + if (!_FAT_fat_isValidCluster(partition, tempCluster)) { + return false; // This will only happen if the disc is full + } + } else { + return false; // Got to the end of the directory, not extending it + } + } + position.cluster = tempCluster; + } else if ((position.cluster == FAT16_ROOT_DIR_CLUSTER) && (position.sector == (partition->dataStart - partition->rootDirStart))) { + return false; // Got to end of root directory, can't extend it + } + } + *entryPosition = position; + return true; +} + +bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry) { + DIR_ENTRY_POSITION entryStart; + DIR_ENTRY_POSITION entryEnd; + uint8_t entryData[0x20]; + ucs2_t lfn[MAX_LFN_LENGTH]; + bool notFound, found; + int lfnPos; + uint8_t lfnChkSum, chkSum; + bool lfnExists; + int i; + + lfnChkSum = 0; + + entryStart = entry->dataEnd; + + // Make sure we are using the correct root directory, in case of FAT32 + if (entryStart.cluster == FAT16_ROOT_DIR_CLUSTER) { + entryStart.cluster = partition->rootDirCluster; + } + + entryEnd = entryStart; + + lfnExists = false; + + found = false; + notFound = false; + + while (!found && !notFound) { + if (_FAT_directory_incrementDirEntryPosition (partition, &entryEnd, false) == false) { + notFound = true; + } + + _FAT_cache_readPartialSector (partition->cache, entryData, + _FAT_fat_clusterToSector(partition, entryEnd.cluster) + entryEnd.sector, + entryEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + + if (entryData[DIR_ENTRY_attributes] == ATTRIB_LFN) { + // It's an LFN + if (entryData[LFN_offset_ordinal] & LFN_DEL) { + lfnExists = false; + } else if (entryData[LFN_offset_ordinal] & LFN_END) { + // Last part of LFN, make sure it isn't deleted using previous if(Thanks MoonLight) + entryStart = entryEnd; // This is the start of a directory entry + lfnExists = true; + lfnPos = (entryData[LFN_offset_ordinal] & ~LFN_END) * 13; + if (lfnPos > MAX_LFN_LENGTH - 1) { + lfnPos = MAX_LFN_LENGTH - 1; + } + lfn[lfnPos] = '\0'; // Set end of lfn to null character + lfnChkSum = entryData[LFN_offset_checkSum]; + } + if (lfnChkSum != entryData[LFN_offset_checkSum]) { + lfnExists = false; + } + if (lfnExists) { + lfnPos = ((entryData[LFN_offset_ordinal] & ~LFN_END) - 1) * 13; + if (lfnPos > LAST_LFN_POS) { + // Force it within the buffer. Will corrupt the filename but prevent buffer overflows + lfnPos = LAST_LFN_POS; + } + for (i = 0; i < 13; i++) { + lfn[lfnPos + i] = entryData[LFN_offset_table[i]] | (entryData[LFN_offset_table[i]+1] << 8); + } + } + } else if (entryData[DIR_ENTRY_attributes] & ATTRIB_VOL) { + // This is a volume name, don't bother with it + } else if (entryData[0] == DIR_ENTRY_LAST) { + notFound = true; + } else if ((entryData[0] != DIR_ENTRY_FREE) && (entryData[0] > 0x20) && !(entryData[DIR_ENTRY_attributes] & ATTRIB_VOL)) { + if (lfnExists) { + // Calculate file checksum + chkSum = 0; + for (i=0; i < 11; i++) { + // NOTE: The operation is an unsigned char rotate right + chkSum = ((chkSum & 1) ? 0x80 : 0) + (chkSum >> 1) + entryData[i]; + } + if (chkSum != lfnChkSum) { + lfnExists = false; + entry->filename[0] = '\0'; + } + } + + if (lfnExists) { + if (_FAT_directory_ucs2tombs (entry->filename, lfn, MAX_FILENAME_LENGTH) == (size_t)-1) { + // Failed to convert the file name to UTF-8. Maybe the wrong locale is set? + return false; + } + } else { + entryStart = entryEnd; + _FAT_directory_entryGetAlias (entryData, entry->filename); + } + found = true; + } + } + + // If no file is found, return false + if (notFound) { + return false; + } else { + // Fill in the directory entry struct + entry->dataStart = entryStart; + entry->dataEnd = entryEnd; + memcpy (entry->entryData, entryData, DIR_ENTRY_DATA_SIZE); + return true; + } +} + +bool _FAT_directory_getFirstEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster) { + entry->dataStart.cluster = dirCluster; + entry->dataStart.sector = 0; + entry->dataStart.offset = -1; // Start before the beginning of the directory + + entry->dataEnd = entry->dataStart; + + return _FAT_directory_getNextEntry (partition, entry); +} + +bool _FAT_directory_getRootEntry (PARTITION* partition, DIR_ENTRY* entry) { + entry->dataStart.cluster = 0; + entry->dataStart.sector = 0; + entry->dataStart.offset = 0; + + entry->dataEnd = entry->dataStart; + + memset (entry->filename, '\0', MAX_FILENAME_LENGTH); + entry->filename[0] = '.'; + + memset (entry->entryData, 0, DIR_ENTRY_DATA_SIZE); + memset (entry->entryData, ' ', 11); + entry->entryData[0] = '.'; + + entry->entryData[DIR_ENTRY_attributes] = ATTRIB_DIR; + + u16_to_u8array (entry->entryData, DIR_ENTRY_cluster, partition->rootDirCluster); + u16_to_u8array (entry->entryData, DIR_ENTRY_clusterHigh, partition->rootDirCluster >> 16); + + return true; +} + +bool _FAT_directory_getVolumeLabel (PARTITION* partition, char *label) { + DIR_ENTRY entry; + DIR_ENTRY_POSITION entryEnd; + uint8_t entryData[DIR_ENTRY_DATA_SIZE]; + int i; + bool end; + + _FAT_directory_getRootEntry(partition, &entry); + + entryEnd = entry.dataEnd; + + // Make sure we are using the correct root directory, in case of FAT32 + if (entryEnd.cluster == FAT16_ROOT_DIR_CLUSTER) { + entryEnd.cluster = partition->rootDirCluster; + } + + label[0]='\0'; + label[11]='\0'; + end = false; + //this entry should be among the first 3 entries in the root directory table, if not, then system can have trouble displaying the right volume label + while(!end) { + if (_FAT_directory_incrementDirEntryPosition (partition, &entryEnd, false) == false) { + end = true; + } + + if(!_FAT_cache_readPartialSector (partition->cache, entryData, + _FAT_fat_clusterToSector(partition, entryEnd.cluster) + entryEnd.sector, + entryEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE)) + { //error reading + return false; + } + if (entryData[DIR_ENTRY_attributes] == ATTRIB_VOL && entryData[0] != DIR_ENTRY_FREE) { + for (i = 0; i < 11; i++) { + label[i] = entryData[DIR_ENTRY_name + i]; + } + return true; + } else if (entryData[0] == DIR_ENTRY_LAST) { + end = true; + } + } + return false; +} + +bool _FAT_directory_entryFromPosition (PARTITION* partition, DIR_ENTRY* entry) { + DIR_ENTRY_POSITION entryStart = entry->dataStart; + DIR_ENTRY_POSITION entryEnd = entry->dataEnd; + bool entryStillValid; + bool finished; + ucs2_t lfn[MAX_LFN_LENGTH]; + int i; + int lfnPos; + uint8_t entryData[DIR_ENTRY_DATA_SIZE]; + + memset (entry->filename, '\0', MAX_FILENAME_LENGTH); + + // Create an empty directory entry to overwrite the old ones with + for ( entryStillValid = true, finished = false; + entryStillValid && !finished; + entryStillValid = _FAT_directory_incrementDirEntryPosition (partition, &entryStart, false)) + { + _FAT_cache_readPartialSector (partition->cache, entryData, + _FAT_fat_clusterToSector(partition, entryStart.cluster) + entryStart.sector, + entryStart.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + + if ((entryStart.cluster == entryEnd.cluster) + && (entryStart.sector == entryEnd.sector) + && (entryStart.offset == entryEnd.offset)) { + // Copy the entry data and stop, since this is the last section of the directory entry + memcpy (entry->entryData, entryData, DIR_ENTRY_DATA_SIZE); + finished = true; + } else { + // Copy the long file name data + lfnPos = ((entryData[LFN_offset_ordinal] & ~LFN_END) - 1) * 13; + if (lfnPos > LAST_LFN_POS) { + lfnPos = LAST_LFN_POS_CORRECTION; + } + for (i = 0; i < 13; i++) { + lfn[lfnPos + i] = entryData[LFN_offset_table[i]] | (entryData[LFN_offset_table[i]+1] << 8); + } + } + } + + if (!entryStillValid) { + return false; + } + + if ((entryStart.cluster == entryEnd.cluster) + && (entryStart.sector == entryEnd.sector) + && (entryStart.offset == entryEnd.offset)) { + // Since the entry doesn't have a long file name, extract the short filename + if (!_FAT_directory_entryGetAlias (entry->entryData, entry->filename)) { + return false; + } + } else { + // Encode the long file name into a multibyte string + if (_FAT_directory_ucs2tombs (entry->filename, lfn, MAX_FILENAME_LENGTH) == (size_t)-1) { + return false; + } + } + + return true; +} + + + +bool _FAT_directory_entryFromPath (PARTITION* partition, DIR_ENTRY* entry, const char* path, const char* pathEnd) { + size_t dirnameLength; + const char* pathPosition; + const char* nextPathPosition; + uint32_t dirCluster; + bool foundFile; + char alias[MAX_ALIAS_LENGTH]; + bool found, notFound; + + pathPosition = path; + + found = false; + notFound = false; + + if (pathEnd == NULL) { + // Set pathEnd to the end of the path string + pathEnd = strchr (path, '\0'); + } + + if (pathPosition[0] == DIR_SEPARATOR) { + // Start at root directory + dirCluster = partition->rootDirCluster; + // Consume separator(s) + while (pathPosition[0] == DIR_SEPARATOR) { + pathPosition++; + } + // If the path is only specifying a directory in the form of "/" return it + if (pathPosition >= pathEnd) { + _FAT_directory_getRootEntry (partition, entry); + found = true; + } + } else { + // Start in current working directory + dirCluster = partition->cwdCluster; + } + + // If the path is only specifying a directory in the form "." + // and this is the root directory, return it + if ((dirCluster == partition->rootDirCluster) && (strcmp(".", pathPosition) == 0)) { + _FAT_directory_getRootEntry (partition, entry); + found = true; + } + + while (!found && !notFound) { + // Get the name of the next required subdirectory within the path + nextPathPosition = strchr (pathPosition, DIR_SEPARATOR); + if (nextPathPosition != NULL) { + dirnameLength = nextPathPosition - pathPosition; + } else { + dirnameLength = strlen(pathPosition); + } + + if (dirnameLength > MAX_FILENAME_LENGTH) { + // The path is too long to bother with + return false; + } + + // Look for the directory within the path + foundFile = _FAT_directory_getFirstEntry (partition, entry, dirCluster); + + while (foundFile && !found && !notFound) { // It hasn't already found the file + // Check if the filename matches + if ((dirnameLength == strnlen(entry->filename, MAX_FILENAME_LENGTH)) + && (_FAT_directory_mbsncasecmp(pathPosition, entry->filename, dirnameLength) == 0)) { + found = true; + } + + // Check if the alias matches + _FAT_directory_entryGetAlias (entry->entryData, alias); + if ((dirnameLength == strnlen(alias, MAX_ALIAS_LENGTH)) + && (strncasecmp(pathPosition, alias, dirnameLength) == 0)) { + found = true; + } + + if (found && !(entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR) && (nextPathPosition != NULL)) { + // Make sure that we aren't trying to follow a file instead of a directory in the path + found = false; + } + + if (!found) { + foundFile = _FAT_directory_getNextEntry (partition, entry); + } + } + + if (!foundFile) { + // Check that the search didn't get to the end of the directory + notFound = true; + found = false; + } else if ((nextPathPosition == NULL) || (nextPathPosition >= pathEnd)) { + // Check that we reached the end of the path + found = true; + } else if (entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR) { + dirCluster = _FAT_directory_entryGetCluster (partition, entry->entryData); + pathPosition = nextPathPosition; + // Consume separator(s) + while (pathPosition[0] == DIR_SEPARATOR) { + pathPosition++; + } + // The requested directory was found + if (pathPosition >= pathEnd) { + found = true; + } else { + found = false; + } + } + } + + if (found && !notFound) { + if (partition->filesysType == FS_FAT32 && (entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR) && + _FAT_directory_entryGetCluster (partition, entry->entryData) == CLUSTER_ROOT) + { + // On FAT32 it should specify an actual cluster for the root entry, + // not cluster 0 as on FAT16 + _FAT_directory_getRootEntry (partition, entry); + } + return true; + } else { + return false; + } +} + +bool _FAT_directory_removeEntry (PARTITION* partition, DIR_ENTRY* entry) { + DIR_ENTRY_POSITION entryStart = entry->dataStart; + DIR_ENTRY_POSITION entryEnd = entry->dataEnd; + bool entryStillValid; + bool finished; + uint8_t entryData[DIR_ENTRY_DATA_SIZE]; + + // Create an empty directory entry to overwrite the old ones with + for ( entryStillValid = true, finished = false; + entryStillValid && !finished; + entryStillValid = _FAT_directory_incrementDirEntryPosition (partition, &entryStart, false)) + { + _FAT_cache_readPartialSector (partition->cache, entryData, _FAT_fat_clusterToSector(partition, entryStart.cluster) + entryStart.sector, entryStart.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + entryData[0] = DIR_ENTRY_FREE; + _FAT_cache_writePartialSector (partition->cache, entryData, _FAT_fat_clusterToSector(partition, entryStart.cluster) + entryStart.sector, entryStart.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + if ((entryStart.cluster == entryEnd.cluster) && (entryStart.sector == entryEnd.sector) && (entryStart.offset == entryEnd.offset)) { + finished = true; + } + } + + if (!entryStillValid) { + return false; + } + + return true; +} + +static bool _FAT_directory_findEntryGap (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster, size_t size) { + DIR_ENTRY_POSITION gapStart; + DIR_ENTRY_POSITION gapEnd; + uint8_t entryData[DIR_ENTRY_DATA_SIZE]; + size_t dirEntryRemain; + bool endOfDirectory, entryStillValid; + + // Scan Dir for free entry + gapEnd.offset = 0; + gapEnd.sector = 0; + gapEnd.cluster = dirCluster; + + gapStart = gapEnd; + + entryStillValid = true; + dirEntryRemain = size; + endOfDirectory = false; + + while (entryStillValid && !endOfDirectory && (dirEntryRemain > 0)) { + _FAT_cache_readPartialSector (partition->cache, entryData, + _FAT_fat_clusterToSector(partition, gapEnd.cluster) + gapEnd.sector, + gapEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + if (entryData[0] == DIR_ENTRY_LAST) { + gapStart = gapEnd; + -- dirEntryRemain; + endOfDirectory = true; + } else if (entryData[0] == DIR_ENTRY_FREE) { + if (dirEntryRemain == size) { + gapStart = gapEnd; + } + -- dirEntryRemain; + } else { + dirEntryRemain = size; + } + + if (!endOfDirectory && (dirEntryRemain > 0)) { + entryStillValid = _FAT_directory_incrementDirEntryPosition (partition, &gapEnd, true); + } + } + + // Make sure the scanning didn't fail + if (!entryStillValid) { + return false; + } + + // Save the start entry, since we know it is valid + entry->dataStart = gapStart; + + if (endOfDirectory) { + memset (entryData, DIR_ENTRY_LAST, DIR_ENTRY_DATA_SIZE); + dirEntryRemain += 1; // Increase by one to take account of End Of Directory Marker + while ((dirEntryRemain > 0) && entryStillValid) { + // Get the gapEnd before incrementing it, so the second to last one is saved + entry->dataEnd = gapEnd; + // Increment gapEnd, moving onto the next entry + entryStillValid = _FAT_directory_incrementDirEntryPosition (partition, &gapEnd, true); + -- dirEntryRemain; + // Fill the entry with blanks + _FAT_cache_writePartialSector (partition->cache, entryData, + _FAT_fat_clusterToSector(partition, gapEnd.cluster) + gapEnd.sector, + gapEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + } + if (!entryStillValid) { + return false; + } + } else { + entry->dataEnd = gapEnd; + } + + return true; +} + +static bool _FAT_directory_entryExists (PARTITION* partition, const char* name, uint32_t dirCluster) { + DIR_ENTRY tempEntry; + bool foundFile; + char alias[MAX_ALIAS_LENGTH]; + size_t dirnameLength; + + dirnameLength = strnlen(name, MAX_FILENAME_LENGTH); + + if (dirnameLength >= MAX_FILENAME_LENGTH) { + return false; + } + + // Make sure the entry doesn't already exist + foundFile = _FAT_directory_getFirstEntry (partition, &tempEntry, dirCluster); + + while (foundFile) { // It hasn't already found the file + // Check if the filename matches + if ((dirnameLength == strnlen(tempEntry.filename, MAX_FILENAME_LENGTH)) + && (_FAT_directory_mbsncasecmp(name, tempEntry.filename, dirnameLength) == 0)) { + return true; + } + + // Check if the alias matches + _FAT_directory_entryGetAlias (tempEntry.entryData, alias); + if ((strncasecmp(name, alias, MAX_ALIAS_LENGTH) == 0)) { + return true; + } + foundFile = _FAT_directory_getNextEntry (partition, &tempEntry); + } + return false; +} + +/* +Creates an alias for a long file name. If the alias is not an exact match for the +filename, it returns the number of characters in the alias. If the two names match, +it returns 0. If there was an error, it returns -1. +*/ +static int _FAT_directory_createAlias (char* alias, const char* lfn) { + bool lossyConversion = false; // Set when the alias had to be modified to be valid + int lfnPos = 0; + int aliasPos = 0; + wchar_t lfnChar; + int oemChar; + mbstate_t ps = {0}; + int bytesUsed = 0; + const char* lfnExt; + int aliasExtLen; + + // Strip leading periods + while (lfn[lfnPos] == '.') { + lfnPos ++; + lossyConversion = true; + } + + // Primary portion of alias + while (aliasPos < 8 && lfn[lfnPos] != '.' && lfn[lfnPos] != '\0') { + bytesUsed = mbrtowc(&lfnChar, lfn + lfnPos, MAX_FILENAME_LENGTH - lfnPos, &ps); + if (bytesUsed < 0) { + return -1; + } + oemChar = wctob(towupper((wint_t)lfnChar)); + if (wctob((wint_t)lfnChar) != oemChar) { + // Case of letter was changed + lossyConversion = true; + } + if (oemChar == ' ') { + // Skip spaces in filename + lossyConversion = true; + lfnPos += bytesUsed; + continue; + } + if (oemChar == EOF) { + oemChar = '_'; // Replace unconvertable characters with underscores + lossyConversion = true; + } + if (strchr (ILLEGAL_ALIAS_CHARACTERS, oemChar) != NULL) { + // Invalid Alias character + oemChar = '_'; // Replace illegal characters with underscores + lossyConversion = true; + } + + alias[aliasPos] = (char)oemChar; + aliasPos++; + lfnPos += bytesUsed; + } + + if (lfn[lfnPos] != '.' && lfn[lfnPos] != '\0') { + // Name was more than 8 characters long + lossyConversion = true; + } + + // Alias extension + lfnExt = strrchr (lfn, '.'); + if (lfnExt != NULL && lfnExt != strchr (lfn, '.')) { + // More than one period in name + lossyConversion = true; + } + if (lfnExt != NULL && lfnExt[1] != '\0') { + lfnExt++; + alias[aliasPos] = '.'; + aliasPos++; + memset (&ps, 0, sizeof(ps)); + for (aliasExtLen = 0; aliasExtLen < MAX_ALIAS_EXT_LENGTH && *lfnExt != '\0'; aliasExtLen++) { + bytesUsed = mbrtowc(&lfnChar, lfnExt, MAX_FILENAME_LENGTH - lfnPos, &ps); + if (bytesUsed < 0) { + return -1; + } + oemChar = wctob(towupper((wint_t)lfnChar)); + if (wctob((wint_t)lfnChar) != oemChar) { + // Case of letter was changed + lossyConversion = true; + } + if (oemChar == ' ') { + // Skip spaces in alias + lossyConversion = true; + lfnExt += bytesUsed; + continue; + } + if (oemChar == EOF) { + oemChar = '_'; // Replace unconvertable characters with underscores + lossyConversion = true; + } + if (strchr (ILLEGAL_ALIAS_CHARACTERS, oemChar) != NULL) { + // Invalid Alias character + oemChar = '_'; // Replace illegal characters with underscores + lossyConversion = true; + } + + alias[aliasPos] = (char)oemChar; + aliasPos++; + lfnExt += bytesUsed; + } + if (*lfnExt != '\0') { + // Extension was more than 3 characters long + lossyConversion = true; + } + } + + alias[aliasPos] = '\0'; + if (lossyConversion) { + return aliasPos; + } else { + return 0; + } +} + +bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster) { + size_t entrySize; + uint8_t lfnEntry[DIR_ENTRY_DATA_SIZE]; + int i,j; // Must be signed for use when decrementing in for loop + char *tmpCharPtr; + DIR_ENTRY_POSITION curEntryPos; + bool entryStillValid; + uint8_t aliasCheckSum = 0; + char alias [MAX_ALIAS_LENGTH]; + int aliasLen; + int lfnLen; + + // Make sure the filename is not 0 length + if (strnlen (entry->filename, MAX_FILENAME_LENGTH) < 1) { + return false; + } + + // Make sure the filename is at least a valid LFN + lfnLen = _FAT_directory_lfnLength (entry->filename); + if (lfnLen < 0) { + return false; + } + + // Remove trailing spaces + for (i = strlen (entry->filename) - 1; (i > 0) && (entry->filename[i] == ' '); --i) { + entry->filename[i] = '\0'; + } + // Remove leading spaces + for (i = 0; (i < (int)strlen (entry->filename)) && (entry->filename[i] == ' '); ++i) ; + if (i > 0) { + memmove (entry->filename, entry->filename + i, strlen (entry->filename + i)); + } + + // Remove junk in filename + i = strlen (entry->filename); + memset (entry->filename + i, '\0', MAX_FILENAME_LENGTH - i); + + // Make sure the entry doesn't already exist + if (_FAT_directory_entryExists (partition, entry->filename, dirCluster)) { + return false; + } + + // Clear out alias, so we can generate a new one + memset (entry->entryData, ' ', 11); + + if ( strncmp(entry->filename, ".", MAX_FILENAME_LENGTH) == 0) { + // "." entry + entry->entryData[0] = '.'; + entrySize = 1; + } else if ( strncmp(entry->filename, "..", MAX_FILENAME_LENGTH) == 0) { + // ".." entry + entry->entryData[0] = '.'; + entry->entryData[1] = '.'; + entrySize = 1; + } else { + // Normal file name + aliasLen = _FAT_directory_createAlias (alias, entry->filename); + if (aliasLen < 0) { + return false; + } else if (aliasLen == 0) { + // It's a normal short filename + entrySize = 1; + } else { + // It's a long filename with an alias + entrySize = ((lfnLen + LFN_ENTRY_LENGTH - 1) / LFN_ENTRY_LENGTH) + 1; + + // Generate full alias for all cases except when the alias is simply an upper case version of the LFN + // and there isn't already a file with that name + if (strncasecmp (alias, entry->filename, MAX_ALIAS_LENGTH) != 0 || + _FAT_directory_entryExists (partition, alias, dirCluster)) + { + // expand primary part to 8 characters long by padding the end with underscores + i = MAX_ALIAS_PRI_LENGTH - 1; + // Move extension to last 3 characters + while (alias[i] != '.' && i > 0) i--; + if (i > 0) { + j = MAX_ALIAS_LENGTH - MAX_ALIAS_EXT_LENGTH - 2; // 1 char for '.', one for NUL, 3 for extension + memmove (alias + j, alias + i, strlen(alias) - i); + // Pad primary component + memset (alias + i, '_', j - i); + alias[MAX_ALIAS_LENGTH-1]=0; + } + + // Generate numeric tail + for (i = 1; i <= MAX_NUMERIC_TAIL; i++) { + j = i; + tmpCharPtr = alias + MAX_ALIAS_PRI_LENGTH - 1; + while (j > 0) { + *tmpCharPtr = '0' + (j % 10); // ASCII numeric value + tmpCharPtr--; + j /= 10; + } + *tmpCharPtr = '~'; + if (!_FAT_directory_entryExists (partition, alias, dirCluster)) { + break; + } + } + if (i > MAX_NUMERIC_TAIL) { + // Couldn't get a valid alias + return false; + } + } + } + + // Copy alias or short file name into directory entry data + for (i = 0, j = 0; (j < 8) && (alias[i] != '.') && (alias[i] != '\0'); i++, j++) { + entry->entryData[j] = alias[i]; + } + while (j < 8) { + entry->entryData[j] = ' '; + ++ j; + } + if (alias[i] == '.') { + // Copy extension + ++ i; + while ((alias[i] != '\0') && (j < 11)) { + entry->entryData[j] = alias[i]; + ++ i; + ++ j; + } + } + while (j < 11) { + entry->entryData[j] = ' '; + ++ j; + } + + // Generate alias checksum + for (i=0; i < ALIAS_ENTRY_LENGTH; i++) { + // NOTE: The operation is an unsigned char rotate right + aliasCheckSum = ((aliasCheckSum & 1) ? 0x80 : 0) + (aliasCheckSum >> 1) + entry->entryData[i]; + } + } + + // Find or create space for the entry + if (_FAT_directory_findEntryGap (partition, entry, dirCluster, entrySize) == false) { + return false; + } + + // Write out directory entry + curEntryPos = entry->dataStart; + + { + // lfn is only pushed onto the stack here, reducing overall stack usage + ucs2_t lfn[MAX_LFN_LENGTH] = {0}; + _FAT_directory_mbstoucs2 (lfn, entry->filename, MAX_LFN_LENGTH); + + for (entryStillValid = true, i = entrySize; entryStillValid && i > 0; + entryStillValid = _FAT_directory_incrementDirEntryPosition (partition, &curEntryPos, false), -- i ) + { + if (i > 1) { + // Long filename entry + lfnEntry[LFN_offset_ordinal] = (i - 1) | ((size_t)i == entrySize ? LFN_END : 0); + for (j = 0; j < 13; j++) { + if (lfn [(i - 2) * 13 + j] == '\0') { + if ((j > 1) && (lfn [(i - 2) * 13 + (j-1)] == '\0')) { + u16_to_u8array (lfnEntry, LFN_offset_table[j], 0xffff); // Padding + } else { + u16_to_u8array (lfnEntry, LFN_offset_table[j], 0x0000); // Terminating null character + } + } else { + u16_to_u8array (lfnEntry, LFN_offset_table[j], lfn [(i - 2) * 13 + j]); + } + } + + lfnEntry[LFN_offset_checkSum] = aliasCheckSum; + lfnEntry[LFN_offset_flag] = ATTRIB_LFN; + lfnEntry[LFN_offset_reserved1] = 0; + u16_to_u8array (lfnEntry, LFN_offset_reserved2, 0); + _FAT_cache_writePartialSector (partition->cache, lfnEntry, _FAT_fat_clusterToSector(partition, curEntryPos.cluster) + curEntryPos.sector, curEntryPos.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + } else { + // Alias & file data + _FAT_cache_writePartialSector (partition->cache, entry->entryData, _FAT_fat_clusterToSector(partition, curEntryPos.cluster) + curEntryPos.sector, curEntryPos.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + } + } + } + + return true; +} + +bool _FAT_directory_chdir (PARTITION* partition, const char* path) { + DIR_ENTRY entry; + + if (!_FAT_directory_entryFromPath (partition, &entry, path, NULL)) { + return false; + } + + if (!(entry.entryData[DIR_ENTRY_attributes] & ATTRIB_DIR)) { + return false; + } + + partition->cwdCluster = _FAT_directory_entryGetCluster (partition, entry.entryData); + + return true; +} + +void _FAT_directory_entryStat (PARTITION* partition, DIR_ENTRY* entry, struct stat *st) { + // Fill in the stat struct + // Some of the values are faked for the sake of compatibility + st->st_dev = _FAT_disc_hostType(partition->disc); // The device is the 32bit ioType value + st->st_ino = (ino_t)(_FAT_directory_entryGetCluster(partition, entry->entryData)); // The file serial number is the start cluster + st->st_mode = (_FAT_directory_isDirectory(entry) ? S_IFDIR : S_IFREG) | + (S_IRUSR | S_IRGRP | S_IROTH) | + (_FAT_directory_isWritable (entry) ? (S_IWUSR | S_IWGRP | S_IWOTH) : 0); // Mode bits based on dirEntry ATTRIB byte + st->st_nlink = 1; // Always one hard link on a FAT file + st->st_uid = 1; // Faked for FAT + st->st_gid = 2; // Faked for FAT + st->st_rdev = st->st_dev; + st->st_size = u8array_to_u32 (entry->entryData, DIR_ENTRY_fileSize); // File size + st->st_atime = _FAT_filetime_to_time_t ( + 0, + u8array_to_u16 (entry->entryData, DIR_ENTRY_aDate) + ); +#ifndef LIBFAT_PC + st->st_spare1 = 0; +#endif + st->st_mtime = _FAT_filetime_to_time_t ( + u8array_to_u16 (entry->entryData, DIR_ENTRY_mTime), + u8array_to_u16 (entry->entryData, DIR_ENTRY_mDate) + ); +#ifndef LIBFAT_PC + st->st_spare2 = 0; +#endif + st->st_ctime = _FAT_filetime_to_time_t ( + u8array_to_u16 (entry->entryData, DIR_ENTRY_cTime), + u8array_to_u16 (entry->entryData, DIR_ENTRY_cDate) + ); +#ifndef LIBFAT_PC + st->st_spare3 = 0; + st->st_blksize = BYTES_PER_READ; // Prefered file I/O block size + st->st_blocks = (st->st_size + BYTES_PER_READ - 1) / BYTES_PER_READ; // File size in blocks + st->st_spare4[0] = 0; + st->st_spare4[1] = 0; +#endif +} diff --git a/jni/desmume/src/utils/libfat/directory.h b/jni/desmume/src/utils/libfat/directory.h new file mode 100755 index 0000000..9342921 --- /dev/null +++ b/jni/desmume/src/utils/libfat/directory.h @@ -0,0 +1,178 @@ +/* + directory.h + Reading, writing and manipulation of the directory structure on + a FAT partition + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _DIRECTORY_H +#define _DIRECTORY_H + +#include <sys/stat.h> + +#include "common.h" +#include "partition.h" + +#define DIR_ENTRY_DATA_SIZE 0x20 +#define MAX_LFN_LENGTH 256 +#define MAX_FILENAME_LENGTH 768 // 256 UCS-2 characters encoded into UTF-8 can use up to 768 UTF-8 chars +#define MAX_ALIAS_LENGTH 13 +#define LFN_ENTRY_LENGTH 13 +#define ALIAS_ENTRY_LENGTH 11 +#define MAX_ALIAS_EXT_LENGTH 3 +#define MAX_ALIAS_PRI_LENGTH 8 +#define MAX_NUMERIC_TAIL 999999 +#define FAT16_ROOT_DIR_CLUSTER 0 + +#define DIR_SEPARATOR '/' + +// File attributes +#define ATTRIB_ARCH 0x20 // Archive +#define ATTRIB_DIR 0x10 // Directory +#define ATTRIB_LFN 0x0F // Long file name +#define ATTRIB_VOL 0x08 // Volume +#define ATTRIB_SYS 0x04 // System +#define ATTRIB_HID 0x02 // Hidden +#define ATTRIB_RO 0x01 // Read only + +typedef enum {FT_DIRECTORY, FT_FILE} FILE_TYPE; + +typedef struct { + uint32_t cluster; + sec_t sector; + int32_t offset; +} DIR_ENTRY_POSITION; + +typedef struct { + uint8_t entryData[DIR_ENTRY_DATA_SIZE]; + DIR_ENTRY_POSITION dataStart; // Points to the start of the LFN entries of a file, or the alias for no LFN + DIR_ENTRY_POSITION dataEnd; // Always points to the file/directory's alias entry + char filename[MAX_FILENAME_LENGTH]; +} DIR_ENTRY; + +// Directory entry offsets +enum DIR_ENTRY_offset { + DIR_ENTRY_name = 0x00, + DIR_ENTRY_extension = 0x08, + DIR_ENTRY_attributes = 0x0B, + DIR_ENTRY_reserved = 0x0C, + DIR_ENTRY_cTime_ms = 0x0D, + DIR_ENTRY_cTime = 0x0E, + DIR_ENTRY_cDate = 0x10, + DIR_ENTRY_aDate = 0x12, + DIR_ENTRY_clusterHigh = 0x14, + DIR_ENTRY_mTime = 0x16, + DIR_ENTRY_mDate = 0x18, + DIR_ENTRY_cluster = 0x1A, + DIR_ENTRY_fileSize = 0x1C +}; + +/* +Returns true if the file specified by entry is a directory +*/ +static inline bool _FAT_directory_isDirectory (DIR_ENTRY* entry) { + return ((entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR) != 0); +} + +static inline bool _FAT_directory_isWritable (DIR_ENTRY* entry) { + return ((entry->entryData[DIR_ENTRY_attributes] & ATTRIB_RO) == 0); +} + +static inline bool _FAT_directory_isDot (DIR_ENTRY* entry) { + return ((entry->filename[0] == '.') && ((entry->filename[1] == '\0') || + ((entry->filename[1] == '.') && entry->filename[2] == '\0'))); +} + +/* +Reads the first directory entry from the directory starting at dirCluster +Places result in entry +entry will be destroyed even if no directory entry is found +Returns true on success, false on failure +*/ +bool _FAT_directory_getFirstEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster); + +/* +Reads the next directory entry after the one already pointed to by entry +Places result in entry +entry will be destroyed even if no directory entry is found +Returns true on success, false on failure +*/ +bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry); + +/* +Gets the directory entry corrsponding to the supplied path +entry will be destroyed even if no directory entry is found +pathEnd specifies the end of the path string, for cutting strings short if needed + specify NULL to use the full length of path + pathEnd is only a suggestion, and the path string will be searched up until the next PATH_SEPARATOR + after pathEND. +Returns true on success, false on failure +*/ +bool _FAT_directory_entryFromPath (PARTITION* partition, DIR_ENTRY* entry, const char* path, const char* pathEnd); + +/* +Changes the current directory to the one specified by path +Returns true on success, false on failure +*/ +bool _FAT_directory_chdir (PARTITION* partition, const char* path); + +/* +Removes the directory entry specified by entry +Assumes that entry is valid +Returns true on success, false on failure +*/ +bool _FAT_directory_removeEntry (PARTITION* partition, DIR_ENTRY* entry); + +/* +Add a directory entry to the directory specified by dirCluster +The fileData, dataStart and dataEnd elements of the DIR_ENTRY struct are +updated with the new directory entry position and alias. +Returns true on success, false on failure +*/ +bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster); + +/* +Get the start cluster of a file from it's entry data +*/ +uint32_t _FAT_directory_entryGetCluster (PARTITION* partition, const uint8_t* entryData); + +/* +Fill in the file name and entry data of DIR_ENTRY* entry. +Assumes that the entry's dataStart and dataEnd are correct +Returns true on success, false on failure +*/ +bool _FAT_directory_entryFromPosition (PARTITION* partition, DIR_ENTRY* entry); + +/* +Fill in a stat struct based on a file entry +*/ +void _FAT_directory_entryStat (PARTITION* partition, DIR_ENTRY* entry, struct stat *st); + +/* +Get volume label +*/ +bool _FAT_directory_getVolumeLabel (PARTITION* partition, char *label); + +#endif // _DIRECTORY_H diff --git a/jni/desmume/src/utils/libfat/disc.cpp b/jni/desmume/src/utils/libfat/disc.cpp new file mode 100755 index 0000000..1fac0ed --- /dev/null +++ b/jni/desmume/src/utils/libfat/disc.cpp @@ -0,0 +1,105 @@ +/* + disc.c + Interface to the low level disc functions. Used by the higher level + file system code. + + Copyright (c) 2008 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "disc.h" + +/* +The list of interfaces consists of a series of name/interface pairs. +The interface is returned via a simple function. This allows for +platforms where the interface has to be "assembled" before it can +be used, like DLDI on the NDS. For cases where a simple struct +is available, wrapper functions are used. +The list is terminated by a NULL/NULL entry. +*/ + +/* ====================== Wii ====================== */ +#if defined (__wii__) +#include <sdcard/wiisd_io.h> +#include <ogc/usbstorage.h> +#include <sdcard/gcsd.h> + +static const DISC_INTERFACE* get_io_wiisd (void) { + return &__io_wiisd; +} +static const DISC_INTERFACE* get_io_usbstorage (void) { + return &__io_usbstorage; +} + +static const DISC_INTERFACE* get_io_gcsda (void) { + return &__io_gcsda; +} +static const DISC_INTERFACE* get_io_gcsdb (void) { + return &__io_gcsdb; +} + +const INTERFACE_ID _FAT_disc_interfaces[] = { + {"sd", get_io_wiisd}, + {"usb", get_io_usbstorage}, + {"carda", get_io_gcsda}, + {"cardb", get_io_gcsdb}, + {NULL, NULL} +}; + +/* ==================== Gamecube ==================== */ +#elif defined (__gamecube__) +#include <sdcard/gcsd.h> + +static const DISC_INTERFACE* get_io_gcsda (void) { + return &__io_gcsda; +} +static const DISC_INTERFACE* get_io_gcsdb (void) { + return &__io_gcsdb; +} + +const INTERFACE_ID _FAT_disc_interfaces[] = { + {"carda", get_io_gcsda}, + {"cardb", get_io_gcsdb}, + {NULL, NULL} +}; + +/* ====================== NDS ====================== */ +#elif defined (NDS) +#include <nds/arm9/dldi.h> + +const INTERFACE_ID _FAT_disc_interfaces[] = { + {"fat", dldiGetInternal}, + {NULL, NULL} +}; + +/* ====================== GBA ====================== */ +#elif defined (GBA) +#include <disc.h> + +const INTERFACE_ID _FAT_disc_interfaces[] = { + {"fat", discGetInterface}, + {NULL, NULL} +}; + +#endif + diff --git a/jni/desmume/src/utils/libfat/disc.h b/jni/desmume/src/utils/libfat/disc.h new file mode 100755 index 0000000..5c955f9 --- /dev/null +++ b/jni/desmume/src/utils/libfat/disc.h @@ -0,0 +1,110 @@ +/* + disc.h + Interface to the low level disc functions. Used by the higher level + file system code. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef _DISC_H +#define _DISC_H + +#include "common.h" + +/* +A list of all default devices to try at startup, +terminated by a {NULL,NULL} entry. +*/ +typedef struct { + const char* name; + const DISC_INTERFACE* (*getInterface)(void); +} INTERFACE_ID; +extern const INTERFACE_ID _FAT_disc_interfaces[]; + +/* +Check if a disc is inserted +Return true if a disc is inserted and ready, false otherwise +*/ +static inline bool _FAT_disc_isInserted (const DISC_INTERFACE* disc) { + return disc->isInserted(); +} + +/* +Read numSectors sectors from a disc, starting at sector. +numSectors is between 1 and LIMIT_SECTORS if LIMIT_SECTORS is defined, +else it is at least 1 +sector is 0 or greater +buffer is a pointer to the memory to fill +*/ +static inline bool _FAT_disc_readSectors (const DISC_INTERFACE* disc, sec_t sector, sec_t numSectors, void* buffer) { + return disc->readSectors (sector, numSectors, buffer); +} + +/* +Write numSectors sectors to a disc, starting at sector. +numSectors is between 1 and LIMIT_SECTORS if LIMIT_SECTORS is defined, +else it is at least 1 +sector is 0 or greater +buffer is a pointer to the memory to read from +*/ +static inline bool _FAT_disc_writeSectors (const DISC_INTERFACE* disc, sec_t sector, sec_t numSectors, const void* buffer) { + return disc->writeSectors (sector, numSectors, buffer); +} + +/* +Reset the card back to a ready state +*/ +static inline bool _FAT_disc_clearStatus (const DISC_INTERFACE* disc) { + return disc->clearStatus(); +} + +/* +Initialise the disc to a state ready for data reading or writing +*/ +static inline bool _FAT_disc_startup (const DISC_INTERFACE* disc) { + return disc->startup(); +} + +/* +Put the disc in a state ready for power down. +Complete any pending writes and disable the disc if necessary +*/ +static inline bool _FAT_disc_shutdown (const DISC_INTERFACE* disc) { + return disc->shutdown(); +} + +/* +Return a 32 bit value unique to each type of interface +*/ +static inline uint32_t _FAT_disc_hostType (const DISC_INTERFACE* disc) { + return disc->ioType; +} + +/* +Return a 32 bit value that specifies the capabilities of the disc +*/ +static inline uint32_t _FAT_disc_features (const DISC_INTERFACE* disc) { + return disc->features; +} + +#endif // _DISC_H diff --git a/jni/desmume/src/utils/libfat/disc_io.h b/jni/desmume/src/utils/libfat/disc_io.h new file mode 100755 index 0000000..2640c63 --- /dev/null +++ b/jni/desmume/src/utils/libfat/disc_io.h @@ -0,0 +1,60 @@ +/* + disc_io.h + Interface template for low level disc functions. + + Copyright (c) 2006 Michael "Chishm" Chisholm + Based on code originally written by MightyMax + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef NDS_DISC_IO_INCLUDE +#define NDS_DISC_IO_INCLUDE + +#define FEATURE_MEDIUM_CANREAD 0x00000001 +#define FEATURE_MEDIUM_CANWRITE 0x00000002 +#define FEATURE_SLOT_GBA 0x00000010 +#define FEATURE_SLOT_NDS 0x00000020 + +typedef uint32_t sec_t; + +typedef bool (* FN_MEDIUM_STARTUP)(void) ; +typedef bool (* FN_MEDIUM_ISINSERTED)(void) ; +typedef bool (* FN_MEDIUM_READSECTORS)(sec_t sector, sec_t numSectors, void* buffer) ; +typedef bool (* FN_MEDIUM_WRITESECTORS)(sec_t sector, sec_t numSectors, const void* buffer) ; +typedef bool (* FN_MEDIUM_CLEARSTATUS)(void) ; +typedef bool (* FN_MEDIUM_SHUTDOWN)(void) ; + +struct DISC_INTERFACE_STRUCT { + unsigned long ioType ; + unsigned long features ; + FN_MEDIUM_STARTUP startup ; + FN_MEDIUM_ISINSERTED isInserted ; + FN_MEDIUM_READSECTORS readSectors ; + FN_MEDIUM_WRITESECTORS writeSectors ; + FN_MEDIUM_CLEARSTATUS clearStatus ; + FN_MEDIUM_SHUTDOWN shutdown ; +} ; + +typedef struct DISC_INTERFACE_STRUCT DISC_INTERFACE ; + +#endif // define NDS_DISC_IO_INCLUDE diff --git a/jni/desmume/src/utils/libfat/fat.h b/jni/desmume/src/utils/libfat/fat.h new file mode 100755 index 0000000..968c604 --- /dev/null +++ b/jni/desmume/src/utils/libfat/fat.h @@ -0,0 +1,106 @@ +/* + fat.h + Simple functionality for startup, mounting and unmounting of FAT-based devices. + + Copyright (c) 2006 - 2009 + Michael "Chishm" Chisholm + Dave "WinterMute" Murphy + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _LIBFAT_H +#define _LIBFAT_H + +#ifdef __cplusplus +extern "C" { +#endif + +// When compiling for NDS, make sure NDS is defined +#ifndef NDS + #if defined ARM9 || defined ARM7 + #define NDS + #endif +#endif + +#ifndef _MSC_VER +#include <stdint.h> +#endif + +#if defined(__gamecube__) || defined (__wii__) +# include <ogc/disc_io.h> +#else +# ifdef NDS +# include "nds/disc_io.h" +# else +# include "disc_io.h" +# endif +#endif + +/* +Initialise any inserted block-devices. +Add the fat device driver to the devoptab, making it available for standard file functions. +cacheSize: The number of pages to allocate for each inserted block-device +setAsDefaultDevice: if true, make this the default device driver for file operations +*/ +extern bool fatInit (uint32_t cacheSize, bool setAsDefaultDevice); + +/* +Calls fatInit with setAsDefaultDevice = true and cacheSize optimised for the host system. +*/ +extern bool fatInitDefault (void); + +/* +Mount the device pointed to by interface, and set up a devoptab entry for it as "name:". +You can then access the filesystem using "name:/". +This will mount the active partition or the first valid partition on the disc, +and will use a cache size optimized for the host system. +*/ +extern bool fatMountSimple (const char* name, const DISC_INTERFACE* interface); + +/* +Mount the device pointed to by interface, and set up a devoptab entry for it as "name:". +You can then access the filesystem using "name:/". +If startSector = 0, it will mount the active partition of the first valid partition on +the disc. Otherwise it will try to mount the partition starting at startSector. +cacheSize specifies the number of pages to allocate for the cache. +This will not startup the disc, so you need to call interface->startup(); first. +*/ +extern bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize, uint32_t SectorsPerPage); + +/* +Unmount the partition specified by name. +If there are open files, it will attempt to synchronise them to disc. +*/ +extern void fatUnmount (const char* name); + +/* +Get Volume Label +*/ +extern void fatGetVolumeLabel (const char* name, char *label); + +#ifdef __cplusplus +} +#endif + +#endif // _LIBFAT_H diff --git a/jni/desmume/src/utils/libfat/fatdir.cpp b/jni/desmume/src/utils/libfat/fatdir.cpp new file mode 100755 index 0000000..51d0178 --- /dev/null +++ b/jni/desmume/src/utils/libfat/fatdir.cpp @@ -0,0 +1,615 @@ +/* + fatdir.c + + Functions used by the newlib disc stubs to interface with + this library + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <string.h> +#include <errno.h> +#include <ctype.h> + +#ifndef _MSC_VER +#include <unistd.h> +#ifndef ANDROID +#include <sys/dir.h> +#endif +#endif + +#include "fatdir.h" + +#include "cache.h" +#include "file_allocation_table.h" +#include "partition.h" +#include "directory.h" +#include "bit_ops.h" +#include "filetime.h" +#include "lock.h" + + +int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st) { + PARTITION* partition = NULL; + DIR_ENTRY dirEntry; + + // Get the partition this file is on + partition = _FAT_partition_getPartitionFromPath (path); + if (partition == NULL) { + r->_errno = ENODEV; + return -1; + } + + // Move the path pointer to the start of the actual path + if (strchr (path, ':') != NULL) { + path = strchr (path, ':') + 1; + } + if (strchr (path, ':') != NULL) { + r->_errno = EINVAL; + return -1; + } + + _FAT_lock(&partition->lock); + + // Search for the file on the disc + if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, NULL)) { + _FAT_unlock(&partition->lock); + r->_errno = ENOENT; + return -1; + } + + // Fill in the stat struct + _FAT_directory_entryStat (partition, &dirEntry, st); + + _FAT_unlock(&partition->lock); + return 0; +} + +int _FAT_link_r (struct _reent *r, const char *existing, const char *newLink) { + r->_errno = ENOTSUP; + return -1; +} + +int _FAT_unlink_r (struct _reent *r, const char *path) { + PARTITION* partition = NULL; + DIR_ENTRY dirEntry; + DIR_ENTRY dirContents; + uint32_t cluster; + bool nextEntry; + bool errorOccured = false; + + // Get the partition this directory is on + partition = _FAT_partition_getPartitionFromPath (path); + if (partition == NULL) { + r->_errno = ENODEV; + return -1; + } + + // Make sure we aren't trying to write to a read-only disc + if (partition->readOnly) { + r->_errno = EROFS; + return -1; + } + + // Move the path pointer to the start of the actual path + if (strchr (path, ':') != NULL) { + path = strchr (path, ':') + 1; + } + if (strchr (path, ':') != NULL) { + r->_errno = EINVAL; + return -1; + } + + _FAT_lock(&partition->lock); + + // Search for the file on the disc + if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, NULL)) { + _FAT_unlock(&partition->lock); + r->_errno = ENOENT; + return -1; + } + + cluster = _FAT_directory_entryGetCluster (partition, dirEntry.entryData); + + + // If this is a directory, make sure it is empty + if (_FAT_directory_isDirectory (&dirEntry)) { + nextEntry = _FAT_directory_getFirstEntry (partition, &dirContents, cluster); + + while (nextEntry) { + if (!_FAT_directory_isDot (&dirContents)) { + // The directory had something in it that isn't a reference to itself or it's parent + _FAT_unlock(&partition->lock); + r->_errno = EPERM; + return -1; + } + nextEntry = _FAT_directory_getNextEntry (partition, &dirContents); + } + } + + if (_FAT_fat_isValidCluster(partition, cluster)) { + // Remove the cluster chain for this file + if (!_FAT_fat_clearLinks (partition, cluster)) { + r->_errno = EIO; + errorOccured = true; + } + } + + // Remove the directory entry for this file + if (!_FAT_directory_removeEntry (partition, &dirEntry)) { + r->_errno = EIO; + errorOccured = true; + } + + // Flush any sectors in the disc cache + if (!_FAT_cache_flush(partition->cache)) { + r->_errno = EIO; + errorOccured = true; + } + + _FAT_unlock(&partition->lock); + if (errorOccured) { + return -1; + } else { + return 0; + } +} + +int _FAT_chdir_r (struct _reent *r, const char *path) { + PARTITION* partition = NULL; + + // Get the partition this directory is on + partition = _FAT_partition_getPartitionFromPath (path); + if (partition == NULL) { + r->_errno = ENODEV; + return -1; + } + + // Move the path pointer to the start of the actual path + if (strchr (path, ':') != NULL) { + path = strchr (path, ':') + 1; + } + if (strchr (path, ':') != NULL) { + r->_errno = EINVAL; + return -1; + } + + _FAT_lock(&partition->lock); + + // Try changing directory + if (_FAT_directory_chdir (partition, path)) { + // Successful + _FAT_unlock(&partition->lock); + return 0; + } else { + // Failed + _FAT_unlock(&partition->lock); + r->_errno = ENOTDIR; + return -1; + } +} + +int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) { + PARTITION* partition = NULL; + DIR_ENTRY oldDirEntry; + DIR_ENTRY newDirEntry; + const char *pathEnd; + uint32_t dirCluster; + + // Get the partition this directory is on + partition = _FAT_partition_getPartitionFromPath (oldName); + if (partition == NULL) { + r->_errno = ENODEV; + return -1; + } + + _FAT_lock(&partition->lock); + + // Make sure the same partition is used for the old and new names + if (partition != _FAT_partition_getPartitionFromPath (newName)) { + _FAT_unlock(&partition->lock); + r->_errno = EXDEV; + return -1; + } + + // Make sure we aren't trying to write to a read-only disc + if (partition->readOnly) { + _FAT_unlock(&partition->lock); + r->_errno = EROFS; + return -1; + } + + // Move the path pointer to the start of the actual path + if (strchr (oldName, ':') != NULL) { + oldName = strchr (oldName, ':') + 1; + } + if (strchr (oldName, ':') != NULL) { + _FAT_unlock(&partition->lock); + r->_errno = EINVAL; + return -1; + } + if (strchr (newName, ':') != NULL) { + newName = strchr (newName, ':') + 1; + } + if (strchr (newName, ':') != NULL) { + _FAT_unlock(&partition->lock); + r->_errno = EINVAL; + return -1; + } + + // Search for the file on the disc + if (!_FAT_directory_entryFromPath (partition, &oldDirEntry, oldName, NULL)) { + _FAT_unlock(&partition->lock); + r->_errno = ENOENT; + return -1; + } + + // Make sure there is no existing file / directory with the new name + if (_FAT_directory_entryFromPath (partition, &newDirEntry, newName, NULL)) { + _FAT_unlock(&partition->lock); + r->_errno = EEXIST; + return -1; + } + + // Create the new file entry + // Get the directory it has to go in + pathEnd = strrchr (newName, DIR_SEPARATOR); + if (pathEnd == NULL) { + // No path was specified + dirCluster = partition->cwdCluster; + pathEnd = newName; + } else { + // Path was specified -- get the right dirCluster + // Recycling newDirEntry, since it needs to be recreated anyway + if (!_FAT_directory_entryFromPath (partition, &newDirEntry, newName, pathEnd) || + !_FAT_directory_isDirectory(&newDirEntry)) { + _FAT_unlock(&partition->lock); + r->_errno = ENOTDIR; + return -1; + } + dirCluster = _FAT_directory_entryGetCluster (partition, newDirEntry.entryData); + // Move the pathEnd past the last DIR_SEPARATOR + pathEnd += 1; + } + + // Copy the entry data + memcpy (&newDirEntry, &oldDirEntry, sizeof(DIR_ENTRY)); + + // Set the new name + strncpy (newDirEntry.filename, pathEnd, MAX_FILENAME_LENGTH - 1); + + // Write the new entry + if (!_FAT_directory_addEntry (partition, &newDirEntry, dirCluster)) { + _FAT_unlock(&partition->lock); + r->_errno = ENOSPC; + return -1; + } + + // Remove the old entry + if (!_FAT_directory_removeEntry (partition, &oldDirEntry)) { + _FAT_unlock(&partition->lock); + r->_errno = EIO; + return -1; + } + + // Flush any sectors in the disc cache + if (!_FAT_cache_flush (partition->cache)) { + _FAT_unlock(&partition->lock); + r->_errno = EIO; + return -1; + } + + _FAT_unlock(&partition->lock); + return 0; +} + +int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) { + PARTITION* partition = NULL; + bool fileExists; + DIR_ENTRY dirEntry; + const char* pathEnd; + uint32_t parentCluster, dirCluster; + uint8_t newEntryData[DIR_ENTRY_DATA_SIZE]; + + partition = _FAT_partition_getPartitionFromPath (path); + if (partition == NULL) { + r->_errno = ENODEV; + return -1; + } + + // Move the path pointer to the start of the actual path + if (strchr (path, ':') != NULL) { + path = strchr (path, ':') + 1; + } + if (strchr (path, ':') != NULL) { + r->_errno = EINVAL; + return -1; + } + + _FAT_lock(&partition->lock); + + // Search for the file/directory on the disc + fileExists = _FAT_directory_entryFromPath (partition, &dirEntry, path, NULL); + + // Make sure it doesn't exist + if (fileExists) { + _FAT_unlock(&partition->lock); + r->_errno = EEXIST; + return -1; + } + + if (partition->readOnly) { + // We can't write to a read-only partition + _FAT_unlock(&partition->lock); + r->_errno = EROFS; + return -1; + } + + // Get the directory it has to go in + pathEnd = strrchr (path, DIR_SEPARATOR); + if (pathEnd == NULL) { + // No path was specified + parentCluster = partition->cwdCluster; + pathEnd = path; + } else { + // Path was specified -- get the right parentCluster + // Recycling dirEntry, since it needs to be recreated anyway + if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, pathEnd) || + !_FAT_directory_isDirectory(&dirEntry)) { + _FAT_unlock(&partition->lock); + r->_errno = ENOTDIR; + return -1; + } + parentCluster = _FAT_directory_entryGetCluster (partition, dirEntry.entryData); + // Move the pathEnd past the last DIR_SEPARATOR + pathEnd += 1; + } + // Create the entry data + strncpy (dirEntry.filename, pathEnd, MAX_FILENAME_LENGTH - 1); + memset (dirEntry.entryData, 0, DIR_ENTRY_DATA_SIZE); + + // Set the creation time and date + dirEntry.entryData[DIR_ENTRY_cTime_ms] = 0; + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cTime, _FAT_filetime_getTimeFromRTC()); + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cDate, _FAT_filetime_getDateFromRTC()); + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_mTime, _FAT_filetime_getTimeFromRTC()); + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_mDate, _FAT_filetime_getDateFromRTC()); + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_aDate, _FAT_filetime_getDateFromRTC()); + + // Set the directory attribute + dirEntry.entryData[DIR_ENTRY_attributes] = ATTRIB_DIR; + + // Get a cluster for the new directory + dirCluster = _FAT_fat_linkFreeClusterCleared (partition, CLUSTER_FREE); + if (!_FAT_fat_isValidCluster(partition, dirCluster)) { + // No space left on disc for the cluster + _FAT_unlock(&partition->lock); + r->_errno = ENOSPC; + return -1; + } + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cluster, dirCluster); + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_clusterHigh, dirCluster >> 16); + + // Write the new directory's entry to it's parent + if (!_FAT_directory_addEntry (partition, &dirEntry, parentCluster)) { + _FAT_unlock(&partition->lock); + r->_errno = ENOSPC; + return -1; + } + + // Create the dot entry within the directory + memset (newEntryData, 0, DIR_ENTRY_DATA_SIZE); + memset (newEntryData, ' ', 11); + newEntryData[DIR_ENTRY_name] = '.'; + newEntryData[DIR_ENTRY_attributes] = ATTRIB_DIR; + u16_to_u8array (newEntryData, DIR_ENTRY_cluster, dirCluster); + u16_to_u8array (newEntryData, DIR_ENTRY_clusterHigh, dirCluster >> 16); + + // Write it to the directory, erasing that sector in the process + _FAT_cache_eraseWritePartialSector ( partition->cache, newEntryData, + _FAT_fat_clusterToSector (partition, dirCluster), 0, DIR_ENTRY_DATA_SIZE); + + + // Create the double dot entry within the directory + + // if ParentDir == Rootdir then ".."" always link to Cluster 0 + if(parentCluster == partition->rootDirCluster) + parentCluster = FAT16_ROOT_DIR_CLUSTER; + + newEntryData[DIR_ENTRY_name + 1] = '.'; + u16_to_u8array (newEntryData, DIR_ENTRY_cluster, parentCluster); + u16_to_u8array (newEntryData, DIR_ENTRY_clusterHigh, parentCluster >> 16); + + // Write it to the directory + _FAT_cache_writePartialSector ( partition->cache, newEntryData, + _FAT_fat_clusterToSector (partition, dirCluster), DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + + // Flush any sectors in the disc cache + if (!_FAT_cache_flush(partition->cache)) { + _FAT_unlock(&partition->lock); + r->_errno = EIO; + return -1; + } + + _FAT_unlock(&partition->lock); + return 0; +} +// +//int _FAT_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf) +//{ +// PARTITION* partition = NULL; +// unsigned int freeClusterCount; +// +// // Get the partition of the requested path +// partition = _FAT_partition_getPartitionFromPath (path); +// if (partition == NULL) { +// r->_errno = ENODEV; +// return -1; +// } +// +// _FAT_lock(&partition->lock); +// +// freeClusterCount = _FAT_fat_freeClusterCount (partition); +// +// // FAT clusters = POSIX blocks +// buf->f_bsize = partition->bytesPerCluster; // File system block size. +// buf->f_frsize = partition->bytesPerCluster; // Fundamental file system block size. +// +// buf->f_blocks = partition->fat.lastCluster - CLUSTER_FIRST + 1; // Total number of blocks on file system in units of f_frsize. +// buf->f_bfree = freeClusterCount; // Total number of free blocks. +// buf->f_bavail = freeClusterCount; // Number of free blocks available to non-privileged process. +// +// // Treat requests for info on inodes as clusters +// buf->f_files = partition->fat.lastCluster - CLUSTER_FIRST + 1; // Total number of file serial numbers. +// buf->f_ffree = freeClusterCount; // Total number of free file serial numbers. +// buf->f_favail = freeClusterCount; // Number of file serial numbers available to non-privileged process. +// +// // File system ID. 32bit ioType value +// buf->f_fsid = _FAT_disc_hostType(partition->disc); +// +// // Bit mask of f_flag values. +// buf->f_flag = ST_NOSUID /* No support for ST_ISUID and ST_ISGID file mode bits */ +// | (partition->readOnly ? ST_RDONLY /* Read only file system */ : 0 ) ; +// // Maximum filename length. +// buf->f_namemax = MAX_FILENAME_LENGTH; +// +// _FAT_unlock(&partition->lock); +// return 0; +//} + +DIR_ITER* _FAT_diropen_r(struct _reent *r, DIR_ITER *dirState, const char *path) { + DIR_ENTRY dirEntry; + DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); + bool fileExists; + + state->partition = _FAT_partition_getPartitionFromPath (path); + if (state->partition == NULL) { + r->_errno = ENODEV; + return NULL; + } + + // Move the path pointer to the start of the actual path + if (strchr (path, ':') != NULL) { + path = strchr (path, ':') + 1; + } + if (strchr (path, ':') != NULL) { + r->_errno = EINVAL; + return NULL; + } + + _FAT_lock(&state->partition->lock); + + // Get the start cluster of the directory + fileExists = _FAT_directory_entryFromPath (state->partition, &dirEntry, path, NULL); + + if (!fileExists) { + _FAT_unlock(&state->partition->lock); + r->_errno = ENOENT; + return NULL; + } + + // Make sure it is a directory + if (! _FAT_directory_isDirectory (&dirEntry)) { + _FAT_unlock(&state->partition->lock); + r->_errno = ENOTDIR; + return NULL; + } + + // Save the start cluster for use when resetting the directory data + state->startCluster = _FAT_directory_entryGetCluster (state->partition, dirEntry.entryData); + + // Get the first entry for use with a call to dirnext + state->validEntry = + _FAT_directory_getFirstEntry (state->partition, &(state->currentEntry), state->startCluster); + + // We are now using this entry + state->inUse = true; + _FAT_unlock(&state->partition->lock); + return (DIR_ITER*) state; +} + +int _FAT_dirreset_r (struct _reent *r, DIR_ITER *dirState) { + DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); + + _FAT_lock(&state->partition->lock); + + // Make sure we are still using this entry + if (!state->inUse) { + _FAT_unlock(&state->partition->lock); + r->_errno = EBADF; + return -1; + } + + // Get the first entry for use with a call to dirnext + state->validEntry = + _FAT_directory_getFirstEntry (state->partition, &(state->currentEntry), state->startCluster); + + _FAT_unlock(&state->partition->lock); + return 0; +} + +int _FAT_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *filestat) { + DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); + + _FAT_lock(&state->partition->lock); + + // Make sure we are still using this entry + if (!state->inUse) { + _FAT_unlock(&state->partition->lock); + r->_errno = EBADF; + return -1; + } + + // Make sure there is another file to report on + if (! state->validEntry) { + _FAT_unlock(&state->partition->lock); + r->_errno = ENOENT; + return -1; + } + + // Get the filename + strncpy (filename, state->currentEntry.filename, MAX_FILENAME_LENGTH); + // Get the stats, if requested + if (filestat != NULL) { + _FAT_directory_entryStat (state->partition, &(state->currentEntry), filestat); + } + + // Look for the next entry for use next time + state->validEntry = + _FAT_directory_getNextEntry (state->partition, &(state->currentEntry)); + + _FAT_unlock(&state->partition->lock); + return 0; +} + +int _FAT_dirclose_r (struct _reent *r, DIR_ITER *dirState) { + DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct); + + // We are no longer using this entry + _FAT_lock(&state->partition->lock); + state->inUse = false; + _FAT_unlock(&state->partition->lock); + + return 0; +} diff --git a/jni/desmume/src/utils/libfat/fatdir.h b/jni/desmume/src/utils/libfat/fatdir.h new file mode 100755 index 0000000..7c7a19c --- /dev/null +++ b/jni/desmume/src/utils/libfat/fatdir.h @@ -0,0 +1,78 @@ +/* + fatdir.h + + Functions used by the newlib disc stubs to interface with + this library + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _FATDIR_H +#define _FATDIR_H + +#include <sys/stat.h> + +#include "common.h" +#include "directory.h" + +#ifndef LIBFAT_PC +#include <sys/statvfs.h> +#include <sys/iosupport.h> +#include <sys/reent.h> +#endif + + +typedef struct { + PARTITION* partition; + DIR_ENTRY currentEntry; + uint32_t startCluster; + bool inUse; + bool validEntry; +} DIR_STATE_STRUCT; + +extern int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st); + +extern int _FAT_link_r (struct _reent *r, const char *existing, const char *newLink); + +extern int _FAT_unlink_r (struct _reent *r, const char *name); + +extern int _FAT_chdir_r (struct _reent *r, const char *name); + +extern int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName); + +extern int _FAT_mkdir_r (struct _reent *r, const char *path, int mode); + +extern int _FAT_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf); + +/* +Directory iterator functions +*/ +extern DIR_ITER* _FAT_diropen_r(struct _reent *r, DIR_ITER *dirState, const char *path); +extern int _FAT_dirreset_r (struct _reent *r, DIR_ITER *dirState); +extern int _FAT_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *filestat); +extern int _FAT_dirclose_r (struct _reent *r, DIR_ITER *dirState); + + +#endif // _FATDIR_H diff --git a/jni/desmume/src/utils/libfat/fatfile.cpp b/jni/desmume/src/utils/libfat/fatfile.cpp new file mode 100755 index 0000000..2e80af7 --- /dev/null +++ b/jni/desmume/src/utils/libfat/fatfile.cpp @@ -0,0 +1,1134 @@ +/* + fatfile.c + + Functions used by the newlib disc stubs to interface with + this library + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2009-10-23 oggzee: fixes for cluster aligned file size (write, truncate, seek) +*/ + + +#include "fatfile.h" + +#include <fcntl.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#ifndef _MSC_VER +#include <unistd.h> +#endif + +#include "cache.h" +#include "file_allocation_table.h" +#include "bit_ops.h" +#include "filetime.h" +#include "lock.h" + +intptr_t _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode) { + PARTITION* partition = NULL; + bool fileExists; + DIR_ENTRY dirEntry; + const char* pathEnd; + uint32_t dirCluster; + FILE_STRUCT* file = (FILE_STRUCT*) fileStruct; + partition = _FAT_partition_getPartitionFromPath (path); + + if (partition == NULL) { + r->_errno = ENODEV; + return -1; + } + + // Move the path pointer to the start of the actual path + if (strchr (path, ':') != NULL) { + path = strchr (path, ':') + 1; + } + if (strchr (path, ':') != NULL) { + r->_errno = EINVAL; + return -1; + } + + // Determine which mode the file is openned for + if ((flags & 0x03) == O_RDONLY) { + // Open the file for read-only access + file->read = true; + file->write = false; + file->append = false; + } else if ((flags & 0x03) == O_WRONLY) { + // Open file for write only access + file->read = false; + file->write = true; + file->append = false; + } else if ((flags & 0x03) == O_RDWR) { + // Open file for read/write access + file->read = true; + file->write = true; + file->append = false; + } else { + r->_errno = EACCES; + return -1; + } + + // Make sure we aren't trying to write to a read-only disc + if (file->write && partition->readOnly) { + r->_errno = EROFS; + return -1; + } + + // Search for the file on the disc + _FAT_lock(&partition->lock); + fileExists = _FAT_directory_entryFromPath (partition, &dirEntry, path, NULL); + + // The file shouldn't exist if we are trying to create it + if ((flags & O_CREAT) && (flags & O_EXCL) && fileExists) { + _FAT_unlock(&partition->lock); + r->_errno = EEXIST; + return -1; + } + + // It should not be a directory if we're openning a file, + if (fileExists && _FAT_directory_isDirectory(&dirEntry)) { + _FAT_unlock(&partition->lock); + r->_errno = EISDIR; + return -1; + } + + // We haven't modified the file yet + file->modified = false; + + // If the file doesn't exist, create it if we're allowed to + if (!fileExists) { + if (flags & O_CREAT) { + if (partition->readOnly) { + // We can't write to a read-only partition + _FAT_unlock(&partition->lock); + r->_errno = EROFS; + return -1; + } + // Create the file + // Get the directory it has to go in + pathEnd = strrchr (path, DIR_SEPARATOR); + if (pathEnd == NULL) { + // No path was specified + dirCluster = partition->cwdCluster; + pathEnd = path; + } else { + // Path was specified -- get the right dirCluster + // Recycling dirEntry, since it needs to be recreated anyway + if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, pathEnd) || + !_FAT_directory_isDirectory(&dirEntry)) { + _FAT_unlock(&partition->lock); + r->_errno = ENOTDIR; + return -1; + } + dirCluster = _FAT_directory_entryGetCluster (partition, dirEntry.entryData); + // Move the pathEnd past the last DIR_SEPARATOR + pathEnd += 1; + } + // Create the entry data + strncpy (dirEntry.filename, pathEnd, MAX_FILENAME_LENGTH - 1); + memset (dirEntry.entryData, 0, DIR_ENTRY_DATA_SIZE); + + // Set the creation time and date + dirEntry.entryData[DIR_ENTRY_cTime_ms] = 0; + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cTime, _FAT_filetime_getTimeFromRTC()); + u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cDate, _FAT_filetime_getDateFromRTC()); + + if (!_FAT_directory_addEntry (partition, &dirEntry, dirCluster)) { + _FAT_unlock(&partition->lock); + r->_errno = ENOSPC; + return -1; + } + + // File entry is modified + file->modified = true; + } else { + // file doesn't exist, and we aren't creating it + _FAT_unlock(&partition->lock); + r->_errno = ENOENT; + return -1; + } + } + + file->filesize = u8array_to_u32 (dirEntry.entryData, DIR_ENTRY_fileSize); + + /* Allow LARGEFILEs with undefined results + // Make sure that the file size can fit in the available space + if (!(flags & O_LARGEFILE) && (file->filesize >= (1<<31))) { + r->_errno = EFBIG; + return -1; + } + */ + + // Make sure we aren't trying to write to a read-only file + if (file->write && !_FAT_directory_isWritable(&dirEntry)) { + _FAT_unlock(&partition->lock); + r->_errno = EROFS; + return -1; + } + + // Associate this file with a particular partition + file->partition = partition; + + file->startCluster = _FAT_directory_entryGetCluster (partition, dirEntry.entryData); + + // Truncate the file if requested + if ((flags & O_TRUNC) && file->write && (file->startCluster != 0)) { + _FAT_fat_clearLinks (partition, file->startCluster); + file->startCluster = CLUSTER_FREE; + file->filesize = 0; + // File is modified since we just cut it all off + file->modified = true; + } + + // Remember the position of this file's directory entry + file->dirEntryStart = dirEntry.dataStart; // Points to the start of the LFN entries of a file, or the alias for no LFN + file->dirEntryEnd = dirEntry.dataEnd; + + // Reset read/write pointer + file->currentPosition = 0; + file->rwPosition.cluster = file->startCluster; + file->rwPosition.sector = 0; + file->rwPosition.byte = 0; + + if (flags & O_APPEND) { + file->append = true; + + // Set append pointer to the end of the file + file->appendPosition.cluster = _FAT_fat_lastCluster (partition, file->startCluster); + file->appendPosition.sector = (file->filesize % partition->bytesPerCluster) / BYTES_PER_READ; + file->appendPosition.byte = file->filesize % BYTES_PER_READ; + + // Check if the end of the file is on the end of a cluster + if ( (file->filesize > 0) && ((file->filesize % partition->bytesPerCluster)==0) ){ + // Set flag to allocate a new cluster + file->appendPosition.sector = partition->sectorsPerCluster; + file->appendPosition.byte = 0; + } + } else { + file->append = false; + // Use something sane for the append pointer, so the whole file struct contains known values + file->appendPosition = file->rwPosition; + } + + file->inUse = true; + + // Insert this file into the double-linked list of open files + partition->openFileCount += 1; + if (partition->firstOpenFile) { + file->nextOpenFile = partition->firstOpenFile; + partition->firstOpenFile->prevOpenFile = file; + } else { + file->nextOpenFile = NULL; + } + file->prevOpenFile = NULL; + partition->firstOpenFile = file; + + _FAT_unlock(&partition->lock); + + return (intptr_t) file; +} + +/* +Synchronizes the file data to disc. +Does no locking of its own -- lock the partition before calling. +Returns 0 on success, an error code on failure. +*/ +int _FAT_syncToDisc (FILE_STRUCT* file) { + uint8_t dirEntryData[DIR_ENTRY_DATA_SIZE]; + + if (!file || !file->inUse) { + return EBADF; + } + + if (file->write && file->modified) { + // Load the old entry + _FAT_cache_readPartialSector (file->partition->cache, dirEntryData, + _FAT_fat_clusterToSector(file->partition, file->dirEntryEnd.cluster) + file->dirEntryEnd.sector, + file->dirEntryEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + + // Write new data to the directory entry + // File size + u32_to_u8array (dirEntryData, DIR_ENTRY_fileSize, file->filesize); + + // Start cluster + u16_to_u8array (dirEntryData, DIR_ENTRY_cluster, file->startCluster); + u16_to_u8array (dirEntryData, DIR_ENTRY_clusterHigh, file->startCluster >> 16); + + // Modification time and date + u16_to_u8array (dirEntryData, DIR_ENTRY_mTime, _FAT_filetime_getTimeFromRTC()); + u16_to_u8array (dirEntryData, DIR_ENTRY_mDate, _FAT_filetime_getDateFromRTC()); + + // Access date + u16_to_u8array (dirEntryData, DIR_ENTRY_aDate, _FAT_filetime_getDateFromRTC()); + + // Set archive attribute + dirEntryData[DIR_ENTRY_attributes] |= ATTRIB_ARCH; + + // Write the new entry + _FAT_cache_writePartialSector (file->partition->cache, dirEntryData, + _FAT_fat_clusterToSector(file->partition, file->dirEntryEnd.cluster) + file->dirEntryEnd.sector, + file->dirEntryEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); + + // Flush any sectors in the disc cache + if (!_FAT_cache_flush(file->partition->cache)) { + return EIO; + } + } + + file->modified = false; + + return 0; +} + + +intptr_t _FAT_close_r (struct _reent *r, intptr_t fd) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + intptr_t ret = 0; + + if (!file->inUse) { + r->_errno = EBADF; + return -1; + } + + _FAT_lock(&file->partition->lock); + + if (file->write) { + ret = _FAT_syncToDisc (file); + if (ret != 0) { + r->_errno = ret; + ret = -1; + } + } + + file->inUse = false; + + // Remove this file from the double-linked list of open files + file->partition->openFileCount -= 1; + if (file->nextOpenFile) { + file->nextOpenFile->prevOpenFile = file->prevOpenFile; + } + if (file->prevOpenFile) { + file->prevOpenFile->nextOpenFile = file->nextOpenFile; + } else { + file->partition->firstOpenFile = file->nextOpenFile; + } + + _FAT_unlock(&file->partition->lock); + + return ret; +} + +ssize_t _FAT_read_r (struct _reent *r, intptr_t fd, char *ptr, size_t len) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + PARTITION* partition; + CACHE* cache; + FILE_POSITION position; + uint32_t tempNextCluster; + unsigned int tempVar; + size_t remain; + bool flagNoError = true; + + // Short circuit cases where len is 0 (or less) + if (len <= 0) { + return 0; + } + + // Make sure we can actually read from the file + if ((file == NULL) || !file->inUse || !file->read) { + r->_errno = EBADF; + return -1; + } + + partition = file->partition; + _FAT_lock(&partition->lock); + + // Don't try to read if the read pointer is past the end of file + if (file->currentPosition >= file->filesize || file->startCluster == CLUSTER_FREE) { + r->_errno = EOVERFLOW; + _FAT_unlock(&partition->lock); + return 0; + } + + // Don't read past end of file + if (len + file->currentPosition > file->filesize) { + r->_errno = EOVERFLOW; + len = file->filesize - file->currentPosition; + } + + remain = len; + position = file->rwPosition; + cache = file->partition->cache; + + // Align to sector + tempVar = BYTES_PER_READ - position.byte; + if (tempVar > remain) { + tempVar = remain; + } + + if ((tempVar < BYTES_PER_READ) && flagNoError) + { + _FAT_cache_readPartialSector ( cache, ptr, _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, + position.byte, tempVar); + + remain -= tempVar; + ptr += tempVar; + + position.byte += tempVar; + if (position.byte >= BYTES_PER_READ) { + position.byte = 0; + position.sector++; + } + } + + // align to cluster + // tempVar is number of sectors to read + if (remain > (partition->sectorsPerCluster - position.sector) * BYTES_PER_READ) { + tempVar = partition->sectorsPerCluster - position.sector; + } else { + tempVar = remain / BYTES_PER_READ; + } + + if ((tempVar > 0) && flagNoError) { + if (! _FAT_cache_readSectors (cache, _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, + tempVar, ptr)) + { + flagNoError = false; + r->_errno = EIO; + } else { + ptr += tempVar * BYTES_PER_READ; + remain -= tempVar * BYTES_PER_READ; + position.sector += tempVar; + } + } + + // Move onto next cluster + // It should get to here without reading anything if a cluster is due to be allocated + if ((position.sector >= partition->sectorsPerCluster) && flagNoError) { + tempNextCluster = _FAT_fat_nextCluster(partition, position.cluster); + if ((remain == 0) && (tempNextCluster == CLUSTER_EOF)) { + position.sector = partition->sectorsPerCluster; + } else if (!_FAT_fat_isValidCluster(partition, tempNextCluster)) { + r->_errno = EIO; + flagNoError = false; + } else { + position.sector = 0; + position.cluster = tempNextCluster; + } + } + + // Read in whole clusters, contiguous blocks at a time + while ((remain >= partition->bytesPerCluster) && flagNoError) { + uint32_t chunkEnd; + uint32_t nextChunkStart = position.cluster; + size_t chunkSize = 0; + + do { + chunkEnd = nextChunkStart; + nextChunkStart = _FAT_fat_nextCluster (partition, chunkEnd); + chunkSize += partition->bytesPerCluster; + } while ((nextChunkStart == chunkEnd + 1) && +#ifdef LIMIT_SECTORS + (chunkSize + partition->bytesPerCluster <= LIMIT_SECTORS * BYTES_PER_READ) && +#endif + (chunkSize + partition->bytesPerCluster <= remain)); + + if (!_FAT_cache_readSectors (cache, _FAT_fat_clusterToSector (partition, position.cluster), + chunkSize / BYTES_PER_READ, ptr)) + { + flagNoError = false; + r->_errno = EIO; + break; + } + ptr += chunkSize; + remain -= chunkSize; + + // Advance to next cluster + if ((remain == 0) && (nextChunkStart == CLUSTER_EOF)) { + position.sector = partition->sectorsPerCluster; + position.cluster = chunkEnd; + } else if (!_FAT_fat_isValidCluster(partition, nextChunkStart)) { + r->_errno = EIO; + flagNoError = false; + } else { + position.sector = 0; + position.cluster = nextChunkStart; + } + } + + // Read remaining sectors + tempVar = remain / BYTES_PER_READ; // Number of sectors left + if ((tempVar > 0) && flagNoError) { + if (!_FAT_cache_readSectors (cache, _FAT_fat_clusterToSector (partition, position.cluster), + tempVar, ptr)) + { + flagNoError = false; + r->_errno = EIO; + } else { + ptr += tempVar * BYTES_PER_READ; + remain -= tempVar * BYTES_PER_READ; + position.sector += tempVar; + } + } + + // Last remaining sector + // Check if anything is left + if ((remain > 0) && flagNoError) { + _FAT_cache_readPartialSector ( cache, ptr, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, 0, remain); + position.byte += remain; + remain = 0; + } + + // Length read is the wanted length minus the stuff not read + len = len - remain; + + // Update file information + file->rwPosition = position; + file->currentPosition += len; + + _FAT_unlock(&partition->lock); + return len; +} + +// if current position is on the cluster border and more data has to be written +// then get next cluster or allocate next cluster +// this solves the over-allocation problems when file size is aligned to cluster size +// return true on succes, false on error +static bool _FAT_check_position_for_next_cluster(struct _reent *r, + FILE_POSITION *position, PARTITION* partition, size_t remain, bool *flagNoError) +{ + uint32_t tempNextCluster; + // do nothing if no more data to write + if (remain == 0) return true; + if (flagNoError && *flagNoError == false) return false; + if ((remain < 0) || (position->sector > partition->sectorsPerCluster)) { + // invalid arguments - internal error + r->_errno = EINVAL; + goto err; + } + if (position->sector == partition->sectorsPerCluster) { + // need to advance to next cluster + tempNextCluster = _FAT_fat_nextCluster(partition, position->cluster); + if ((tempNextCluster == CLUSTER_EOF) || (tempNextCluster == CLUSTER_FREE)) { + // Ran out of clusters so get a new one + tempNextCluster = _FAT_fat_linkFreeCluster(partition, position->cluster); + } + if (!_FAT_fat_isValidCluster(partition, tempNextCluster)) { + // Couldn't get a cluster, so abort + r->_errno = ENOSPC; + goto err; + } + position->sector = 0; + position->cluster = tempNextCluster; + } + return true; +err: + if (flagNoError) *flagNoError = false; + return false; +} + +/* +Extend a file so that the size is the same as the rwPosition +*/ +static bool _FAT_file_extend_r (struct _reent *r, FILE_STRUCT* file) { + PARTITION* partition = file->partition; + CACHE* cache = file->partition->cache; + FILE_POSITION position; + uint8_t zeroBuffer [BYTES_PER_READ] = {0}; + uint32_t remain; + uint32_t tempNextCluster; + unsigned int sector; + + position.byte = file->filesize % BYTES_PER_READ; + position.sector = (file->filesize % partition->bytesPerCluster) / BYTES_PER_READ; + // It is assumed that there is always a startCluster + // This will be true when _FAT_file_extend_r is called from _FAT_write_r + position.cluster = _FAT_fat_lastCluster (partition, file->startCluster); + + remain = file->currentPosition - file->filesize; + + if ((remain > 0) && (file->filesize > 0) && (position.sector == 0) && (position.byte == 0)) { + // Get a new cluster on the edge of a cluster boundary + tempNextCluster = _FAT_fat_linkFreeCluster(partition, position.cluster); + if (!_FAT_fat_isValidCluster(partition, tempNextCluster)) { + // Couldn't get a cluster, so abort + r->_errno = ENOSPC; + return false; + } + position.cluster = tempNextCluster; + position.sector = 0; + } + + if (remain + position.byte < BYTES_PER_READ) { + // Only need to clear to the end of the sector + _FAT_cache_writePartialSector (cache, zeroBuffer, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, position.byte, remain); + position.byte += remain; + } else { + if (position.byte > 0) { + _FAT_cache_writePartialSector (cache, zeroBuffer, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, position.byte, + BYTES_PER_READ - position.byte); + remain -= (BYTES_PER_READ - position.byte); + position.byte = 0; + position.sector ++; + } + + while (remain >= BYTES_PER_READ) { + if (position.sector >= partition->sectorsPerCluster) { + position.sector = 0; + // Ran out of clusters so get a new one + tempNextCluster = _FAT_fat_linkFreeCluster(partition, position.cluster); + if (!_FAT_fat_isValidCluster(partition, tempNextCluster)) { + // Couldn't get a cluster, so abort + r->_errno = ENOSPC; + return false; + } + position.cluster = tempNextCluster; + } + + sector = _FAT_fat_clusterToSector (partition, position.cluster) + position.sector; + _FAT_cache_writeSectors (cache, sector, 1, zeroBuffer); + + remain -= BYTES_PER_READ; + position.sector ++; + } + + if (!_FAT_check_position_for_next_cluster(r, &position, partition, remain, NULL)) { + // error already marked + return false; + } + + if (remain > 0) { + _FAT_cache_writePartialSector (cache, zeroBuffer, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, 0, remain); + position.byte = remain; + } + } + + file->rwPosition = position; + file->filesize = file->currentPosition; + return true; +} + +ssize_t _FAT_write_r (struct _reent *r, intptr_t fd, const char *ptr, size_t len) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + PARTITION* partition; + CACHE* cache; + FILE_POSITION position; + uint32_t tempNextCluster; + unsigned int tempVar; + size_t remain; + bool flagNoError = true; + bool flagAppending = false; + + // Make sure we can actually write to the file + if ((file == NULL) || !file->inUse || !file->write) { + r->_errno = EBADF; + return -1; + } + + partition = file->partition; + cache = file->partition->cache; + _FAT_lock(&partition->lock); + + // Only write up to the maximum file size, taking into account wrap-around of ints + if (len + file->filesize > FILE_MAX_SIZE || len + file->filesize < file->filesize) { + len = FILE_MAX_SIZE - file->filesize; + } + + // Short circuit cases where len is 0 (or less) + if (len <= 0) { + _FAT_unlock(&partition->lock); + return 0; + } + + remain = len; + + // Get a new cluster for the start of the file if required + if (file->startCluster == CLUSTER_FREE) { + tempNextCluster = _FAT_fat_linkFreeCluster (partition, CLUSTER_FREE); + if (!_FAT_fat_isValidCluster(partition, tempNextCluster)) { + // Couldn't get a cluster, so abort immediately + _FAT_unlock(&partition->lock); + r->_errno = ENOSPC; + return -1; + } + file->startCluster = tempNextCluster; + + // Appending starts at the begining for a 0 byte file + file->appendPosition.cluster = file->startCluster; + file->appendPosition.sector = 0; + file->appendPosition.byte = 0; + + file->rwPosition.cluster = file->startCluster; + file->rwPosition.sector = 0; + file->rwPosition.byte = 0; + } + + if (file->append) { + position = file->appendPosition; + flagAppending = true; + } else { + // If the write pointer is past the end of the file, extend the file to that size + if (file->currentPosition > file->filesize) { + if (!_FAT_file_extend_r (r, file)) { + _FAT_unlock(&partition->lock); + return -1; + } + } + + // Write at current read pointer + position = file->rwPosition; + + // If it is writing past the current end of file, set appending flag + if (len + file->currentPosition > file->filesize) { + flagAppending = true; + } + } + + // Move onto next cluster if needed + _FAT_check_position_for_next_cluster(r, &position, partition, remain, &flagNoError); + + // Align to sector + tempVar = BYTES_PER_READ - position.byte; + if (tempVar > remain) { + tempVar = remain; + } + + if ((tempVar < BYTES_PER_READ) && flagNoError) { + // Write partial sector to disk + _FAT_cache_writePartialSector (cache, ptr, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, position.byte, tempVar); + + remain -= tempVar; + ptr += tempVar; + position.byte += tempVar; + + + // Move onto next sector + if (position.byte >= BYTES_PER_READ) { + position.byte = 0; + position.sector ++; + } + } + + // Align to cluster + // tempVar is number of sectors to write + if (remain > (partition->sectorsPerCluster - position.sector) * BYTES_PER_READ) { + tempVar = partition->sectorsPerCluster - position.sector; + } else { + tempVar = remain / BYTES_PER_READ; + } + + if ((tempVar > 0 && tempVar < partition->sectorsPerCluster) && flagNoError) { + if (!_FAT_cache_writeSectors (cache, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, tempVar, ptr)) + { + flagNoError = false; + r->_errno = EIO; + } else { + ptr += tempVar * BYTES_PER_READ; + remain -= tempVar * BYTES_PER_READ; + position.sector += tempVar; + } + } + + // Write whole clusters + while ((remain >= partition->bytesPerCluster) && flagNoError) { + // allocate next cluster + _FAT_check_position_for_next_cluster(r, &position, partition, remain, &flagNoError); + if (!flagNoError) break; + // set indexes to the current position + uint32_t chunkEnd = position.cluster; + uint32_t nextChunkStart = position.cluster; + size_t chunkSize = partition->bytesPerCluster; + FILE_POSITION next_position = position; + + // group consecutive clusters + while (flagNoError && +#ifdef LIMIT_SECTORS + (chunkSize + partition->bytesPerCluster <= LIMIT_SECTORS * BYTES_PER_READ) && +#endif + (chunkSize + partition->bytesPerCluster < remain)) + { + // pretend to use up all sectors in next_position + next_position.sector = partition->sectorsPerCluster; + // get or allocate next cluster + _FAT_check_position_for_next_cluster(r, &next_position, partition, + remain - chunkSize, &flagNoError); + if (!flagNoError) break; // exit loop on error + nextChunkStart = next_position.cluster; + if (nextChunkStart != chunkEnd + 1) break; // exit loop if not consecutive + chunkEnd = nextChunkStart; + chunkSize += partition->bytesPerCluster; + } + + if ( !_FAT_cache_writeSectors (cache, + _FAT_fat_clusterToSector(partition, position.cluster), chunkSize / BYTES_PER_READ, ptr)) + { + flagNoError = false; + r->_errno = EIO; + break; + } + ptr += chunkSize; + remain -= chunkSize; + + if ((chunkEnd != nextChunkStart) && _FAT_fat_isValidCluster(partition, nextChunkStart)) { + // new cluster is already allocated (because it was not consecutive) + position.cluster = nextChunkStart; + position.sector = 0; + } else { + // Allocate a new cluster when next writing the file + position.cluster = chunkEnd; + position.sector = partition->sectorsPerCluster; + } + } + + // allocate next cluster if needed + _FAT_check_position_for_next_cluster(r, &position, partition, remain, &flagNoError); + + // Write remaining sectors + tempVar = remain / BYTES_PER_READ; // Number of sectors left + if ((tempVar > 0) && flagNoError) { + if (!_FAT_cache_writeSectors (cache, _FAT_fat_clusterToSector (partition, position.cluster), tempVar, ptr)) + { + flagNoError = false; + r->_errno = EIO; + } else { + ptr += tempVar * BYTES_PER_READ; + remain -= tempVar * BYTES_PER_READ; + position.sector += tempVar; + } + } + + // Last remaining sector + if ((remain > 0) && flagNoError) { + if (flagAppending) { + _FAT_cache_eraseWritePartialSector ( cache, ptr, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, 0, remain); + } else { + _FAT_cache_writePartialSector ( cache, ptr, + _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, 0, remain); + } + position.byte += remain; + remain = 0; + } + + + // Amount written is the originally requested amount minus stuff remaining + len = len - remain; + + // Update file information + file->modified = true; + if (file->append) { + // Appending doesn't affect the read pointer + file->appendPosition = position; + file->filesize += len; + } else { + // Writing also shifts the read pointer + file->rwPosition = position; + file->currentPosition += len; + if (file->filesize < file->currentPosition) { + file->filesize = file->currentPosition; + } + } + _FAT_unlock(&partition->lock); + + return len; +} + + +off_t _FAT_seek_r (struct _reent *r, intptr_t fd, off_t pos, int dir) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + PARTITION* partition; + uint32_t cluster, nextCluster; + int clusCount; + off_t newPosition; + uint32_t position; + + if ((file == NULL) || (file->inUse == false)) { + // invalid file + r->_errno = EBADF; + return -1; + } + + partition = file->partition; + _FAT_lock(&partition->lock); + + switch (dir) { + case SEEK_SET: + newPosition = pos; + break; + case SEEK_CUR: + newPosition = (off_t)file->currentPosition + pos; + break; + case SEEK_END: + newPosition = (off_t)file->filesize + pos; + break; + default: + _FAT_unlock(&partition->lock); + r->_errno = EINVAL; + return -1; + } + + if ((pos > 0) && (newPosition < 0)) { + _FAT_unlock(&partition->lock); + r->_errno = EOVERFLOW; + return -1; + } + + // newPosition can only be larger than the FILE_MAX_SIZE on platforms where + // off_t is larger than 32 bits. + if (newPosition < 0 || ((sizeof(newPosition) > 4) && newPosition > (off_t)FILE_MAX_SIZE)) { + _FAT_unlock(&partition->lock); + r->_errno = EINVAL; + return -1; + } + + position = (uint32_t)newPosition; + + // Only change the read/write position if it is within the bounds of the current filesize, + // or at the very edge of the file + if (position <= file->filesize && file->startCluster != CLUSTER_FREE) { + // Calculate where the correct cluster is + // how many clusters from start of file + clusCount = position / partition->bytesPerCluster; + cluster = file->startCluster; + if (position >= file->currentPosition) { + // start from current cluster + int currentCount = file->currentPosition / partition->bytesPerCluster; + if (file->rwPosition.sector == partition->sectorsPerCluster) { + currentCount--; + } + clusCount -= currentCount; + cluster = file->rwPosition.cluster; + } + // Calculate the sector and byte of the current position, + // and store them + file->rwPosition.sector = (position % partition->bytesPerCluster) / BYTES_PER_READ; + file->rwPosition.byte = position % BYTES_PER_READ; + + nextCluster = _FAT_fat_nextCluster (partition, cluster); + while ((clusCount > 0) && (nextCluster != CLUSTER_FREE) && (nextCluster != CLUSTER_EOF)) { + clusCount--; + cluster = nextCluster; + nextCluster = _FAT_fat_nextCluster (partition, cluster); + } + + // Check if ran out of clusters and it needs to allocate a new one + if (clusCount > 0) { + if ((clusCount == 1) && (file->filesize == position) && (file->rwPosition.sector == 0)) { + // Set flag to allocate a new cluster + file->rwPosition.sector = partition->sectorsPerCluster; + file->rwPosition.byte = 0; + } else { + _FAT_unlock(&partition->lock); + r->_errno = EINVAL; + return -1; + } + } + + file->rwPosition.cluster = cluster; + } + + // Save position + file->currentPosition = position; + + _FAT_unlock(&partition->lock); + return position; +} + + + +int _FAT_fstat_r (struct _reent *r, intptr_t fd, struct stat *st) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + PARTITION* partition; + DIR_ENTRY fileEntry; + + if ((file == NULL) || (file->inUse == false)) { + // invalid file + r->_errno = EBADF; + return -1; + } + + partition = file->partition; + _FAT_lock(&partition->lock); + + // Get the file's entry data + fileEntry.dataStart = file->dirEntryStart; + fileEntry.dataEnd = file->dirEntryEnd; + + if (!_FAT_directory_entryFromPosition (partition, &fileEntry)) { + _FAT_unlock(&partition->lock); + r->_errno = EIO; + return -1; + } + + // Fill in the stat struct + _FAT_directory_entryStat (partition, &fileEntry, st); + + // Fix stats that have changed since the file was openned + st->st_ino = (ino_t)(file->startCluster); // The file serial number is the start cluster + st->st_size = file->filesize; // File size + + _FAT_unlock(&partition->lock); + return 0; +} + +int _FAT_ftruncate_r (struct _reent *r, intptr_t fd, off_t len) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + PARTITION* partition; + int ret=0; + uint32_t newSize = (uint32_t)len; + + if (len < 0) { + // Trying to truncate to a negative size + r->_errno = EINVAL; + return -1; + } + + if ((sizeof(len) > 4) && len > (off_t)FILE_MAX_SIZE) { + // Trying to extend the file beyond what FAT supports + r->_errno = EFBIG; + return -1; + } + + if (!file || !file->inUse) { + // invalid file + r->_errno = EBADF; + return -1; + } + + if (!file->write) { + // Read-only file + r->_errno = EINVAL; + return -1; + } + + partition = file->partition; + _FAT_lock(&partition->lock); + + if (newSize > file->filesize) { + // Expanding the file + FILE_POSITION savedPosition; + uint32_t savedOffset; + // Get a new cluster for the start of the file if required + if (file->startCluster == CLUSTER_FREE) { + uint32_t tempNextCluster = _FAT_fat_linkFreeCluster (partition, CLUSTER_FREE); + if (!_FAT_fat_isValidCluster(partition, tempNextCluster)) { + // Couldn't get a cluster, so abort immediately + _FAT_unlock(&partition->lock); + r->_errno = ENOSPC; + return -1; + } + file->startCluster = tempNextCluster; + + file->rwPosition.cluster = file->startCluster; + file->rwPosition.sector = 0; + file->rwPosition.byte = 0; + } + // Save the read/write pointer + savedPosition = file->rwPosition; + savedOffset = file->currentPosition; + // Set the position to the new size + file->currentPosition = newSize; + // Extend the file to the new position + if (!_FAT_file_extend_r (r, file)) { + ret = -1; + } + // Set the append position to the new rwPointer + if (file->append) { + file->appendPosition = file->rwPosition; + } + // Restore the old rwPointer; + file->rwPosition = savedPosition; + file->currentPosition = savedOffset; + } else if (newSize < file->filesize){ + // Shrinking the file + if (len == 0) { + // Cutting the file down to nothing, clear all clusters used + _FAT_fat_clearLinks (partition, file->startCluster); + file->startCluster = CLUSTER_FREE; + + file->appendPosition.cluster = CLUSTER_FREE; + file->appendPosition.sector = 0; + file->appendPosition.byte = 0; + } else { + // Trimming the file down to the required size + unsigned int chainLength; + uint32_t lastCluster; + + // Drop the unneeded end of the cluster chain. + // If the end falls on a cluster boundary, drop that cluster too, + // then set a flag to allocate a cluster as needed + chainLength = ((newSize-1) / partition->bytesPerCluster) + 1; + lastCluster = _FAT_fat_trimChain (partition, file->startCluster, chainLength); + + if (file->append) { + file->appendPosition.byte = newSize % BYTES_PER_READ; + // Does the end of the file fall on the edge of a cluster? + if (newSize % partition->bytesPerCluster == 0) { + // Set a flag to allocate a new cluster + file->appendPosition.sector = partition->sectorsPerCluster; + } else { + file->appendPosition.sector = (newSize % partition->bytesPerCluster) / BYTES_PER_READ; + } + file->appendPosition.cluster = lastCluster; + } + } + } else { + // Truncating to same length, so don't do anything + } + + file->filesize = newSize; + file->modified = true; + + _FAT_unlock(&partition->lock); + return ret; +} + +int _FAT_fsync_r (struct _reent *r, intptr_t fd) { + FILE_STRUCT* file = (FILE_STRUCT*) fd; + int ret = 0; + + if (!file->inUse) { + r->_errno = EBADF; + return -1; + } + + _FAT_lock(&file->partition->lock); + + ret = _FAT_syncToDisc (file); + if (ret != 0) { + r->_errno = ret; + ret = -1; + } + + _FAT_unlock(&file->partition->lock); + + return ret; +} diff --git a/jni/desmume/src/utils/libfat/fatfile.h b/jni/desmume/src/utils/libfat/fatfile.h new file mode 100755 index 0000000..ae66508 --- /dev/null +++ b/jni/desmume/src/utils/libfat/fatfile.h @@ -0,0 +1,108 @@ +/* + fatfile.h + + Functions used by the newlib disc stubs to interface with + this library + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _FATFILE_H +#define _FATFILE_H + +#include "common.h" +#include "partition.h" +#include "directory.h" + +#ifndef LIBFAT_PC +#include <sys/reent.h> +#include <sys/stat.h> +#endif + + +#define FILE_MAX_SIZE ((uint32_t)0xFFFFFFFF) // 4GiB - 1B + +typedef struct { + u32 cluster; + sec_t sector; + s32 byte; +} FILE_POSITION; + +struct _FILE_STRUCT; + +struct _FILE_STRUCT { + uint32_t filesize; + uint32_t startCluster; + uint32_t currentPosition; + FILE_POSITION rwPosition; + FILE_POSITION appendPosition; + DIR_ENTRY_POSITION dirEntryStart; // Points to the start of the LFN entries of a file, or the alias for no LFN + DIR_ENTRY_POSITION dirEntryEnd; // Always points to the file's alias entry + PARTITION* partition; + struct _FILE_STRUCT* prevOpenFile; // The previous entry in a double-linked list of open files + struct _FILE_STRUCT* nextOpenFile; // The next entry in a double-linked list of open files + bool read; + bool write; + bool append; + bool inUse; + bool modified; +}; + +typedef struct _FILE_STRUCT FILE_STRUCT; + +intptr_t _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode); + +intptr_t _FAT_close_r (struct _reent *r, intptr_t fd); + +ssize_t _FAT_write_r (struct _reent *r,intptr_t fd, const char *ptr, size_t len); + +ssize_t _FAT_read_r (struct _reent *r, intptr_t fd, char *ptr, size_t len); + +off_t _FAT_seek_r (struct _reent *r, intptr_t fd, off_t pos, int dir); + +int _FAT_fstat_r (struct _reent *r, intptr_t fd, struct stat *st); + +int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st); + +int _FAT_link_r (struct _reent *r, const char *existing, const char *newLink); + +int _FAT_unlink_r (struct _reent *r, const char *name); + +int _FAT_chdir_r (struct _reent *r, const char *name); + +int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName); + +int _FAT_ftruncate_r (struct _reent *r, intptr_t fd, off_t len); + +int _FAT_fsync_r (struct _reent *r, intptr_t fd); + +/* +Synchronizes the file data to disc. +Does no locking of its own -- lock the partition before calling. +Returns 0 on success, an error code on failure. +*/ +extern int _FAT_syncToDisc (FILE_STRUCT* file); + +#endif // _FATFILE_H diff --git a/jni/desmume/src/utils/libfat/file_allocation_table.cpp b/jni/desmume/src/utils/libfat/file_allocation_table.cpp new file mode 100755 index 0000000..639a637 --- /dev/null +++ b/jni/desmume/src/utils/libfat/file_allocation_table.cpp @@ -0,0 +1,383 @@ +/* + file_allocation_table.c + Reading, writing and manipulation of the FAT structure on + a FAT partition + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "file_allocation_table.h" +#include "partition.h" +#include <string.h> + +/* +Gets the cluster linked from input cluster +*/ +uint32_t _FAT_fat_nextCluster(PARTITION* partition, uint32_t cluster) +{ + uint32_t nextCluster = CLUSTER_FREE; + sec_t sector; + int offset; + + if (cluster == CLUSTER_FREE) { + return CLUSTER_FREE; + } + + switch (partition->filesysType) + { + case FS_UNKNOWN: + return CLUSTER_ERROR; + break; + + case FS_FAT12: + { + u32 nextCluster_h; + sector = partition->fat.fatStart + (((cluster * 3) / 2) / BYTES_PER_READ); + offset = ((cluster * 3) / 2) % BYTES_PER_READ; + + + _FAT_cache_readLittleEndianValue (partition->cache, &nextCluster, sector, offset, sizeof(u8)); + + offset++; + + if (offset >= BYTES_PER_READ) { + offset = 0; + sector++; + } + nextCluster_h = 0; + + _FAT_cache_readLittleEndianValue (partition->cache, &nextCluster_h, sector, offset, sizeof(u8)); + nextCluster |= (nextCluster_h << 8); + + if (cluster & 0x01) { + nextCluster = nextCluster >> 4; + } else { + nextCluster &= 0x0FFF; + } + + if (nextCluster >= 0x0FF7) + { + nextCluster = CLUSTER_EOF; + } + + break; + } + case FS_FAT16: + sector = partition->fat.fatStart + ((cluster << 1) / BYTES_PER_READ); + offset = (cluster % (BYTES_PER_READ >> 1)) << 1; + + _FAT_cache_readLittleEndianValue (partition->cache, &nextCluster, sector, offset, sizeof(u16)); + + if (nextCluster >= 0xFFF7) { + nextCluster = CLUSTER_EOF; + } + break; + + case FS_FAT32: + sector = partition->fat.fatStart + ((cluster << 2) / BYTES_PER_READ); + offset = (cluster % (BYTES_PER_READ >> 2)) << 2; + + _FAT_cache_readLittleEndianValue (partition->cache, &nextCluster, sector, offset, sizeof(u32)); + + if (nextCluster >= 0x0FFFFFF7) { + nextCluster = CLUSTER_EOF; + } + break; + + default: + return CLUSTER_ERROR; + break; + } + + return nextCluster; +} + +/* +writes value into the correct offset within a partition's FAT, based +on the cluster number. +*/ +static bool _FAT_fat_writeFatEntry (PARTITION* partition, uint32_t cluster, uint32_t value) { + sec_t sector; + int offset; + uint32_t oldValue; + + if ((cluster < CLUSTER_FIRST) || (cluster > partition->fat.lastCluster /* This will catch CLUSTER_ERROR */)) + { + return false; + } + + switch (partition->filesysType) + { + case FS_UNKNOWN: + return false; + break; + + case FS_FAT12: + sector = partition->fat.fatStart + (((cluster * 3) / 2) / BYTES_PER_READ); + offset = ((cluster * 3) / 2) % BYTES_PER_READ; + + if (cluster & 0x01) { + + _FAT_cache_readLittleEndianValue (partition->cache, &oldValue, sector, offset, sizeof(u8)); + + value = (value << 4) | (oldValue & 0x0F); + + _FAT_cache_writeLittleEndianValue (partition->cache, value & 0xFF, sector, offset, sizeof(u8)); + + offset++; + if (offset >= BYTES_PER_READ) { + offset = 0; + sector++; + } + + _FAT_cache_writeLittleEndianValue (partition->cache, (value >> 8) & 0xFF, sector, offset, sizeof(u8)); + + } else { + + _FAT_cache_writeLittleEndianValue (partition->cache, value, sector, offset, sizeof(u8)); + + offset++; + if (offset >= BYTES_PER_READ) { + offset = 0; + sector++; + } + + _FAT_cache_readLittleEndianValue (partition->cache, &oldValue, sector, offset, sizeof(u8)); + + value = ((value >> 8) & 0x0F) | (oldValue & 0xF0); + + _FAT_cache_writeLittleEndianValue (partition->cache, value, sector, offset, sizeof(u8)); + } + + break; + + case FS_FAT16: + sector = partition->fat.fatStart + ((cluster << 1) / BYTES_PER_READ); + offset = (cluster % (BYTES_PER_READ >> 1)) << 1; + + _FAT_cache_writeLittleEndianValue (partition->cache, value, sector, offset, sizeof(u16)); + + break; + + case FS_FAT32: + sector = partition->fat.fatStart + ((cluster << 2) / BYTES_PER_READ); + offset = (cluster % (BYTES_PER_READ >> 2)) << 2; + + _FAT_cache_writeLittleEndianValue (partition->cache, value, sector, offset, sizeof(u32)); + + break; + + default: + return false; + break; + } + + return true; +} + +/*----------------------------------------------------------------- +gets the first available free cluster, sets it +to end of file, links the input cluster to it then returns the +cluster number +If an error occurs, return CLUSTER_ERROR +-----------------------------------------------------------------*/ +uint32_t _FAT_fat_linkFreeCluster(PARTITION* partition, uint32_t cluster) { + uint32_t firstFree; + uint32_t curLink; + uint32_t lastCluster; + bool loopedAroundFAT = false; + + lastCluster = partition->fat.lastCluster; + + if (cluster > lastCluster) { + return CLUSTER_ERROR; + } + + // Check if the cluster already has a link, and return it if so + curLink = _FAT_fat_nextCluster(partition, cluster); + if ((curLink >= CLUSTER_FIRST) && (curLink <= lastCluster)) { + return curLink; // Return the current link - don't allocate a new one + } + + // Get a free cluster + firstFree = partition->fat.firstFree; + // Start at first valid cluster + if (firstFree < CLUSTER_FIRST) { + firstFree = CLUSTER_FIRST; + } + + // Search until a free cluster is found + while (_FAT_fat_nextCluster(partition, firstFree) != CLUSTER_FREE) { + firstFree++; + if (firstFree > lastCluster) { + if (loopedAroundFAT) { + // If couldn't get a free cluster then return an error + partition->fat.firstFree = firstFree; + return CLUSTER_ERROR; + } else { + // Try looping back to the beginning of the FAT + // This was suggested by loopy + firstFree = CLUSTER_FIRST; + loopedAroundFAT = true; + } + } + } + partition->fat.firstFree = firstFree; + + if ((cluster >= CLUSTER_FIRST) && (cluster < lastCluster)) + { + // Update the linked from FAT entry + _FAT_fat_writeFatEntry (partition, cluster, firstFree); + } + // Create the linked to FAT entry + _FAT_fat_writeFatEntry (partition, firstFree, CLUSTER_EOF); + + return firstFree; +} + +/*----------------------------------------------------------------- +gets the first available free cluster, sets it +to end of file, links the input cluster to it, clears the new +cluster to 0 valued bytes, then returns the cluster number +If an error occurs, return CLUSTER_ERROR +-----------------------------------------------------------------*/ +uint32_t _FAT_fat_linkFreeClusterCleared (PARTITION* partition, uint32_t cluster) { + uint32_t newCluster; + uint32_t i; + uint8_t emptySector[BYTES_PER_READ]; + + // Link the cluster + newCluster = _FAT_fat_linkFreeCluster(partition, cluster); + + if (newCluster == CLUSTER_FREE || newCluster == CLUSTER_ERROR) { + return CLUSTER_ERROR; + } + + // Clear all the sectors within the cluster + memset (emptySector, 0, BYTES_PER_READ); + for (i = 0; i < partition->sectorsPerCluster; i++) { + _FAT_cache_writeSectors (partition->cache, + _FAT_fat_clusterToSector (partition, newCluster) + i, + 1, emptySector); + } + + return newCluster; +} + + +/*----------------------------------------------------------------- +_FAT_fat_clearLinks +frees any cluster used by a file +-----------------------------------------------------------------*/ +bool _FAT_fat_clearLinks (PARTITION* partition, uint32_t cluster) { + uint32_t nextCluster; + + if ((cluster < CLUSTER_FIRST) || (cluster > partition->fat.lastCluster /* This will catch CLUSTER_ERROR */)) + return false; + + // If this clears up more space in the FAT before the current free pointer, move it backwards + if (cluster < partition->fat.firstFree) { + partition->fat.firstFree = cluster; + } + + while ((cluster != CLUSTER_EOF) && (cluster != CLUSTER_FREE) && (cluster != CLUSTER_ERROR)) { + // Store next cluster before erasing the link + nextCluster = _FAT_fat_nextCluster (partition, cluster); + + // Erase the link + _FAT_fat_writeFatEntry (partition, cluster, CLUSTER_FREE); + + // Move onto next cluster + cluster = nextCluster; + } + + return true; +} + +/*----------------------------------------------------------------- +_FAT_fat_trimChain +Drop all clusters past the chainLength. +If chainLength is 0, all clusters are dropped. +If chainLength is 1, the first cluster is kept and the rest are +dropped, and so on. +Return the last cluster left in the chain. +-----------------------------------------------------------------*/ +uint32_t _FAT_fat_trimChain (PARTITION* partition, uint32_t startCluster, unsigned int chainLength) { + uint32_t nextCluster; + + if (chainLength == 0) { + // Drop the entire chain + _FAT_fat_clearLinks (partition, startCluster); + return CLUSTER_FREE; + } else { + // Find the last cluster in the chain, and the one after it + chainLength--; + nextCluster = _FAT_fat_nextCluster (partition, startCluster); + while ((chainLength > 0) && (nextCluster != CLUSTER_FREE) && (nextCluster != CLUSTER_EOF)) { + chainLength--; + startCluster = nextCluster; + nextCluster = _FAT_fat_nextCluster (partition, startCluster); + } + + // Drop all clusters after the last in the chain + if (nextCluster != CLUSTER_FREE && nextCluster != CLUSTER_EOF) { + _FAT_fat_clearLinks (partition, nextCluster); + } + + // Mark the last cluster in the chain as the end of the file + _FAT_fat_writeFatEntry (partition, startCluster, CLUSTER_EOF); + + return startCluster; + } +} + +/*----------------------------------------------------------------- +_FAT_fat_lastCluster +Trace the cluster links until the last one is found +-----------------------------------------------------------------*/ +uint32_t _FAT_fat_lastCluster (PARTITION* partition, uint32_t cluster) { + while ((_FAT_fat_nextCluster(partition, cluster) != CLUSTER_FREE) && (_FAT_fat_nextCluster(partition, cluster) != CLUSTER_EOF)) { + cluster = _FAT_fat_nextCluster(partition, cluster); + } + return cluster; +} + +/*----------------------------------------------------------------- +_FAT_fat_freeClusterCount +Return the number of free clusters available +-----------------------------------------------------------------*/ +unsigned int _FAT_fat_freeClusterCount (PARTITION* partition) { + unsigned int count = 0; + uint32_t curCluster; + + for (curCluster = CLUSTER_FIRST; curCluster <= partition->fat.lastCluster; curCluster++) { + if (_FAT_fat_nextCluster(partition, curCluster) == CLUSTER_FREE) { + count++; + } + } + + return count; +} + diff --git a/jni/desmume/src/utils/libfat/file_allocation_table.h b/jni/desmume/src/utils/libfat/file_allocation_table.h new file mode 100755 index 0000000..560c616 --- /dev/null +++ b/jni/desmume/src/utils/libfat/file_allocation_table.h @@ -0,0 +1,70 @@ +/* + file_allocation_table.h + Reading, writing and manipulation of the FAT structure on + a FAT partition + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _FAT_H +#define _FAT_H + +#include "common.h" +#include "partition.h" + +#define CLUSTER_EOF_16 0xFFFF +#define CLUSTER_EOF 0x0FFFFFFF +#define CLUSTER_FREE 0x00000000 +#define CLUSTER_ROOT 0x00000000 +#define CLUSTER_FIRST 0x00000002 +#define CLUSTER_ERROR 0xFFFFFFFF + +#define CLUSTERS_PER_FAT12 4085 +#define CLUSTERS_PER_FAT16 65525 + + +uint32_t _FAT_fat_nextCluster(PARTITION* partition, uint32_t cluster); + +uint32_t _FAT_fat_linkFreeCluster(PARTITION* partition, uint32_t cluster); +uint32_t _FAT_fat_linkFreeClusterCleared (PARTITION* partition, uint32_t cluster); + +bool _FAT_fat_clearLinks (PARTITION* partition, uint32_t cluster); + +uint32_t _FAT_fat_trimChain (PARTITION* partition, uint32_t startCluster, unsigned int chainLength); + +uint32_t _FAT_fat_lastCluster (PARTITION* partition, uint32_t cluster); + +unsigned int _FAT_fat_freeClusterCount (PARTITION* partition); + +static inline sec_t _FAT_fat_clusterToSector (PARTITION* partition, uint32_t cluster) { + return (cluster >= CLUSTER_FIRST) ? + ((cluster - CLUSTER_FIRST) * (sec_t)partition->sectorsPerCluster) + partition->dataStart : + partition->rootDirStart; +} + +static inline bool _FAT_fat_isValidCluster (PARTITION* partition, uint32_t cluster) { + return (cluster >= CLUSTER_FIRST) && (cluster <= partition->fat.lastCluster /* This will catch CLUSTER_ERROR */); +} + +#endif // _FAT_H diff --git a/jni/desmume/src/utils/libfat/filetime.cpp b/jni/desmume/src/utils/libfat/filetime.cpp new file mode 100755 index 0000000..d297bf6 --- /dev/null +++ b/jni/desmume/src/utils/libfat/filetime.cpp @@ -0,0 +1,107 @@ +/* + filetime.c + Conversion of file time and date values to various other types + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include <time.h> +#include "filetime.h" +#include "common.h" + +#define MAX_HOUR 23 +#define MAX_MINUTE 59 +#define MAX_SECOND 59 + +#define MAX_MONTH 11 +#define MIN_MONTH 0 +#define MAX_DAY 31 +#define MIN_DAY 1 + +uint16_t _FAT_filetime_getTimeFromRTC (void) { +#ifdef USE_RTC_TIME + struct tm timeParts; + time_t epochTime; + + if (time(&epochTime) == (time_t)-1) { + return 0; + } + localtime_r(&epochTime, &timeParts); + + // Check that the values are all in range. + // If they are not, return 0 (no timestamp) + if ((timeParts.tm_hour < 0) || (timeParts.tm_hour > MAX_HOUR)) return 0; + if ((timeParts.tm_min < 0) || (timeParts.tm_min > MAX_MINUTE)) return 0; + if ((timeParts.tm_sec < 0) || (timeParts.tm_sec > MAX_SECOND)) return 0; + + return ( + ((timeParts.tm_hour & 0x1F) << 11) | + ((timeParts.tm_min & 0x3F) << 5) | + ((timeParts.tm_sec >> 1) & 0x1F) + ); +#else + return 0; +#endif +} + + +uint16_t _FAT_filetime_getDateFromRTC (void) { +#ifdef USE_RTC_TIME + struct tm timeParts; + time_t epochTime; + + if (time(&epochTime) == (time_t)-1) { + return 0; + } + localtime_r(&epochTime, &timeParts); + + if ((timeParts.tm_mon < MIN_MONTH) || (timeParts.tm_mon > MAX_MONTH)) return 0; + if ((timeParts.tm_mday < MIN_DAY) || (timeParts.tm_mday > MAX_DAY)) return 0; + + return ( + (((timeParts.tm_year - 80) & 0x7F) <<9) | // Adjust for MS-FAT base year (1980 vs 1900 for tm_year) + (((timeParts.tm_mon + 1) & 0xF) << 5) | + (timeParts.tm_mday & 0x1F) + ); +#else + return 0; +#endif +} + +time_t _FAT_filetime_to_time_t (uint16_t t, uint16_t d) { + struct tm timeParts; + + timeParts.tm_hour = t >> 11; + timeParts.tm_min = (t >> 5) & 0x3F; + timeParts.tm_sec = (t & 0x1F) << 1; + + timeParts.tm_mday = d & 0x1F; + timeParts.tm_mon = ((d >> 5) & 0x0F) - 1; + timeParts.tm_year = (d >> 9) + 80; + + timeParts.tm_isdst = 0; + + return mktime(&timeParts); +} diff --git a/jni/desmume/src/utils/libfat/filetime.h b/jni/desmume/src/utils/libfat/filetime.h new file mode 100755 index 0000000..3bfd8ed --- /dev/null +++ b/jni/desmume/src/utils/libfat/filetime.h @@ -0,0 +1,41 @@ +/* + filetime.h + Conversion of file time and date values to various other types + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _FILETIME_H +#define _FILETIME_H + +#include "common.h" +#include <sys/types.h> + +uint16_t _FAT_filetime_getTimeFromRTC (void); +uint16_t _FAT_filetime_getDateFromRTC (void); + +time_t _FAT_filetime_to_time_t (uint16_t t, uint16_t d); + + +#endif // _FILETIME_H diff --git a/jni/desmume/src/utils/libfat/libfat.cpp b/jni/desmume/src/utils/libfat/libfat.cpp new file mode 100755 index 0000000..957964d --- /dev/null +++ b/jni/desmume/src/utils/libfat/libfat.cpp @@ -0,0 +1,276 @@ +/* + libfat.c + Simple functionality for startup, mounting and unmounting of FAT-based devices. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <string.h> +#include <stdio.h> + +#include "common.h" +#include "partition.h" +#include "fatfile.h" +#include "fatdir.h" +#include "lock.h" +#include "mem_allocate.h" +#include "disc.h" + +#ifndef LIBFAT_PC +#include <sys/iosupport.h> +#include <unistd.h> +#endif + + +static const devoptab_t dotab_fat = { + "fat", + sizeof (FILE_STRUCT), + _FAT_open_r, + _FAT_close_r, + _FAT_write_r, + _FAT_read_r, + _FAT_seek_r, + _FAT_fstat_r, + _FAT_stat_r, + _FAT_link_r, + _FAT_unlink_r, + _FAT_chdir_r, + _FAT_rename_r, + _FAT_mkdir_r, + sizeof (DIR_STATE_STRUCT), + _FAT_diropen_r, + _FAT_dirreset_r, + _FAT_dirnext_r, + _FAT_dirclose_r, +#ifndef LIBFAT_PC + _FAT_statvfs_r, +#endif + _FAT_ftruncate_r, + _FAT_fsync_r, + NULL, /* Device data */ + NULL, + NULL +}; + +#ifdef LIBFAT_PC +static devoptab_t* _sole_device = NULL; +devoptab_t* GetDeviceOpTab(const char* name) +{ + return _sole_device; +} +#endif + + +bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize, uint32_t SectorsPerPage) { + PARTITION* partition; + devoptab_t* devops; + //char* nameCopy; + + if(!name || strlen(name) > 8 || !interface) + return false; + + if(!interface->startup()) + return false; + + if(!interface->isInserted()) + return false; + + //char devname[10]; + //sprintf(devname, "%s:", name); + //if(FindDevice(devname) >= 0) + // return true; + + devops = (devoptab_t*)_FAT_mem_allocate (sizeof(devoptab_t) + strlen(name) + 1); + if (!devops) { + return false; + } + +#ifdef LIBFAT_PC + _sole_device = devops; +#endif + + // Use the space allocated at the end of the devoptab struct for storing the name + //nameCopy = (char*)(devops+1); + + // Initialize the file system + partition = _FAT_partition_constructor (interface, cacheSize, SectorsPerPage, startSector); + if (!partition) { + _FAT_mem_free (devops); + return false; + } + + // Add an entry for this device to the devoptab table + memcpy (devops, &dotab_fat, sizeof(dotab_fat)); + //strcpy (nameCopy, name); + //devops->name = nameCopy; + devops->deviceData = partition; + + //AddDevice (devops); + + return true; +} + +bool fatMountSimple (const char* name, const DISC_INTERFACE* interface) { + return fatMount (name, interface, 0, DEFAULT_CACHE_PAGES, DEFAULT_SECTORS_PAGE); +} + +void fatUnmountDirect (devoptab_t *devops) { + PARTITION* partition = (PARTITION*)devops->deviceData; + _FAT_partition_destructor (partition); + _FAT_mem_free (devops); + _sole_device = NULL; +} + +//void fatUnmount (const char* name) { +// devoptab_t *devops; +// PARTITION* partition; +// +// if(!name) +// return; +// +// devops = (devoptab_t*)GetDeviceOpTab (name); +// if (!devops) { +// return; +// } +// +// // Perform a quick check to make sure we're dealing with a libfat controlled device +// //if (devops->open_r != dotab_fat.open_r) { +// // return; +// //} +// +// if (RemoveDevice (name) == -1) { +// return; +// } +// +// partition = (PARTITION*)devops->deviceData; +// _FAT_partition_destructor (partition); +// _FAT_mem_free (devops); +//} + +//bool fatInit (uint32_t cacheSize, bool setAsDefaultDevice) { +// int i; +// int defaultDevice = -1; +// const DISC_INTERFACE *disc; +// +// for (i = 0; +// _FAT_disc_interfaces[i].name != NULL && _FAT_disc_interfaces[i].getInterface != NULL; +// i++) +// { +// disc = _FAT_disc_interfaces[i].getInterface(); +// if (fatMount (_FAT_disc_interfaces[i].name, disc, 0, cacheSize, DEFAULT_SECTORS_PAGE)) { +// // The first device to successfully mount is set as the default +// if (defaultDevice < 0) { +// defaultDevice = i; +// } +// } +// } +// +// if (defaultDevice < 0) { +// // None of our devices mounted +// return false; +// } +// +// if (setAsDefaultDevice) { +// char filePath[MAXPATHLEN * 2]; +// strcpy (filePath, _FAT_disc_interfaces[defaultDevice].name); +// strcat (filePath, ":/"); +//#ifdef ARGV_MAGIC +// if ( __system_argv->argvMagic == ARGV_MAGIC && __system_argv->argc >= 1 && strrchr( __system_argv->argv[0], '/' )!=NULL ) { +// // Check the app's path against each of our mounted devices, to see +// // if we can support it. If so, change to that path. +// for (i = 0; +// _FAT_disc_interfaces[i].name != NULL && _FAT_disc_interfaces[i].getInterface != NULL; +// i++) +// { +// if ( !strncasecmp( __system_argv->argv[0], _FAT_disc_interfaces[i].name, +// strlen(_FAT_disc_interfaces[i].name))) +// { +// char *lastSlash; +// strcpy(filePath, __system_argv->argv[0]); +// lastSlash = strrchr( filePath, '/' ); +// +// if ( NULL != lastSlash) { +// if ( *(lastSlash - 1) == ':') lastSlash++; +// *lastSlash = 0; +// } +// } +// } +// } +//#endif +// chdir (filePath); +// } +// +// return true; +//} + +//bool fatInitDefault (void) { +// return fatInit (DEFAULT_CACHE_PAGES, true); +//} + +//void fatGetVolumeLabel (const char* name, char *label) { +// devoptab_t *devops; +// PARTITION* partition; +// char *buf; +// int namelen,i; +// +// if(!name || !label) +// return; +// +// namelen = strlen(name); +// buf=(char*)_FAT_mem_allocate(sizeof(char)*namelen+2); +// strcpy(buf,name); +// +// if (name[namelen-1] == '/') { +// buf[namelen-1]='\0'; +// namelen--; +// } +// +// if (name[namelen-1] != ':') { +// buf[namelen]=':'; +// buf[namelen+1]='\0'; +// } +// +// devops = (devoptab_t*)GetDeviceOpTab(buf); +// +// for(i=0;buf[i]!='\0' && buf[i]!=':';i++); +// if (!devops || strncasecmp(buf,devops->name,i)) { +// _FAT_mem_free(buf); +// return; +// } +// +// _FAT_mem_free(buf); +// +// // Perform a quick check to make sure we're dealing with a libfat controlled device +// if (devops->open_r != dotab_fat.open_r) { +// return; +// } +// +// partition = (PARTITION*)devops->deviceData; +// +// if(!_FAT_directory_getVolumeLabel(partition, label)) { +// strncpy(label,partition->label,11); +// label[11]='\0'; +// } +// if(!strncmp(label, "NO NAME", 7)) label[0]='\0'; +//} diff --git a/jni/desmume/src/utils/libfat/libfat_pc.h b/jni/desmume/src/utils/libfat/libfat_pc.h new file mode 100755 index 0000000..9f59b5f --- /dev/null +++ b/jni/desmume/src/utils/libfat/libfat_pc.h @@ -0,0 +1,120 @@ +#ifndef _LIBFAT_PC_H +#define _LIBFAT_PC_H + +#ifdef LIBFAT_PC + +#include "../../types.h" + +#ifdef _MSC_VER + +#define ENOTSUP 0 +#define EOVERFLOW 0 + +#include <time.h> +#include <stdio.h> + +#define strcasecmp(x,y) _stricmp(x,y) +#define strncasecmp(x, y, l) strnicmp(x, y, l) + +typedef unsigned __int64 uint64_t; +typedef __int64 int64_t; +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef char int8_t; + +typedef int32_t ssize_t; + +#include <sys/stat.h> + +#define S_IRUSR S_IREAD +#define S_IRGRP S_IREAD +#define S_IROTH S_IREAD +#define S_IWUSR S_IWRITE +#define S_IWGRP S_IWRITE +#define S_IWOTH S_IWRITE + +//struct stat { +// u32 st_dev; +// u32 st_ino; +// u32 st_mode; +// u32 st_nlink; +// u32 st_uid; +// u32 st_gid; +// u32 st_rdev; +// s64 st_size; +// time_t st_atime; +// time_t st_mtime; +// time_t st_ctime; +// s32 st_blksize; +// s32 st_blocks; +// u32 st_attr; +//}; + +#else // (!_MSC_VER) + +#include <unistd.h> + +#endif //_MSC_VER + +struct _reent { + intptr_t _errno; +}; + +#ifdef __APPLE__ +typedef __darwin_mode_t mode_t; +#elif defined(_MSC_VER) +typedef uint32_t mode_t; +#else +#include <sys/types.h> +#endif + +struct DIR_ITER { + void* dirStruct; +}; + +struct devoptab_t { + const char *name; + int structSize; + intptr_t (*open_r)(struct _reent *r, void *fileStruct, const char *path, int flags, int mode); + intptr_t (*close_r)(struct _reent *r, intptr_t fd); + ssize_t (*write_r)(struct _reent *r, intptr_t fd, const char *ptr, size_t len); + ssize_t (*read_r)(struct _reent *r, intptr_t fd, char *ptr, size_t len); + off_t (*seek_r)(struct _reent *r, intptr_t fd, off_t pos, int dir); + int (*fstat_r)(struct _reent *r, intptr_t fd, struct stat *st); + int (*stat_r)(struct _reent *r, const char *file, struct stat *st); + int (*link_r)(struct _reent *r, const char *existing, const char *newLink); + int (*unlink_r)(struct _reent *r, const char *name); + int (*chdir_r)(struct _reent *r, const char *name); + int (*rename_r) (struct _reent *r, const char *oldName, const char *newName); + int (*mkdir_r) (struct _reent *r, const char *path, int mode); + + int dirStateSize; + + DIR_ITER* (*diropen_r)(struct _reent *r, DIR_ITER *dirState, const char *path); + int (*dirreset_r)(struct _reent *r, DIR_ITER *dirState); + int (*dirnext_r)(struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *filestat); + int (*dirclose_r)(struct _reent *r, DIR_ITER *dirState); + #ifndef LIBFAT_PC + int (*statvfs_r)(struct _reent *r, const char *path, struct statvfs *buf); + #endif + int (*ftruncate_r)(struct _reent *r, intptr_t fd, off_t len); + int (*fsync_r)(struct _reent *r, intptr_t fd); + + void *deviceData; + + int (*chmod_r)(struct _reent *r, const char *path, mode_t mode); + int (*fchmod_r)(struct _reent *r, int fd, mode_t mode); + +}; + + +devoptab_t* GetDeviceOpTab(const char* name); + +#define _ATTR_WEAK_ + +#endif //LIBFAT_PC + +#endif //_LIBFAT_PC_H diff --git a/jni/desmume/src/utils/libfat/libfat_public_api.cpp b/jni/desmume/src/utils/libfat/libfat_public_api.cpp new file mode 100755 index 0000000..3d20059 --- /dev/null +++ b/jni/desmume/src/utils/libfat/libfat_public_api.cpp @@ -0,0 +1,116 @@ +#include <string.h> +#include <fcntl.h> + + +#include "libfat_public_api.h" +#include "common.h" +#include "disc_io.h" +#include "fatfile.h" + + +struct Instance +{ + void* buffer; + int size_bytes; + devoptab_t* devops; +}; + +Instance sInstance; +Instance* gInstance = NULL; + +bool MEDIUM_STARTUP(void) +{ + return true; +} +bool MEDIUM_ISINSERTED(void) +{ + return true; +} +bool MEDIUM_io(bool write, sec_t sector, sec_t numSectors, void* buffer) +{ + int todo = (int)numSectors*512; + int loc = (int)sector*512; + int have = gInstance->size_bytes - loc; + if(todo>have) + return false; + if(write) + memcpy((u8*)gInstance->buffer + loc,buffer,todo); + else + memcpy(buffer,(u8*)gInstance->buffer + loc,todo); + return true; +} + +bool MEDIUM_READSECTORS(sec_t sector, sec_t numSectors, void* buffer) +{ + return MEDIUM_io(false,sector,numSectors,buffer); +} +bool MEDIUM_WRITESECTORS(sec_t sector, sec_t numSectors, const void* buffer) +{ + return MEDIUM_io(true,sector,numSectors,(void*)buffer); +} +bool MEDIUM_CLEARSTATUS(void) +{ + return true; +} +bool MEDIUM_SHUTDOWN(void) +{ + return true; +} + +DISC_INTERFACE_STRUCT discio = { + 0, //unsigned long ioType ; + FEATURE_MEDIUM_CANWRITE | FEATURE_MEDIUM_CANREAD, //unsigned long features ; + MEDIUM_STARTUP, // FN_MEDIUM_STARTUP startup ; + MEDIUM_ISINSERTED, //FN_MEDIUM_ISINSERTED isInserted ; + MEDIUM_READSECTORS, //FN_MEDIUM_READSECTORS readSectors ; + MEDIUM_WRITESECTORS, //FN_MEDIUM_WRITESECTORS writeSectors ; + MEDIUM_CLEARSTATUS, //FN_MEDIUM_CLEARSTATUS clearStatus ; + MEDIUM_SHUTDOWN, //FN_MEDIUM_SHUTDOWN shutdown ; +} ; + + +//not declared in any libfat headers...? +bool fatMountSimple (const char* name, const DISC_INTERFACE* interface); +void fatUnmountDirect (devoptab_t *devops); + +namespace LIBFAT +{ + void Init(void* buffer, int size_bytes) + { + gInstance = &sInstance; + gInstance->buffer = buffer; + gInstance->size_bytes = size_bytes; + fatMountSimple("fat",&discio); + gInstance->devops = GetDeviceOpTab(NULL); + + + int zzz=9; + } + + bool MkDir(const char *path) + { + _reent r; + return gInstance->devops->mkdir_r(&r,path,0) == 0; + } + + bool WriteFile(const char *path, const void* data, int len) + { + _reent r; + FILE_STRUCT file; + intptr_t fd = gInstance->devops->open_r(&r,&file,path,O_CREAT | O_RDWR,0); + if(fd != -1) + { + ssize_t ret = gInstance->devops->write_r(&r, fd, (char*)data, len); + gInstance->devops->close_r(&r, fd); + if(ret == len) + return true; + } + return false; + } + + void Shutdown() + { + fatUnmountDirect(gInstance->devops); + gInstance = NULL; + } +} diff --git a/jni/desmume/src/utils/libfat/libfat_public_api.h b/jni/desmume/src/utils/libfat/libfat_public_api.h new file mode 100755 index 0000000..d0a7f7f --- /dev/null +++ b/jni/desmume/src/utils/libfat/libfat_public_api.h @@ -0,0 +1,12 @@ +#ifndef _LIBFAT_PUBLIC_API_H_ +#define _LIBFAT_PUBLIC_API_H_ + +namespace LIBFAT +{ + void Init(void* buffer, int size_bytes); + void Shutdown(); + bool MkDir(const char *path); + bool WriteFile(const char *path, const void* data, int len); +}; + +#endif //_LIBFAT_PUBLIC_API_H_ diff --git a/jni/desmume/src/utils/libfat/lock.cpp b/jni/desmume/src/utils/libfat/lock.cpp new file mode 100755 index 0000000..d7b0343 --- /dev/null +++ b/jni/desmume/src/utils/libfat/lock.cpp @@ -0,0 +1,29 @@ +#include "common.h" + +#ifndef USE_LWP_LOCK + +#ifndef mutex_t +typedef int mutex_t; +#endif + +void _ATTR_WEAK_ _FAT_lock_init(mutex_t *mutex) +{ + return; +} + +void _ATTR_WEAK_ _FAT_lock_deinit(mutex_t *mutex) +{ + return; +} + +void _ATTR_WEAK_ _FAT_lock(mutex_t *mutex) +{ + return; +} + +void _ATTR_WEAK_ _FAT_unlock(mutex_t *mutex) +{ + return; +} + +#endif // USE_LWP_LOCK diff --git a/jni/desmume/src/utils/libfat/lock.h b/jni/desmume/src/utils/libfat/lock.h new file mode 100755 index 0000000..de5723a --- /dev/null +++ b/jni/desmume/src/utils/libfat/lock.h @@ -0,0 +1,72 @@ +/* + lock.h + + Copyright (c) 2008 Sven Peter <svpe@gmx.net> + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef _LOCK_H +#define _LOCK_H + +#include "common.h" + +#ifdef USE_LWP_LOCK + +static inline void _FAT_lock_init(mutex_t *mutex) +{ + LWP_MutexInit(mutex, false); +} + +static inline void _FAT_lock_deinit(mutex_t *mutex) +{ + LWP_MutexDestroy(*mutex); +} + +static inline void _FAT_lock(mutex_t *mutex) +{ + LWP_MutexLock(*mutex); +} + +static inline void _FAT_unlock(mutex_t *mutex) +{ + LWP_MutexUnlock(*mutex); +} + +#else + +// We still need a blank lock type +#ifndef mutex_t +typedef int mutex_t; +#endif + +void _FAT_lock_init(mutex_t *mutex); +void _FAT_lock_deinit(mutex_t *mutex); +void _FAT_lock(mutex_t *mutex); +void _FAT_unlock(mutex_t *mutex); + +#endif // USE_LWP_LOCK + + +#endif // _LOCK_H + diff --git a/jni/desmume/src/utils/libfat/mem_allocate.h b/jni/desmume/src/utils/libfat/mem_allocate.h new file mode 100755 index 0000000..35e32ec --- /dev/null +++ b/jni/desmume/src/utils/libfat/mem_allocate.h @@ -0,0 +1,52 @@ +/* + mem_allocate.h + Memory allocation and destruction calls + Replace these calls with custom allocators if + malloc is unavailable + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _MEM_ALLOCATE_H +#define _MEM_ALLOCATE_H + +#include <stdlib.h> + +static inline void* _FAT_mem_allocate (size_t size) { + return malloc (size); +} + +static inline void* _FAT_mem_align (size_t size) { +#ifdef __wii__ + return memalign (32, size); +#else + return malloc (size); +#endif +} + +static inline void _FAT_mem_free (void* mem) { + free (mem); +} + +#endif // _MEM_ALLOCATE_H diff --git a/jni/desmume/src/utils/libfat/partition.cpp b/jni/desmume/src/utils/libfat/partition.cpp new file mode 100755 index 0000000..1692af0 --- /dev/null +++ b/jni/desmume/src/utils/libfat/partition.cpp @@ -0,0 +1,310 @@ +/* + partition.c + Functions for mounting and dismounting partitions + on various block devices. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "partition.h" +#include "bit_ops.h" +#include "file_allocation_table.h" +#include "directory.h" +#include "mem_allocate.h" +#include "fatfile.h" + +#include <string.h> +#include <ctype.h> + +#ifndef LIBFAT_PC +#include <sys/iosupport.h> +#endif + +/* +This device name, as known by devkitPro toolchains +*/ +const char* DEVICE_NAME = "fat"; + +/* +Data offsets +*/ + +// BIOS Parameter Block offsets +enum BPB { + BPB_jmpBoot = 0x00, + BPB_OEMName = 0x03, + // BIOS Parameter Block + BPB_bytesPerSector = 0x0B, + BPB_sectorsPerCluster = 0x0D, + BPB_reservedSectors = 0x0E, + BPB_numFATs = 0x10, + BPB_rootEntries = 0x11, + BPB_numSectorsSmall = 0x13, + BPB_mediaDesc = 0x15, + BPB_sectorsPerFAT = 0x16, + BPB_sectorsPerTrk = 0x18, + BPB_numHeads = 0x1A, + BPB_numHiddenSectors = 0x1C, + BPB_numSectors = 0x20, + // Ext BIOS Parameter Block for FAT16 + BPB_FAT16_driveNumber = 0x24, + BPB_FAT16_reserved1 = 0x25, + BPB_FAT16_extBootSig = 0x26, + BPB_FAT16_volumeID = 0x27, + BPB_FAT16_volumeLabel = 0x2B, + BPB_FAT16_fileSysType = 0x36, + // Bootcode + BPB_FAT16_bootCode = 0x3E, + // FAT32 extended block + BPB_FAT32_sectorsPerFAT32 = 0x24, + BPB_FAT32_extFlags = 0x28, + BPB_FAT32_fsVer = 0x2A, + BPB_FAT32_rootClus = 0x2C, + BPB_FAT32_fsInfo = 0x30, + BPB_FAT32_bkBootSec = 0x32, + // Ext BIOS Parameter Block for FAT32 + BPB_FAT32_driveNumber = 0x40, + BPB_FAT32_reserved1 = 0x41, + BPB_FAT32_extBootSig = 0x42, + BPB_FAT32_volumeID = 0x43, + BPB_FAT32_volumeLabel = 0x47, + BPB_FAT32_fileSysType = 0x52, + // Bootcode + BPB_FAT32_bootCode = 0x5A, + BPB_bootSig_55 = 0x1FE, + BPB_bootSig_AA = 0x1FF +}; + +static const char FAT_SIG[3] = {'F', 'A', 'T'}; + + +sec_t FindFirstValidPartition(const DISC_INTERFACE* disc) +{ + uint8_t part_table[16*4]; + uint8_t *ptr; + int i; + + uint8_t sectorBuffer[BYTES_PER_READ] = {0}; + + // Read first sector of disc + if (!_FAT_disc_readSectors (disc, 0, 1, sectorBuffer)) { + return 0; + } + + memcpy(part_table,sectorBuffer+0x1BE,16*4); + ptr = part_table; + + for(i=0;i<4;i++,ptr+=16) { + sec_t part_lba = u8array_to_u32(ptr, 0x8); + + if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) || + !memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { + return part_lba; + } + + if(ptr[4]==0) continue; + + if(ptr[4]==0x0F) { + sec_t part_lba2=part_lba; + sec_t next_lba2=0; + int n; + + for(n=0;n<8;n++) // max 8 logic partitions + { + if(!_FAT_disc_readSectors (disc, part_lba+next_lba2, 1, sectorBuffer)) return 0; + + part_lba2 = part_lba + next_lba2 + u8array_to_u32(sectorBuffer, 0x1C6) ; + next_lba2 = u8array_to_u32(sectorBuffer, 0x1D6); + + if(!_FAT_disc_readSectors (disc, part_lba2, 1, sectorBuffer)) return 0; + + if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) || + !memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) + { + return part_lba2; + } + + if(next_lba2==0) break; + } + } else { + if(!_FAT_disc_readSectors (disc, part_lba, 1, sectorBuffer)) return 0; + if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) || + !memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { + return part_lba; + } + } + } + return 0; +} + +PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t sectorsPerPage, sec_t startSector) { + PARTITION* partition; + uint8_t sectorBuffer[BYTES_PER_READ] = {0}; + + // Read first sector of disc + if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) { + return NULL; + } + + // Make sure it is a valid MBR or boot sector + if ( (sectorBuffer[BPB_bootSig_55] != 0x55) || (sectorBuffer[BPB_bootSig_AA] != 0xAA)) { + return NULL; + } + + if (startSector != 0) { + // We're told where to start the partition, so just accept it + } else if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { + // Check if there is a FAT string, which indicates this is a boot sector + startSector = 0; + } else if (!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { + // Check for FAT32 + startSector = 0; + } else { + startSector = FindFirstValidPartition(disc); + if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) { + return NULL; + } + } + + // Now verify that this is indeed a FAT partition + if (memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) && + memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) + { + return NULL; + } + + partition = (PARTITION*) _FAT_mem_allocate (sizeof(PARTITION)); + if (partition == NULL) { + return NULL; + } + + // Init the partition lock + _FAT_lock_init(&partition->lock); + + if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG))) + strncpy(partition->label, (char*)(sectorBuffer + BPB_FAT16_volumeLabel), 11); + else + strncpy(partition->label, (char*)(sectorBuffer + BPB_FAT32_volumeLabel), 11); + partition->label[11] = '\0'; + + // Set partition's disc interface + partition->disc = disc; + + // Store required information about the file system + partition->fat.sectorsPerFat = u8array_to_u16(sectorBuffer, BPB_sectorsPerFAT); + if (partition->fat.sectorsPerFat == 0) { + partition->fat.sectorsPerFat = u8array_to_u32( sectorBuffer, BPB_FAT32_sectorsPerFAT32); + } + + partition->numberOfSectors = u8array_to_u16( sectorBuffer, BPB_numSectorsSmall); + if (partition->numberOfSectors == 0) { + partition->numberOfSectors = u8array_to_u32( sectorBuffer, BPB_numSectors); + } + + partition->bytesPerSector = BYTES_PER_READ; // Sector size is redefined to be 512 bytes + partition->sectorsPerCluster = sectorBuffer[BPB_sectorsPerCluster] * u8array_to_u16(sectorBuffer, BPB_bytesPerSector) / BYTES_PER_READ; + partition->bytesPerCluster = partition->bytesPerSector * partition->sectorsPerCluster; + partition->fat.fatStart = startSector + u8array_to_u16(sectorBuffer, BPB_reservedSectors); + + partition->rootDirStart = partition->fat.fatStart + (sectorBuffer[BPB_numFATs] * partition->fat.sectorsPerFat); + partition->dataStart = partition->rootDirStart + + (( u8array_to_u16(sectorBuffer, BPB_rootEntries) * DIR_ENTRY_DATA_SIZE) / partition->bytesPerSector); + + partition->totalSize = ((uint64_t)partition->numberOfSectors - (partition->dataStart - startSector)) * (uint64_t)partition->bytesPerSector; + + // Store info about FAT + uint32_t clusterCount = (partition->numberOfSectors - (uint32_t)(partition->dataStart - startSector)) / partition->sectorsPerCluster; + partition->fat.lastCluster = clusterCount + CLUSTER_FIRST - 1; + partition->fat.firstFree = CLUSTER_FIRST; + + if (clusterCount < CLUSTERS_PER_FAT12) { + partition->filesysType = FS_FAT12; // FAT12 volume + } else if (clusterCount < CLUSTERS_PER_FAT16) { + partition->filesysType = FS_FAT16; // FAT16 volume + } else { + partition->filesysType = FS_FAT32; // FAT32 volume + } + + if (partition->filesysType != FS_FAT32) { + partition->rootDirCluster = FAT16_ROOT_DIR_CLUSTER; + } else { + // Set up for the FAT32 way + partition->rootDirCluster = u8array_to_u32(sectorBuffer, BPB_FAT32_rootClus); + // Check if FAT mirroring is enabled + if (!(sectorBuffer[BPB_FAT32_extFlags] & 0x80)) { + // Use the active FAT + partition->fat.fatStart = partition->fat.fatStart + ( partition->fat.sectorsPerFat * (sectorBuffer[BPB_FAT32_extFlags] & 0x0F)); + } + } + + // Create a cache to use + partition->cache = _FAT_cache_constructor (cacheSize, sectorsPerPage, partition->disc, startSector+partition->numberOfSectors); + + // Set current directory to the root + partition->cwdCluster = partition->rootDirCluster; + + // Check if this disc is writable, and set the readOnly property appropriately + partition->readOnly = !(_FAT_disc_features(disc) & FEATURE_MEDIUM_CANWRITE); + + // There are currently no open files on this partition + partition->openFileCount = 0; + partition->firstOpenFile = NULL; + + return partition; +} + +void _FAT_partition_destructor (PARTITION* partition) { + FILE_STRUCT* nextFile; + + _FAT_lock(&partition->lock); + + // Synchronize open files + nextFile = partition->firstOpenFile; + while (nextFile) { + _FAT_syncToDisc (nextFile); + nextFile = nextFile->nextOpenFile; + } + + // Free memory used by the cache, writing it to disc at the same time + _FAT_cache_destructor (partition->cache); + + // Unlock the partition and destroy the lock + _FAT_unlock(&partition->lock); + _FAT_lock_deinit(&partition->lock); + + // Free memory used by the partition + _FAT_mem_free (partition); +} + +PARTITION* _FAT_partition_getPartitionFromPath (const char* path) { + const devoptab_t *devops; + + devops = GetDeviceOpTab (path); + + if (!devops) { + return NULL; + } + + return (PARTITION*)devops->deviceData; +} diff --git a/jni/desmume/src/utils/libfat/partition.h b/jni/desmume/src/utils/libfat/partition.h new file mode 100755 index 0000000..52e6648 --- /dev/null +++ b/jni/desmume/src/utils/libfat/partition.h @@ -0,0 +1,89 @@ +/* + partition.h + Functions for mounting and dismounting partitions + on various block devices. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _PARTITION_H +#define _PARTITION_H + +#include "common.h" +#include "cache.h" +#include "lock.h" + +// Device name +extern const char* DEVICE_NAME; + +// Filesystem type +typedef enum {FS_UNKNOWN, FS_FAT12, FS_FAT16, FS_FAT32} FS_TYPE; + +typedef struct { + sec_t fatStart; + uint32_t sectorsPerFat; + uint32_t lastCluster; + uint32_t firstFree; +} FAT; + +typedef struct { + const DISC_INTERFACE* disc; + CACHE* cache; + // Info about the partition + FS_TYPE filesysType; + uint64_t totalSize; + sec_t rootDirStart; + uint32_t rootDirCluster; + uint32_t numberOfSectors; + sec_t dataStart; + uint32_t bytesPerSector; + uint32_t sectorsPerCluster; + uint32_t bytesPerCluster; + FAT fat; + // Values that may change after construction + uint32_t cwdCluster; // Current working directory cluster + int openFileCount; + struct _FILE_STRUCT* firstOpenFile; // The start of a linked list of files + mutex_t lock; // A lock for partition operations + bool readOnly; // If this is set, then do not try writing to the disc + char label[12]; // Volume label +} PARTITION; + +/* +Mount the supplied device and return a pointer to the struct necessary to use it +*/ +PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t SectorsPerPage, sec_t startSector); + +/* +Dismount the device and free all structures used. +Will also attempt to synchronise all open files to disc. +*/ +void _FAT_partition_destructor (PARTITION* partition); + +/* +Return the partition specified in a path, as taken from the devoptab. +*/ +PARTITION* _FAT_partition_getPartitionFromPath (const char* path); + +#endif // _PARTITION_H diff --git a/jni/desmume/src/utils/md5.cpp b/jni/desmume/src/utils/md5.cpp new file mode 100755 index 0000000..3ba6e37 --- /dev/null +++ b/jni/desmume/src/utils/md5.cpp @@ -0,0 +1,248 @@ +/// \file +/// \brief RFC 1321 compliant MD5 implementation, +/// RFC 1321 compliant MD5 implementation, +/// by Christophe Devine <devine@cr0.net>; +/// this program is licensed under the GPL. + +//Modified October 3, 2003, to remove testing code, and add include of "types.h". +//Added simple MD5 to ASCII string conversion function. +// -Xodnizel + +#include <string.h> +#include "../types.h" +#include "md5.h" + +typedef u8 uint8; +typedef u16 uint16; +typedef u32 uint32; + +#define GET_UINT32(n,b,i) \ +{ \ + (n) = ( (uint32) (b)[(i) + 3] << 24 ) \ + | ( (uint32) (b)[(i) + 2] << 16 ) \ + | ( (uint32) (b)[(i) + 1] << 8 ) \ + | ( (uint32) (b)[(i) ] ); \ +} + +#define PUT_UINT32(n,b,i) \ +{ \ + (b)[(i) ] = (uint8) ( (n) ); \ + (b)[(i) + 1] = (uint8) ( (n) >> 8 ); \ + (b)[(i) + 2] = (uint8) ( (n) >> 16 ); \ + (b)[(i) + 3] = (uint8) ( (n) >> 24 ); \ +} + +void md5_starts( struct md5_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; +} + +static void md5_process( struct md5_context *ctx, uint8 data[64] ) +{ + uint32 A, B, C, D, X[16]; + + GET_UINT32( X[0], data, 0 ); + GET_UINT32( X[1], data, 4 ); + GET_UINT32( X[2], data, 8 ); + GET_UINT32( X[3], data, 12 ); + GET_UINT32( X[4], data, 16 ); + GET_UINT32( X[5], data, 20 ); + GET_UINT32( X[6], data, 24 ); + GET_UINT32( X[7], data, 28 ); + GET_UINT32( X[8], data, 32 ); + GET_UINT32( X[9], data, 36 ); + GET_UINT32( X[10], data, 40 ); + GET_UINT32( X[11], data, 44 ); + GET_UINT32( X[12], data, 48 ); + GET_UINT32( X[13], data, 52 ); + GET_UINT32( X[14], data, 56 ); + GET_UINT32( X[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define P(a,b,c,d,k,s,t) \ +{ \ + a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) + + P( A, B, C, D, 0, 7, 0xD76AA478 ); + P( D, A, B, C, 1, 12, 0xE8C7B756 ); + P( C, D, A, B, 2, 17, 0x242070DB ); + P( B, C, D, A, 3, 22, 0xC1BDCEEE ); + P( A, B, C, D, 4, 7, 0xF57C0FAF ); + P( D, A, B, C, 5, 12, 0x4787C62A ); + P( C, D, A, B, 6, 17, 0xA8304613 ); + P( B, C, D, A, 7, 22, 0xFD469501 ); + P( A, B, C, D, 8, 7, 0x698098D8 ); + P( D, A, B, C, 9, 12, 0x8B44F7AF ); + P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); + P( B, C, D, A, 11, 22, 0x895CD7BE ); + P( A, B, C, D, 12, 7, 0x6B901122 ); + P( D, A, B, C, 13, 12, 0xFD987193 ); + P( C, D, A, B, 14, 17, 0xA679438E ); + P( B, C, D, A, 15, 22, 0x49B40821 ); + +#undef F + +#define F(x,y,z) (y ^ (z & (x ^ y))) + + P( A, B, C, D, 1, 5, 0xF61E2562 ); + P( D, A, B, C, 6, 9, 0xC040B340 ); + P( C, D, A, B, 11, 14, 0x265E5A51 ); + P( B, C, D, A, 0, 20, 0xE9B6C7AA ); + P( A, B, C, D, 5, 5, 0xD62F105D ); + P( D, A, B, C, 10, 9, 0x02441453 ); + P( C, D, A, B, 15, 14, 0xD8A1E681 ); + P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); + P( A, B, C, D, 9, 5, 0x21E1CDE6 ); + P( D, A, B, C, 14, 9, 0xC33707D6 ); + P( C, D, A, B, 3, 14, 0xF4D50D87 ); + P( B, C, D, A, 8, 20, 0x455A14ED ); + P( A, B, C, D, 13, 5, 0xA9E3E905 ); + P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); + P( C, D, A, B, 7, 14, 0x676F02D9 ); + P( B, C, D, A, 12, 20, 0x8D2A4C8A ); + +#undef F + +#define F(x,y,z) (x ^ y ^ z) + + P( A, B, C, D, 5, 4, 0xFFFA3942 ); + P( D, A, B, C, 8, 11, 0x8771F681 ); + P( C, D, A, B, 11, 16, 0x6D9D6122 ); + P( B, C, D, A, 14, 23, 0xFDE5380C ); + P( A, B, C, D, 1, 4, 0xA4BEEA44 ); + P( D, A, B, C, 4, 11, 0x4BDECFA9 ); + P( C, D, A, B, 7, 16, 0xF6BB4B60 ); + P( B, C, D, A, 10, 23, 0xBEBFBC70 ); + P( A, B, C, D, 13, 4, 0x289B7EC6 ); + P( D, A, B, C, 0, 11, 0xEAA127FA ); + P( C, D, A, B, 3, 16, 0xD4EF3085 ); + P( B, C, D, A, 6, 23, 0x04881D05 ); + P( A, B, C, D, 9, 4, 0xD9D4D039 ); + P( D, A, B, C, 12, 11, 0xE6DB99E5 ); + P( C, D, A, B, 15, 16, 0x1FA27CF8 ); + P( B, C, D, A, 2, 23, 0xC4AC5665 ); + +#undef F + +#define F(x,y,z) (y ^ (x | ~z)) + + P( A, B, C, D, 0, 6, 0xF4292244 ); + P( D, A, B, C, 7, 10, 0x432AFF97 ); + P( C, D, A, B, 14, 15, 0xAB9423A7 ); + P( B, C, D, A, 5, 21, 0xFC93A039 ); + P( A, B, C, D, 12, 6, 0x655B59C3 ); + P( D, A, B, C, 3, 10, 0x8F0CCC92 ); + P( C, D, A, B, 10, 15, 0xFFEFF47D ); + P( B, C, D, A, 1, 21, 0x85845DD1 ); + P( A, B, C, D, 8, 6, 0x6FA87E4F ); + P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); + P( C, D, A, B, 6, 15, 0xA3014314 ); + P( B, C, D, A, 13, 21, 0x4E0811A1 ); + P( A, B, C, D, 4, 6, 0xF7537E82 ); + P( D, A, B, C, 11, 10, 0xBD3AF235 ); + P( C, D, A, B, 2, 15, 0x2AD7D2BB ); + P( B, C, D, A, 9, 21, 0xEB86D391 ); + +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; +} + +void md5_update( struct md5_context *ctx, uint8 *input, uint32 length ) +{ + uint32 left, fill; + + if( ! length ) return; + + left = ( ctx->total[0] >> 3 ) & 0x3F; + fill = 64 - left; + + ctx->total[0] += length << 3; + ctx->total[1] += length >> 29; + + ctx->total[0] &= 0xFFFFFFFF; + ctx->total[1] += ctx->total[0] < ( length << 3 ); + + if( left && length >= fill ) + { + memcpy( (void *) (ctx->buffer + left), (void *) input, fill ); + md5_process( ctx, ctx->buffer ); + length -= fill; + input += fill; + left = 0; + } + + while( length >= 64 ) + { + md5_process( ctx, input ); + length -= 64; + input += 64; + } + + if( length ) + { + memcpy( (void *) (ctx->buffer + left), (void *) input, length ); + } +} + +static uint8 md5_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +void md5_finish( struct md5_context *ctx, uint8 digest[16] ) +{ + uint32 last, padn; + uint8 msglen[8]; + + PUT_UINT32( ctx->total[0], msglen, 0 ); + PUT_UINT32( ctx->total[1], msglen, 4 ); + + last = ( ctx->total[0] >> 3 ) & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + md5_update( ctx, md5_padding, padn ); + md5_update( ctx, msglen, 8 ); + + PUT_UINT32( ctx->state[0], digest, 0 ); + PUT_UINT32( ctx->state[1], digest, 4 ); + PUT_UINT32( ctx->state[2], digest, 8 ); + PUT_UINT32( ctx->state[3], digest, 12 ); +} + + +/* Uses a static buffer, so beware of how it's used. */ +char *md5_asciistr(MD5DATA& md5) +{ + uint8* digest = md5.data; + static char str[33]; + static char trans[16]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; + int x; + + for(x=0;x<16;x++) + { + str[x*2]=trans[digest[x]>>4]; + str[x*2+1]=trans[digest[x]&0x0F]; + } + return(str); +} diff --git a/jni/desmume/src/utils/md5.h b/jni/desmume/src/utils/md5.h new file mode 100755 index 0000000..bbd2593 --- /dev/null +++ b/jni/desmume/src/utils/md5.h @@ -0,0 +1,23 @@ +#ifndef _MD5_H +#define _MD5_H + +#include "../types.h" +#include "valuearray.h" + +struct md5_context +{ + u32 total[2]; + u32 state[4]; + u8 buffer[64]; +}; + +typedef ValueArray<uint8,16> MD5DATA; + +void md5_starts( struct md5_context *ctx ); +void md5_update( struct md5_context *ctx, u8 *input, u32 length ); +void md5_finish( struct md5_context *ctx, u8 digest[16] ); + +/* Uses a static buffer, so beware of how it's used. */ +char *md5_asciistr(MD5DATA& md5); + +#endif /* md5.h */ diff --git a/jni/desmume/src/utils/task.cpp b/jni/desmume/src/utils/task.cpp new file mode 100755 index 0000000..1999e7e --- /dev/null +++ b/jni/desmume/src/utils/task.cpp @@ -0,0 +1,312 @@ +/* + Copyright (C) 2009-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "types.h" +#include "task.h" +#include <stdio.h> + +#ifdef _WINDOWS +#include <windows.h> +#else +#include <pthread.h> +#endif + +#ifdef _MSC_VER +class Task::Impl { +public: + Impl(); + ~Impl(); + + bool spinlock; + + void start(bool spinlock); + void shutdown(); + + //execute some work + void execute(const TWork &work, void* param); + + //wait for the work to complete + void* finish(); + + static DWORD __stdcall s_taskProc(void *ptr); + void taskProc(); + void init(); + + //the work function that shall be executed + TWork work; + void* param; + + HANDLE incomingWork, workDone, hThread; + volatile bool bIncomingWork, bWorkDone, bKill; + bool bStarted; +}; + +static void* killTask(void* task) +{ + ((Task::Impl*)task)->bKill = true; + return 0; +} + +Task::Impl::~Impl() +{ + shutdown(); +} + +Task::Impl::Impl() + : work(NULL) + , bIncomingWork(false) + , bWorkDone(true) + , bKill(false) + , bStarted(false) + , incomingWork(INVALID_HANDLE_VALUE) + , workDone(INVALID_HANDLE_VALUE) + , hThread(INVALID_HANDLE_VALUE) +{ +} + +DWORD __stdcall Task::Impl::s_taskProc(void *ptr) +{ + //just past the buck to the instance method + ((Task::Impl*)ptr)->taskProc(); + return 0; +} + +void Task::Impl::taskProc() +{ + for(;;) { + if(bKill) break; + + //wait for a chunk of work + if(spinlock) while(!bIncomingWork) Sleep(0); + else WaitForSingleObject(incomingWork,INFINITE); + + bIncomingWork = false; + //execute the work + param = work(param); + //signal completion + if(!spinlock) SetEvent(workDone); + bWorkDone = true; + } +} + +void Task::Impl::start(bool spinlock) +{ + bIncomingWork = false; + bWorkDone = true; + bKill = false; + bStarted = true; + this->spinlock = spinlock; + incomingWork = CreateEvent(NULL,FALSE,FALSE,NULL); + workDone = CreateEvent(NULL,FALSE,FALSE,NULL); + hThread = CreateThread(NULL,0,Task::Impl::s_taskProc,(void*)this, 0, NULL); +} +void Task::Impl::shutdown() +{ + if(!bStarted) return; + bStarted = false; + + execute(killTask,this); + finish(); + + CloseHandle(incomingWork); + CloseHandle(workDone); + CloseHandle(hThread); + + incomingWork = INVALID_HANDLE_VALUE; + workDone = INVALID_HANDLE_VALUE; + hThread = INVALID_HANDLE_VALUE; +} + +void Task::Impl::execute(const TWork &work, void* param) +{ + //setup the work + this->work = work; + this->param = param; + bWorkDone = false; + //signal it to start + if(!spinlock) SetEvent(incomingWork); + bIncomingWork = true; +} + +void* Task::Impl::finish() +{ + //just wait for the work to be done + if(spinlock) + while(!bWorkDone) + Sleep(0); + else WaitForSingleObject(workDone,INFINITE); + return param; +} + +#else + +class Task::Impl { +private: + pthread_t _thread; + bool _isThreadRunning; + +public: + Impl(); + ~Impl(); + + void start(bool spinlock); + void execute(const TWork &work, void *param); + void* finish(); + void shutdown(); + + pthread_mutex_t mutex; + pthread_cond_t condWork; + TWork work; + void *param; + void *ret; + bool exitThread; +}; + +static void* taskProc(void *arg) +{ + Task::Impl *ctx = (Task::Impl *)arg; + + do { + pthread_mutex_lock(&ctx->mutex); + + while (ctx->work == NULL && !ctx->exitThread) { + pthread_cond_wait(&ctx->condWork, &ctx->mutex); + } + + if (ctx->work != NULL) { + ctx->ret = ctx->work(ctx->param); + } else { + ctx->ret = NULL; + } + + ctx->work = NULL; + pthread_cond_signal(&ctx->condWork); + + pthread_mutex_unlock(&ctx->mutex); + + } while(!ctx->exitThread); + + return NULL; +} + +Task::Impl::Impl() +{ + _isThreadRunning = false; + work = NULL; + param = NULL; + ret = NULL; + exitThread = false; + + pthread_mutex_init(&mutex, NULL); + pthread_cond_init(&condWork, NULL); +} + +Task::Impl::~Impl() +{ + shutdown(); + pthread_mutex_destroy(&mutex); + pthread_cond_destroy(&condWork); +} + +void Task::Impl::start(bool spinlock) +{ + pthread_mutex_lock(&this->mutex); + + if (this->_isThreadRunning) { + pthread_mutex_unlock(&this->mutex); + return; + } + + this->work = NULL; + this->param = NULL; + this->ret = NULL; + this->exitThread = false; + pthread_create(&this->_thread, NULL, &taskProc, this); + this->_isThreadRunning = true; + + pthread_mutex_unlock(&this->mutex); +} + +void Task::Impl::execute(const TWork &work, void *param) +{ + pthread_mutex_lock(&this->mutex); + + if (work == NULL || !this->_isThreadRunning) { + pthread_mutex_unlock(&this->mutex); + return; + } + + this->work = work; + this->param = param; + pthread_cond_signal(&this->condWork); + + pthread_mutex_unlock(&this->mutex); +} + +void* Task::Impl::finish() +{ + void *returnValue = NULL; + + pthread_mutex_lock(&this->mutex); + + if (!this->_isThreadRunning) { + pthread_mutex_unlock(&this->mutex); + return returnValue; + } + + while (this->work != NULL) { + pthread_cond_wait(&this->condWork, &this->mutex); + } + + returnValue = this->ret; + + pthread_mutex_unlock(&this->mutex); + + return returnValue; +} + +void Task::Impl::shutdown() +{ + pthread_mutex_lock(&this->mutex); + + if (!this->_isThreadRunning) { + pthread_mutex_unlock(&this->mutex); + return; + } + + this->work = NULL; + this->exitThread = true; + pthread_cond_signal(&this->condWork); + + pthread_mutex_unlock(&this->mutex); + + pthread_join(this->_thread, NULL); + + pthread_mutex_lock(&this->mutex); + this->_isThreadRunning = false; + pthread_mutex_unlock(&this->mutex); +} +#endif + +void Task::start(bool spinlock) { impl->start(spinlock); } +void Task::shutdown() { impl->shutdown(); } +Task::Task() : impl(new Task::Impl()) {} +Task::~Task() { delete impl; } +void Task::execute(const TWork &work, void* param) { impl->execute(work,param); } +void* Task::finish() { return impl->finish(); } + + diff --git a/jni/desmume/src/utils/task.h b/jni/desmume/src/utils/task.h new file mode 100755 index 0000000..80cd482 --- /dev/null +++ b/jni/desmume/src/utils/task.h @@ -0,0 +1,48 @@ +/* + Copyright (C) 2009 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _TASK_H_ + +//Sort of like a single-thread thread pool. +//You hand it a worker function and then call finish() to synch with its completion +class Task +{ +public: + Task(); + ~Task(); + + typedef void * (*TWork)(void *); + + // initialize task runner + void start(bool spinlock); + + //execute some work + void execute(const TWork &work, void* param); + + //wait for the work to complete + void* finish(); + + // does the opposite of start + void shutdown(); + + class Impl; + Impl *impl; + +}; + + +#endif diff --git a/jni/desmume/src/utils/tinyxml/tinystr.cpp b/jni/desmume/src/utils/tinyxml/tinystr.cpp new file mode 100755 index 0000000..0665768 --- /dev/null +++ b/jni/desmume/src/utils/tinyxml/tinystr.cpp @@ -0,0 +1,111 @@ +/* +www.sourceforge.net/projects/tinyxml + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + + +#ifndef TIXML_USE_STL + +#include "tinystr.h" + +// Error value for find primitive +const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1); + + +// Null rep. +TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } }; + + +void TiXmlString::reserve (size_type cap) +{ + if (cap > capacity()) + { + TiXmlString tmp; + tmp.init(length(), cap); + memcpy(tmp.start(), data(), length()); + swap(tmp); + } +} + + +TiXmlString& TiXmlString::assign(const char* str, size_type len) +{ + size_type cap = capacity(); + if (len > cap || cap > 3*(len + 8)) + { + TiXmlString tmp; + tmp.init(len); + memcpy(tmp.start(), str, len); + swap(tmp); + } + else + { + memmove(start(), str, len); + set_size(len); + } + return *this; +} + + +TiXmlString& TiXmlString::append(const char* str, size_type len) +{ + size_type newsize = length() + len; + if (newsize > capacity()) + { + reserve (newsize + capacity()); + } + memmove(finish(), str, len); + set_size(newsize); + return *this; +} + + +TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) +{ + TiXmlString tmp; + tmp.reserve(a.length() + b.length()); + tmp += a; + tmp += b; + return tmp; +} + +TiXmlString operator + (const TiXmlString & a, const char* b) +{ + TiXmlString tmp; + TiXmlString::size_type b_len = static_cast<TiXmlString::size_type>( strlen(b) ); + tmp.reserve(a.length() + b_len); + tmp += a; + tmp.append(b, b_len); + return tmp; +} + +TiXmlString operator + (const char* a, const TiXmlString & b) +{ + TiXmlString tmp; + TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) ); + tmp.reserve(a_len + b.length()); + tmp.append(a, a_len); + tmp += b; + return tmp; +} + + +#endif // TIXML_USE_STL diff --git a/jni/desmume/src/utils/tinyxml/tinystr.h b/jni/desmume/src/utils/tinyxml/tinystr.h new file mode 100755 index 0000000..89cca33 --- /dev/null +++ b/jni/desmume/src/utils/tinyxml/tinystr.h @@ -0,0 +1,305 @@ +/* +www.sourceforge.net/projects/tinyxml + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + + +#ifndef TIXML_USE_STL + +#ifndef TIXML_STRING_INCLUDED +#define TIXML_STRING_INCLUDED + +#include <assert.h> +#include <string.h> + +/* The support for explicit isn't that universal, and it isn't really + required - it is used to check that the TiXmlString class isn't incorrectly + used. Be nice to old compilers and macro it here: +*/ +#if defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // Microsoft visual studio, version 6 and higher. + #define TIXML_EXPLICIT explicit +#elif defined(__GNUC__) && (__GNUC__ >= 3 ) + // GCC version 3 and higher.s + #define TIXML_EXPLICIT explicit +#else + #define TIXML_EXPLICIT +#endif + + +/* + TiXmlString is an emulation of a subset of the std::string template. + Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. + Only the member functions relevant to the TinyXML project have been implemented. + The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase + a string and there's no more room, we allocate a buffer twice as big as we need. +*/ +class TiXmlString +{ + public : + // The size type used + typedef size_t size_type; + + // Error value for find primitive + static const size_type npos; // = -1; + + + // TiXmlString empty constructor + TiXmlString () : rep_(&nullrep_) + { + } + + // TiXmlString copy constructor + TiXmlString ( const TiXmlString & copy) : rep_(0) + { + init(copy.length()); + memcpy(start(), copy.data(), length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) + { + init( static_cast<size_type>( strlen(copy) )); + memcpy(start(), copy, length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) + { + init(len); + memcpy(start(), str, len); + } + + // TiXmlString destructor + ~TiXmlString () + { + quit(); + } + + TiXmlString& operator = (const char * copy) + { + return assign( copy, (size_type)strlen(copy)); + } + + TiXmlString& operator = (const TiXmlString & copy) + { + return assign(copy.start(), copy.length()); + } + + + // += operator. Maps to append + TiXmlString& operator += (const char * suffix) + { + return append(suffix, static_cast<size_type>( strlen(suffix) )); + } + + // += operator. Maps to append + TiXmlString& operator += (char single) + { + return append(&single, 1); + } + + // += operator. Maps to append + TiXmlString& operator += (const TiXmlString & suffix) + { + return append(suffix.data(), suffix.length()); + } + + + // Convert a TiXmlString into a null-terminated char * + const char * c_str () const { return rep_->str; } + + // Convert a TiXmlString into a char * (need not be null terminated). + const char * data () const { return rep_->str; } + + // Return the length of a TiXmlString + size_type length () const { return rep_->size; } + + // Alias for length() + size_type size () const { return rep_->size; } + + // Checks if a TiXmlString is empty + bool empty () const { return rep_->size == 0; } + + // Return capacity of string + size_type capacity () const { return rep_->capacity; } + + + // single char extraction + const char& at (size_type index) const + { + assert( index < length() ); + return rep_->str[ index ]; + } + + // [] operator + char& operator [] (size_type index) const + { + assert( index < length() ); + return rep_->str[ index ]; + } + + // find a char in a string. Return TiXmlString::npos if not found + size_type find (char lookup) const + { + return find(lookup, 0); + } + + // find a char in a string from an offset. Return TiXmlString::npos if not found + size_type find (char tofind, size_type offset) const + { + if (offset >= length()) return npos; + + for (const char* p = c_str() + offset; *p != '\0'; ++p) + { + if (*p == tofind) return static_cast< size_type >( p - c_str() ); + } + return npos; + } + + void clear () + { + //Lee: + //The original was just too strange, though correct: + // TiXmlString().swap(*this); + //Instead use the quit & re-init: + quit(); + init(0,0); + } + + /* Function to reserve a big amount of data when we know we'll need it. Be aware that this + function DOES NOT clear the content of the TiXmlString if any exists. + */ + void reserve (size_type cap); + + TiXmlString& assign (const char* str, size_type len); + + TiXmlString& append (const char* str, size_type len); + + void swap (TiXmlString& other) + { + Rep* r = rep_; + rep_ = other.rep_; + other.rep_ = r; + } + + private: + + void init(size_type sz) { init(sz, sz); } + void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } + char* start() const { return rep_->str; } + char* finish() const { return rep_->str + rep_->size; } + + struct Rep + { + size_type size, capacity; + char str[1]; + }; + + void init(size_type sz, size_type cap) + { + if (cap) + { + // Lee: the original form: + // rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap)); + // doesn't work in some cases of new being overloaded. Switching + // to the normal allocation, although use an 'int' for systems + // that are overly picky about structure alignment. + const size_type bytesNeeded = sizeof(Rep) + cap; + const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); + rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] ); + + rep_->str[ rep_->size = sz ] = '\0'; + rep_->capacity = cap; + } + else + { + rep_ = &nullrep_; + } + } + + void quit() + { + if (rep_ != &nullrep_) + { + // The rep_ is really an array of ints. (see the allocator, above). + // Cast it back before delete, so the compiler won't incorrectly call destructors. + delete [] ( reinterpret_cast<int*>( rep_ ) ); + } + } + + Rep * rep_; + static Rep nullrep_; + +} ; + + +inline bool operator == (const TiXmlString & a, const TiXmlString & b) +{ + return ( a.length() == b.length() ) // optimization on some platforms + && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare +} +inline bool operator < (const TiXmlString & a, const TiXmlString & b) +{ + return strcmp(a.c_str(), b.c_str()) < 0; +} + +inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } +inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } +inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } +inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } + +inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } +inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } +inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } +inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } + +TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); +TiXmlString operator + (const TiXmlString & a, const char* b); +TiXmlString operator + (const char* a, const TiXmlString & b); + + +/* + TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. + Only the operators that we need for TinyXML have been developped. +*/ +class TiXmlOutStream : public TiXmlString +{ +public : + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const TiXmlString & in) + { + *this += in; + return *this; + } + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const char * in) + { + *this += in; + return *this; + } + +} ; + +#endif // TIXML_STRING_INCLUDED +#endif // TIXML_USE_STL diff --git a/jni/desmume/src/utils/tinyxml/tinyxml.cpp b/jni/desmume/src/utils/tinyxml/tinyxml.cpp new file mode 100755 index 0000000..9c161df --- /dev/null +++ b/jni/desmume/src/utils/tinyxml/tinyxml.cpp @@ -0,0 +1,1886 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code by Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include <ctype.h> + +#ifdef TIXML_USE_STL +#include <sstream> +#include <iostream> +#endif + +#include "tinyxml.h" + +FILE* TiXmlFOpen( const char* filename, const char* mode ); + +bool TiXmlBase::condenseWhiteSpace = true; + +// Microsoft compiler security +FILE* TiXmlFOpen( const char* filename, const char* mode ) +{ + #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + FILE* fp = 0; + errno_t err = fopen_s( &fp, filename, mode ); + if ( !err && fp ) + return fp; + return 0; + #else + return fopen( filename, mode ); + #endif +} + +void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) +{ + int i=0; + + while( i<(int)str.length() ) + { + unsigned char c = (unsigned char) str[i]; + + if ( c == '&' + && i < ( (int)str.length() - 2 ) + && str[i+1] == '#' + && str[i+2] == 'x' ) + { + // Hexadecimal character reference. + // Pass through unchanged. + // © -- copyright symbol, for example. + // + // The -1 is a bug fix from Rob Laveaux. It keeps + // an overflow from happening if there is no ';'. + // There are actually 2 ways to exit this loop - + // while fails (error case) and break (semicolon found). + // However, there is no mechanism (currently) for + // this function to return an error. + while ( i<(int)str.length()-1 ) + { + outString->append( str.c_str() + i, 1 ); + ++i; + if ( str[i] == ';' ) + break; + } + } + else if ( c == '&' ) + { + outString->append( entity[0].str, entity[0].strLength ); + ++i; + } + else if ( c == '<' ) + { + outString->append( entity[1].str, entity[1].strLength ); + ++i; + } + else if ( c == '>' ) + { + outString->append( entity[2].str, entity[2].strLength ); + ++i; + } + else if ( c == '\"' ) + { + outString->append( entity[3].str, entity[3].strLength ); + ++i; + } + else if ( c == '\'' ) + { + outString->append( entity[4].str, entity[4].strLength ); + ++i; + } + else if ( c < 32 ) + { + // Easy pass at non-alpha/numeric/symbol + // Below 32 is symbolic. + char buf[ 32 ]; + + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); + #else + sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); + #endif + + //*ME: warning C4267: convert 'size_t' to 'int' + //*ME: Int-Cast to make compiler happy ... + outString->append( buf, (int)strlen( buf ) ); + ++i; + } + else + { + //char realc = (char) c; + //outString->append( &realc, 1 ); + *outString += (char) c; // somewhat more efficient function call. + ++i; + } + } +} + + +TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() +{ + parent = 0; + type = _type; + firstChild = 0; + lastChild = 0; + prev = 0; + next = 0; +} + + +TiXmlNode::~TiXmlNode() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } +} + + +void TiXmlNode::CopyTo( TiXmlNode* target ) const +{ + target->SetValue (value.c_str() ); + target->userData = userData; + target->location = location; +} + + +void TiXmlNode::Clear() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } + + firstChild = 0; + lastChild = 0; +} + + +TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) +{ + assert( node->parent == 0 || node->parent == this ); + assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); + + if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT ) + { + delete node; + if ( GetDocument() ) + GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + node->parent = this; + + node->prev = lastChild; + node->next = 0; + + if ( lastChild ) + lastChild->next = node; + else + firstChild = node; // it was an empty list. + + lastChild = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) +{ + if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) + { + if ( GetDocument() ) + GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + + return LinkEndChild( node ); +} + + +TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) +{ + if ( !beforeThis || beforeThis->parent != this ) { + return 0; + } + if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) + { + if ( GetDocument() ) + GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->next = beforeThis; + node->prev = beforeThis->prev; + if ( beforeThis->prev ) + { + beforeThis->prev->next = node; + } + else + { + assert( firstChild == beforeThis ); + firstChild = node; + } + beforeThis->prev = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) +{ + if ( !afterThis || afterThis->parent != this ) { + return 0; + } + if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) + { + if ( GetDocument() ) + GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->prev = afterThis; + node->next = afterThis->next; + if ( afterThis->next ) + { + afterThis->next->prev = node; + } + else + { + assert( lastChild == afterThis ); + lastChild = node; + } + afterThis->next = node; + return node; +} + + +TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) +{ + if ( !replaceThis ) + return 0; + + if ( replaceThis->parent != this ) + return 0; + + if ( withThis.ToDocument() ) { + // A document can never be a child. Thanks to Noam. + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = withThis.Clone(); + if ( !node ) + return 0; + + node->next = replaceThis->next; + node->prev = replaceThis->prev; + + if ( replaceThis->next ) + replaceThis->next->prev = node; + else + lastChild = node; + + if ( replaceThis->prev ) + replaceThis->prev->next = node; + else + firstChild = node; + + delete replaceThis; + node->parent = this; + return node; +} + + +bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) +{ + if ( !removeThis ) { + return false; + } + + if ( removeThis->parent != this ) + { + assert( 0 ); + return false; + } + + if ( removeThis->next ) + removeThis->next->prev = removeThis->prev; + else + lastChild = removeThis->prev; + + if ( removeThis->prev ) + removeThis->prev->next = removeThis->next; + else + firstChild = removeThis->next; + + delete removeThis; + return true; +} + +const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = firstChild; node; node = node->next ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = lastChild; node; node = node->prev ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const +{ + if ( !previous ) + { + return FirstChild(); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling(); + } +} + + +const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const +{ + if ( !previous ) + { + return FirstChild( val ); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling( val ); + } +} + + +const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = next; node; node = node->next ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = prev; node; node = node->prev ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +void TiXmlElement::RemoveAttribute( const char * name ) +{ + #ifdef TIXML_USE_STL + TIXML_STRING str( name ); + TiXmlAttribute* node = attributeSet.Find( str ); + #else + TiXmlAttribute* node = attributeSet.Find( name ); + #endif + if ( node ) + { + attributeSet.Remove( node ); + delete node; + } +} + +const TiXmlElement* TiXmlNode::FirstChildElement() const +{ + const TiXmlNode* node; + + for ( node = FirstChild(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const +{ + const TiXmlNode* node; + + for ( node = FirstChild( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::NextSiblingElement() const +{ + const TiXmlNode* node; + + for ( node = NextSibling(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const +{ + const TiXmlNode* node; + + for ( node = NextSibling( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlDocument* TiXmlNode::GetDocument() const +{ + const TiXmlNode* node; + + for( node = this; node; node = node->parent ) + { + if ( node->ToDocument() ) + return node->ToDocument(); + } + return 0; +} + + +TiXmlElement::TiXmlElement (const char * _value) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} + + +#ifdef TIXML_USE_STL +TiXmlElement::TiXmlElement( const std::string& _value ) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} +#endif + + +TiXmlElement::TiXmlElement( const TiXmlElement& copy) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) +{ + firstChild = lastChild = 0; + copy.CopyTo( this ); +} + + +TiXmlElement& TiXmlElement::operator=( const TiXmlElement& base ) +{ + ClearThis(); + base.CopyTo( this ); + return *this; +} + + +TiXmlElement::~TiXmlElement() +{ + ClearThis(); +} + + +void TiXmlElement::ClearThis() +{ + Clear(); + while( attributeSet.First() ) + { + TiXmlAttribute* node = attributeSet.First(); + attributeSet.Remove( node ); + delete node; + } +} + + +const char* TiXmlElement::Attribute( const char* name ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + return node->Value(); + return 0; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( attrib ) + return &attrib->ValueStr(); + return 0; +} +#endif + + +const char* TiXmlElement::Attribute( const char* name, int* i ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const char* result = 0; + + if ( attrib ) { + result = attrib->Value(); + if ( i ) { + attrib->QueryIntValue( i ); + } + } + return result; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const std::string* result = 0; + + if ( attrib ) { + result = &attrib->ValueStr(); + if ( i ) { + attrib->QueryIntValue( i ); + } + } + return result; +} +#endif + + +const char* TiXmlElement::Attribute( const char* name, double* d ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const char* result = 0; + + if ( attrib ) { + result = attrib->Value(); + if ( d ) { + attrib->QueryDoubleValue( d ); + } + } + return result; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const std::string* result = 0; + + if ( attrib ) { + result = &attrib->ValueStr(); + if ( d ) { + attrib->QueryDoubleValue( d ); + } + } + return result; +} +#endif + + +int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryIntValue( ival ); +} + + +int TiXmlElement::QueryUnsignedAttribute( const char* name, unsigned* value ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + + int ival = 0; + int result = node->QueryIntValue( &ival ); + *value = (unsigned)ival; + return result; +} + + +int TiXmlElement::QueryBoolAttribute( const char* name, bool* bval ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + + int result = TIXML_WRONG_TYPE; + if ( StringEqual( node->Value(), "true", true, TIXML_ENCODING_UNKNOWN ) + || StringEqual( node->Value(), "yes", true, TIXML_ENCODING_UNKNOWN ) + || StringEqual( node->Value(), "1", true, TIXML_ENCODING_UNKNOWN ) ) + { + *bval = true; + result = TIXML_SUCCESS; + } + else if ( StringEqual( node->Value(), "false", true, TIXML_ENCODING_UNKNOWN ) + || StringEqual( node->Value(), "no", true, TIXML_ENCODING_UNKNOWN ) + || StringEqual( node->Value(), "0", true, TIXML_ENCODING_UNKNOWN ) ) + { + *bval = false; + result = TIXML_SUCCESS; + } + return result; +} + + + +#ifdef TIXML_USE_STL +int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryIntValue( ival ); +} +#endif + + +int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryDoubleValue( dval ); +} + + +#ifdef TIXML_USE_STL +int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryDoubleValue( dval ); +} +#endif + + +void TiXmlElement::SetAttribute( const char * name, int val ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetIntValue( val ); + } +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetAttribute( const std::string& name, int val ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetIntValue( val ); + } +} +#endif + + +void TiXmlElement::SetDoubleAttribute( const char * name, double val ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetDoubleValue( val ); + } +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetDoubleAttribute( const std::string& name, double val ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetDoubleValue( val ); + } +} +#endif + + +void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname ); + if ( attrib ) { + attrib->SetValue( cvalue ); + } +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name ); + if ( attrib ) { + attrib->SetValue( _value ); + } +} +#endif + + +void TiXmlElement::Print( FILE* cfile, int depth ) const +{ + int i; + assert( cfile ); + for ( i=0; i<depth; i++ ) { + fprintf( cfile, " " ); + } + + fprintf( cfile, "<%s", value.c_str() ); + + const TiXmlAttribute* attrib; + for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() ) + { + fprintf( cfile, " " ); + attrib->Print( cfile, depth ); + } + + // There are 3 different formatting approaches: + // 1) An element without children is printed as a <foo /> node + // 2) An element with only a text child is printed as <foo> text </foo> + // 3) An element with children is printed on multiple lines. + TiXmlNode* node; + if ( !firstChild ) + { + fprintf( cfile, " />" ); + } + else if ( firstChild == lastChild && firstChild->ToText() ) + { + fprintf( cfile, ">" ); + firstChild->Print( cfile, depth + 1 ); + fprintf( cfile, "</%s>", value.c_str() ); + } + else + { + fprintf( cfile, ">" ); + + for ( node = firstChild; node; node=node->NextSibling() ) + { + if ( !node->ToText() ) + { + fprintf( cfile, "\n" ); + } + node->Print( cfile, depth+1 ); + } + fprintf( cfile, "\n" ); + for( i=0; i<depth; ++i ) { + fprintf( cfile, " " ); + } + fprintf( cfile, "</%s>", value.c_str() ); + } +} + + +void TiXmlElement::CopyTo( TiXmlElement* target ) const +{ + // superclass: + TiXmlNode::CopyTo( target ); + + // Element class: + // Clone the attributes, then clone the children. + const TiXmlAttribute* attribute = 0; + for( attribute = attributeSet.First(); + attribute; + attribute = attribute->Next() ) + { + target->SetAttribute( attribute->Name(), attribute->Value() ); + } + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + target->LinkEndChild( node->Clone() ); + } +} + +bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const +{ + if ( visitor->VisitEnter( *this, attributeSet.First() ) ) + { + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + if ( !node->Accept( visitor ) ) + break; + } + } + return visitor->VisitExit( *this ); +} + + +TiXmlNode* TiXmlElement::Clone() const +{ + TiXmlElement* clone = new TiXmlElement( Value() ); + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +const char* TiXmlElement::GetText() const +{ + const TiXmlNode* child = this->FirstChild(); + if ( child ) { + const TiXmlText* childText = child->ToText(); + if ( childText ) { + return childText->Value(); + } + } + return 0; +} + + +TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + ClearError(); +} + +TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} + + +#ifdef TIXML_USE_STL +TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} +#endif + + +TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + copy.CopyTo( this ); +} + + +TiXmlDocument& TiXmlDocument::operator=( const TiXmlDocument& copy ) +{ + Clear(); + copy.CopyTo( this ); + return *this; +} + + +bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) +{ + return LoadFile( Value(), encoding ); +} + + +bool TiXmlDocument::SaveFile() const +{ + return SaveFile( Value() ); +} + +bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) +{ + TIXML_STRING filename( _filename ); + value = filename; + + // reading in binary mode so that tinyxml can normalize the EOL + FILE* file = TiXmlFOpen( value.c_str (), "rb" ); + + if ( file ) + { + bool result = LoadFile( file, encoding ); + fclose( file ); + return result; + } + else + { + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } +} + +bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) +{ + if ( !file ) + { + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Delete the existing data: + Clear(); + location.Clear(); + + // Get the file size, so we can pre-allocate the string. HUGE speed impact. + long length = 0; + fseek( file, 0, SEEK_END ); + length = ftell( file ); + fseek( file, 0, SEEK_SET ); + + // Strange case, but good to handle up front. + if ( length <= 0 ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Subtle bug here. TinyXml did use fgets. But from the XML spec: + // 2.11 End-of-Line Handling + // <snip> + // <quote> + // ...the XML processor MUST behave as if it normalized all line breaks in external + // parsed entities (including the document entity) on input, before parsing, by translating + // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to + // a single #xA character. + // </quote> + // + // It is not clear fgets does that, and certainly isn't clear it works cross platform. + // Generally, you expect fgets to translate from the convention of the OS to the c/unix + // convention, and not work generally. + + /* + while( fgets( buf, sizeof(buf), file ) ) + { + data += buf; + } + */ + + char* buf = new char[ length+1 ]; + buf[0] = 0; + + if ( fread( buf, length, 1, file ) != 1 ) { + delete [] buf; + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Process the buffer in place to normalize new lines. (See comment above.) + // Copies from the 'p' to 'q' pointer, where p can advance faster if + // a newline-carriage return is hit. + // + // Wikipedia: + // Systems based on ASCII or a compatible character set use either LF (Line feed, '\n', 0x0A, 10 in decimal) or + // CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)... + // * LF: Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others + // * CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS + // * CR: Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9 + + const char* p = buf; // the read head + char* q = buf; // the write head + const char CR = 0x0d; + const char LF = 0x0a; + + buf[length] = 0; + while( *p ) { + assert( p < (buf+length) ); + assert( q <= (buf+length) ); + assert( q <= p ); + + if ( *p == CR ) { + *q++ = LF; + p++; + if ( *p == LF ) { // check for CR+LF (and skip LF) + p++; + } + } + else { + *q++ = *p++; + } + } + assert( q <= (buf+length) ); + *q = 0; + + Parse( buf, 0, encoding ); + + delete [] buf; + return !Error(); +} + + +bool TiXmlDocument::SaveFile( const char * filename ) const +{ + // The old c stuff lives on... + FILE* fp = TiXmlFOpen( filename, "w" ); + if ( fp ) + { + bool result = SaveFile( fp ); + fclose( fp ); + return result; + } + return false; +} + + +bool TiXmlDocument::SaveFile( FILE* fp ) const +{ + if ( useMicrosoftBOM ) + { + const unsigned char TIXML_UTF_LEAD_0 = 0xefU; + const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; + const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + + fputc( TIXML_UTF_LEAD_0, fp ); + fputc( TIXML_UTF_LEAD_1, fp ); + fputc( TIXML_UTF_LEAD_2, fp ); + } + Print( fp, 0 ); + return (ferror(fp) == 0); +} + + +void TiXmlDocument::CopyTo( TiXmlDocument* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->error = error; + target->errorId = errorId; + target->errorDesc = errorDesc; + target->tabsize = tabsize; + target->errorLocation = errorLocation; + target->useMicrosoftBOM = useMicrosoftBOM; + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + target->LinkEndChild( node->Clone() ); + } +} + + +TiXmlNode* TiXmlDocument::Clone() const +{ + TiXmlDocument* clone = new TiXmlDocument(); + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlDocument::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + node->Print( cfile, depth ); + fprintf( cfile, "\n" ); + } +} + + +bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const +{ + if ( visitor->VisitEnter( *this ) ) + { + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + if ( !node->Accept( visitor ) ) + break; + } + } + return visitor->VisitExit( *this ); +} + + +const TiXmlAttribute* TiXmlAttribute::Next() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; +} + +/* +TiXmlAttribute* TiXmlAttribute::Next() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; +} +*/ + +const TiXmlAttribute* TiXmlAttribute::Previous() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; +} + +/* +TiXmlAttribute* TiXmlAttribute::Previous() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; +} +*/ + +void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const +{ + TIXML_STRING n, v; + + EncodeString( name, &n ); + EncodeString( value, &v ); + + if (value.find ('\"') == TIXML_STRING::npos) { + if ( cfile ) { + fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; + } + } + else { + if ( cfile ) { + fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; + } + } +} + + +int TiXmlAttribute::QueryIntValue( int* ival ) const +{ + if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +int TiXmlAttribute::QueryDoubleValue( double* dval ) const +{ + if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +void TiXmlAttribute::SetIntValue( int _value ) +{ + char buf [64]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); + #else + sprintf (buf, "%d", _value); + #endif + SetValue (buf); +} + +void TiXmlAttribute::SetDoubleValue( double _value ) +{ + char buf [256]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value); + #else + sprintf (buf, "%g", _value); + #endif + SetValue (buf); +} + +int TiXmlAttribute::IntValue() const +{ + return atoi (value.c_str ()); +} + +double TiXmlAttribute::DoubleValue() const +{ + return atof (value.c_str ()); +} + + +TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) +{ + copy.CopyTo( this ); +} + + +TiXmlComment& TiXmlComment::operator=( const TiXmlComment& base ) +{ + Clear(); + base.CopyTo( this ); + return *this; +} + + +void TiXmlComment::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + for ( int i=0; i<depth; i++ ) + { + fprintf( cfile, " " ); + } + fprintf( cfile, "<!--%s-->", value.c_str() ); +} + + +void TiXmlComment::CopyTo( TiXmlComment* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlComment::Clone() const +{ + TiXmlComment* clone = new TiXmlComment(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlText::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + if ( cdata ) + { + int i; + fprintf( cfile, "\n" ); + for ( i=0; i<depth; i++ ) { + fprintf( cfile, " " ); + } + fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() ); // unformatted output + } + else + { + TIXML_STRING buffer; + EncodeString( value, &buffer ); + fprintf( cfile, "%s", buffer.c_str() ); + } +} + + +void TiXmlText::CopyTo( TiXmlText* target ) const +{ + TiXmlNode::CopyTo( target ); + target->cdata = cdata; +} + + +bool TiXmlText::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlText::Clone() const +{ + TiXmlText* clone = 0; + clone = new TiXmlText( "" ); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlDeclaration::TiXmlDeclaration( const char * _version, + const char * _encoding, + const char * _standalone ) + : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} + + +#ifdef TIXML_USE_STL +TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ) + : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} +#endif + + +TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) + : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) +{ + copy.CopyTo( this ); +} + + +TiXmlDeclaration& TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) +{ + Clear(); + copy.CopyTo( this ); + return *this; +} + + +void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const +{ + if ( cfile ) fprintf( cfile, "<?xml " ); + if ( str ) (*str) += "<?xml "; + + if ( !version.empty() ) { + if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ()); + if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; } + } + if ( !encoding.empty() ) { + if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ()); + if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; } + } + if ( !standalone.empty() ) { + if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ()); + if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; } + } + if ( cfile ) fprintf( cfile, "?>" ); + if ( str ) (*str) += "?>"; +} + + +void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->version = version; + target->encoding = encoding; + target->standalone = standalone; +} + + +bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlDeclaration::Clone() const +{ + TiXmlDeclaration* clone = new TiXmlDeclaration(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlUnknown::Print( FILE* cfile, int depth ) const +{ + for ( int i=0; i<depth; i++ ) + fprintf( cfile, " " ); + fprintf( cfile, "<%s>", value.c_str() ); +} + + +void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlUnknown::Clone() const +{ + TiXmlUnknown* clone = new TiXmlUnknown(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlAttributeSet::TiXmlAttributeSet() +{ + sentinel.next = &sentinel; + sentinel.prev = &sentinel; +} + + +TiXmlAttributeSet::~TiXmlAttributeSet() +{ + assert( sentinel.next == &sentinel ); + assert( sentinel.prev == &sentinel ); +} + + +void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) +{ + #ifdef TIXML_USE_STL + assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. + #else + assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. + #endif + + addMe->next = &sentinel; + addMe->prev = sentinel.prev; + + sentinel.prev->next = addMe; + sentinel.prev = addMe; +} + +void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) +{ + TiXmlAttribute* node; + + for( node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node == removeMe ) + { + node->prev->next = node->next; + node->next->prev = node->prev; + node->next = 0; + node->prev = 0; + return; + } + } + assert( 0 ); // we tried to remove a non-linked attribute. +} + + +#ifdef TIXML_USE_STL +TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const +{ + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node->name == name ) + return node; + } + return 0; +} + +TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name ) +{ + TiXmlAttribute* attrib = Find( _name ); + if ( !attrib ) { + attrib = new TiXmlAttribute(); + Add( attrib ); + attrib->SetName( _name ); + } + return attrib; +} +#endif + + +TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const +{ + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( strcmp( node->name.c_str(), name ) == 0 ) + return node; + } + return 0; +} + + +TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name ) +{ + TiXmlAttribute* attrib = Find( _name ); + if ( !attrib ) { + attrib = new TiXmlAttribute(); + Add( attrib ); + attrib->SetName( _name ); + } + return attrib; +} + + +#ifdef TIXML_USE_STL +std::istream& operator>> (std::istream & in, TiXmlNode & base) +{ + TIXML_STRING tag; + tag.reserve( 8 * 1000 ); + base.StreamIn( &in, &tag ); + + base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); + return in; +} +#endif + + +#ifdef TIXML_USE_STL +std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) +{ + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out << printer.Str(); + + return out; +} + + +std::string& operator<< (std::string& out, const TiXmlNode& base ) +{ + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out.append( printer.Str() ); + + return out; +} +#endif + + +TiXmlHandle TiXmlHandle::FirstChild() const +{ + if ( node ) + { + TiXmlNode* child = node->FirstChild(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const +{ + if ( node ) + { + TiXmlNode* child = node->FirstChild( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement() const +{ + if ( node ) + { + TiXmlElement* child = node->FirstChildElement(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const +{ + if ( node ) + { + TiXmlElement* child = node->FirstChildElement( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::Child( int count ) const +{ + if ( node ) + { + int i; + TiXmlNode* child = node->FirstChild(); + for ( i=0; + child && i<count; + child = child->NextSibling(), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const +{ + if ( node ) + { + int i; + TiXmlNode* child = node->FirstChild( value ); + for ( i=0; + child && i<count; + child = child->NextSibling( value ), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::ChildElement( int count ) const +{ + if ( node ) + { + int i; + TiXmlElement* child = node->FirstChildElement(); + for ( i=0; + child && i<count; + child = child->NextSiblingElement(), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const +{ + if ( node ) + { + int i; + TiXmlElement* child = node->FirstChildElement( value ); + for ( i=0; + child && i<count; + child = child->NextSiblingElement( value ), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) +{ + return true; +} + +bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) +{ + return true; +} + +bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) +{ + DoIndent(); + buffer += "<"; + buffer += element.Value(); + + for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) + { + buffer += " "; + attrib->Print( 0, 0, &buffer ); + } + + if ( !element.FirstChild() ) + { + buffer += " />"; + DoLineBreak(); + } + else + { + buffer += ">"; + if ( element.FirstChild()->ToText() + && element.LastChild() == element.FirstChild() + && element.FirstChild()->ToText()->CDATA() == false ) + { + simpleTextPrint = true; + // no DoLineBreak()! + } + else + { + DoLineBreak(); + } + } + ++depth; + return true; +} + + +bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) +{ + --depth; + if ( !element.FirstChild() ) + { + // nothing. + } + else + { + if ( simpleTextPrint ) + { + simpleTextPrint = false; + } + else + { + DoIndent(); + } + buffer += "</"; + buffer += element.Value(); + buffer += ">"; + DoLineBreak(); + } + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlText& text ) +{ + if ( text.CDATA() ) + { + DoIndent(); + buffer += "<![CDATA["; + buffer += text.Value(); + buffer += "]]>"; + DoLineBreak(); + } + else if ( simpleTextPrint ) + { + TIXML_STRING str; + TiXmlBase::EncodeString( text.ValueTStr(), &str ); + buffer += str; + } + else + { + DoIndent(); + TIXML_STRING str; + TiXmlBase::EncodeString( text.ValueTStr(), &str ); + buffer += str; + DoLineBreak(); + } + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) +{ + DoIndent(); + declaration.Print( 0, 0, &buffer ); + DoLineBreak(); + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlComment& comment ) +{ + DoIndent(); + buffer += "<!--"; + buffer += comment.Value(); + buffer += "-->"; + DoLineBreak(); + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) +{ + DoIndent(); + buffer += "<"; + buffer += unknown.Value(); + buffer += ">"; + DoLineBreak(); + return true; +} + diff --git a/jni/desmume/src/utils/tinyxml/tinyxml.h b/jni/desmume/src/utils/tinyxml/tinyxml.h new file mode 100755 index 0000000..a3589e5 --- /dev/null +++ b/jni/desmume/src/utils/tinyxml/tinyxml.h @@ -0,0 +1,1805 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code by Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + + +#ifndef TINYXML_INCLUDED +#define TINYXML_INCLUDED + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4530 ) +#pragma warning( disable : 4786 ) +#endif + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +// Help out windows: +#if defined( _DEBUG ) && !defined( DEBUG ) +#define DEBUG +#endif + +#ifdef TIXML_USE_STL + #include <string> + #include <iostream> + #include <sstream> + #define TIXML_STRING std::string +#else + #include "tinystr.h" + #define TIXML_STRING TiXmlString +#endif + +// Deprecated library function hell. Compilers want to use the +// new safe versions. This probably doesn't fully address the problem, +// but it gets closer. There are too many compilers for me to fully +// test. If you get compilation troubles, undefine TIXML_SAFE +#define TIXML_SAFE + +#ifdef TIXML_SAFE + #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + // Microsoft visual studio, version 2005 and higher. + #define TIXML_SNPRINTF _snprintf_s + #define TIXML_SSCANF sscanf_s + #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // Microsoft visual studio, version 6 and higher. + //#pragma message( "Using _sn* functions." ) + #define TIXML_SNPRINTF _snprintf + #define TIXML_SSCANF sscanf + #elif defined(__GNUC__) && (__GNUC__ >= 3 ) + // GCC version 3 and higher.s + //#warning( "Using sn* functions." ) + #define TIXML_SNPRINTF snprintf + #define TIXML_SSCANF sscanf + #else + #define TIXML_SNPRINTF snprintf + #define TIXML_SSCANF sscanf + #endif +#endif + +class TiXmlDocument; +class TiXmlElement; +class TiXmlComment; +class TiXmlUnknown; +class TiXmlAttribute; +class TiXmlText; +class TiXmlDeclaration; +class TiXmlParsingData; + +const int TIXML_MAJOR_VERSION = 2; +const int TIXML_MINOR_VERSION = 6; +const int TIXML_PATCH_VERSION = 2; + +/* Internal structure for tracking location of items + in the XML file. +*/ +struct TiXmlCursor +{ + TiXmlCursor() { Clear(); } + void Clear() { row = col = -1; } + + int row; // 0 based. + int col; // 0 based. +}; + + +/** + Implements the interface to the "Visitor pattern" (see the Accept() method.) + If you call the Accept() method, it requires being passed a TiXmlVisitor + class to handle callbacks. For nodes that contain other nodes (Document, Element) + you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves + are simply called with Visit(). + + If you return 'true' from a Visit method, recursive parsing will continue. If you return + false, <b>no children of this node or its sibilings</b> will be Visited. + + All flavors of Visit methods have a default implementation that returns 'true' (continue + visiting). You need to only override methods that are interesting to you. + + Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. + + You should never change the document from a callback. + + @sa TiXmlNode::Accept() +*/ +class TiXmlVisitor +{ +public: + virtual ~TiXmlVisitor() {} + + /// Visit a document. + virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } + /// Visit a document. + virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } + + /// Visit an element. + virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } + /// Visit an element. + virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } + + /// Visit a declaration + virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } + /// Visit a text node + virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } + /// Visit a comment node + virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } + /// Visit an unknown node + virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } +}; + +// Only used by Attribute::Query functions +enum +{ + TIXML_SUCCESS, + TIXML_NO_ATTRIBUTE, + TIXML_WRONG_TYPE +}; + + +// Used by the parsing routines. +enum TiXmlEncoding +{ + TIXML_ENCODING_UNKNOWN, + TIXML_ENCODING_UTF8, + TIXML_ENCODING_LEGACY +}; + +const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; + +/** TiXmlBase is a base class for every class in TinyXml. + It does little except to establish that TinyXml classes + can be printed and provide some utility functions. + + In XML, the document and elements can contain + other elements and other types of nodes. + + @verbatim + A Document can contain: Element (container or leaf) + Comment (leaf) + Unknown (leaf) + Declaration( leaf ) + + An Element can contain: Element (container or leaf) + Text (leaf) + Attributes (not on tree) + Comment (leaf) + Unknown (leaf) + + A Decleration contains: Attributes (not on tree) + @endverbatim +*/ +class TiXmlBase +{ + friend class TiXmlNode; + friend class TiXmlElement; + friend class TiXmlDocument; + +public: + TiXmlBase() : userData(0) {} + virtual ~TiXmlBase() {} + + /** All TinyXml classes can print themselves to a filestream + or the string class (TiXmlString in non-STL mode, std::string + in STL mode.) Either or both cfile and str can be null. + + This is a formatted print, and will insert + tabs and newlines. + + (For an unformatted stream, use the << operator.) + */ + virtual void Print( FILE* cfile, int depth ) const = 0; + + /** The world does not agree on whether white space should be kept or + not. In order to make everyone happy, these global, static functions + are provided to set whether or not TinyXml will condense all white space + into a single space or not. The default is to condense. Note changing this + value is not thread safe. + */ + static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } + + /// Return the current white space setting. + static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } + + /** Return the position, in the original source file, of this node or attribute. + The row and column are 1-based. (That is the first row and first column is + 1,1). If the returns values are 0 or less, then the parser does not have + a row and column value. + + Generally, the row and column value will be set when the TiXmlDocument::Load(), + TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set + when the DOM was created from operator>>. + + The values reflect the initial load. Once the DOM is modified programmatically + (by adding or changing nodes and attributes) the new values will NOT update to + reflect changes in the document. + + There is a minor performance cost to computing the row and column. Computation + can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. + + @sa TiXmlDocument::SetTabSize() + */ + int Row() const { return location.row + 1; } + int Column() const { return location.col + 1; } ///< See Row() + + void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. + void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. + const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. + + // Table that returs, for a given lead byte, the total number of bytes + // in the UTF-8 sequence. + static const int utf8ByteTable[256]; + + virtual const char* Parse( const char* p, + TiXmlParsingData* data, + TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; + + /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, + or they will be transformed into entities! + */ + static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); + + enum + { + TIXML_NO_ERROR = 0, + TIXML_ERROR, + TIXML_ERROR_OPENING_FILE, + TIXML_ERROR_PARSING_ELEMENT, + TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, + TIXML_ERROR_READING_ELEMENT_VALUE, + TIXML_ERROR_READING_ATTRIBUTES, + TIXML_ERROR_PARSING_EMPTY, + TIXML_ERROR_READING_END_TAG, + TIXML_ERROR_PARSING_UNKNOWN, + TIXML_ERROR_PARSING_COMMENT, + TIXML_ERROR_PARSING_DECLARATION, + TIXML_ERROR_DOCUMENT_EMPTY, + TIXML_ERROR_EMBEDDED_NULL, + TIXML_ERROR_PARSING_CDATA, + TIXML_ERROR_DOCUMENT_TOP_ONLY, + + TIXML_ERROR_STRING_COUNT + }; + +protected: + + static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); + + inline static bool IsWhiteSpace( char c ) + { + return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); + } + inline static bool IsWhiteSpace( int c ) + { + if ( c < 256 ) + return IsWhiteSpace( (char) c ); + return false; // Again, only truly correct for English/Latin...but usually works. + } + + #ifdef TIXML_USE_STL + static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); + static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); + #endif + + /* Reads an XML name into the string provided. Returns + a pointer just past the last character of the name, + or 0 if the function has an error. + */ + static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); + + /* Reads text. Returns a pointer past the given end tag. + Wickedly complex options, but it keeps the (sensitive) code in one place. + */ + static const char* ReadText( const char* in, // where to start + TIXML_STRING* text, // the string read + bool ignoreWhiteSpace, // whether to keep the white space + const char* endTag, // what ends this text + bool ignoreCase, // whether to ignore case in the end tag + TiXmlEncoding encoding ); // the current encoding + + // If an entity has been found, transform it into a character. + static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); + + // Get a character, while interpreting entities. + // The length can be from 0 to 4 bytes. + inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) + { + assert( p ); + if ( encoding == TIXML_ENCODING_UTF8 ) + { + *length = utf8ByteTable[ *((const unsigned char*)p) ]; + assert( *length >= 0 && *length < 5 ); + } + else + { + *length = 1; + } + + if ( *length == 1 ) + { + if ( *p == '&' ) + return GetEntity( p, _value, length, encoding ); + *_value = *p; + return p+1; + } + else if ( *length ) + { + //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), + // and the null terminator isn't needed + for( int i=0; p[i] && i<*length; ++i ) { + _value[i] = p[i]; + } + return p + (*length); + } + else + { + // Not valid text. + return 0; + } + } + + // Return true if the next characters in the stream are any of the endTag sequences. + // Ignore case only works for english, and should only be relied on when comparing + // to English words: StringEqual( p, "version", true ) is fine. + static bool StringEqual( const char* p, + const char* endTag, + bool ignoreCase, + TiXmlEncoding encoding ); + + static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; + + TiXmlCursor location; + + /// Field containing a generic user pointer + void* userData; + + // None of these methods are reliable for any language except English. + // Good for approximation, not great for accuracy. + static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); + static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); + inline static int ToLower( int v, TiXmlEncoding encoding ) + { + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( v < 128 ) return tolower( v ); + return v; + } + else + { + return tolower( v ); + } + } + static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); + +private: + TiXmlBase( const TiXmlBase& ); // not implemented. + void operator=( const TiXmlBase& base ); // not allowed. + + struct Entity + { + const char* str; + unsigned int strLength; + char chr; + }; + enum + { + NUM_ENTITY = 5, + MAX_ENTITY_LENGTH = 6 + + }; + static Entity entity[ NUM_ENTITY ]; + static bool condenseWhiteSpace; +}; + + +/** The parent class for everything in the Document Object Model. + (Except for attributes). + Nodes have siblings, a parent, and children. A node can be + in a document, or stand on its own. The type of a TiXmlNode + can be queried, and it can be cast to its more defined type. +*/ +class TiXmlNode : public TiXmlBase +{ + friend class TiXmlDocument; + friend class TiXmlElement; + +public: + #ifdef TIXML_USE_STL + + /** An input stream operator, for every class. Tolerant of newlines and + formatting, but doesn't expect them. + */ + friend std::istream& operator >> (std::istream& in, TiXmlNode& base); + + /** An output stream operator, for every class. Note that this outputs + without any newlines or formatting, as opposed to Print(), which + includes tabs and new lines. + + The operator<< and operator>> are not completely symmetric. Writing + a node to a stream is very well defined. You'll get a nice stream + of output, without any extra whitespace or newlines. + + But reading is not as well defined. (As it always is.) If you create + a TiXmlElement (for example) and read that from an input stream, + the text needs to define an element or junk will result. This is + true of all input streams, but it's worth keeping in mind. + + A TiXmlDocument will read nodes until it reads a root element, and + all the children of that root element. + */ + friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); + + /// Appends the XML node or attribute to a std::string. + friend std::string& operator<< (std::string& out, const TiXmlNode& base ); + + #endif + + /** The types of XML nodes supported by TinyXml. (All the + unsupported types are picked up by UNKNOWN.) + */ + enum NodeType + { + TINYXML_DOCUMENT, + TINYXML_ELEMENT, + TINYXML_COMMENT, + TINYXML_UNKNOWN, + TINYXML_TEXT, + TINYXML_DECLARATION, + TINYXML_TYPECOUNT + }; + + virtual ~TiXmlNode(); + + /** The meaning of 'value' changes for the specific type of + TiXmlNode. + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + + The subclasses will wrap this function. + */ + const char *Value() const { return value.c_str (); } + + #ifdef TIXML_USE_STL + /** Return Value() as a std::string. If you only use STL, + this is more efficient than calling Value(). + Only available in STL mode. + */ + const std::string& ValueStr() const { return value; } + #endif + + const TIXML_STRING& ValueTStr() const { return value; } + + /** Changes the value of the node. Defined as: + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + */ + void SetValue(const char * _value) { value = _value;} + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Delete all the children of this node. Does not affect 'this'. + void Clear(); + + /// One step up the DOM. + TiXmlNode* Parent() { return parent; } + const TiXmlNode* Parent() const { return parent; } + + const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. + TiXmlNode* FirstChild() { return firstChild; } + const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. + /// The first child of this node with the matching 'value'. Will be null if none found. + TiXmlNode* FirstChild( const char * _value ) { + // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) + // call the method, cast the return back to non-const. + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); + } + const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. + TiXmlNode* LastChild() { return lastChild; } + + const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. + TiXmlNode* LastChild( const char * _value ) { + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. + #endif + + /** An alternate way to walk the children of a node. + One way to iterate over nodes is: + @verbatim + for( child = parent->FirstChild(); child; child = child->NextSibling() ) + @endverbatim + + IterateChildren does the same thing with the syntax: + @verbatim + child = 0; + while( child = parent->IterateChildren( child ) ) + @endverbatim + + IterateChildren takes the previous child as input and finds + the next one. If the previous child is null, it returns the + first. IterateChildren will return null when done. + */ + const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); + } + + /// This flavor of IterateChildren searches for children with a particular 'value' + const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + #endif + + /** Add a new node related to this. Adds a child past the LastChild. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); + + + /** Add a new node related to this. Adds a child past the LastChild. + + NOTE: the node to be added is passed by pointer, and will be + henceforth owned (and deleted) by tinyXml. This method is efficient + and avoids an extra copy, but should be used with care as it + uses a different memory model than the other insert functions. + + @sa InsertEndChild + */ + TiXmlNode* LinkEndChild( TiXmlNode* addThis ); + + /** Add a new node related to this. Adds a child before the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); + + /** Add a new node related to this. Adds a child after the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); + + /** Replace a child of this node. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); + + /// Delete a child of this node. + bool RemoveChild( TiXmlNode* removeThis ); + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling() const { return prev; } + TiXmlNode* PreviousSibling() { return prev; } + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling( const char * ) const; + TiXmlNode* PreviousSibling( const char *_prev ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Navigate to a sibling node. + const TiXmlNode* NextSibling() const { return next; } + TiXmlNode* NextSibling() { return next; } + + /// Navigate to a sibling node with the given 'value'. + const TiXmlNode* NextSibling( const char * ) const; + TiXmlNode* NextSibling( const char* _next ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement() const; + TiXmlElement* NextSiblingElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement( const char * ) const; + TiXmlElement* NextSiblingElement( const char *_next ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement() const; + TiXmlElement* FirstChildElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); + } + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement( const char * _value ) const; + TiXmlElement* FirstChildElement( const char * _value ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /** Query the type (as an enumerated value, above) of this node. + The possible types are: TINYXML_DOCUMENT, TINYXML_ELEMENT, TINYXML_COMMENT, + TINYXML_UNKNOWN, TINYXML_TEXT, and TINYXML_DECLARATION. + */ + int Type() const { return type; } + + /** Return a pointer to the Document this node lives in. + Returns null if not in a document. + */ + const TiXmlDocument* GetDocument() const; + TiXmlDocument* GetDocument() { + return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); + } + + /// Returns true if this node has no children. + bool NoChildren() const { return !firstChild; } + + virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + /** Create an exact duplicate of this node and return it. The memory must be deleted + by the caller. + */ + virtual TiXmlNode* Clone() const = 0; + + /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the + XML tree will be conditionally visited and the host will be called back + via the TiXmlVisitor interface. + + This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse + the XML for the callbacks, so the performance of TinyXML is unchanged by using this + interface versus any other.) + + The interface has been based on ideas from: + + - http://www.saxproject.org/ + - http://c2.com/cgi/wiki?HierarchicalVisitorPattern + + Which are both good references for "visiting". + + An example of using Accept(): + @verbatim + TiXmlPrinter printer; + tinyxmlDoc.Accept( &printer ); + const char* xmlcstr = printer.CStr(); + @endverbatim + */ + virtual bool Accept( TiXmlVisitor* visitor ) const = 0; + +protected: + TiXmlNode( NodeType _type ); + + // Copy to the allocated object. Shared functionality between Clone, Copy constructor, + // and the assignment operator. + void CopyTo( TiXmlNode* target ) const; + + #ifdef TIXML_USE_STL + // The real work of the input operator. + virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; + #endif + + // Figure out what is at *p, and parse it. Returns null if it is not an xml node. + TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); + + TiXmlNode* parent; + NodeType type; + + TiXmlNode* firstChild; + TiXmlNode* lastChild; + + TIXML_STRING value; + + TiXmlNode* prev; + TiXmlNode* next; + +private: + TiXmlNode( const TiXmlNode& ); // not implemented. + void operator=( const TiXmlNode& base ); // not allowed. +}; + + +/** An attribute is a name-value pair. Elements have an arbitrary + number of attributes, each with a unique name. + + @note The attributes are not TiXmlNodes, since they are not + part of the tinyXML document object model. There are other + suggested ways to look at this problem. +*/ +class TiXmlAttribute : public TiXmlBase +{ + friend class TiXmlAttributeSet; + +public: + /// Construct an empty attribute. + TiXmlAttribute() : TiXmlBase() + { + document = 0; + prev = next = 0; + } + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlAttribute( const std::string& _name, const std::string& _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + #endif + + /// Construct an attribute with a name and value. + TiXmlAttribute( const char * _name, const char * _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + + const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. + const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. + #ifdef TIXML_USE_STL + const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. + #endif + int IntValue() const; ///< Return the value of this attribute, converted to an integer. + double DoubleValue() const; ///< Return the value of this attribute, converted to a double. + + // Get the tinyxml string representation + const TIXML_STRING& NameTStr() const { return name; } + + /** QueryIntValue examines the value string. It is an alternative to the + IntValue() method with richer error checking. + If the value is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. + + A specialized but useful call. Note that for success it returns 0, + which is the opposite of almost all other TinyXml calls. + */ + int QueryIntValue( int* _value ) const; + /// QueryDoubleValue examines the value string. See QueryIntValue(). + int QueryDoubleValue( double* _value ) const; + + void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. + void SetValue( const char* _value ) { value = _value; } ///< Set the value. + + void SetIntValue( int _value ); ///< Set the value from an integer. + void SetDoubleValue( double _value ); ///< Set the value from a double. + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetName( const std::string& _name ) { name = _name; } + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Get the next sibling attribute in the DOM. Returns null at end. + const TiXmlAttribute* Next() const; + TiXmlAttribute* Next() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); + } + + /// Get the previous sibling attribute in the DOM. Returns null at beginning. + const TiXmlAttribute* Previous() const; + TiXmlAttribute* Previous() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); + } + + bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } + bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } + bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } + + /* Attribute parsing starts: first letter of the name + returns: the next char after the value end quote + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + // Prints this Attribute to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + + // [internal use] + // Set the document pointer so the attribute can report errors. + void SetDocument( TiXmlDocument* doc ) { document = doc; } + +private: + TiXmlAttribute( const TiXmlAttribute& ); // not implemented. + void operator=( const TiXmlAttribute& base ); // not allowed. + + TiXmlDocument* document; // A pointer back to a document, for error reporting. + TIXML_STRING name; + TIXML_STRING value; + TiXmlAttribute* prev; + TiXmlAttribute* next; +}; + + +/* A class used to manage a group of attributes. + It is only used internally, both by the ELEMENT and the DECLARATION. + + The set can be changed transparent to the Element and Declaration + classes that use it, but NOT transparent to the Attribute + which has to implement a next() and previous() method. Which makes + it a bit problematic and prevents the use of STL. + + This version is implemented with circular lists because: + - I like circular lists + - it demonstrates some independence from the (typical) doubly linked list. +*/ +class TiXmlAttributeSet +{ +public: + TiXmlAttributeSet(); + ~TiXmlAttributeSet(); + + void Add( TiXmlAttribute* attribute ); + void Remove( TiXmlAttribute* attribute ); + + const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + + TiXmlAttribute* Find( const char* _name ) const; + TiXmlAttribute* FindOrCreate( const char* _name ); + +# ifdef TIXML_USE_STL + TiXmlAttribute* Find( const std::string& _name ) const; + TiXmlAttribute* FindOrCreate( const std::string& _name ); +# endif + + +private: + //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), + //*ME: this class must be also use a hidden/disabled copy-constructor !!! + TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed + void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) + + TiXmlAttribute sentinel; +}; + + +/** The element is a container class. It has a value, the element name, + and can contain other elements, text, comments, and unknowns. + Elements also contain an arbitrary number of attributes. +*/ +class TiXmlElement : public TiXmlNode +{ +public: + /// Construct an element. + TiXmlElement (const char * in_value); + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlElement( const std::string& _value ); + #endif + + TiXmlElement( const TiXmlElement& ); + + TiXmlElement& operator=( const TiXmlElement& base ); + + virtual ~TiXmlElement(); + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + */ + const char* Attribute( const char* name ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an integer, + the integer value will be put in the return 'i', if 'i' + is non-null. + */ + const char* Attribute( const char* name, int* i ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an double, + the double value will be put in the return 'd', if 'd' + is non-null. + */ + const char* Attribute( const char* name, double* d ) const; + + /** QueryIntAttribute examines the attribute - it is an alternative to the + Attribute() method with richer error checking. + If the attribute is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. If the attribute + does not exist, then TIXML_NO_ATTRIBUTE is returned. + */ + int QueryIntAttribute( const char* name, int* _value ) const; + /// QueryUnsignedAttribute examines the attribute - see QueryIntAttribute(). + int QueryUnsignedAttribute( const char* name, unsigned* _value ) const; + /** QueryBoolAttribute examines the attribute - see QueryIntAttribute(). + Note that '1', 'true', or 'yes' are considered true, while '0', 'false' + and 'no' are considered false. + */ + int QueryBoolAttribute( const char* name, bool* _value ) const; + /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). + int QueryDoubleAttribute( const char* name, double* _value ) const; + /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). + int QueryFloatAttribute( const char* name, float* _value ) const { + double d; + int result = QueryDoubleAttribute( name, &d ); + if ( result == TIXML_SUCCESS ) { + *_value = (float)d; + } + return result; + } + + #ifdef TIXML_USE_STL + /// QueryStringAttribute examines the attribute - see QueryIntAttribute(). + int QueryStringAttribute( const char* name, std::string* _value ) const { + const char* cstr = Attribute( name ); + if ( cstr ) { + *_value = std::string( cstr ); + return TIXML_SUCCESS; + } + return TIXML_NO_ATTRIBUTE; + } + + /** Template form of the attribute query which will try to read the + attribute into the specified type. Very easy, very powerful, but + be careful to make sure to call this with the correct type. + + NOTE: This method doesn't work correctly for 'string' types that contain spaces. + + @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE + */ + template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + + std::stringstream sstream( node->ValueStr() ); + sstream >> *outValue; + if ( !sstream.fail() ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; + } + + int QueryValueAttribute( const std::string& name, std::string* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + *outValue = node->ValueStr(); + return TIXML_SUCCESS; + } + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char* name, const char * _value ); + + #ifdef TIXML_USE_STL + const std::string* Attribute( const std::string& name ) const; + const std::string* Attribute( const std::string& name, int* i ) const; + const std::string* Attribute( const std::string& name, double* d ) const; + int QueryIntAttribute( const std::string& name, int* _value ) const; + int QueryDoubleAttribute( const std::string& name, double* _value ) const; + + /// STL std::string form. + void SetAttribute( const std::string& name, const std::string& _value ); + ///< STL std::string form. + void SetAttribute( const std::string& name, int _value ); + ///< STL std::string form. + void SetDoubleAttribute( const std::string& name, double value ); + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char * name, int value ); + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetDoubleAttribute( const char * name, double value ); + + /** Deletes an attribute with the given name. + */ + void RemoveAttribute( const char * name ); + #ifdef TIXML_USE_STL + void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. + #endif + + const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. + TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } + const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. + TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, GetText() is limited compared to getting the TiXmlText child + and accessing it directly. + + If the first child of 'this' is a TiXmlText, the GetText() + returns the character string of the Text node, else null is returned. + + This is a convenient method for getting the text of simple contained text: + @verbatim + <foo>This is text</foo> + const char* str = fooElement->GetText(); + @endverbatim + + 'str' will be a pointer to "This is text". + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + <foo><b>This is text</b></foo> + @endverbatim + + then the value of str would be null. The first child node isn't a text node, it is + another element. From this XML: + @verbatim + <foo>This is <b>text</b></foo> + @endverbatim + GetText() will return "This is ". + + WARNING: GetText() accesses a child node - don't become confused with the + similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are + safe type casts on the referenced node. + */ + const char* GetText() const; + + /// Creates a new Element and returns it - the returned element is a copy. + virtual TiXmlNode* Clone() const; + // Print the Element to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: next char past '<' + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + + void CopyTo( TiXmlElement* target ) const; + void ClearThis(); // like clear, but initializes 'this' object as well + + // Used to be public [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + /* [internal use] + Reads the "value" of the element -- another element, or text. + This should terminate with the current end tag. + */ + const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + +private: + TiXmlAttributeSet attributeSet; +}; + + +/** An XML comment. +*/ +class TiXmlComment : public TiXmlNode +{ +public: + /// Constructs an empty comment. + TiXmlComment() : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {} + /// Construct a comment from text. + TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) { + SetValue( _value ); + } + TiXmlComment( const TiXmlComment& ); + TiXmlComment& operator=( const TiXmlComment& base ); + + virtual ~TiXmlComment() {} + + /// Returns a copy of this Comment. + virtual TiXmlNode* Clone() const; + // Write this Comment to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: at the ! of the !-- + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlComment* target ) const; + + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif +// virtual void StreamOut( TIXML_OSTREAM * out ) const; + +private: + +}; + + +/** XML text. A text node can have 2 ways to output the next. "normal" output + and CDATA. It will default to the mode it was parsed from the XML file and + you generally want to leave it alone, but you can change the output mode with + SetCDATA() and query it with CDATA(). +*/ +class TiXmlText : public TiXmlNode +{ + friend class TiXmlElement; +public: + /** Constructor for text element. By default, it is treated as + normal, encoded text. If you want it be output as a CDATA text + element, set the parameter _cdata to 'true' + */ + TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) + { + SetValue( initValue ); + cdata = false; + } + virtual ~TiXmlText() {} + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) + { + SetValue( initValue ); + cdata = false; + } + #endif + + TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TINYXML_TEXT ) { copy.CopyTo( this ); } + TiXmlText& operator=( const TiXmlText& base ) { base.CopyTo( this ); return *this; } + + // Write this text object to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /// Queries whether this represents text using a CDATA section. + bool CDATA() const { return cdata; } + /// Turns on or off a CDATA representation of text. + void SetCDATA( bool _cdata ) { cdata = _cdata; } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + /// [internal use] Creates a new Element and returns it. + virtual TiXmlNode* Clone() const; + void CopyTo( TiXmlText* target ) const; + + bool Blank() const; // returns true if all white space and new lines + // [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + bool cdata; // true if this should be input and output as a CDATA style text element +}; + + +/** In correct XML the declaration is the first entry in the file. + @verbatim + <?xml version="1.0" standalone="yes"?> + @endverbatim + + TinyXml will happily read or write files without a declaration, + however. There are 3 possible attributes to the declaration: + version, encoding, and standalone. + + Note: In this version of the code, the attributes are + handled as special cases, not generic attributes, simply + because there can only be at most 3 and they are always the same. +*/ +class TiXmlDeclaration : public TiXmlNode +{ +public: + /// Construct an empty declaration. + TiXmlDeclaration() : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {} + +#ifdef TIXML_USE_STL + /// Constructor. + TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ); +#endif + + /// Construct. + TiXmlDeclaration( const char* _version, + const char* _encoding, + const char* _standalone ); + + TiXmlDeclaration( const TiXmlDeclaration& copy ); + TiXmlDeclaration& operator=( const TiXmlDeclaration& copy ); + + virtual ~TiXmlDeclaration() {} + + /// Version. Will return an empty string if none was found. + const char *Version() const { return version.c_str (); } + /// Encoding. Will return an empty string if none was found. + const char *Encoding() const { return encoding.c_str (); } + /// Is this a standalone document? + const char *Standalone() const { return standalone.c_str (); } + + /// Creates a copy of this Declaration and returns it. + virtual TiXmlNode* Clone() const; + // Print this declaration to a FILE stream. + virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlDeclaration* target ) const; + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + + TIXML_STRING version; + TIXML_STRING encoding; + TIXML_STRING standalone; +}; + + +/** Any tag that tinyXml doesn't recognize is saved as an + unknown. It is a tag of text, but should not be modified. + It will be written back to the XML, unchanged, when the file + is saved. + + DTD tags get thrown into TiXmlUnknowns. +*/ +class TiXmlUnknown : public TiXmlNode +{ +public: + TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {} + virtual ~TiXmlUnknown() {} + + TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) { copy.CopyTo( this ); } + TiXmlUnknown& operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); return *this; } + + /// Creates a copy of this Unknown and returns it. + virtual TiXmlNode* Clone() const; + // Print this Unknown to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected: + void CopyTo( TiXmlUnknown* target ) const; + + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + +}; + + +/** Always the top level node. A document binds together all the + XML pieces. It can be saved, loaded, and printed to the screen. + The 'value' of a document node is the xml file name. +*/ +class TiXmlDocument : public TiXmlNode +{ +public: + /// Create an empty document, that has no name. + TiXmlDocument(); + /// Create a document with a name. The name of the document is also the filename of the xml. + TiXmlDocument( const char * documentName ); + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlDocument( const std::string& documentName ); + #endif + + TiXmlDocument( const TiXmlDocument& copy ); + TiXmlDocument& operator=( const TiXmlDocument& copy ); + + virtual ~TiXmlDocument() {} + + /** Load a file using the current document value. + Returns true if successful. Will delete any existing + document data before loading. + */ + bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the current document value. Returns true if successful. + bool SaveFile() const; + /// Load a file using the given filename. Returns true if successful. + bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given filename. Returns true if successful. + bool SaveFile( const char * filename ) const; + /** Load a file using the given FILE*. Returns true if successful. Note that this method + doesn't stream - the entire object pointed at by the FILE* + will be interpreted as an XML file. TinyXML doesn't stream in XML from the current + file location. Streaming may be added in the future. + */ + bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given FILE*. Returns true if successful. + bool SaveFile( FILE* ) const; + + #ifdef TIXML_USE_STL + bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. + { + return LoadFile( filename.c_str(), encoding ); + } + bool SaveFile( const std::string& filename ) const ///< STL std::string version. + { + return SaveFile( filename.c_str() ); + } + #endif + + /** Parse the given null terminated block of xml data. Passing in an encoding to this + method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml + to use that encoding, regardless of what TinyXml might otherwise try to detect. + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + + /** Get the root element -- the only top level element -- of the document. + In well formed XML, there should only be one. TinyXml is tolerant of + multiple elements at the document level. + */ + const TiXmlElement* RootElement() const { return FirstChildElement(); } + TiXmlElement* RootElement() { return FirstChildElement(); } + + /** If an error occurs, Error will be set to true. Also, + - The ErrorId() will contain the integer identifier of the error (not generally useful) + - The ErrorDesc() method will return the name of the error. (very useful) + - The ErrorRow() and ErrorCol() will return the location of the error (if known) + */ + bool Error() const { return error; } + + /// Contains a textual (english) description of the error if one occurs. + const char * ErrorDesc() const { return errorDesc.c_str (); } + + /** Generally, you probably want the error string ( ErrorDesc() ). But if you + prefer the ErrorId, this function will fetch it. + */ + int ErrorId() const { return errorId; } + + /** Returns the location (if known) of the error. The first column is column 1, + and the first row is row 1. A value of 0 means the row and column wasn't applicable + (memory errors, for example, have no row/column) or the parser lost the error. (An + error in the error reporting, in that case.) + + @sa SetTabSize, Row, Column + */ + int ErrorRow() const { return errorLocation.row+1; } + int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() + + /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) + to report the correct values for row and column. It does not change the output + or input in any way. + + By calling this method, with a tab size + greater than 0, the row and column of each node and attribute is stored + when the file is loaded. Very useful for tracking the DOM back in to + the source file. + + The tab size is required for calculating the location of nodes. If not + set, the default of 4 is used. The tabsize is set per document. Setting + the tabsize to 0 disables row/column tracking. + + Note that row and column tracking is not supported when using operator>>. + + The tab size needs to be enabled before the parse or load. Correct usage: + @verbatim + TiXmlDocument doc; + doc.SetTabSize( 8 ); + doc.Load( "myfile.xml" ); + @endverbatim + + @sa Row, Column + */ + void SetTabSize( int _tabsize ) { tabsize = _tabsize; } + + int TabSize() const { return tabsize; } + + /** If you have handled the error, it can be reset with this call. The error + state is automatically cleared if you Parse a new XML block. + */ + void ClearError() { error = false; + errorId = 0; + errorDesc = ""; + errorLocation.row = errorLocation.col = 0; + //errorLocation.last = 0; + } + + /** Write the document to standard out using formatted printing ("pretty print"). */ + void Print() const { Print( stdout, 0 ); } + + /* Write the document to a string using formatted printing ("pretty print"). This + will allocate a character array (new char[]) and return it as a pointer. The + calling code pust call delete[] on the return char* to avoid a memory leak. + */ + //char* PrintToMemory() const; + + /// Print this Document to a FILE stream. + virtual void Print( FILE* cfile, int depth = 0 ) const; + // [internal use] + void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + + virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + // [internal use] + virtual TiXmlNode* Clone() const; + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + void CopyTo( TiXmlDocument* target ) const; + + bool error; + int errorId; + TIXML_STRING errorDesc; + int tabsize; + TiXmlCursor errorLocation; + bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. +}; + + +/** + A TiXmlHandle is a class that wraps a node pointer with null checks; this is + an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml + DOM structure. It is a separate utility class. + + Take an example: + @verbatim + <Document> + <Element attributeA = "valueA"> + <Child attributeB = "value1" /> + <Child attributeB = "value2" /> + </Element> + <Document> + @endverbatim + + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + easy to write a *lot* of code that looks like: + + @verbatim + TiXmlElement* root = document.FirstChildElement( "Document" ); + if ( root ) + { + TiXmlElement* element = root->FirstChildElement( "Element" ); + if ( element ) + { + TiXmlElement* child = element->FirstChildElement( "Child" ); + if ( child ) + { + TiXmlElement* child2 = child->NextSiblingElement( "Child" ); + if ( child2 ) + { + // Finally do something useful. + @endverbatim + + And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity + of such code. A TiXmlHandle checks for null pointers so it is perfectly safe + and correct to use: + + @verbatim + TiXmlHandle docHandle( &document ); + TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); + if ( child2 ) + { + // do something useful + @endverbatim + + Which is MUCH more concise and useful. + + It is also safe to copy handles - internally they are nothing more than node pointers. + @verbatim + TiXmlHandle handleCopy = handle; + @endverbatim + + What they should not be used for is iteration: + + @verbatim + int i=0; + while ( true ) + { + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); + if ( !child ) + break; + // do something + ++i; + } + @endverbatim + + It seems reasonable, but it is in fact two embedded while loops. The Child method is + a linear walk to find the element, so this code would iterate much more than it needs + to. Instead, prefer: + + @verbatim + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); + + for( child; child; child=child->NextSiblingElement() ) + { + // do something + } + @endverbatim +*/ +class TiXmlHandle +{ +public: + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } + /// Copy constructor + TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } + TiXmlHandle operator=( const TiXmlHandle& ref ) { if ( &ref != this ) this->node = ref.node; return *this; } + + /// Return a handle to the first child node. + TiXmlHandle FirstChild() const; + /// Return a handle to the first child node with the given name. + TiXmlHandle FirstChild( const char * value ) const; + /// Return a handle to the first child element. + TiXmlHandle FirstChildElement() const; + /// Return a handle to the first child element with the given name. + TiXmlHandle FirstChildElement( const char * value ) const; + + /** Return a handle to the "index" child with the given name. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( const char* value, int index ) const; + /** Return a handle to the "index" child. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( int index ) const; + /** Return a handle to the "index" child element with the given name. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( const char* value, int index ) const; + /** Return a handle to the "index" child element. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( int index ) const; + + #ifdef TIXML_USE_STL + TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } + TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } + + TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } + TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } + #endif + + /** Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* ToNode() const { return node; } + /** Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } + /** Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } + /** Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } + + /** @deprecated use ToNode. + Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* Node() const { return ToNode(); } + /** @deprecated use ToElement. + Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* Element() const { return ToElement(); } + /** @deprecated use ToText() + Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* Text() const { return ToText(); } + /** @deprecated use ToUnknown() + Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* Unknown() const { return ToUnknown(); } + +private: + TiXmlNode* node; +}; + + +/** Print to memory functionality. The TiXmlPrinter is useful when you need to: + + -# Print to memory (especially in non-STL mode) + -# Control formatting (line endings, etc.) + + When constructed, the TiXmlPrinter is in its default "pretty printing" mode. + Before calling Accept() you can call methods to control the printing + of the XML document. After TiXmlNode::Accept() is called, the printed document can + be accessed via the CStr(), Str(), and Size() methods. + + TiXmlPrinter uses the Visitor API. + @verbatim + TiXmlPrinter printer; + printer.SetIndent( "\t" ); + + doc.Accept( &printer ); + fprintf( stdout, "%s", printer.CStr() ); + @endverbatim +*/ +class TiXmlPrinter : public TiXmlVisitor +{ +public: + TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), + buffer(), indent( " " ), lineBreak( "\n" ) {} + + virtual bool VisitEnter( const TiXmlDocument& doc ); + virtual bool VisitExit( const TiXmlDocument& doc ); + + virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); + virtual bool VisitExit( const TiXmlElement& element ); + + virtual bool Visit( const TiXmlDeclaration& declaration ); + virtual bool Visit( const TiXmlText& text ); + virtual bool Visit( const TiXmlComment& comment ); + virtual bool Visit( const TiXmlUnknown& unknown ); + + /** Set the indent characters for printing. By default 4 spaces + but tab (\t) is also useful, or null/empty string for no indentation. + */ + void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } + /// Query the indention string. + const char* Indent() { return indent.c_str(); } + /** Set the line breaking string. By default set to newline (\n). + Some operating systems prefer other characters, or can be + set to the null/empty string for no indenation. + */ + void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } + /// Query the current line breaking string. + const char* LineBreak() { return lineBreak.c_str(); } + + /** Switch over to "stream printing" which is the most dense formatting without + linebreaks. Common when the XML is needed for network transmission. + */ + void SetStreamPrinting() { indent = ""; + lineBreak = ""; + } + /// Return the result. + const char* CStr() { return buffer.c_str(); } + /// Return the length of the result string. + size_t Size() { return buffer.size(); } + + #ifdef TIXML_USE_STL + /// Return the result. + const std::string& Str() { return buffer; } + #endif + +private: + void DoIndent() { + for( int i=0; i<depth; ++i ) + buffer += indent; + } + void DoLineBreak() { + buffer += lineBreak; + } + + int depth; + bool simpleTextPrint; + TIXML_STRING buffer; + TIXML_STRING indent; + TIXML_STRING lineBreak; +}; + + +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + +#endif diff --git a/jni/desmume/src/utils/tinyxml/tinyxmlerror.cpp b/jni/desmume/src/utils/tinyxml/tinyxmlerror.cpp new file mode 100755 index 0000000..538c21d --- /dev/null +++ b/jni/desmume/src/utils/tinyxml/tinyxmlerror.cpp @@ -0,0 +1,52 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include "tinyxml.h" + +// The goal of the seperate error file is to make the first +// step towards localization. tinyxml (currently) only supports +// english error messages, but the could now be translated. +// +// It also cleans up the code a bit. +// + +const char* TiXmlBase::errorString[ TiXmlBase::TIXML_ERROR_STRING_COUNT ] = +{ + "No error", + "Error", + "Failed to open file", + "Error parsing Element.", + "Failed to read Element name", + "Error reading Element value.", + "Error reading Attributes.", + "Error: empty tag.", + "Error reading end tag.", + "Error parsing Unknown.", + "Error parsing Comment.", + "Error parsing Declaration.", + "Error document empty.", + "Error null (0) or unexpected EOF found in input stream.", + "Error parsing CDATA.", + "Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.", +}; diff --git a/jni/desmume/src/utils/tinyxml/tinyxmlparser.cpp b/jni/desmume/src/utils/tinyxml/tinyxmlparser.cpp new file mode 100755 index 0000000..81b7eae --- /dev/null +++ b/jni/desmume/src/utils/tinyxml/tinyxmlparser.cpp @@ -0,0 +1,1638 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code by Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include <ctype.h> +#include <stddef.h> + +#include "tinyxml.h" + +//#define DEBUG_PARSER +#if defined( DEBUG_PARSER ) +# if defined( DEBUG ) && defined( _MSC_VER ) +# include <windows.h> +# define TIXML_LOG OutputDebugString +# else +# define TIXML_LOG printf +# endif +#endif + +// Note tha "PutString" hardcodes the same list. This +// is less flexible than it appears. Changing the entries +// or order will break putstring. +TiXmlBase::Entity TiXmlBase::entity[ TiXmlBase::NUM_ENTITY ] = +{ + { "&", 5, '&' }, + { "<", 4, '<' }, + { ">", 4, '>' }, + { """, 6, '\"' }, + { "'", 6, '\'' } +}; + +// Bunch of unicode info at: +// http://www.unicode.org/faq/utf_bom.html +// Including the basic of this table, which determines the #bytes in the +// sequence from the lead byte. 1 placed for invalid sequences -- +// although the result will be junk, pass it through as much as possible. +// Beware of the non-characters in UTF-8: +// ef bb bf (Microsoft "lead bytes") +// ef bf be +// ef bf bf + +const unsigned char TIXML_UTF_LEAD_0 = 0xefU; +const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; +const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + +const int TiXmlBase::utf8ByteTable[256] = +{ + // 0 1 2 3 4 5 6 7 8 9 a b c d e f + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte + 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid +}; + + +void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) +{ + const unsigned long BYTE_MASK = 0xBF; + const unsigned long BYTE_MARK = 0x80; + const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + + if (input < 0x80) + *length = 1; + else if ( input < 0x800 ) + *length = 2; + else if ( input < 0x10000 ) + *length = 3; + else if ( input < 0x200000 ) + *length = 4; + else + { *length = 0; return; } // This code won't covert this correctly anyway. + + output += *length; + + // Scary scary fall throughs. + switch (*length) + { + case 4: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 3: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 2: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 1: + --output; + *output = (char)(input | FIRST_BYTE_MARK[*length]); + } +} + + +/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) +{ + // This will only work for low-ascii, everything else is assumed to be a valid + // letter. I'm not sure this is the best approach, but it is quite tricky trying + // to figure out alhabetical vs. not across encoding. So take a very + // conservative approach. + +// if ( encoding == TIXML_ENCODING_UTF8 ) +// { + if ( anyByte < 127 ) + return isalpha( anyByte ); + else + return 1; // What else to do? The unicode set is huge...get the english ones right. +// } +// else +// { +// return isalpha( anyByte ); +// } +} + + +/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) +{ + // This will only work for low-ascii, everything else is assumed to be a valid + // letter. I'm not sure this is the best approach, but it is quite tricky trying + // to figure out alhabetical vs. not across encoding. So take a very + // conservative approach. + +// if ( encoding == TIXML_ENCODING_UTF8 ) +// { + if ( anyByte < 127 ) + return isalnum( anyByte ); + else + return 1; // What else to do? The unicode set is huge...get the english ones right. +// } +// else +// { +// return isalnum( anyByte ); +// } +} + + +class TiXmlParsingData +{ + friend class TiXmlDocument; + public: + void Stamp( const char* now, TiXmlEncoding encoding ); + + const TiXmlCursor& Cursor() const { return cursor; } + + private: + // Only used by the document! + TiXmlParsingData( const char* start, int _tabsize, int row, int col ) + { + assert( start ); + stamp = start; + tabsize = _tabsize; + cursor.row = row; + cursor.col = col; + } + + TiXmlCursor cursor; + const char* stamp; + int tabsize; +}; + + +void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) +{ + assert( now ); + + // Do nothing if the tabsize is 0. + if ( tabsize < 1 ) + { + return; + } + + // Get the current row, column. + int row = cursor.row; + int col = cursor.col; + const char* p = stamp; + assert( p ); + + while ( p < now ) + { + // Treat p as unsigned, so we have a happy compiler. + const unsigned char* pU = (const unsigned char*)p; + + // Code contributed by Fletcher Dunn: (modified by lee) + switch (*pU) { + case 0: + // We *should* never get here, but in case we do, don't + // advance past the terminating null character, ever + return; + + case '\r': + // bump down to the next line + ++row; + col = 0; + // Eat the character + ++p; + + // Check for \r\n sequence, and treat this as a single character + if (*p == '\n') { + ++p; + } + break; + + case '\n': + // bump down to the next line + ++row; + col = 0; + + // Eat the character + ++p; + + // Check for \n\r sequence, and treat this as a single + // character. (Yes, this bizarre thing does occur still + // on some arcane platforms...) + if (*p == '\r') { + ++p; + } + break; + + case '\t': + // Eat the character + ++p; + + // Skip to next tab stop + col = (col / tabsize + 1) * tabsize; + break; + + case TIXML_UTF_LEAD_0: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( *(p+1) && *(p+2) ) + { + // In these cases, don't advance the column. These are + // 0-width spaces. + if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) + p += 3; + else + { p +=3; ++col; } // A normal character. + } + } + else + { + ++p; + ++col; + } + break; + + default: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // Eat the 1 to 4 byte utf8 character. + int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; + if ( step == 0 ) + step = 1; // Error case from bad encoding, but handle gracefully. + p += step; + + // Just advance one column, of course. + ++col; + } + else + { + ++p; + ++col; + } + break; + } + } + cursor.row = row; + cursor.col = col; + assert( cursor.row >= -1 ); + assert( cursor.col >= -1 ); + stamp = p; + assert( stamp ); +} + + +const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) +{ + if ( !p || !*p ) + { + return 0; + } + if ( encoding == TIXML_ENCODING_UTF8 ) + { + while ( *p ) + { + const unsigned char* pU = (const unsigned char*)p; + + // Skip the stupid Microsoft UTF-8 Byte order marks + if ( *(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==TIXML_UTF_LEAD_1 + && *(pU+2)==TIXML_UTF_LEAD_2 ) + { + p += 3; + continue; + } + else if(*(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==0xbfU + && *(pU+2)==0xbeU ) + { + p += 3; + continue; + } + else if(*(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==0xbfU + && *(pU+2)==0xbfU ) + { + p += 3; + continue; + } + + if ( IsWhiteSpace( *p ) ) // Still using old rules for white space. + ++p; + else + break; + } + } + else + { + while ( *p && IsWhiteSpace( *p ) ) + ++p; + } + + return p; +} + +#ifdef TIXML_USE_STL +/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) +{ + for( ;; ) + { + if ( !in->good() ) return false; + + int c = in->peek(); + // At this scope, we can't get to a document. So fail silently. + if ( !IsWhiteSpace( c ) || c <= 0 ) + return true; + + *tag += (char) in->get(); + } +} + +/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) +{ + //assert( character > 0 && character < 128 ); // else it won't work in utf-8 + while ( in->good() ) + { + int c = in->peek(); + if ( c == character ) + return true; + if ( c <= 0 ) // Silent failure: can't get document at this scope + return false; + + in->get(); + *tag += (char) c; + } + return false; +} +#endif + +// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The +// "assign" optimization removes over 10% of the execution time. +// +const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) +{ + // Oddly, not supported on some comilers, + //name->clear(); + // So use this: + *name = ""; + assert( p ); + + // Names start with letters or underscores. + // Of course, in unicode, tinyxml has no idea what a letter *is*. The + // algorithm is generous. + // + // After that, they can be letters, underscores, numbers, + // hyphens, or colons. (Colons are valid ony for namespaces, + // but tinyxml can't tell namespaces from names.) + if ( p && *p + && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) + { + const char* start = p; + while( p && *p + && ( IsAlphaNum( (unsigned char ) *p, encoding ) + || *p == '_' + || *p == '-' + || *p == '.' + || *p == ':' ) ) + { + //(*name) += *p; // expensive + ++p; + } + if ( p-start > 0 ) { + name->assign( start, p-start ); + } + return p; + } + return 0; +} + +const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) +{ + // Presume an entity, and pull it out. + TIXML_STRING ent; + int i; + *length = 0; + + if ( *(p+1) && *(p+1) == '#' && *(p+2) ) + { + unsigned long ucs = 0; + ptrdiff_t delta = 0; + unsigned mult = 1; + + if ( *(p+2) == 'x' ) + { + // Hexadecimal. + if ( !*(p+3) ) return 0; + + const char* q = p+3; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != 'x' ) + { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else if ( *q >= 'a' && *q <= 'f' ) + ucs += mult * (*q - 'a' + 10); + else if ( *q >= 'A' && *q <= 'F' ) + ucs += mult * (*q - 'A' + 10 ); + else + return 0; + mult *= 16; + --q; + } + } + else + { + // Decimal. + if ( !*(p+2) ) return 0; + + const char* q = p+2; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != '#' ) + { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else + return 0; + mult *= 10; + --q; + } + } + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // convert the UCS to UTF-8 + ConvertUTF32ToUTF8( ucs, value, length ); + } + else + { + *value = (char)ucs; + *length = 1; + } + return p + delta + 1; + } + + // Now try to match it. + for( i=0; i<NUM_ENTITY; ++i ) + { + if ( strncmp( entity[i].str, p, entity[i].strLength ) == 0 ) + { + assert( strlen( entity[i].str ) == entity[i].strLength ); + *value = entity[i].chr; + *length = 1; + return ( p + entity[i].strLength ); + } + } + + // So it wasn't an entity, its unrecognized, or something like that. + *value = *p; // Don't put back the last one, since we return it! + //*length = 1; // Leave unrecognized entities - this doesn't really work. + // Just writes strange XML. + return p+1; +} + + +bool TiXmlBase::StringEqual( const char* p, + const char* tag, + bool ignoreCase, + TiXmlEncoding encoding ) +{ + assert( p ); + assert( tag ); + if ( !p || !*p ) + { + assert( 0 ); + return false; + } + + const char* q = p; + + if ( ignoreCase ) + { + while ( *q && *tag && ToLower( *q, encoding ) == ToLower( *tag, encoding ) ) + { + ++q; + ++tag; + } + + if ( *tag == 0 ) + return true; + } + else + { + while ( *q && *tag && *q == *tag ) + { + ++q; + ++tag; + } + + if ( *tag == 0 ) // Have we found the end of the tag, and everything equal? + return true; + } + return false; +} + +const char* TiXmlBase::ReadText( const char* p, + TIXML_STRING * text, + bool trimWhiteSpace, + const char* endTag, + bool caseInsensitive, + TiXmlEncoding encoding ) +{ + *text = ""; + if ( !trimWhiteSpace // certain tags always keep whitespace + || !condenseWhiteSpace ) // if true, whitespace is always kept + { + // Keep all the white space. + while ( p && *p + && !StringEqual( p, endTag, caseInsensitive, encoding ) + ) + { + int len; + char cArr[4] = { 0, 0, 0, 0 }; + p = GetChar( p, cArr, &len, encoding ); + text->append( cArr, len ); + } + } + else + { + bool whitespace = false; + + // Remove leading white space: + p = SkipWhiteSpace( p, encoding ); + while ( p && *p + && !StringEqual( p, endTag, caseInsensitive, encoding ) ) + { + if ( *p == '\r' || *p == '\n' ) + { + whitespace = true; + ++p; + } + else if ( IsWhiteSpace( *p ) ) + { + whitespace = true; + ++p; + } + else + { + // If we've found whitespace, add it before the + // new character. Any whitespace just becomes a space. + if ( whitespace ) + { + (*text) += ' '; + whitespace = false; + } + int len; + char cArr[4] = { 0, 0, 0, 0 }; + p = GetChar( p, cArr, &len, encoding ); + if ( len == 1 ) + (*text) += cArr[0]; // more efficient + else + text->append( cArr, len ); + } + } + } + if ( p && *p ) + p += strlen( endTag ); + return ( p && *p ) ? p : 0; +} + +#ifdef TIXML_USE_STL + +void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + // The basic issue with a document is that we don't know what we're + // streaming. Read something presumed to be a tag (and hope), then + // identify it, and call the appropriate stream method on the tag. + // + // This "pre-streaming" will never read the closing ">" so the + // sub-tag can orient itself. + + if ( !StreamTo( in, '<', tag ) ) + { + SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + while ( in->good() ) + { + int tagIndex = (int) tag->length(); + while ( in->good() && in->peek() != '>' ) + { + int c = in->get(); + if ( c <= 0 ) + { + SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + break; + } + (*tag) += (char) c; + } + + if ( in->good() ) + { + // We now have something we presume to be a node of + // some sort. Identify it, and call the node to + // continue streaming. + TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); + + if ( node ) + { + node->StreamIn( in, tag ); + bool isElement = node->ToElement() != 0; + delete node; + node = 0; + + // If this is the root element, we're done. Parsing will be + // done by the >> operator. + if ( isElement ) + { + return; + } + } + else + { + SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + } + } + // We should have returned sooner. + SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); +} + +#endif + +const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) +{ + ClearError(); + + // Parse away, at the document level. Since a document + // contains nothing but other tags, most of what happens + // here is skipping white space. + if ( !p || !*p ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + // Note that, for a document, this needs to come + // before the while space skip, so that parsing + // starts from the pointer we are given. + location.Clear(); + if ( prevData ) + { + location.row = prevData->cursor.row; + location.col = prevData->cursor.col; + } + else + { + location.row = 0; + location.col = 0; + } + TiXmlParsingData data( p, TabSize(), location.row, location.col ); + location = data.Cursor(); + + if ( encoding == TIXML_ENCODING_UNKNOWN ) + { + // Check for the Microsoft UTF-8 lead bytes. + const unsigned char* pU = (const unsigned char*)p; + if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 + && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 + && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) + { + encoding = TIXML_ENCODING_UTF8; + useMicrosoftBOM = true; + } + } + + p = SkipWhiteSpace( p, encoding ); + if ( !p ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + while ( p && *p ) + { + TiXmlNode* node = Identify( p, encoding ); + if ( node ) + { + p = node->Parse( p, &data, encoding ); + LinkEndChild( node ); + } + else + { + break; + } + + // Did we get encoding info? + if ( encoding == TIXML_ENCODING_UNKNOWN + && node->ToDeclaration() ) + { + TiXmlDeclaration* dec = node->ToDeclaration(); + const char* enc = dec->Encoding(); + assert( enc ); + + if ( *enc == 0 ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice + else + encoding = TIXML_ENCODING_LEGACY; + } + + p = SkipWhiteSpace( p, encoding ); + } + + // Was this empty? + if ( !firstChild ) { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); + return 0; + } + + // All is well. + return p; +} + +void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + // The first error in a chain is more accurate - don't set again! + if ( error ) + return; + + assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); + error = true; + errorId = err; + errorDesc = errorString[ errorId ]; + + errorLocation.Clear(); + if ( pError && data ) + { + data->Stamp( pError, encoding ); + errorLocation = data->Cursor(); + } +} + + +TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) +{ + TiXmlNode* returnNode = 0; + + p = SkipWhiteSpace( p, encoding ); + if( !p || !*p || *p != '<' ) + { + return 0; + } + + p = SkipWhiteSpace( p, encoding ); + + if ( !p || !*p ) + { + return 0; + } + + // What is this thing? + // - Elements start with a letter or underscore, but xml is reserved. + // - Comments: <!-- + // - Decleration: <?xml + // - Everthing else is unknown to tinyxml. + // + + const char* xmlHeader = { "<?xml" }; + const char* commentHeader = { "<!--" }; + const char* dtdHeader = { "<!" }; + const char* cdataHeader = { "<![CDATA[" }; + + if ( StringEqual( p, xmlHeader, true, encoding ) ) + { + #ifdef DEBUG_PARSER + TIXML_LOG( "XML parsing Declaration\n" ); + #endif + returnNode = new TiXmlDeclaration(); + } + else if ( StringEqual( p, commentHeader, false, encoding ) ) + { + #ifdef DEBUG_PARSER + TIXML_LOG( "XML parsing Comment\n" ); + #endif + returnNode = new TiXmlComment(); + } + else if ( StringEqual( p, cdataHeader, false, encoding ) ) + { + #ifdef DEBUG_PARSER + TIXML_LOG( "XML parsing CDATA\n" ); + #endif + TiXmlText* text = new TiXmlText( "" ); + text->SetCDATA( true ); + returnNode = text; + } + else if ( StringEqual( p, dtdHeader, false, encoding ) ) + { + #ifdef DEBUG_PARSER + TIXML_LOG( "XML parsing Unknown(1)\n" ); + #endif + returnNode = new TiXmlUnknown(); + } + else if ( IsAlpha( *(p+1), encoding ) + || *(p+1) == '_' ) + { + #ifdef DEBUG_PARSER + TIXML_LOG( "XML parsing Element\n" ); + #endif + returnNode = new TiXmlElement( "" ); + } + else + { + #ifdef DEBUG_PARSER + TIXML_LOG( "XML parsing Unknown(2)\n" ); + #endif + returnNode = new TiXmlUnknown(); + } + + if ( returnNode ) + { + // Set the parent, so it can report errors + returnNode->parent = this; + } + return returnNode; +} + +#ifdef TIXML_USE_STL + +void TiXmlElement::StreamIn (std::istream * in, TIXML_STRING * tag) +{ + // We're called with some amount of pre-parsing. That is, some of "this" + // element is in "tag". Go ahead and stream to the closing ">" + while( in->good() ) + { + int c = in->get(); + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + (*tag) += (char) c ; + + if ( c == '>' ) + break; + } + + if ( tag->length() < 3 ) return; + + // Okay...if we are a "/>" tag, then we're done. We've read a complete tag. + // If not, identify and stream. + + if ( tag->at( tag->length() - 1 ) == '>' + && tag->at( tag->length() - 2 ) == '/' ) + { + // All good! + return; + } + else if ( tag->at( tag->length() - 1 ) == '>' ) + { + // There is more. Could be: + // text + // cdata text (which looks like another node) + // closing tag + // another node. + for ( ;; ) + { + StreamWhiteSpace( in, tag ); + + // Do we have text? + if ( in->good() && in->peek() != '<' ) + { + // Yep, text. + TiXmlText text( "" ); + text.StreamIn( in, tag ); + + // What follows text is a closing tag or another node. + // Go around again and figure it out. + continue; + } + + // We now have either a closing tag...or another node. + // We should be at a "<", regardless. + if ( !in->good() ) return; + assert( in->peek() == '<' ); + int tagIndex = (int) tag->length(); + + bool closingTag = false; + bool firstCharFound = false; + + for( ;; ) + { + if ( !in->good() ) + return; + + int c = in->peek(); + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + if ( c == '>' ) + break; + + *tag += (char) c; + in->get(); + + // Early out if we find the CDATA id. + if ( c == '[' && tag->size() >= 9 ) + { + size_t len = tag->size(); + const char* start = tag->c_str() + len - 9; + if ( strcmp( start, "<![CDATA[" ) == 0 ) { + assert( !closingTag ); + break; + } + } + + if ( !firstCharFound && c != '<' && !IsWhiteSpace( c ) ) + { + firstCharFound = true; + if ( c == '/' ) + closingTag = true; + } + } + // If it was a closing tag, then read in the closing '>' to clean up the input stream. + // If it was not, the streaming will be done by the tag. + if ( closingTag ) + { + if ( !in->good() ) + return; + + int c = in->get(); + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + assert( c == '>' ); + *tag += (char) c; + + // We are done, once we've found our closing tag. + return; + } + else + { + // If not a closing tag, id it, and stream. + const char* tagloc = tag->c_str() + tagIndex; + TiXmlNode* node = Identify( tagloc, TIXML_DEFAULT_ENCODING ); + if ( !node ) + return; + node->StreamIn( in, tag ); + delete node; + node = 0; + + // No return: go around from the beginning: text, closing tag, or node. + } + } + } +} +#endif + +const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + p = SkipWhiteSpace( p, encoding ); + TiXmlDocument* document = GetDocument(); + + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding ); + return 0; + } + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + + if ( *p != '<' ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding ); + return 0; + } + + p = SkipWhiteSpace( p+1, encoding ); + + // Read the name. + const char* pErr = p; + + p = ReadName( p, &value, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding ); + return 0; + } + + TIXML_STRING endTag ("</"); + endTag += value; + + // Check for and read attributes. Also look for an empty + // tag or an end tag. + while ( p && *p ) + { + pErr = p; + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); + return 0; + } + if ( *p == '/' ) + { + ++p; + // Empty tag. + if ( *p != '>' ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY, p, data, encoding ); + return 0; + } + return (p+1); + } + else if ( *p == '>' ) + { + // Done with attributes (if there were any.) + // Read the value -- which can include other + // elements -- read the end tag, and return. + ++p; + p = ReadValue( p, data, encoding ); // Note this is an Element method, and will set the error if one happens. + if ( !p || !*p ) { + // We were looking for the end tag, but found nothing. + // Fix for [ 1663758 ] Failure to report error on bad XML + if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding ); + return 0; + } + + // We should find the end tag now + // note that: + // </foo > and + // </foo> + // are both valid end tags. + if ( StringEqual( p, endTag.c_str(), false, encoding ) ) + { + p += endTag.length(); + p = SkipWhiteSpace( p, encoding ); + if ( p && *p && *p == '>' ) { + ++p; + return p; + } + if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding ); + return 0; + } + else + { + if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding ); + return 0; + } + } + else + { + // Try to read an attribute: + TiXmlAttribute* attrib = new TiXmlAttribute(); + if ( !attrib ) + { + return 0; + } + + attrib->SetDocument( document ); + pErr = p; + p = attrib->Parse( p, data, encoding ); + + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding ); + delete attrib; + return 0; + } + + // Handle the strange case of double attributes: + #ifdef TIXML_USE_STL + TiXmlAttribute* node = attributeSet.Find( attrib->NameTStr() ); + #else + TiXmlAttribute* node = attributeSet.Find( attrib->Name() ); + #endif + if ( node ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding ); + delete attrib; + return 0; + } + + attributeSet.Add( attrib ); + } + } + return p; +} + + +const char* TiXmlElement::ReadValue( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + TiXmlDocument* document = GetDocument(); + + // Read in text and elements in any order. + const char* pWithWhiteSpace = p; + p = SkipWhiteSpace( p, encoding ); + + while ( p && *p ) + { + if ( *p != '<' ) + { + // Take what we have, make a text element. + TiXmlText* textNode = new TiXmlText( "" ); + + if ( !textNode ) + { + return 0; + } + + if ( TiXmlBase::IsWhiteSpaceCondensed() ) + { + p = textNode->Parse( p, data, encoding ); + } + else + { + // Special case: we want to keep the white space + // so that leading spaces aren't removed. + p = textNode->Parse( pWithWhiteSpace, data, encoding ); + } + + if ( !textNode->Blank() ) + LinkEndChild( textNode ); + else + delete textNode; + } + else + { + // We hit a '<' + // Have we hit a new element or an end tag? This could also be + // a TiXmlText in the "CDATA" style. + if ( StringEqual( p, "</", false, encoding ) ) + { + return p; + } + else + { + TiXmlNode* node = Identify( p, encoding ); + if ( node ) + { + p = node->Parse( p, data, encoding ); + LinkEndChild( node ); + } + else + { + return 0; + } + } + } + pWithWhiteSpace = p; + p = SkipWhiteSpace( p, encoding ); + } + + if ( !p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE, 0, 0, encoding ); + } + return p; +} + + +#ifdef TIXML_USE_STL +void TiXmlUnknown::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->get(); + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + (*tag) += (char) c; + + if ( c == '>' ) + { + // All is well. + return; + } + } +} +#endif + + +const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + TiXmlDocument* document = GetDocument(); + p = SkipWhiteSpace( p, encoding ); + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + if ( !p || !*p || *p != '<' ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, p, data, encoding ); + return 0; + } + ++p; + value = ""; + + while ( p && *p && *p != '>' ) + { + value += *p; + ++p; + } + + if ( !p ) + { + if ( document ) + document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding ); + } + if ( p && *p == '>' ) + return p+1; + return p; +} + +#ifdef TIXML_USE_STL +void TiXmlComment::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->get(); + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + (*tag) += (char) c; + + if ( c == '>' + && tag->at( tag->length() - 2 ) == '-' + && tag->at( tag->length() - 3 ) == '-' ) + { + // All is well. + return; + } + } +} +#endif + + +const char* TiXmlComment::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + TiXmlDocument* document = GetDocument(); + value = ""; + + p = SkipWhiteSpace( p, encoding ); + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + const char* startTag = "<!--"; + const char* endTag = "-->"; + + if ( !StringEqual( p, startTag, false, encoding ) ) + { + if ( document ) + document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); + return 0; + } + p += strlen( startTag ); + + // [ 1475201 ] TinyXML parses entities in comments + // Oops - ReadText doesn't work, because we don't want to parse the entities. + // p = ReadText( p, &value, false, endTag, false, encoding ); + // + // from the XML spec: + /* + [Definition: Comments may appear anywhere in a document outside other markup; in addition, + they may appear within the document type declaration at places allowed by the grammar. + They are not part of the document's character data; an XML processor MAY, but need not, + make it possible for an application to retrieve the text of comments. For compatibility, + the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity + references MUST NOT be recognized within comments. + + An example of a comment: + + <!-- declarations for <head> & <body> --> + */ + + value = ""; + // Keep all the white space. + while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) + { + value.append( p, 1 ); + ++p; + } + if ( p && *p ) + p += strlen( endTag ); + + return p; +} + + +const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) return 0; + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + // Read the name, the '=' and the value. + const char* pErr = p; + p = ReadName( p, &name, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); + return 0; + } + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p || *p != '=' ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + + ++p; // skip '=' + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + + const char* end; + const char SINGLE_QUOTE = '\''; + const char DOUBLE_QUOTE = '\"'; + + if ( *p == SINGLE_QUOTE ) + { + ++p; + end = "\'"; // single quote in string + p = ReadText( p, &value, false, end, false, encoding ); + } + else if ( *p == DOUBLE_QUOTE ) + { + ++p; + end = "\""; // double quote in string + p = ReadText( p, &value, false, end, false, encoding ); + } + else + { + // All attribute values should be in single or double quotes. + // But this is such a common error that the parser will try + // its best, even without them. + value = ""; + while ( p && *p // existence + && !IsWhiteSpace( *p ) // whitespace + && *p != '/' && *p != '>' ) // tag end + { + if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { + // [ 1451649 ] Attribute values with trailing quotes not handled correctly + // We did not have an opening quote but seem to have a + // closing one. Give up and throw an error. + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + value += *p; + ++p; + } + } + return p; +} + +#ifdef TIXML_USE_STL +void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->peek(); + if ( !cdata && (c == '<' ) ) + { + return; + } + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + (*tag) += (char) c; + in->get(); // "commits" the peek made above + + if ( cdata && c == '>' && tag->size() >= 3 ) { + size_t len = tag->size(); + if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { + // terminator of cdata. + return; + } + } + } +} +#endif + +const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + value = ""; + TiXmlDocument* document = GetDocument(); + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + + const char* const startTag = "<![CDATA["; + const char* const endTag = "]]>"; + + if ( cdata || StringEqual( p, startTag, false, encoding ) ) + { + cdata = true; + + if ( !StringEqual( p, startTag, false, encoding ) ) + { + if ( document ) + document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); + return 0; + } + p += strlen( startTag ); + + // Keep all the white space, ignore the encoding, etc. + while ( p && *p + && !StringEqual( p, endTag, false, encoding ) + ) + { + value += *p; + ++p; + } + + TIXML_STRING dummy; + p = ReadText( p, &dummy, false, endTag, false, encoding ); + return p; + } + else + { + bool ignoreWhite = true; + + const char* end = "<"; + p = ReadText( p, &value, ignoreWhite, end, false, encoding ); + if ( p && *p ) + return p-1; // don't truncate the '<' + return 0; + } +} + +#ifdef TIXML_USE_STL +void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->get(); + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + (*tag) += (char) c; + + if ( c == '>' ) + { + // All is well. + return; + } + } +} +#endif + +const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) +{ + p = SkipWhiteSpace( p, _encoding ); + // Find the beginning, find the end, and look for + // the stuff in-between. + TiXmlDocument* document = GetDocument(); + if ( !p || !*p || !StringEqual( p, "<?xml", true, _encoding ) ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); + return 0; + } + if ( data ) + { + data->Stamp( p, _encoding ); + location = data->Cursor(); + } + p += 5; + + version = ""; + encoding = ""; + standalone = ""; + + while ( p && *p ) + { + if ( *p == '>' ) + { + ++p; + return p; + } + + p = SkipWhiteSpace( p, _encoding ); + if ( StringEqual( p, "version", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + version = attrib.Value(); + } + else if ( StringEqual( p, "encoding", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + encoding = attrib.Value(); + } + else if ( StringEqual( p, "standalone", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + standalone = attrib.Value(); + } + else + { + // Read over whatever it is. + while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) + ++p; + } + } + return 0; +} + +bool TiXmlText::Blank() const +{ + for ( unsigned i=0; i<value.length(); i++ ) + if ( !IsWhiteSpace( value[i] ) ) + return false; + return true; +} + diff --git a/jni/desmume/src/utils/valuearray.h b/jni/desmume/src/utils/valuearray.h new file mode 100755 index 0000000..cc24d9f --- /dev/null +++ b/jni/desmume/src/utils/valuearray.h @@ -0,0 +1,38 @@ +/* + Copyright (C) 2008 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _VALUEARRAY_H_ +#define _VALUEARRAY_H_ + +template<typename T, int N> +struct ValueArray +{ + T data[N]; + T &operator[](int index) { return data[index]; } + static const int size = N; + bool operator!=(ValueArray<T,N> &other) { return !operator==(other); } + bool operator==(ValueArray<T,N> &other) + { + for(int i=0;i<size;i++) + if(data[i] != other[i]) + return false; + return true; + } +}; + +#endif + diff --git a/jni/desmume/src/utils/vfat.cpp b/jni/desmume/src/utils/vfat.cpp new file mode 100755 index 0000000..c648d1a --- /dev/null +++ b/jni/desmume/src/utils/vfat.cpp @@ -0,0 +1,229 @@ +/* + Copyright (C) 2006 yopyop + Copyright (C) 2006 Mic + Copyright (C) 2010-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <string> +#include <string.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <stack> + +#include "../types.h" +#include "../debug.h" +#include "../fs.h" + +#include "emufat.h" +#include "vfat.h" +#include "libfat/libfat_public_api.h" + + +enum EListCallbackArg { + EListCallbackArg_Item, EListCallbackArg_Pop +}; + +typedef void (*ListCallback)(FsEntry* fs, EListCallbackArg); + +// List all files and subdirectories recursively +static void list_files(const char *filepath, ListCallback list_callback) +{ + char DirSpec[255+1], SubDir[255+1]; + FsEntry entry; + void * hFind; + char *fname; + u32 dwError; + + strncpy(DirSpec, filepath, ARRAY_SIZE(DirSpec)); + DirSpec[255] = 0 ; // hard limit the string here + + hFind = FsReadFirst(DirSpec, &entry); + if (hFind == NULL) return; + + do { + fname = (strlen(entry.cAlternateFileName)>0) ? entry.cAlternateFileName : entry.cFileName; + list_callback(&entry,EListCallbackArg_Item); + printf("cflash added %s\n",entry.cFileName); + + if ((entry.flags & FS_IS_DIR) && (strcmp(fname, ".")) && (strcmp(fname, ".."))) + { + if (strlen(fname)+strlen(filepath)+2 < 256) + { + sprintf(SubDir, "%s%c%s", filepath, FS_SEPARATOR, fname); + list_files(SubDir, list_callback); + list_callback(&entry, EListCallbackArg_Pop); + } + } + } while (FsReadNext(hFind, &entry) != 0); + + dwError = FsError(); + FsClose(hFind); + if (dwError != FS_ERR_NO_MORE_FILES) return; +} + +static u64 dataSectors = 0; +void count_ListCallback(FsEntry* fs, EListCallbackArg arg) +{ + if(arg == EListCallbackArg_Pop) return; + u32 sectors = 1; + if(fs->flags & FS_IS_DIR) + { + } + else + sectors += (fs->fileSize+511)/512 + 1; + dataSectors += sectors; +} + +static std::string currPath; +static std::stack<std::string> pathStack; +static std::stack<std::string> virtPathStack; +static std::string currVirtPath; +void build_ListCallback(FsEntry* fs, EListCallbackArg arg) +{ + char* fname = (strlen(fs->cAlternateFileName)>0) ? fs->cAlternateFileName : fs->cFileName; + + //we use cFileName always because it is a LFN and we are making sure that we always make a fat32 image + fname = fs->cFileName; + + if(arg == EListCallbackArg_Pop) + { + currPath = pathStack.top(); + pathStack.pop(); + currVirtPath = virtPathStack.top(); + virtPathStack.pop(); + return; + } + + if(fs->flags & FS_IS_DIR) + { + if(!strcmp(fname,".")) return; + if(!strcmp(fname,"..")) return; + + pathStack.push(currPath); + virtPathStack.push(currVirtPath); + + currVirtPath = currVirtPath + "/" + fname; + bool ok = LIBFAT::MkDir(currVirtPath.c_str()); + + if(!ok) + printf("ERROR adding dir %s via libfat\n",currVirtPath.c_str()); + + currPath = currPath + std::string(1,FS_SEPARATOR) + fname; + return; + } + else + { + std::string path = currPath + std::string(1,FS_SEPARATOR) + fname; + + FILE* inf = fopen(path.c_str(),"rb"); + if(inf) + { + fseek(inf,0,SEEK_END); + long len = ftell(inf); + fseek(inf,0,SEEK_SET); + u8 *buf = new u8[len]; + fread(buf,1,len,inf); + fclose(inf); + + std::string path = currVirtPath + "/" + fname; + printf("adding path %s for libfat\n",path.c_str()); + bool ok = LIBFAT::WriteFile(path.c_str(),buf,len); + if(!ok) + printf("ERROR adding file to fat\n"); + delete[] buf; + } else printf("ERROR opening file for fat\n"); + } + +} + + + +bool VFAT::build(const char* path, int extra_MB) +{ + dataSectors = 0; + currVirtPath = ""; + currPath = path; + list_files(path, count_ListCallback); + + dataSectors += 8; //a few for reserved sectors, etc. + + dataSectors += extra_MB*1024*1024/512; //add extra write space + //dataSectors += 16*1024*1024/512; //add 16MB worth of write space. this is probably enough for anyone, but maybe it should be configurable. + //we could always suggest to users to add a big file to their directory to overwrite (that would cause the image to get padded) + + //this seems to be the minimum size that will turn into a solid fat32 + if(dataSectors<36*1024*1024/512) + dataSectors = 36*1024*1024/512; + + if(dataSectors>=(0x80000000>>9)) + { + printf("error allocating memory for fat (%d KBytes)\n",(dataSectors*512)/1024); + printf("total fat sizes > 2GB are never going to work\n"); + } + + delete file; + try + { + file = new EMUFILE_MEMORY(dataSectors*512); + } + catch(std::bad_alloc) + { + printf("error allocating memory for fat (%d KBytes)\n",(dataSectors*512)/1024); + printf("(out of memory)\n"); + return false; + } + + //debug.. + //file = new EMUFILE_FILE("c:\\temp.ima","rb+"); + + //format the disk + { + EmuFat fat(file); + EmuFatVolume vol; + u8 ok = vol.init(&fat); + vol.formatNew(dataSectors); + + //ensure we are working in memory, just in case we were testing with a disk file. + //libfat will need to go straight to memory (for now; we could easily change it to work with the disk) + file = file->memwrap(); + } + EMUFILE_MEMORY* memf = (EMUFILE_MEMORY*)file; + + //setup libfat and write all the files through it + LIBFAT::Init(memf->buf(),memf->size()); + list_files(path, build_ListCallback); + LIBFAT::Shutdown(); + + return true; +} + +VFAT::VFAT() + : file(NULL) +{ +} + +VFAT::~VFAT() +{ + delete file; +} + +EMUFILE* VFAT::detach() +{ + EMUFILE* ret = file; + file = NULL; + return ret; +} \ No newline at end of file diff --git a/jni/desmume/src/utils/vfat.h b/jni/desmume/src/utils/vfat.h new file mode 100755 index 0000000..0f640e3 --- /dev/null +++ b/jni/desmume/src/utils/vfat.h @@ -0,0 +1,36 @@ +/* + Copyright (C) 2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _VFAT_H + +class EMUFILE; + +//THIS CLASS IS NOT THREAD SAFE!! SORRY SO SLOPPY +class VFAT +{ +public: + VFAT(); + ~VFAT(); + bool build(const char* path, int extra_MB=0); + + EMUFILE* detach(); + +private: + EMUFILE* file; +}; + +#endif //_VFAT_H diff --git a/jni/desmume/src/utils/xstring.cpp b/jni/desmume/src/utils/xstring.cpp new file mode 100755 index 0000000..96c0a03 --- /dev/null +++ b/jni/desmume/src/utils/xstring.cpp @@ -0,0 +1,747 @@ +//taken from fceux on 10/27/08 +//subsequently modified for desmume + +/* + Copyright (C) 2008-2009 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "xstring.h" +#include <string> + +//a vc-style substring operation (very kind and lenient) +std::string strsub(const std::string& str, int pos, int len) { + int strlen = str.size(); + + if(strlen==0) return str; //empty strings always return empty strings + if(pos>=strlen) return str; //if you start past the end of the string, return the entire string. this is unusual, but there you have it + + //clipping + if(pos<0) { + len += pos; + pos = 0; + } + + if (pos+len>=strlen) + len=strlen-pos+1; + + //return str.str().substr(pos,len); + return str.substr(pos,len); +} + +std::string strmid(const std::string& str, int pos, int len) { return strsub(str,pos,len); } +std::string strleft(const std::string& str, int len) { return strsub(str,0,len); } +std::string strright(const std::string& str, int len) { return len ? strsub(str,str.size()-len,len) : ""; } +std::string toupper(const std::string& str) +{ + std::string ret = str; + for(u32 i=0;i<str.size();i++) + ret[i] = toupper(ret[i]); + return ret; +} + +///Upper case routine. Returns number of characters modified +int str_ucase(char *str) { + u32 i=0,j=0; + + while (i < strlen(str)) { + if ((str[i] >= 'a') && (str[i] <= 'z')) { + str[i] &= ~0x20; + j++; + } + i++; + } + return j; +} + + +///Lower case routine. Returns number of characters modified +int str_lcase(char *str) { + u32 i=0,j=0; + + while (i < strlen(str)) { + if ((str[i] >= 'A') && (str[i] <= 'Z')) { + str[i] |= 0x20; + j++; + } + i++; + } + return j; +} + + +///White space-trimming routine + +///Removes whitespace from left side of string, depending on the flags set (See STRIP_x definitions in xstring.h) +///Returns number of characters removed +int str_ltrim(char *str, int flags) { + u32 i=0; + + while (str[0]) { + if ((str[0] != ' ') || (str[0] != '\t') || (str[0] != '\r') || (str[0] != '\n')) break; + + if ((flags & STRIP_SP) && (str[0] == ' ')) { + i++; + strcpy(str,str+1); + } + if ((flags & STRIP_TAB) && (str[0] == '\t')) { + i++; + strcpy(str,str+1); + } + if ((flags & STRIP_CR) && (str[0] == '\r')) { + i++; + strcpy(str,str+1); + } + if ((flags & STRIP_LF) && (str[0] == '\n')) { + i++; + strcpy(str,str+1); + } + } + return i; +} + + +///White space-trimming routine + +///Removes whitespace from right side of string, depending on the flags set (See STRIP_x definitions in xstring.h) +///Returns number of characters removed +int str_rtrim(char *str, int flags) { + u32 i=0; + + while (strlen(str)) { + if ((str[strlen(str)-1] != ' ') || + (str[strlen(str)-1] != '\t') || + (str[strlen(str)-1] != '\r') || + (str[strlen(str)-1] != '\n')) break; + + if ((flags & STRIP_SP) && (str[0] == ' ')) { + i++; + str[strlen(str)-1] = 0; + } + if ((flags & STRIP_TAB) && (str[0] == '\t')) { + i++; + str[strlen(str)-1] = 0; + } + if ((flags & STRIP_CR) && (str[0] == '\r')) { + i++; + str[strlen(str)-1] = 0; + } + if ((flags & STRIP_LF) && (str[0] == '\n')) { + i++; + str[strlen(str)-1] = 0; + } + } + return i; +} + + +///White space-stripping routine + +///Removes whitespace depending on the flags set (See STRIP_x definitions in xstring.h) +///Returns number of characters removed, or -1 on error +int str_strip(char *str, int flags) { + u32 i=0,j=0; + char *astr,chr; + + if (!strlen(str)) return -1; + if (!(flags & (STRIP_SP|STRIP_TAB|STRIP_CR|STRIP_LF))) return -1; + if (!(astr = (char*)malloc(strlen(str)+1))) return -1; + while (i < strlen(str)) { + chr = str[i++]; + if ((flags & STRIP_SP) && (chr == ' ')) chr = 0; + if ((flags & STRIP_TAB) && (chr == '\t')) chr = 0; + if ((flags & STRIP_CR) && (chr == '\r')) chr = 0; + if ((flags & STRIP_LF) && (chr == '\n')) chr = 0; + + if (chr) astr[j++] = chr; + } + astr[j] = 0; + strcpy(str,astr); + free(astr); + return j; +} + + +///Character replacement routine + +///Replaces all instances of 'search' with 'replace' +///Returns number of characters modified +int chr_replace(char *str, char search, char replace) { + u32 i=0,j=0; + + while (i < strlen(str)) { + if (str[i] == search) { + str[i] = replace; + j++; + } + i++; + } + return j; +} + + +///Sub-String replacement routine + +///Replaces all instances of 'search' with 'replace' +///Returns number of sub-strings modified, or -1 on error +int str_replace(char *str, char *search, char *replace) { + u32 i=0,j=0; + int searchlen,replacelen; + char *astr; + + searchlen = strlen(search); + replacelen = strlen(replace); + if ((!strlen(str)) || (!searchlen)) return -1; //note: allow *replace to have a length of zero! + if (!(astr = (char*)malloc(strlen(str)+1))) return -1; + while (i < strlen(str)) { + if (!strncmp(str+i,search,searchlen)) { + if (replacelen) memcpy(astr+j,replace,replacelen); + i += searchlen; + j += replacelen; + } + else astr[j++] = str[i++]; + } + astr[j] = 0; + strcpy(str,astr); + free(astr); + return j; +} + +static const struct Base64Table +{ + Base64Table() + { + size_t a=0; + for(a=0; a<256; ++a) data[a] = 0xFF; // mark everything as invalid by default + // create value->ascii mapping + a=0; + for(unsigned char c='A'; c<='Z'; ++c) data[a++] = c; // 0..25 + for(unsigned char c='a'; c<='z'; ++c) data[a++] = c; // 26..51 + for(unsigned char c='0'; c<='9'; ++c) data[a++] = c; // 52..61 + data[62] = '+'; // 62 + data[63] = '/'; // 63 + // create ascii->value mapping (but due to overlap, write it to highbit region) + for(a=0; a<64; ++a) data[data[a]^0x80] = a; // + data[((unsigned char)'=') ^ 0x80] = 0; + } + unsigned char operator[] (size_t pos) const { return data[pos]; } +private: + unsigned char data[256]; +} Base64Table; + +std::string u32ToHexString(u32 val) +{ + char temp[16]; + sprintf(temp,"%08X",val); + return temp; +} + +///Converts the provided data to a string in a standard, user-friendly, round-trippable format +std::string BytesToString(const void* data, int len) +{ + char temp[16]; + if(len==1) { + sprintf(temp,"%d",*(const unsigned char*)data); + return temp; + } else if(len==2) { + sprintf(temp,"%d",*(const unsigned short*)data); + return temp; + } else if(len==4) { + sprintf(temp,"%d",*(const unsigned int*)data); + return temp; + } + + std::string ret; + if(1) // use base64 + { + const unsigned char* src = (const unsigned char*)data; + ret = "base64:"; + for(int n; len > 0; len -= n) + { + unsigned char input[3] = {0,0,0}; + for(n=0; n<3 && n<len; ++n) + input[n] = *src++; + unsigned char output[4] = + { + Base64Table[ input[0] >> 2 ], + Base64Table[ ((input[0] & 0x03) << 4) | (input[1] >> 4) ], + n<2 ? '=' : Base64Table[ ((input[1] & 0x0F) << 2) | (input[2] >> 6) ], + n<3 ? '=' : Base64Table[ input[2] & 0x3F ] + }; + ret.append(output, output+4); + } + } + else // use hex + { + ret.resize(len*2+2); + ret[0] = '0'; + ret[1] = 'x'; + for(int i=0;i<len;i++) + { + int a = (((const unsigned char*)data)[i]>>4); + int b = (((const unsigned char*)data)[i])&15; + if(a>9) a += 'A'-10; + else a += '0'; + if(b>9) b += 'A'-10; + else b += '0'; + ret[2+i*2] = a; + ret[2+i*2+1] = b; + } + } + return ret; +} + +///returns -1 if this is not a hex string +int HexStringToBytesLength(const std::string& str) +{ + if(str.size()>2 && str[0] == '0' && toupper(str[1]) == 'X') + return str.size()/2-1; + else return -1; +} + +int Base64StringToBytesLength(const std::string& str) +{ + if(str.size() < 7 || (str.size()-7) % 4 || str.substr(0,7) != "base64:") return -1; + + size_t c = ((str.size() - 7) / 4) * 3; + if(str[str.size()-1] == '=') { --c; + if(str[str.size()-2] == '=') --c; } + return c; +} + +///parses a string in the same format as BytesToString +///returns true if success. +bool StringToBytes(const std::string& str, void* data, int len) +{ + if(str.substr(0,7) == "base64:") + { + // base64 + unsigned char* tgt = (unsigned char*)data; + for(size_t pos = 7; pos < str.size() && len > 0; ) + { + unsigned char input[4], converted[4]; + for(int i=0; i<4; ++i) + { + if(pos >= str.size() && i > 0) return false; // invalid data + input[i] = str[pos++]; + if(input[i] & 0x80) return false; // illegal character + converted[i] = Base64Table[input[i]^0x80]; + if(converted[i] & 0x80) return false; // illegal character + } + unsigned char outpacket[3] = + { + (converted[0] << 2) | (converted[1] >> 4), + (converted[1] << 4) | (converted[2] >> 2), + (converted[2] << 6) | (converted[3]) + }; + int outlen = (input[2] == '=') ? 1 : (input[3] == '=' ? 2 : 3); + if(outlen > len) outlen = len; + memcpy(tgt, outpacket, outlen); + tgt += outlen; + len -= outlen; + } + return true; + } + if(str.size()>2 && str[0] == '0' && toupper(str[1]) == 'X') + { + // hex + int amt = len; + int bytesAvailable = str.size()/2; + if(bytesAvailable < amt) + amt = bytesAvailable; + const char* cstr = str.c_str()+2; + for(int i=0;i<amt;i++) { + char a = toupper(cstr[i*2]); + char b = toupper(cstr[i*2+1]); + if(a>='A') a=a-'A'+10; + else a-='0'; + if(b>='A') b=b-'A'+10; + else b-='0'; + unsigned char val = ((unsigned char)a<<4)|(unsigned char)b; + ((unsigned char*)data)[i] = val; + } + return true; + } + + if(len==1) { + int x = atoi(str.c_str()); + *(unsigned char*)data = x; + return true; + } else if(len==2) { + int x = atoi(str.c_str()); + *(unsigned short*)data = x; + return true; + } else if(len==4) { + int x = atoi(str.c_str()); + *(unsigned int*)data = x; + return true; + } + //we can't handle it + return false; +} + +#include <string> +#include <vector> +/// \brief convert input string into vector of string tokens +/// +/// \note consecutive delimiters will be treated as single delimiter +/// \note delimiters are _not_ included in return data +/// +/// \param input string to be parsed +/// \param delims list of delimiters. + +std::vector<std::string> tokenize_str(const std::string & str, + const std::string & delims=", \t") +{ + using namespace std; + // Skip delims at beginning, find start of first token + string::size_type lastPos = str.find_first_not_of(delims, 0); + // Find next delimiter @ end of token + string::size_type pos = str.find_first_of(delims, lastPos); + + // output vector + vector<string> tokens; + + while (string::npos != pos || string::npos != lastPos) + { + // Found a token, add it to the vector. + tokens.push_back(str.substr(lastPos, pos - lastPos)); + // Skip delims. Note the "not_of". this is beginning of token + lastPos = str.find_first_not_of(delims, pos); + // Find next delimiter at end of token. + pos = str.find_first_of(delims, lastPos); + } + + return tokens; +} + +//this code was taken from WINE (LGPL) +//http://google.com/codesearch?hl=en&q=+lang:c+splitpath+show:CPvw9Z-euls:_RSotQzmLeU:KGzljMEYFbY&sa=N&cd=9&ct=rc&cs_p=http://gentoo.osuosl.org/distfiles/Wine-20050524.tar.gz&cs_f=wine-20050524/programs/winefile/splitpath.c +void splitpath(const char* path, char* drv, char* dir, char* name, char* ext) +{ + const char* end; /* end of processed string */ + const char* p; /* search pointer */ + const char* s; /* copy pointer */ + + /* extract drive name */ + if (path[0] && path[1]==':') { + if (drv) { + *drv++ = *path++; + *drv++ = *path++; + *drv = '\0'; + } else path+=2; + } else if (drv) + *drv = '\0'; + + /* search for end of string or stream separator */ + for(end=path; *end && *end!=':'; ) + end++; + + /* search for begin of file extension */ + for(p=end; p>path && *--p!='\\' && *p!='/'; ) + if (*p == '.') { + end = p; + break; + } + + if (ext) + for(s=end; (*ext=*s++); ) + ext++; + else + for(s=end; *s++; ) {} + + /* search for end of directory name */ + for(p=end; p>path; ) + if (*--p=='\\' || *p=='/') { + p++; + break; + } + + if (name) { + for(s=p; s<end; ) + *name++ = *s++; + + *name = '\0'; + } else + for(s=p; s<end; ) + *s++; + + if (dir) { + for(s=path; s<p; ) + *dir++ = *s++; + + *dir = '\0'; + } +} + +//mbg 5/12/08 +//for the curious, I tested U16ToHexStr and it was 10x faster than printf. +//so the author of these dedicated functions is not insane, and I will leave them. + +static char TempArray[11]; + +uint16 FastStrToU16(char* s, bool& valid) +{ + int i; + uint16 v=0; + for(i=0; i < 4; i++) + { + if(s[i] == 0) return v; + v<<=4; + if(s[i] >= '0' && s[i] <= '9') + { + v+=s[i]-'0'; + } + else if(s[i] >= 'a' && s[i] <= 'f') + { + v+=s[i]-'a'+10; + } + else if(s[i] >= 'A' && s[i] <= 'F') + { + v+=s[i]-'A'+10; + } + else + { + valid = false; + return 0xFFFF; + } + } + valid = true; + return v; +} + +char *U8ToDecStr(uint8 a) +{ + TempArray[0] = '0' + a/100; + TempArray[1] = '0' + (a%100)/10; + TempArray[2] = '0' + (a%10); + TempArray[3] = 0; + return TempArray; +} + +char *U16ToDecStr(uint16 a) +{ + TempArray[0] = '0' + a/10000; + TempArray[1] = '0' + (a%10000)/1000; + TempArray[2] = '0' + (a%1000)/100; + TempArray[3] = '0' + (a%100)/10; + TempArray[4] = '0' + (a%10); + TempArray[5] = 0; + return TempArray; +} + +char *U32ToDecStr(char* buf, uint32 a) +{ + buf[0] = '0' + a/1000000000; + buf[1] = '0' + (a%1000000000)/100000000; + buf[2] = '0' + (a%100000000)/10000000; + buf[3] = '0' + (a%10000000)/1000000; + buf[4] = '0' + (a%1000000)/100000; + buf[5] = '0' + (a%100000)/10000; + buf[6] = '0' + (a%10000)/1000; + buf[7] = '0' + (a%1000)/100; + buf[8] = '0' + (a%100)/10; + buf[9] = '0' + (a%10); + buf[10] = 0; + return buf; +} +char *U32ToDecStr(uint32 a) +{ + return U32ToDecStr(TempArray,a); +} + +char *U16ToHexStr(uint16 a) +{ + TempArray[0] = a/4096 > 9?'A'+a/4096-10:'0' + a/4096; + TempArray[1] = (a%4096)/256 > 9?'A'+(a%4096)/256 - 10:'0' + (a%4096)/256; + TempArray[2] = (a%256)/16 > 9?'A'+(a%256)/16 - 10:'0' + (a%256)/16; + TempArray[3] = a%16 > 9?'A'+(a%16) - 10:'0' + (a%16); + TempArray[4] = 0; + return TempArray; +} + +char *U8ToHexStr(uint8 a) +{ + TempArray[0] = a/16 > 9?'A'+a/16 - 10:'0' + a/16; + TempArray[1] = a%16 > 9?'A'+(a%16) - 10:'0' + (a%16); + TempArray[2] = 0; + return TempArray; +} + +std::string stditoa(int n) +{ + char tempbuf[16]; + sprintf(tempbuf, "%d", n); + return tempbuf; +} + + +std::string readNullTerminatedAscii(std::istream* is) +{ + std::string ret; + ret.reserve(50); + for(;;) + { + int c = is->get(); + if(c == 0) break; + else ret += (char)c; + } + return ret; +} + +// replace all instances of victim with replacement +std::string mass_replace(const std::string &source, const std::string &victim, const std::string &replacement) +{ + std::string answer = source; + std::string::size_type j = 0; + while ((j = answer.find(victim, j)) != std::string::npos ) + { + answer.replace(j, victim.length(), replacement); + j+= replacement.length(); + } + return answer; +} + +//http://www.codeproject.com/KB/string/UtfConverter.aspx +#include "ConvertUTF.h" +namespace UtfConverter +{ + static std::wstring FromUtf8(const std::string& utf8string) + { + size_t widesize = utf8string.length(); + if (sizeof(wchar_t) == 2) + { + wchar_t* widestringnative = new wchar_t[widesize+1]; + const UTF8* sourcestart = reinterpret_cast<const UTF8*>(utf8string.c_str()); + const UTF8* sourceend = sourcestart + widesize; + UTF16* targetstart = reinterpret_cast<UTF16*>(widestringnative); + UTF16* targetend = targetstart + widesize+1; + ConversionResult res = ConvertUTF8toUTF16(&sourcestart, sourceend, &targetstart, targetend, strictConversion); + if (res != conversionOK) + { + delete [] widestringnative; + throw std::exception(); + } + *targetstart = 0; + std::wstring resultstring(widestringnative); + delete [] widestringnative; + return resultstring; + } + else if (sizeof(wchar_t) == 4) + { + wchar_t* widestringnative = new wchar_t[widesize+1]; + const UTF8* sourcestart = reinterpret_cast<const UTF8*>(utf8string.c_str()); + const UTF8* sourceend = sourcestart + widesize; + UTF32* targetstart = reinterpret_cast<UTF32*>(widestringnative); + UTF32* targetend = targetstart + widesize; + ConversionResult res = ConvertUTF8toUTF32(&sourcestart, sourceend, &targetstart, targetend, strictConversion); + if (res != conversionOK) + { + delete [] widestringnative; + throw std::exception(); + } + *targetstart = 0; + std::wstring resultstring(widestringnative); + delete [] widestringnative; + return resultstring; + } + else + { + throw std::exception(); + } + return L""; + } + + static std::string ToUtf8(const std::wstring& widestring) + { + size_t widesize = widestring.length(); + + if (sizeof(wchar_t) == 2) + { + size_t utf8size = 3 * widesize + 1; + char* utf8stringnative = new char[utf8size]; + const UTF16* sourcestart = reinterpret_cast<const UTF16*>(widestring.c_str()); + const UTF16* sourceend = sourcestart + widesize; + UTF8* targetstart = reinterpret_cast<UTF8*>(utf8stringnative); + UTF8* targetend = targetstart + utf8size; + ConversionResult res = ConvertUTF16toUTF8(&sourcestart, sourceend, &targetstart, targetend, strictConversion); + if (res != conversionOK) + { + delete [] utf8stringnative; + throw std::exception(); + } + *targetstart = 0; + std::string resultstring(utf8stringnative); + delete [] utf8stringnative; + return resultstring; + } + else if (sizeof(wchar_t) == 4) + { + size_t utf8size = 4 * widesize + 1; + char* utf8stringnative = new char[utf8size]; + const UTF32* sourcestart = reinterpret_cast<const UTF32*>(widestring.c_str()); + const UTF32* sourceend = sourcestart + widesize; + UTF8* targetstart = reinterpret_cast<UTF8*>(utf8stringnative); + UTF8* targetend = targetstart + utf8size; + ConversionResult res = ConvertUTF32toUTF8(&sourcestart, sourceend, &targetstart, targetend, strictConversion); + if (res != conversionOK) + { + delete [] utf8stringnative; + throw std::exception(); + } + *targetstart = 0; + std::string resultstring(utf8stringnative); + delete [] utf8stringnative; + return resultstring; + } + else + { + throw std::exception(); + } + return ""; + } +} + +//convert a std::string to std::wstring +std::wstring mbstowcs(std::string str) +{ + try { + return UtfConverter::FromUtf8(str); + } catch(std::exception) { + return L"(failed UTF-8 conversion)"; + } +} + +std::string wcstombs(std::wstring str) +{ + return UtfConverter::ToUtf8(str); +} + + +//TODO - dont we already have another function that can do this +std::string getExtension(const char* input) { + char buf[1024]; + strcpy(buf,input); + char* dot=strrchr(buf,'.'); + if(!dot) + return ""; + char ext [512]; + strcpy(ext, dot+1); + int k, extlen=strlen(ext); + for(k=0;k<extlen;k++) + ext[k]=tolower(ext[k]); + return ext; +} + diff --git a/jni/desmume/src/utils/xstring.h b/jni/desmume/src/utils/xstring.h new file mode 100755 index 0000000..2a990f0 --- /dev/null +++ b/jni/desmume/src/utils/xstring.h @@ -0,0 +1,138 @@ +//taken from fceux on 27-oct-2008 +//subsequently modified for desmume + +/* + Copyright (C) 2008-2009 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _STRINGUTIL_H_ +#define _STRINGUTIL_H_ + +#include <string> +#include <string.h> +#include <stdlib.h> +#include <vector> +#include <iostream> +#include <cstdio> + +#include "../types.h" +#include "../emufile.h" + +//definitions for str_strip() flags +#define STRIP_SP 0x01 // space +#define STRIP_TAB 0x02 // tab +#define STRIP_CR 0x04 // carriage return +#define STRIP_LF 0x08 // line feed + + +int str_ucase(char *str); +int str_lcase(char *str); +int str_ltrim(char *str, int flags); +int str_rtrim(char *str, int flags); +int str_strip(char *str, int flags); +int chr_replace(char *str, char search, char replace); +int str_replace(char *str, char *search, char *replace); + +std::string strsub(const std::string& str, int pos, int len); +std::string strmid(const std::string& str, int pos, int len); +std::string strleft(const std::string& str, int len); +std::string strright(const std::string& str, int len); +std::string toupper(const std::string& str); + +int HexStringToBytesLength(const std::string& str); +int Base64StringToBytesLength(const std::string& str); +std::string u32ToHexString(u32 val); +std::string BytesToString(const void* data, int len); +bool StringToBytes(const std::string& str, void* data, int len); + +std::vector<std::string> tokenize_str(const std::string & str,const std::string & delims); +void splitpath(const char* path, char* drv, char* dir, char* name, char* ext); + +uint16 FastStrToU16(char* s, bool& valid); +char *U16ToDecStr(uint16 a); +char *U32ToDecStr(uint32 a); +char *U32ToDecStr(char* buf, uint32 a); +char *U8ToDecStr(uint8 a); +char *U8ToHexStr(uint8 a); +char *U16ToHexStr(uint16 a); + +std::string stditoa(int n); + +std::string readNullTerminatedAscii(std::istream* is); + +//extracts a decimal uint from an istream +template<typename T> T templateIntegerDecFromIstream(EMUFILE* is) +{ + unsigned int ret = 0; + bool pre = true; + + for(;;) + { + int c = is->fgetc(); + if(c == -1) return ret; + int d = c - '0'; + if((d<0 || d>9)) + { + if(!pre) + break; + } + else + { + pre = false; + ret *= 10; + ret += d; + } + } + is->unget(); + return ret; +} + +inline u32 u32DecFromIstream(EMUFILE* is) { return templateIntegerDecFromIstream<u32>(is); } +inline u64 u64DecFromIstream(EMUFILE* is) { return templateIntegerDecFromIstream<u64>(is); } + +//puts an optionally 0-padded decimal integer of type T into the ostream (0-padding is quicker) +template<typename T, int DIGITS, bool PAD> void putdec(EMUFILE* os, T dec) +{ + char temp[DIGITS]; + int ctr = 0; + for(int i=0;i<DIGITS;i++) + { + int quot = dec/10; + int rem = dec%10; + temp[DIGITS-1-i] = '0' + rem; + if(!PAD) + { + if(rem != 0) ctr = i; + } + dec = quot; + } + if(!PAD) + os->fwrite(temp+DIGITS-ctr-1,ctr+1); + else + os->fwrite(temp,DIGITS); +} + +std::string mass_replace(const std::string &source, const std::string &victim, const std::string &replacement); + +std::wstring mbstowcs(std::string str); +std::string wcstombs(std::wstring str); + + +//TODO - dont we already have another function that can do this +std::string getExtension(const char* input); + + +#endif diff --git a/jni/desmume/src/utils/xstring_r7b.h b/jni/desmume/src/utils/xstring_r7b.h new file mode 100755 index 0000000..391a669 --- /dev/null +++ b/jni/desmume/src/utils/xstring_r7b.h @@ -0,0 +1,153 @@ +//taken from fceux on 27-oct-2008 +//subsequently modified for desmume + +/* + Copyright (C) 2008-2009 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _STRINGUTIL_H_ +#define _STRINGUTIL_H_ + +#include <string> +#include <string.h> +#include <stdlib.h> +#include <vector> +#include <iostream> +#include <cstdio> + +#include "../types.h" +#include "../emufile.h" + +#ifdef ANDROID +//Google makes not supporting wstring a source of pride. +namespace std { +typedef string wstring; +} +#endif + + +//definitions for str_strip() flags +#define STRIP_SP 0x01 // space +#define STRIP_TAB 0x02 // tab +#define STRIP_CR 0x04 // carriage return +#define STRIP_LF 0x08 // line feed + + +int str_ucase(char *str); +int str_lcase(char *str); +int str_ltrim(char *str, int flags); +int str_rtrim(char *str, int flags); +int str_strip(char *str, int flags); +int chr_replace(char *str, char search, char replace); +int str_replace(char *str, char *search, char *replace); + +std::string strsub(const std::string& str, int pos, int len); +std::string strmid(const std::string& str, int pos, int len); +std::string strleft(const std::string& str, int len); +std::string strright(const std::string& str, int len); +std::string toupper(const std::string& str); + +int HexStringToBytesLength(const std::string& str); +int Base64StringToBytesLength(const std::string& str); +std::string u32ToHexString(u32 val); +std::string BytesToString(const void* data, int len); +bool StringToBytes(const std::string& str, void* data, int len); + +std::vector<std::string> tokenize_str(const std::string & str,const std::string & delims); +void splitpath(const char* path, char* drv, char* dir, char* name, char* ext); + +uint16 FastStrToU16(char* s, bool& valid); +char *U16ToDecStr(uint16 a); +char *U32ToDecStr(uint32 a); +char *U32ToDecStr(char* buf, uint32 a); +char *U8ToDecStr(uint8 a); +char *U8ToHexStr(uint8 a); +char *U16ToHexStr(uint16 a); + +std::string stditoa(int n); + +std::string readNullTerminatedAscii(std::istream* is); + +//extracts a decimal uint from an istream +template<typename T> T templateIntegerDecFromIstream(EMUFILE* is) +{ + unsigned int ret = 0; + bool pre = true; + + for(;;) + { + int c = is->fgetc(); + if(c == -1) return ret; + int d = c - '0'; + if((d<0 || d>9)) + { + if(!pre) + break; + } + else + { + pre = false; + ret *= 10; + ret += d; + } + } + is->unget(); + return ret; +} + +inline u32 u32DecFromIstream(EMUFILE* is) { return templateIntegerDecFromIstream<u32>(is); } +inline u64 u64DecFromIstream(EMUFILE* is) { return templateIntegerDecFromIstream<u64>(is); } + +//puts an optionally 0-padded decimal integer of type T into the ostream (0-padding is quicker) +template<typename T, int DIGITS, bool PAD> void putdec(EMUFILE* os, T dec) +{ + char temp[DIGITS]; + int ctr = 0; + for(int i=0;i<DIGITS;i++) + { + int quot = dec/10; + int rem = dec%10; + temp[DIGITS-1-i] = '0' + rem; + if(!PAD) + { + if(rem != 0) ctr = i; + } + dec = quot; + } + if(!PAD) + os->fwrite(temp+DIGITS-ctr-1,ctr+1); + else + os->fwrite(temp,DIGITS); +} + +std::string mass_replace(const std::string &source, const std::string &victim, const std::string &replacement); + +std::wstring mbstowcs(std::string str); +std::string wcstombs(std::wstring str); + + +#ifdef ANDROID +std::wstring wstringFromWideLiteral(const wchar_t* ptr); +#define WSTR(X) wstringFromWideLiteral(X) +#else +#define WSTR(X) X +#endif + +//TODO - dont we already have another function that can do this +std::string getExtension(const char* input); + + +#endif diff --git a/jni/desmume/src/version.cpp b/jni/desmume/src/version.cpp new file mode 100755 index 0000000..69c44ae --- /dev/null +++ b/jni/desmume/src/version.cpp @@ -0,0 +1,91 @@ +/* + Copyright (C) 2009-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "types.h" +#include "version.h" + +//todo - everyone will want to support this eventually, i suppose +#if defined(_WINDOWS) && !defined(WXPORT) +#include "svnrev.h" +#else +#ifdef SVN_REV +#define SVN_REV_STR SVN_REV +#else +#define SVN_REV_STR "" +#endif +#endif + +#define DESMUME_NAME "DeSmuME" + +#ifdef _WIN64 +#define DESMUME_PLATFORM_STRING " x64" +#else +#ifdef _WIN32 +#define DESMUME_PLATFORM_STRING " x86" +#else +#define DESMUME_PLATFORM_STRING "" +#endif +#endif + +#ifndef ENABLE_SSE2 + #ifndef ENABLE_SSE + #define DESMUME_CPUEXT_STRING " NOSSE" + #else + #define DESMUME_CPUEXT_STRING " NOSSE2" + #endif +#else +#define DESMUME_CPUEXT_STRING "" +#endif + +#ifdef DEVELOPER +#define DESMUME_FEATURE_STRING " dev+" +#else +#define DESMUME_FEATURE_STRING "" +#endif + +#ifdef DEBUG +#define DESMUME_SUBVERSION_STRING " debug" +#elif defined(PUBLIC_RELEASE) +#define DESMUME_SUBVERSION_STRING "" +#else +#define DESMUME_SUBVERSION_STRING " svn" SVN_REV_STR +#endif + +#ifdef __INTEL_COMPILER +#define DESMUME_COMPILER " (Intel) " +#define DESMUME_COMPILER_DETAIL " (Intel) " +#elif defined(_MSC_VER) +#define DESMUME_COMPILER "" +#define DESMUME_COMPILER_DETAIL " msvc " _Py_STRINGIZE(_MSC_VER) +#define _Py_STRINGIZE(X) _Py_STRINGIZE1((X)) +#define _Py_STRINGIZE1(X) _Py_STRINGIZE2 ## X +#define _Py_STRINGIZE2(X) #X +//re: http://72.14.203.104/search?q=cache:HG-okth5NGkJ:mail.python.org/pipermail/python-checkins/2002-November/030704.html+_msc_ver+compiler+version+string&hl=en&gl=us&ct=clnk&cd=5 +#else +// TODO: make for others compilers +#define DESMUME_COMPILER "" +#define DESMUME_COMPILER_DETAIL "" +#endif + +#define DESMUME_VERSION_NUMERIC 90800 +#define DESMUME_VERSION_STRING " " "0.9.8" DESMUME_SUBVERSION_STRING DESMUME_FEATURE_STRING DESMUME_PLATFORM_STRING DESMUME_CPUEXT_STRING DESMUME_COMPILER +#define DESMUME_NAME_AND_VERSION DESMUME_NAME DESMUME_VERSION_STRING + +u32 EMU_DESMUME_VERSION_NUMERIC() { return DESMUME_VERSION_NUMERIC; } +const char* EMU_DESMUME_VERSION_STRING() { return DESMUME_VERSION_STRING; } +const char* EMU_DESMUME_NAME_AND_VERSION() { return DESMUME_NAME_AND_VERSION; } +const char* EMU_DESMUME_COMPILER_DETAIL() { return DESMUME_COMPILER_DETAIL; } diff --git a/jni/desmume/src/version.h b/jni/desmume/src/version.h new file mode 100755 index 0000000..bbf1987 --- /dev/null +++ b/jni/desmume/src/version.h @@ -0,0 +1,24 @@ +/* + Copyright (C) 2009-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <string> +#include "types.h" + +u32 EMU_DESMUME_VERSION_NUMERIC(); +const char* EMU_DESMUME_VERSION_STRING(); +const char* EMU_DESMUME_NAME_AND_VERSION(); +const char* EMU_DESMUME_COMPILER_DETAIL(); diff --git a/jni/desmume/src/wifi.cpp b/jni/desmume/src/wifi.cpp new file mode 100755 index 0000000..f802a71 --- /dev/null +++ b/jni/desmume/src/wifi.cpp @@ -0,0 +1,2376 @@ +/* + Copyright (C) 2007 Tim Seidel + Copyright (C) 2008-2012 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <assert.h> +#include "wifi.h" +#include "armcpu.h" +#include "NDSSystem.h" +#include "debug.h" +#include "bits.h" + + +#ifdef _WINDOWS + #include <winsock2.h> + #include <ws2tcpip.h> + #define socket_t SOCKET + #define sockaddr_t SOCKADDR + #ifndef WXPORT + #include "windriver.h" + #endif + #define PCAP_DEVICE_NAME description +#else + #include <unistd.h> + #include <stdlib.h> + #include <string.h> + #include <arpa/inet.h> + #include <sys/socket.h> + #define socket_t int + #define sockaddr_t struct sockaddr + #define closesocket close + #define PCAP_DEVICE_NAME name +#endif + +#ifndef INVALID_SOCKET + #define INVALID_SOCKET (socket_t)-1 +#endif + +#define BASEPORT 7000 + +const u8 BroadcastMAC[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + +bool bWFCUserWarned = false; + +#ifdef EXPERIMENTAL_WIFI_COMM +socket_t wifi_socket = INVALID_SOCKET; +sockaddr_t sendAddr; +#ifndef WIN32 +#include "pcap/pcap.h" +#endif +pcap_t *wifi_bridge = NULL; +#endif + +//sometimes this isnt defined +#ifndef PCAP_OPENFLAG_PROMISCUOUS +#define PCAP_OPENFLAG_PROMISCUOUS 1 +#endif + +wifimac_t wifiMac; +SoftAP_t SoftAP; +int wifi_lastmode; + +/******************************************************************************* + + WIFI TODO + + - emulate transmission delays for Beacon and Extra transfers + - emulate delays when receiving as well (may need some queuing system) + - take transfer rate and preamble into account + - figure out RFSTATUS and RFPINS + + *******************************************************************************/ + +/******************************************************************************* + + Firmware info needed for if no firmware image is available + see: http://www.akkit.org/info/dswifi.htm#WifiInit + + written in bytes, to avoid endianess issues + + *******************************************************************************/ + +u8 FW_Mac[6] = { 0x00, 0x09, 0xBF, 0x12, 0x34, 0x56 }; + +const u8 FW_WIFIInit[32] = { 0x02,0x00, 0x17,0x00, 0x26,0x00, 0x18,0x18, + 0x48,0x00, 0x40,0x48, 0x58,0x00, 0x42,0x00, + 0x40,0x01, 0x64,0x80, 0xE0,0xE0, 0x43,0x24, + 0x0E,0x00, 0x32,0x00, 0xF4,0x01, 0x01,0x01 }; +const u8 FW_BBInit[105] = { 0x6D, 0x9E, 0x40, 0x05, + 0x1B, 0x6C, 0x48, 0x80, + 0x38, 0x00, 0x35, 0x07, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0xb0, 0x00, 0x04, 0x01, + 0xd8, 0xff, 0xff, 0xc7, + 0xbb, 0x01, 0xb6, 0x7f, + 0x5a, 0x01, 0x3f, 0x01, + 0x3f, 0x36, 0x36, 0x00, + 0x78, 0x28, 0x55, 0x08, + 0x28, 0x16, 0x00, 0x01, + 0x0e, 0x20, 0x02, 0x98, + 0x98, 0x1f, 0x0a, 0x08, + 0x04, 0x01, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfc, + 0xfa, 0xfa, 0xf8, 0xf8, + 0xf6, 0xa5, 0x12, 0x14, + 0x12, 0x41, 0x23, 0x03, + 0x04, 0x70, 0x35, 0x0E, + 0x16, 0x16, 0x00, 0x00, + 0x06, 0x01, 0xff, 0xfe, + 0xff, 0xff, 0x00, 0x0e, + 0x13, 0x00, 0x00, 0x28, + 0x1c + }; +const u8 FW_RFInit[36] = { 0x07, 0xC0, 0x00, + 0x03, 0x9C, 0x12, + 0x28, 0x17, 0x14, + 0xba, 0xe8, 0x1a, + 0x6f, 0x45, 0x1d, + 0xfa, 0xff, 0x23, + 0x30, 0x1d, 0x24, + 0x01, 0x00, 0x28, + 0x00, 0x00, 0x2c, + 0x03, 0x9c, 0x06, + 0x22, 0x00, 0x08, + 0x6f, 0xff, 0x0d + }; +const u8 FW_RFChannel[6*14] = { 0x28, 0x17, 0x14, /* Channel 1 */ + 0xba, 0xe8, 0x1a, + 0x37, 0x17, 0x14, /* Channel 2 */ + 0x46, 0x17, 0x19, + 0x45, 0x17, 0x14, /* Channel 3 */ + 0xd1, 0x45, 0x1b, + 0x54, 0x17, 0x14, /* Channel 4 */ + 0x5d, 0x74, 0x19, + 0x62, 0x17, 0x14, /* Channel 5 */ + 0xe9, 0xa2, 0x1b, + 0x71, 0x17, 0x14, /* Channel 6 */ + 0x74, 0xd1, 0x19, + 0x80, 0x17, 0x14, /* Channel 7 */ + 0x00, 0x00, 0x18, + 0x8e, 0x17, 0x14, /* Channel 8 */ + 0x8c, 0x2e, 0x1a, + 0x9d, 0x17, 0x14, /* Channel 9 */ + 0x17, 0x5d, 0x18, + 0xab, 0x17, 0x14, /* Channel 10 */ + 0xa3, 0x8b, 0x1a, + 0xba, 0x17, 0x14, /* Channel 11 */ + 0x2f, 0xba, 0x18, + 0xc8, 0x17, 0x14, /* Channel 12 */ + 0xba, 0xe8, 0x1a, + 0xd7, 0x17, 0x14, /* Channel 13 */ + 0x46, 0x17, 0x19, + 0xfa, 0x17, 0x14, /* Channel 14 */ + 0x2f, 0xba, 0x18 + }; +const u8 FW_BBChannel[14] = { 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, /* channel 1- 6 */ + 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, /* channel 7-10 */ + 0xb5, 0xb5, /* channel 11-12 */ + 0xb6, 0xb6 /* channel 13-14 */ + }; + +FW_WFCProfile FW_WFCProfile1 = {"SoftAP", + "", + "", + "", + "", + "", + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + 0, + "", + 0, + 0, + 0, + {0, 0, 0, 0, 0, 0, 0}, + 0, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0} + }; + +FW_WFCProfile FW_WFCProfile2 = {"", + "", + "", + "", + "", + "", + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + 0, + "", + 0, + 0, + 0xFF, + {0, 0, 0, 0, 0, 0, 0}, + 0, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0} + }; + +FW_WFCProfile FW_WFCProfile3 = {"", + "", + "", + "", + "", + "", + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + 0, + "", + 0, + 0, + 0xFF, + {0, 0, 0, 0, 0, 0, 0}, + 0, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0} + }; + +/******************************************************************************* + + Communication interface + + *******************************************************************************/ + +struct WifiComInterface +{ + bool (*Init)(); + void (*DeInit)(); + void (*Reset)(); + void (*SendPacket)(u8* packet, u32 len); + void (*msTrigger)(); +}; + +#ifdef EXPERIMENTAL_WIFI_COMM +bool SoftAP_Init(); +void SoftAP_DeInit(); +void SoftAP_Reset(); +void SoftAP_SendPacket(u8 *packet, u32 len); +void SoftAP_msTrigger(); + +WifiComInterface CI_SoftAP = { + SoftAP_Init, + SoftAP_DeInit, + SoftAP_Reset, + SoftAP_SendPacket, + SoftAP_msTrigger +}; + +bool Adhoc_Init(); +void Adhoc_DeInit(); +void Adhoc_Reset(); +void Adhoc_SendPacket(u8* packet, u32 len); +void Adhoc_msTrigger(); + +WifiComInterface CI_Adhoc = { + Adhoc_Init, + Adhoc_DeInit, + Adhoc_Reset, + Adhoc_SendPacket, + Adhoc_msTrigger +}; +#endif + +WifiComInterface* wifiComs[] = { +#ifdef EXPERIMENTAL_WIFI_COMM + &CI_Adhoc, + &CI_SoftAP, +#endif + NULL +}; +WifiComInterface* wifiCom; + +/******************************************************************************* + + Logging + + *******************************************************************************/ + +// 0: disable logging +// 1: lowest logging, shows most important messages such as errors +// 2: low logging, shows things such as warnings +// 3: medium logging, for debugging, shows lots of stuff +// 4: high logging, for debugging, shows almost everything, may slow down +// 5: highest logging, for debugging, shows everything, may slow down a lot +#define WIFI_LOGGING_LEVEL 3 + +#define WIFI_LOG_USE_LOGC 0 + +#if (WIFI_LOGGING_LEVEL >= 1) + #if WIFI_LOG_USE_LOGC + #define WIFI_LOG(level, ...) if(level <= WIFI_LOGGING_LEVEL) LOGC(8, "WIFI: "__VA_ARGS__); + #else + #define WIFI_LOG(level, ...) if(level <= WIFI_LOGGING_LEVEL) printf("WIFI: "__VA_ARGS__); + #endif +#else +#define WIFI_LOG(level, ...) {} +#endif + +/******************************************************************************* + + Hax + + *******************************************************************************/ + +// TODO: find the right value +// GBAtek says it is 10ĩs, however that value seems too small +// (MP host sends floods of data frames, clients can't keep up) +// 100 would make more sense since CMDCOUNT is set to 166 +// that would be 16.6ms ~= 1 frame +// however this is guessed, like a lot of the wifi here +#define WIFI_CMDCOUNT_SLICE 100 + +/******************************************************************************* + + Helpers + + *******************************************************************************/ + +INLINE u32 WIFI_alignedLen(u32 len) +{ + return ((len + 3) & ~3); +} + +// Fast MAC compares + +INLINE bool WIFI_compareMAC(u8* a, u8* b) +{ + return ((*(u32*)&a[0]) == (*(u32*)&b[0])) && ((*(u16*)&a[4]) == (*(u16*)&b[4])); +} + +INLINE bool WIFI_isBroadcastMAC(u8* a) +{ + return (a[0] & 0x01); + //return ((*(u32*)&a[0]) == 0xFFFFFFFF) && ((*(u16*)&a[4]) == 0xFFFF); +} + +/******************************************************************************* + + CRC32 (http://www.codeproject.com/KB/recipes/crc32_large.aspx) + + *******************************************************************************/ + +u32 WIFI_CRC32Table[256]; + +static u32 reflect(u32 ref, char ch) +{ + u32 value = 0; + + for(int i = 1; i < (ch + 1); i++) + { + if (ref & 1) + value |= 1 << (ch - i); + ref >>= 1; + } + + return value; +} + +static u32 WIFI_calcCRC32(u8 *data, int len) +{ + u32 crc = 0xFFFFFFFF; + + while(len--) + crc = (crc >> 8) ^ WIFI_CRC32Table[(crc & 0xFF) ^ *data++]; + + return (crc ^ 0xFFFFFFFF); +} + +static void WIFI_initCRC32Table() +{ + static bool initialized = false; + if(initialized) return; + initialized = true; + + u32 polynomial = 0x04C11DB7; + + for(int i = 0; i < 0x100; i++) + { + WIFI_CRC32Table[i] = reflect(i, 8) << 24; + for(int j = 0; j < 8; j++) + WIFI_CRC32Table[i] = (WIFI_CRC32Table[i] << 1) ^ (WIFI_CRC32Table[i] & (1 << 31) ? polynomial : 0); + WIFI_CRC32Table[i] = reflect(WIFI_CRC32Table[i], 32); + } +} + +/******************************************************************************* + + RF-Chip + + *******************************************************************************/ + +static void WIFI_resetRF(rffilter_t *rf) +{ + /* reinitialize RF chip with the default values refer RF2958 docs */ + /* CFG1 */ + rf->CFG1.bits.IF_VGA_REG_EN = 1; + rf->CFG1.bits.IF_VCO_REG_EN = 1; + rf->CFG1.bits.RF_VCO_REG_EN = 1; + rf->CFG1.bits.HYBERNATE = 0; + rf->CFG1.bits.REF_SEL = 0; + /* IFPLL1 */ + rf->IFPLL1.bits.DAC = 3; + rf->IFPLL1.bits.P1 = 0; + rf->IFPLL1.bits.LD_EN1 = 0; + rf->IFPLL1.bits.AUTOCAL_EN1 = 0; + rf->IFPLL1.bits.PDP1 = 1; + rf->IFPLL1.bits.CPL1 = 0; + rf->IFPLL1.bits.LPF1 = 0; + rf->IFPLL1.bits.VTC_EN1 = 1; + rf->IFPLL1.bits.KV_EN1 = 0; + rf->IFPLL1.bits.PLL_EN1 = 0; + /* IFPLL2 */ + rf->IFPLL2.bits.IF_N = 0x22; + /* IFPLL3 */ + rf->IFPLL3.bits.KV_DEF1 = 8; + rf->IFPLL3.bits.CT_DEF1 = 7; + rf->IFPLL3.bits.DN1 = 0x1FF; + /* RFPLL1 */ + rf->RFPLL1.bits.DAC = 3; + rf->RFPLL1.bits.P = 0; + rf->RFPLL1.bits.LD_EN = 0; + rf->RFPLL1.bits.AUTOCAL_EN = 0; + rf->RFPLL1.bits.PDP = 1; + rf->RFPLL1.bits.CPL = 0; + rf->RFPLL1.bits.LPF = 0; + rf->RFPLL1.bits.VTC_EN = 0; + rf->RFPLL1.bits.KV_EN = 0; + rf->RFPLL1.bits.PLL_EN = 0; + /* RFPLL2 */ + rf->RFPLL2.bits.NUM2 = 0; + rf->RFPLL2.bits.N2 = 0x5E; + /* RFPLL3 */ + rf->RFPLL3.bits.NUM2 = 0; + /* RFPLL4 */ + rf->RFPLL4.bits.KV_DEF = 8; + rf->RFPLL4.bits.CT_DEF = 7; + rf->RFPLL4.bits.DN = 0x145; + /* CAL1 */ + rf->CAL1.bits.LD_WINDOW = 2; + rf->CAL1.bits.M_CT_VALUE = 8; + rf->CAL1.bits.TLOCK = 7; + rf->CAL1.bits.TVCO = 0x0F; + /* TXRX1 */ + rf->TXRX1.bits.TXBYPASS = 0; + rf->TXRX1.bits.INTBIASEN = 0; + rf->TXRX1.bits.TXENMODE = 0; + rf->TXRX1.bits.TXDIFFMODE = 0; + rf->TXRX1.bits.TXLPFBW = 2; + rf->TXRX1.bits.RXLPFBW = 2; + rf->TXRX1.bits.TXVGC = 0; + rf->TXRX1.bits.PCONTROL = 0; + rf->TXRX1.bits.RXDCFBBYPS = 0; + /* PCNT1 */ + rf->PCNT1.bits.TX_DELAY = 0; + rf->PCNT1.bits.PC_OFFSET = 0; + rf->PCNT1.bits.P_DESIRED = 0; + rf->PCNT1.bits.MID_BIAS = 0; + /* PCNT2 */ + rf->PCNT2.bits.MIN_POWER = 0; + rf->PCNT2.bits.MID_POWER = 0; + rf->PCNT2.bits.MAX_POWER = 0; + /* VCOT1 */ + rf->VCOT1.bits.AUX1 = 0; + rf->VCOT1.bits.AUX = 0; +} + + +void WIFI_setRF_CNT(u16 val) +{ + if (!wifiMac.rfIOStatus.bits.busy) + wifiMac.rfIOCnt.val = val; +} + +void WIFI_setRF_DATA(u16 val, u8 part) +{ + if (!wifiMac.rfIOStatus.bits.busy) + { + rfIOData_t *rfreg = (rfIOData_t *)&wifiMac.RF; + switch (wifiMac.rfIOCnt.bits.readOperation) + { + case 1: /* read from RF chip */ + /* low part of data is ignored on reads */ + /* on high part, the address is read, and the data at this is written back */ + if (part==1) + { + wifiMac.rfIOData.array16[part] = val; + if (wifiMac.rfIOData.bits.address > (sizeof(wifiMac.RF) / 4)) return; /* out of bound */ + /* get content of the addressed register */ + wifiMac.rfIOData.bits.content = rfreg[wifiMac.rfIOData.bits.address].bits.content; + } + break; + case 0: /* write to RF chip */ + wifiMac.rfIOData.array16[part] = val; + if (wifiMac.rfIOData.bits.address > (sizeof(wifiMac.RF) / 4)) return; /* out of bound */ + /* the actual transfer is done on high part write */ + if (part==1) + { + switch (wifiMac.rfIOData.bits.address) + { + case 5: /* write to upper part of the frequency filter */ + case 6: /* write to lower part of the frequency filter */ + { + u32 channelFreqN; + rfreg[wifiMac.rfIOData.bits.address].bits.content = wifiMac.rfIOData.bits.content; + /* get the complete rfpll.n */ + channelFreqN = (u32)wifiMac.RF.RFPLL3.bits.NUM2 + ((u32)wifiMac.RF.RFPLL2.bits.NUM2 << 18) + ((u32)wifiMac.RF.RFPLL2.bits.N2 << 24); + /* frequency setting is out of range */ + if (channelFreqN<0x00A2E8BA) return; + /* substract base frequency (channel 1) */ + channelFreqN -= 0x00A2E8BA; + } + return; + case 13: + /* special purpose register: TEST1, on write, the RF chip resets */ + WIFI_resetRF(&wifiMac.RF); + return; + } + /* set content of the addressed register */ + rfreg[wifiMac.rfIOData.bits.address].bits.content = wifiMac.rfIOData.bits.content; + } + break; + } + } +} + +u16 WIFI_getRF_DATA(u8 part) +{ + if (!wifiMac.rfIOStatus.bits.busy) + return wifiMac.rfIOData.array16[part]; + else + /* data is not (yet) available */ + return 0; + } + +u16 WIFI_getRF_STATUS() +{ + return wifiMac.rfIOStatus.val; +} + +/******************************************************************************* + + BB-Chip + + *******************************************************************************/ + +void WIFI_setBB_CNT(u16 val) +{ + wifiMac.bbIOCnt.val = val; + + if(wifiMac.bbIOCnt.bits.mode == 1) + wifiMac.BB.data[wifiMac.bbIOCnt.bits.address] = WIFI_IOREG(REG_WIFI_BBWRITE); +} + +u8 WIFI_getBB_DATA() +{ + if((!wifiMac.bbIOCnt.bits.enable) || (wifiMac.bbIOCnt.bits.mode != 2)) + return 0; + + return wifiMac.BB.data[wifiMac.bbIOCnt.bits.address]; +} + +/******************************************************************************* + + wifimac IO: a lot of the wifi regs are action registers, that are mirrored + without action, so the default IO via MMU.c does not seem to + be very suitable + + all registers are 16 bit + + *******************************************************************************/ + +static void WIFI_TXStart(u32 slot); + +static void WIFI_triggerIRQMask(u16 mask) +{ + u16 oResult,nResult; + oResult = wifiMac.IE & wifiMac.IF; + wifiMac.IF = wifiMac.IF | (mask & ~0x0400); + nResult = wifiMac.IE & wifiMac.IF; + + if (!oResult && nResult) + { + NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_ARM7_WIFI); /* cascade it via arm7 wifi irq */ + } +} + +static void WIFI_triggerIRQ(u8 irq) +{ + switch (irq) + { + case WIFI_IRQ_TXSTART: + break; + case WIFI_IRQ_TIMEPREBEACON: + if (wifiMac.TXPower & 0x0001) + { + //wifiMac.rfStatus = 1; + //wifiMac.rfPins = 0x0084; + } + break; + case WIFI_IRQ_TIMEBEACON: + wifiMac.BeaconCount1 = wifiMac.BeaconInterval; + + if (wifiMac.ucmpEnable) + { + wifiMac.BeaconCount2 = 0xFFFF; + wifiMac.TXCnt &= 0xFFF2; + + WIFI_TXStart(WIFI_TXSLOT_BEACON); + + if (wifiMac.ListenCount == 0) wifiMac.ListenCount = wifiMac.ListenInterval; + wifiMac.ListenCount--; + } + break; + case WIFI_IRQ_TIMEPOSTBEACON: + if (wifiMac.TXPower & 0x0002) + { + //wifiMac.rfStatus = 9; + //wifiMac.rfPins = 0x0004; + } + break; + case WIFI_IRQ_UNK: + WIFI_LOG(3, "IRQ 12 triggered.\n"); + break; + } + + WIFI_triggerIRQMask(1<<irq); +} + + +bool WIFI_Init() +{ + WIFI_initCRC32Table(); + wifi_lastmode = -999; + WIFI_Reset(); + return true; +} + +void WIFI_DeInit() +{ + if (wifiCom) wifiCom->DeInit(); +} + +void WIFI_Reset() +{ +#ifdef EXPERIMENTAL_WIFI_COMM + //memset(&wifiMac, 0, sizeof(wifimac_t)); + + WIFI_resetRF(&wifiMac.RF); + + memset(wifiMac.IOPorts, 0, sizeof(wifiMac.IOPorts)); + + wifiMac.randomSeed = 1; + + wifiMac.crystalEnabled = FALSE; + wifiMac.powerOn = FALSE; + wifiMac.powerOnPending = FALSE; + + wifiMac.GlobalUsecTimer = wifiMac.usec = wifiMac.ucmp = 0ULL; + + //wifiMac.rfStatus = 0x0000; + //wifiMac.rfPins = 0x0004; + wifiMac.rfStatus = 0x0009; + wifiMac.rfPins = 0x00C6; + + memset(wifiMac.TXSlots, 0, sizeof(wifiMac.TXSlots)); + wifiMac.TXCurSlot = -1; + wifiMac.TXCnt = wifiMac.TXStat = wifiMac.TXSeqNo = wifiMac.TXBusy = 0; + while (!wifiMac.RXPacketQueue.empty()) + wifiMac.RXPacketQueue.pop(); + + if((u32)CommonSettings.wifi.mode >= ARRAY_SIZE(wifiComs)) + CommonSettings.wifi.mode = 0; + if (wifiCom && (wifi_lastmode != CommonSettings.wifi.mode)) + wifiCom->DeInit(); + wifiCom = wifiComs[CommonSettings.wifi.mode]; + if (wifiCom && (wifi_lastmode != CommonSettings.wifi.mode)) + wifiCom->Init(); + else if (wifiCom) + wifiCom->Reset(); + wifi_lastmode = CommonSettings.wifi.mode; + + bWFCUserWarned = false; +#endif +} + + +INLINE u16 WIFI_GetRXFlags(u8* packet) +{ + u16 ret = 0x0010; + u16 frameCtl = *(u16*)&packet[0]; + u32 bssid_offset = 10; + + frameCtl &= 0xE7FF; + + switch(frameCtl & 0x000C) + { + case 0x0000: // Management frame + { + bssid_offset = 16; + + if ((frameCtl & 0x00F0) == 0x0080) + ret |= 0x0001; + } + break; + + case 0x0004: // Control frame + ret |= 0x0005; + break; + + case 0x0008: // Data frame + { + switch (frameCtl & 0x0300) + { + case 0x0000: bssid_offset = 16; break; + case 0x0100: bssid_offset = 4; break; + case 0x0200: bssid_offset = 10; break; + } + + if (frameCtl == 0x0228) + ret |= 0x000C; + else if (frameCtl == 0x0218) + ret |= 0x000D; + else if (frameCtl == 0x0118) + ret |= 0x000E; + else + ret |= 0x0008; + } + break; + } + + if (frameCtl & 0x0400) + ret |= 0x0100; + + if (WIFI_compareMAC(&packet[bssid_offset], &wifiMac.bss.bytes[0])) + ret |= 0x8000; + + return ret; +} + +INLINE void WIFI_MakeRXHeader(u8* buf, u16 flags, u16 xferRate, u16 len, u8 maxRSSI, u8 minRSSI) +{ + *(u16*)&buf[0] = flags; + + // Unknown, seems to always be 0x0040 + // except with from-DS-to-STA data+cfpoll frames (0228) + *(u16*)&buf[2] = ((flags & 0xF) == 0xC) ? 0x0000 : 0x0040; + + // random (probably left unchanged) + //*(u16*)&buf[4] = 0x0000; + + *(u16*)&buf[6] = xferRate; + *(u16*)&buf[8] = len; + + // idk about those, really + buf[10] = 0x20;//maxRSSI; + buf[11] = 0xA0;//minRSSI; +} + +static void WIFI_RXPutWord(u16 val) +{ + /* abort when RX data queuing is not enabled */ + if (!(wifiMac.RXCnt & 0x8000)) return; + /* write the data to cursor position */ + wifiMac.RAM[wifiMac.RXWriteCursor & 0xFFF] = val; + /* move cursor by one */ + wifiMac.RXWriteCursor++; + + /* wrap around */ + if(wifiMac.RXWriteCursor >= (wifiMac.RXRangeEnd >> 1)) + wifiMac.RXWriteCursor = (wifiMac.RXRangeBegin >> 1); + + wifiMac.RXTXAddr = wifiMac.RXWriteCursor; +} + +#ifdef EXPERIMENTAL_WIFI_COMM +static void WIFI_RXQueuePacket(u8* packet, u32 len) +{ + if (!(wifiMac.RXCnt & 0x8000)) return; + + Wifi_RXPacket pkt; + pkt.Data = packet; + pkt.RemHWords = (len - 11) >> 1; + pkt.CurOffset = 12; + pkt.NotStarted = true; + wifiMac.RXPacketQueue.push(pkt); +} +#endif + +template<int stat> static void WIFI_IncrementRXStat() +{ + u16 bitmasks[] = { 0x0001, 0, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, + 0x0080, 0, 0x0100, 0, 0x0200, 0x0400, 0x0800, 0x1000}; + + u16 bitmask = bitmasks[stat]; + + wifiMac.RXStat[stat]++; + if (wifiMac.RXStatIncIE & bitmask) + { + wifiMac.RXStatIncIF |= bitmask; + WIFI_triggerIRQ(WIFI_IRQ_RXINC); + } + + if (wifiMac.RXStat[stat] & 0x80) + { + if (wifiMac.RXStatOvfIE & bitmask) + { + wifiMac.RXStatOvfIF |= bitmask; + WIFI_triggerIRQ(WIFI_IRQ_RXOVF); + } + } +} + +// TODO: find out if this is correct at all +// this was mostly guessed, like most of the MP reply functionality +static void WIFI_DoAutoReply(u8* cmd) +{ + cmd += 12; + + u16 frameCtl = *(u16*)&cmd[0] & 0xE7FF; + if (frameCtl == 0x0228) + { + // if the packet we got is a multiplayer command (data+cf-poll), + // check if it was destined to us + u16 slaveflags = *(u16*)&cmd[24 + 2]; + if (!(slaveflags & (1 << wifiMac.pid))) + return; + + // if it was destined to us, (try to) send a reply + u16 regval = WIFI_IOREG(REG_WIFI_TXBUF_REPLY1); + wifiMac.TXSlots[WIFI_TXSLOT_MPREPLY].RegVal = regval; + + regval &= 0x0FFF; + wifiMac.RAM[regval + 6 + 1] = *(u16*)&cmd[24]; + + WIFI_TXStart(WIFI_TXSLOT_MPREPLY); + } + /*else if (frameCtl == 0x0118) + { + // broadcast MP ACK + // this packet appears to be sent automatically + // PS: nope. Enabling this code causes NSMB to break the connection even quicker. + // Probably it should send the ACK itself whenever it wants to... + + u8 ack[32]; + *(u16*)&ack[0] = 0x0218; + *(u16*)&ack[2] = 0x0000; + *(u16*)&ack[4] = 0x0903; + *(u16*)&ack[6] = 0x00BF; + *(u16*)&ack[8] = 0x0300; + memcpy(&ack[10], &wifiMac.mac.bytes[0], 6); + memcpy(&ack[16], &wifiMac.mac.bytes[0], 6); + *(u16*)&ack[22] = wifiMac.TXSeqNo << 4; wifiMac.TXSeqNo++; + *(u16*)&ack[24] = 0x0555; // lol random + *(u16*)&ack[26] = 0x0000; + *(u32*)&ack[28] = 0x00000000; + + wifiCom->SendPacket(ack, 32); + }*/ +} + +static void WIFI_TXStart(u32 slot) +{ + WIFI_LOG(4, "TX slot %i trying to send a packet: TXCnt = %04X, TXBufLoc = %04X\n", + slot, wifiMac.TXCnt, wifiMac.TXSlots[slot].RegVal); + + u16 reg = wifiMac.TXSlots[slot].RegVal; + if (BIT15(reg)) + { + u16 address = reg & 0x0FFF; + if (address > 0x1000-6) + { + WIFI_LOG(1, "TX slot %i trying to send a packet overflowing from the TX buffer (address %04X). Attempt ignored.\n", + slot, (address << 1)); + return; + } + + u16 txLen = wifiMac.RAM[address+5] & 0x3FFF; + if (txLen == 0) // zero length + { + WIFI_LOG(1, "TX slot %i trying to send a packet with length field set to zero. Attempt ignored.\n", + slot); + return; + } + + u32 timemask = ((wifiMac.RAM[address+4] & 0xFF) == 20) ? 7 : 15; + + wifiMac.TXSlots[slot].CurAddr = address + 6; + wifiMac.TXSlots[slot].RemHWords = (txLen + 1) >> 1; + wifiMac.TXSlots[slot].RemPreamble = (BIT2(WIFI_IOREG(REG_WIFI_PREAMBLE)) && (timemask == 7)) ? 96 : 192; + wifiMac.TXSlots[slot].TimeMask = timemask; + wifiMac.TXSlots[slot].NotStarted = true; + + if (wifiMac.TXCurSlot < 0) + wifiMac.TXCurSlot = slot; + wifiMac.TXBusy |= (1 << slot); + + //wifiMac.rfStatus = 3; + //wifiMac.rfPins = 0x0046; + } +} + +static void WIFI_PreTXAdjustments(u32 slot) +{ + u16 reg = wifiMac.TXSlots[slot].RegVal; + u16 address = reg & 0x0FFF; + u16 txLen = wifiMac.RAM[address+5] & 0x3FFF; + + // Set sequence number if required + if ((!BIT13(reg)) || (slot == WIFI_TXSLOT_BEACON)) + { + wifiMac.RAM[address + 6 + 11] = wifiMac.TXSeqNo << 4; + wifiMac.TXSeqNo++; + // TODO: find out when this happens (if it actually happens at all) + // real-life NSMB multiplayer traffic capture shows no such behavior + //if (slot == WIFI_TXSLOT_MPCMD) wifiMac.TXSeqNo++; + } + + // Set timestamp (for beacons only) + if (slot == WIFI_TXSLOT_BEACON) + { + *(u64*)&wifiMac.RAM[address + 6 + 12] = wifiMac.usec; + //((u8*)wifiMac.RAM)[((address+6+12)<<1) + WIFI_IOREG(0x84)] = 0x01; + } + + // TODO: check if this is correct + // this sometimes happens in real world, but not always + /*if (slot == WIFI_TXSLOT_MPREPLY) + { + wifiMac.RAM[address + 6 + 12] |= 0x8000; + }*/ + + // Calculate and set FCS + u32 crc32 = WIFI_calcCRC32((u8*)&wifiMac.RAM[address + 6], txLen - 4); + *(u32*)&wifiMac.RAM[address + 6 + ((txLen-4) >> 1)] = crc32; +} + +void WIFI_write16(u32 address, u16 val) +{ + BOOL action = FALSE; + if (!nds.power2.wifi) return; + + u32 page = address & 0x7000; + + // 0x2000 - 0x3FFF: unused + if ((page >= 0x2000) && (page < 0x4000)) + return; + + WIFI_LOG(5, "Write at address %08X, %04X\n", address, val); + /*if (address == 0x04804008 && val == 0x0200) + { + printf("WIFI: Write at address %08X, %04X, pc=%08X\n", address, val, NDS_ARM7.instruct_adr); + emu_halt(); + }*/ + + // 0x4000 - 0x5FFF: wifi RAM + if ((page >= 0x4000) && (page < 0x6000)) + { + /* access to the circular buffer */ + address &= 0x1FFF; + /*if (address >= 0x958 && address < (0x95A)) //address < (0x958+0x2A)) + printf("PACKET[%04X] = %04X %08X %08X\n", + NDS_ARM7.R[12], val, NDS_ARM7.R[14], NDS_ARM7.R[5]);*/ + wifiMac.RAM[address >> 1] = val; + return; + } + + // anything else: I/O ports + // only the first mirror (0x0000 - 0x0FFF) causes a special action + if (page == 0x0000) action = TRUE; + + address &= 0x0FFF; + switch (address) + { + case REG_WIFI_ID: + break; + case REG_WIFI_MODE: + { + u16 oldval = wifiMac.macMode; + + if (!BIT0(oldval) && BIT0(val)) + { + WIFI_IOREG(0x034) = 0x0002; + wifiMac.rfPins = 0x0046; + wifiMac.rfStatus = 0x0009; + WIFI_IOREG(0x27C) = 0x0005; + } + + if (BIT0(oldval) && !BIT0(val)) + { + WIFI_IOREG(0x27C) = 0x000A; + } + + if (BIT13(val)) + { + WIFI_IOREG(REG_WIFI_WRITECSRLATCH) = 0x0000; + WIFI_IOREG(0x0C0) = 0x0000; + WIFI_IOREG(0x0C4) = 0x0000; + WIFI_IOREG(REG_WIFI_MAYBE_RATE) = 0x0000; + WIFI_IOREG(0x278) = 0x000F; + } + + if (BIT14(val)) + { + wifiMac.wepMode = 0x0000; + wifiMac.TXStatCnt = 0x0000; + WIFI_IOREG(REG_WIFI_0A) = 0x0000; + wifiMac.mac.words[0] = 0x0000; + wifiMac.mac.words[1] = 0x0000; + wifiMac.mac.words[2] = 0x0000; + wifiMac.bss.words[0] = 0x0000; + wifiMac.bss.words[1] = 0x0000; + wifiMac.bss.words[2] = 0x0000; + wifiMac.pid = 0x0000; + wifiMac.aid = 0x0000; + WIFI_IOREG(REG_WIFI_RETRYLIMIT) = 0x0707; + WIFI_IOREG(0x02E) = 0x0000; + WIFI_IOREG(REG_WIFI_RXRANGEBEGIN) = 0x4000; + WIFI_IOREG(REG_WIFI_RXRANGEEND) = 0x4800; + wifiMac.RXRangeBegin = 0x0000; // 0x4000 + wifiMac.RXRangeEnd = 0x0800; // 0x4800 + WIFI_IOREG(0x084) = 0x0000; + WIFI_IOREG(REG_WIFI_PREAMBLE) = 0x0001; + WIFI_IOREG(REG_WIFI_RXFILTER) = 0x0401; + WIFI_IOREG(0x0D4) = 0x0001; + WIFI_IOREG(REG_WIFI_RXFILTER2) = 0x0008; + WIFI_IOREG(0x0EC) = 0x3F03; + WIFI_IOREG(0x194) = 0x0000; + WIFI_IOREG(0x198) = 0x0000; + WIFI_IOREG(0x1A2) = 0x0001; + WIFI_IOREG(0x224) = 0x0003; + WIFI_IOREG(0x230) = 0x0047; + } + + wifiMac.macMode = val & 0xAFFF; + } + break; + case REG_WIFI_WEP: + wifiMac.wepMode = val; + break; + case REG_WIFI_TXSTATCNT: + wifiMac.TXStatCnt = val; + //printf("txstatcnt=%04X\n", val); + break; + case REG_WIFI_IE: + wifiMac.IE = val; + //printf("wifi ie write %04X\n", val); + break; + case REG_WIFI_IF: + wifiMac.IF &= ~val; /* clear flagging bits */ + break; + case REG_WIFI_MAC0: + case REG_WIFI_MAC1: + case REG_WIFI_MAC2: + wifiMac.mac.words[(address - REG_WIFI_MAC0) >> 1] = val; + break; + case REG_WIFI_BSS0: + case REG_WIFI_BSS1: + case REG_WIFI_BSS2: + wifiMac.bss.words[(address - REG_WIFI_BSS0) >> 1] = val; + break; + case REG_WIFI_RETRYLIMIT: + wifiMac.retryLimit = val; + break; + case REG_WIFI_WEPCNT: + wifiMac.WEP_enable = (val & 0x8000) != 0; + break; + case REG_WIFI_POWERSTATE: + wifiMac.powerOn = ((val & 0x0002)?TRUE:FALSE); + if(wifiMac.powerOn) WIFI_triggerIRQ(WIFI_IRQ_RFWAKEUP); + break; + case REG_WIFI_POWERFORCE: + if((val & 0x8000) && (!wifiMac.powerOnPending)) + { + /* BOOL newPower = ((val & 0x0001)?FALSE:TRUE); + if(newPower != wifiMac.powerOn) + { + if(!newPower) + wifiMac.powerOn = FALSE; + else + wifiMac.powerOnPending = TRUE; + }*/ + wifiMac.powerOn = ((val & 0x0001) ? FALSE : TRUE); + } + break; + case REG_WIFI_POWERACK: + if((val == 0x0000) && wifiMac.powerOnPending) + { + wifiMac.powerOn = TRUE; + wifiMac.powerOnPending = FALSE; + } + break; + case REG_WIFI_POWER_TX: + wifiMac.TXPower = val & 0x0007; + break; + case REG_WIFI_RXCNT: + wifiMac.RXCnt = val & 0xFF0E; + if (BIT0(val)) + { + wifiMac.RXWriteCursor = WIFI_IOREG(REG_WIFI_WRITECSRLATCH); + WIFI_IOREG(REG_WIFI_RXHWWRITECSR) = wifiMac.RXWriteCursor; + //printf("latch RX cursor: %04X @ %08X\n", wifiMac.RXWriteCursor, NDS_ARM7.instruct_adr); + } + if (BIT7(val)) + { + WIFI_LOG(2, "TXBUF_REPLY=%04X\n", WIFI_IOREG(REG_WIFI_TXBUF_REPLY1)); + wifiMac.TXSlots[WIFI_TXSLOT_MPREPLY].RegVal = WIFI_IOREG(REG_WIFI_TXBUF_REPLY1); + WIFI_IOREG(REG_WIFI_TXBUF_REPLY1) = 0x0000; + } + if (!BIT15(val)) + { + while (!wifiMac.RXPacketQueue.empty()) + wifiMac.RXPacketQueue.pop(); + } + break; + case REG_WIFI_RXRANGEBEGIN: + wifiMac.RXRangeBegin = val & 0x1FFE; + if(wifiMac.RXWriteCursor < (wifiMac.RXRangeBegin >> 1)) + wifiMac.RXWriteCursor = (wifiMac.RXRangeBegin >> 1); + break; + case REG_WIFI_RXRANGEEND: + wifiMac.RXRangeEnd = val & 0x1FFE; + if(wifiMac.RXWriteCursor >= (wifiMac.RXRangeEnd >> 1)) + wifiMac.RXWriteCursor = (wifiMac.RXRangeBegin >> 1); + break; + + case REG_WIFI_CIRCBUFRADR: + wifiMac.CircBufReadAddress = (val & 0x1FFE); + break; + case REG_WIFI_RXREADCSR: + wifiMac.RXReadCursor = val; + break; + case REG_WIFI_CIRCBUFWADR: + wifiMac.CircBufWriteAddress = val; + break; + case REG_WIFI_CIRCBUFWRITE: + /* set value into the circ buffer, and move cursor to the next hword on action */ + //printf("wifi: circbuf fifo write at %04X, %04X (action=%i)\n", (wifiMac.CircBufWriteAddress & 0x1FFF), val, action); + wifiMac.RAM[(wifiMac.CircBufWriteAddress >> 1) & 0xFFF] = val; + if (action) + { + /* move to next hword */ + wifiMac.CircBufWriteAddress+=2; + if (wifiMac.CircBufWriteAddress == wifiMac.CircBufWrEnd) + { + /* on end of buffer, add skip hwords to it */ + wifiMac.CircBufWrEnd += wifiMac.CircBufWrSkip * 2; + } + } + break; + case REG_WIFI_CIRCBUFWR_SKIP: + wifiMac.CircBufWrSkip = val; + break; + case REG_WIFI_TXBUF_BEACON: + wifiMac.TXSlots[WIFI_TXSLOT_BEACON].RegVal = val; + if (BIT15(val)) + WIFI_LOG(3, "Beacon transmission enabled to send the packet at %08X every %i milliseconds.\n", + 0x04804000 + ((val & 0x0FFF) << 1), wifiMac.BeaconInterval); + break; + case REG_WIFI_TXBUF_CMD: + wifiMac.TXSlots[WIFI_TXSLOT_MPCMD].RegVal = val; + break; + case REG_WIFI_TXBUF_LOC1: + //printf("-------- TXBUF_LOC1 = %04X %08X --------\n", val, NDS_ARM7.instruct_adr); + wifiMac.TXSlots[WIFI_TXSLOT_LOC1].RegVal = val; + break; + case REG_WIFI_TXBUF_LOC2: + //printf("-------- TXBUF_LOC2 = %04X %08X --------\n", val, NDS_ARM7.instruct_adr); + wifiMac.TXSlots[WIFI_TXSLOT_LOC2].RegVal = val; + break; + case REG_WIFI_TXBUF_LOC3: + //printf("-------- TXBUF_LOC3 = %04X %08X --------\n", val, NDS_ARM7.instruct_adr); + wifiMac.TXSlots[WIFI_TXSLOT_LOC3].RegVal = val; + break; + case REG_WIFI_TXRESET: + WIFI_LOG(4, "Write to TXRESET: %04X\n", val); + break; + case REG_WIFI_TXREQ_RESET: + wifiMac.TXCnt &= ~val; + break; + case REG_WIFI_TXREQ_SET: + //printf("--- TXREQ=%04X ---\n", val); + wifiMac.TXCnt |= val; + if (BIT0(val)) WIFI_TXStart(WIFI_TXSLOT_LOC1); + if (BIT1(val)) WIFI_TXStart(WIFI_TXSLOT_MPCMD); + if (BIT2(val)) WIFI_TXStart(WIFI_TXSLOT_LOC2); + if (BIT3(val)) WIFI_TXStart(WIFI_TXSLOT_LOC3); + if (val & 0xFFF0) WIFI_LOG(2, "Unknown TXREQ bits set: %04X\n", val); + break; + case REG_WIFI_RFCNT: + WIFI_setRF_CNT(val); + break; + case REG_WIFI_RFBUSY: + /* CHECKME: read only? */ + break; + case REG_WIFI_RFDATA1: + WIFI_setRF_DATA(val,0); + break; + case REG_WIFI_RFDATA2: + WIFI_setRF_DATA(val,1); + break; + case REG_WIFI_USCOUNTERCNT: + wifiMac.usecEnable = BIT0(val); + break; + case REG_WIFI_USCOMPARECNT: + wifiMac.ucmpEnable = BIT0(val); + break; + case REG_WIFI_USCOUNTER0: + wifiMac.usec = (wifiMac.usec & 0xFFFFFFFFFFFF0000ULL) | (u64)val; + break; + case REG_WIFI_USCOUNTER1: + wifiMac.usec = (wifiMac.usec & 0xFFFFFFFF0000FFFFULL) | (u64)val << 16; + break; + case REG_WIFI_USCOUNTER2: + wifiMac.usec = (wifiMac.usec & 0xFFFF0000FFFFFFFFULL) | (u64)val << 32; + break; + case REG_WIFI_USCOUNTER3: + wifiMac.usec = (wifiMac.usec & 0x0000FFFFFFFFFFFFULL) | (u64)val << 48; + break; + case REG_WIFI_USCOMPARE0: + wifiMac.ucmp = (wifiMac.ucmp & 0xFFFFFFFFFFFF0000ULL) | (u64)(val & 0xFFFE); + // in NSMB multiplayer, Luigi sets USCOMPARE to the USCOUNTER of Mario, and sets bit0 + // possibly bit0 writes USCOMPARE into USCOUNTER? + // it seems to also trigger IRQ14 + // in NSMB, Luigi sends packets on the first attempt only if we trigger IRQ14 here + if (BIT0(val)) + { + //printf("OBSCURE BIT SET @ %08X\n", NDS_ARM7.instruct_adr); + wifiMac.usec = wifiMac.ucmp; + WIFI_triggerIRQ(WIFI_IRQ_TIMEBEACON); + } + break; + case REG_WIFI_USCOMPARE1: + wifiMac.ucmp = (wifiMac.ucmp & 0xFFFFFFFF0000FFFFULL) | (u64)val << 16; + break; + case REG_WIFI_USCOMPARE2: + wifiMac.ucmp = (wifiMac.ucmp & 0xFFFF0000FFFFFFFFULL) | (u64)val << 32; + break; + case REG_WIFI_USCOMPARE3: + wifiMac.ucmp = (wifiMac.ucmp & 0x0000FFFFFFFFFFFFULL) | (u64)val << 48; + break; + case REG_WIFI_BEACONPERIOD: + wifiMac.BeaconInterval = val & 0x03FF; + break; + case REG_WIFI_BEACONCOUNT1: + wifiMac.BeaconCount1 = val; + break; + case REG_WIFI_BEACONCOUNT2: + wifiMac.BeaconCount2 = val; + break; + case REG_WIFI_BBCNT: + WIFI_setBB_CNT(val); + break; + case REG_WIFI_RXBUF_COUNT: + wifiMac.RXBufCount = val & 0x0FFF; + break; + case REG_WIFI_EXTRACOUNTCNT: + wifiMac.eCountEnable = BIT0(val); + break; + case REG_WIFI_EXTRACOUNT: + WIFI_LOG(3, "EXTRACOUNT=%i (%i ĩs)\n", val, val*WIFI_CMDCOUNT_SLICE); + wifiMac.eCount = (u32)val * WIFI_CMDCOUNT_SLICE; + break; + case REG_WIFI_LISTENINT: + wifiMac.ListenInterval = val & 0x00FF; + break; + case REG_WIFI_LISTENCOUNT: + wifiMac.ListenCount = val & 0x00FF; + break; + case REG_WIFI_POWER_US: + wifiMac.crystalEnabled = !BIT0(val); + break; + case REG_WIFI_IF_SET: + WIFI_triggerIRQMask(val); + break; + case REG_WIFI_CIRCBUFRD_END: + wifiMac.CircBufRdEnd = (val & 0x1FFE); + break; + case REG_WIFI_CIRCBUFRD_SKIP: + wifiMac.CircBufRdSkip = val & 0xFFF; + break; + case REG_WIFI_AID_LOW: + //printf("AID_LOW = %04X @ %08X %08X\n", val, NDS_ARM7.instruct_adr, NDS_ARM7.R[14]); + wifiMac.pid = val & 0x0F; + break; + case REG_WIFI_AID_HIGH: + //printf("AID_HIGH = %04X @ %08X %08X\n", val, NDS_ARM7.instruct_adr, NDS_ARM7.R[14]); + wifiMac.aid = val & 0x07FF; + break; + case 0xD0: + //printf("wifi: rxfilter=%04X\n", val); + break; + case 0x0E0: + //printf("wifi: rxfilter2=%04X\n", val); + break; + + case 0x84: + //printf("TXBUF_TIM = %04X\n", val); + break; + + case 0x94: + printf("!!!!! TXBUF_REPLY = %04X !!!!!\n", val); + break; + + case REG_WIFI_RXSTAT_INC_IE: wifiMac.RXStatIncIE = val; break; + case REG_WIFI_RXSTAT_OVF_IE: wifiMac.RXStatOvfIE = val; break; + + case 0x1A8: + case 0x1AC: + case 0x1B0: + case 0x1B2: + case 0x1B4: + case 0x1B6: + case 0x1B8: + case 0x1BA: + case 0x1BC: + case 0x1BE: + WIFI_LOG(2, "Write to RXSTAT register: %03X = %04X\n", address, val); + break; + + case 0x194: + printf("TX_HDR_CNT = %04X\n", val); + break; + + default: + break; + } + + WIFI_IOREG(address) = val; +} + +u16 WIFI_read16(u32 address) +{ + BOOL action = FALSE; + if (!nds.power2.wifi) return 0; + + u32 page = address & 0x7000; + + // 0x2000 - 0x3FFF: unused + if ((page >= 0x2000) && (page < 0x4000)) + return 0xFFFF; + + WIFI_LOG(5, "Read at address %08X\n", address); + + // 0x4000 - 0x5FFF: wifi RAM + if ((page >= 0x4000) && (page < 0x6000)) + { + return wifiMac.RAM[(address & 0x1FFF) >> 1]; + } + + // anything else: I/O ports + // only the first mirror causes a special action + if (page == 0x0000) action = TRUE; + + address &= 0x0FFF; + switch (address) + { + case REG_WIFI_ID: + return WIFI_CHIPID; + case REG_WIFI_MODE: + return wifiMac.macMode; + case REG_WIFI_WEP: + return wifiMac.wepMode; + case REG_WIFI_IE: + return wifiMac.IE; + case REG_WIFI_IF: + return wifiMac.IF; + case REG_WIFI_POWERSTATE: + return ((wifiMac.powerOn ? 0x0000 : 0x0200) | (wifiMac.powerOnPending ? 0x0102 : 0x0000)); + case REG_WIFI_RFDATA1: + return WIFI_getRF_DATA(0); + case REG_WIFI_RFDATA2: + return WIFI_getRF_DATA(1); + case REG_WIFI_RFBUSY: + case REG_WIFI_BBBUSY: + return 0; /* we are never busy :p */ + case REG_WIFI_BBREAD: + return WIFI_getBB_DATA(); + case REG_WIFI_RANDOM: + // probably not right, but it's better than using the unsaved and shared rand(). + // at the very least, rand() shouldn't be used when movieMode is active. + { + u16 returnValue = wifiMac.randomSeed; + wifiMac.randomSeed = (wifiMac.randomSeed & 1) ^ (((wifiMac.randomSeed << 1) & 0x7FE) | ((wifiMac.randomSeed >> 10) & 0x1)); + return returnValue; + } + + return 0; + case REG_WIFI_MAC0: + case REG_WIFI_MAC1: + case REG_WIFI_MAC2: + return wifiMac.mac.words[(address - REG_WIFI_MAC0) >> 1]; + case REG_WIFI_BSS0: + case REG_WIFI_BSS1: + case REG_WIFI_BSS2: + return wifiMac.bss.words[(address - REG_WIFI_BSS0) >> 1]; + case REG_WIFI_RXCNT: + return wifiMac.RXCnt; + case REG_WIFI_CIRCBUFREAD: + { + u16 val = wifiMac.RAM[wifiMac.CircBufReadAddress >> 1]; + if (action) + { + wifiMac.CircBufReadAddress += 2; + + if (wifiMac.CircBufReadAddress >= wifiMac.RXRangeEnd) + { + wifiMac.CircBufReadAddress = wifiMac.RXRangeBegin; + } + else + { + /* skip does not fire after a reset */ + if (wifiMac.CircBufReadAddress == wifiMac.CircBufRdEnd) + { + wifiMac.CircBufReadAddress += wifiMac.CircBufRdSkip * 2; + wifiMac.CircBufReadAddress &= 0x1FFE; + if (wifiMac.CircBufReadAddress + wifiMac.RXRangeBegin == wifiMac.RXRangeEnd) wifiMac.CircBufReadAddress = 0; + } + } + + if (wifiMac.RXBufCount > 0) + { + if (wifiMac.RXBufCount == 1) + { + WIFI_triggerIRQ(WIFI_IRQ_RXCOUNTEXP); + } + wifiMac.RXBufCount--; + } + } + return val; + } + case REG_WIFI_CIRCBUFRADR: + return wifiMac.CircBufReadAddress; + case REG_WIFI_RXBUF_COUNT: + return wifiMac.RXBufCount; + case REG_WIFI_TXREQ_READ: + return wifiMac.TXCnt | 0x10; + case REG_WIFI_TXBUSY: + return wifiMac.TXBusy; + case REG_WIFI_TXSTAT: + return wifiMac.TXStat; + case REG_WIFI_TXBUF_CMD: + return wifiMac.TXSlots[WIFI_TXSLOT_MPCMD].RegVal; + case REG_WIFI_TXBUF_REPLY2: + return wifiMac.TXSlots[WIFI_TXSLOT_MPREPLY].RegVal; + case REG_WIFI_TXBUF_LOC1: + return wifiMac.TXSlots[WIFI_TXSLOT_LOC1].RegVal; + case REG_WIFI_TXBUF_LOC2: + return wifiMac.TXSlots[WIFI_TXSLOT_LOC2].RegVal; + case REG_WIFI_TXBUF_LOC3: + return wifiMac.TXSlots[WIFI_TXSLOT_LOC3].RegVal; + case REG_WIFI_TXBUF_BEACON: + return wifiMac.TXSlots[WIFI_TXSLOT_BEACON].RegVal; + case REG_WIFI_EXTRACOUNTCNT: + return wifiMac.eCountEnable?1:0; + case REG_WIFI_EXTRACOUNT: + return (u16)((wifiMac.eCount + (WIFI_CMDCOUNT_SLICE-1)) / WIFI_CMDCOUNT_SLICE); + case REG_WIFI_USCOUNTER0: + return (u16)wifiMac.usec; + case REG_WIFI_USCOUNTER1: + return (u16)(wifiMac.usec >> 16); + case REG_WIFI_USCOUNTER2: + return (u16)(wifiMac.usec >> 32); + case REG_WIFI_USCOUNTER3: + return (u16)(wifiMac.usec >> 48); + case REG_WIFI_USCOMPARE0: + return (u16)wifiMac.ucmp; + case REG_WIFI_USCOMPARE1: + return (u16)(wifiMac.ucmp >> 16); + case REG_WIFI_USCOMPARE2: + return (u16)(wifiMac.ucmp >> 32); + case REG_WIFI_USCOMPARE3: + return (u16)(wifiMac.ucmp >> 48); + case REG_WIFI_BEACONCOUNT1: + return wifiMac.BeaconCount1; + case REG_WIFI_BEACONCOUNT2: + return wifiMac.BeaconCount2; + case REG_WIFI_LISTENCOUNT: + return wifiMac.ListenCount; + case REG_WIFI_POWER_US: + return wifiMac.crystalEnabled?0:1; + case REG_WIFI_CIRCBUFRD_END: + return wifiMac.CircBufRdEnd; + case REG_WIFI_CIRCBUFRD_SKIP: + return wifiMac.CircBufRdSkip; + case REG_WIFI_AID_LOW: + return wifiMac.pid; + case REG_WIFI_AID_HIGH: + return wifiMac.aid; + + // RFSTATUS, RFPINS + // TODO: figure out how to emulate those correctly + // without breaking Nintendo's games + case REG_WIFI_RFSTATUS: + return wifiMac.rfStatus; + //return 9; + case REG_WIFI_RFPINS: + return wifiMac.rfPins; + //return 0x00C6; + + case REG_WIFI_RXSTAT_INC_IF: + { + u16 ret = wifiMac.RXStatIncIF; + wifiMac.RXStatIncIF = 0; + return ret; + } + case REG_WIFI_RXSTAT_OVF_IF: + { + u16 ret = wifiMac.RXStatOvfIF; + wifiMac.RXStatOvfIF = 0; + return ret; + } + + case REG_WIFI_RXSTAT_INC_IE: return wifiMac.RXStatIncIE; + case REG_WIFI_RXSTAT_OVF_IE: return wifiMac.RXStatOvfIE; + + case 0x1B0: + case 0x1B2: + case 0x1B4: + case 0x1B6: + case 0x1B8: + case 0x1BA: + case 0x1BC: + case 0x1BE: + { + u16 ret = *(u16*)&wifiMac.RXStat[address & 0xF]; + *(u16*)&wifiMac.RXStat[address & 0xF] = 0; + return ret; + } + + case REG_WIFI_RXTXADDR: + return wifiMac.RXTXAddr; + + case 0x84: + WIFI_LOG(2, "Read to TXBUF_TIM @ %08X %08X\n", NDS_ARM7.instruct_adr, NDS_ARM7.R[14]); + break; + + default: + // printf("wifi: read unhandled reg %03X\n", address); + break; + } + + return WIFI_IOREG(address); +} + + +void WIFI_usTrigger() +{ + wifiMac.GlobalUsecTimer++; + + if (wifiMac.crystalEnabled) + { + /* a usec has passed */ + if (wifiMac.usecEnable) + wifiMac.usec++; + + // Note: the extra counter is decremented every 10 microseconds. + // To avoid a modulo every microsecond, we multiply the counter + // value by 10 and decrement it every microsecond :) + if (wifiMac.eCountEnable) + { + if (wifiMac.eCount > 0) + { + wifiMac.eCount--; + if (wifiMac.eCount == 0) + WIFI_TXStart(WIFI_TXSLOT_MPCMD); + } + } + + // The beacon counters are in milliseconds + // GBATek says they're decremented every 1024 usecs + if (!(wifiMac.usec & 1023)) + { + wifiMac.BeaconCount1--; + + if (wifiMac.BeaconCount1 == (WIFI_IOREG(REG_WIFI_PREBEACONCOUNT) >> 10)) + WIFI_triggerIRQ(WIFI_IRQ_TIMEPREBEACON); + else if (wifiMac.BeaconCount1 == 0) + WIFI_triggerIRQ(WIFI_IRQ_TIMEBEACON); + + if (wifiMac.BeaconCount2 > 0) + { + wifiMac.BeaconCount2--; + if (wifiMac.BeaconCount2 == 0) + WIFI_triggerIRQ(WIFI_IRQ_TIMEPOSTBEACON); + } + } + } + + if ((wifiMac.ucmpEnable) && (wifiMac.ucmp == wifiMac.usec)) + WIFI_triggerIRQ(WIFI_IRQ_TIMEBEACON); + + if (wifiMac.TXCurSlot >= 0) + { + Wifi_TXSlot& slot = wifiMac.TXSlots[wifiMac.TXCurSlot]; + if (slot.RemPreamble > 0) + slot.RemPreamble--; + else if ((wifiMac.GlobalUsecTimer & slot.TimeMask) == 0) + { + if (slot.NotStarted) + { + WIFI_PreTXAdjustments(wifiMac.TXCurSlot); + WIFI_triggerIRQ(WIFI_IRQ_TXSTART); + if (wifiCom) wifiCom->SendPacket((u8*)&wifiMac.RAM[slot.CurAddr], slot.RemHWords << 1); + slot.NotStarted = false; + } + + slot.RemHWords--; + slot.CurAddr++; + wifiMac.RXTXAddr = slot.CurAddr; + + if (slot.RemHWords == 0) + { + if (wifiMac.TXCurSlot == WIFI_TXSLOT_MPCMD) + { + WIFI_triggerIRQ(WIFI_IRQ_UNK); + if (BIT13(wifiMac.TXStatCnt)) + { + WIFI_triggerIRQ(WIFI_IRQ_TXEND); + wifiMac.TXStat = 0x0B01; + } + else if (BIT14(wifiMac.TXStatCnt)) + { + WIFI_triggerIRQ(WIFI_IRQ_TXEND); + wifiMac.TXStat = 0x0801; + } + + slot.RegVal &= 0x7FFF; + } + else if (wifiMac.TXCurSlot == WIFI_TXSLOT_BEACON) + { + if (BIT15(wifiMac.TXStatCnt)) + { + WIFI_triggerIRQ(WIFI_IRQ_TXEND); + wifiMac.TXStat = 0x0301; + } + } + else if (wifiMac.TXCurSlot == WIFI_TXSLOT_MPREPLY) + { + WIFI_triggerIRQ(WIFI_IRQ_TXEND); + slot.RegVal &= 0x7FFF; + WIFI_IOREG(REG_WIFI_TXBUF_REPLY1) = 0; + } + else + { + WIFI_triggerIRQ(WIFI_IRQ_TXEND); + wifiMac.TXStat = 0x0001 | (wifiMac.TXCurSlot == 0 ? 0 : ((wifiMac.TXCurSlot - 1) << 12)); + if (BIT12(slot.RegVal)) wifiMac.TXStat |= 0x0700; + + slot.RegVal &= 0x7FFF; + } + + u16 addr = slot.RegVal & 0x0FFF; + wifiMac.RAM[addr] = 0x0001; + wifiMac.RAM[addr+4] &= 0x00FF; + + wifiMac.TXBusy &= ~(1 << wifiMac.TXCurSlot); + int nextslot = -1; + for (int i = WIFI_TXSLOT_NUM-1; i >= 0; i--) + { + if (BIT_N(wifiMac.TXBusy, i)) + { + nextslot = i; + break; + } + } + + if (nextslot < 0) + { + //wifiMac.rfStatus = 9; + //wifiMac.rfPins = 0x00C6; + wifiMac.TXCurSlot = -1; + } + else + { + wifiMac.TXCurSlot = nextslot; + } + } + } + } + else if (!wifiMac.RXPacketQueue.empty()) + { + if ((wifiMac.GlobalUsecTimer & 7) == 0) + { + Wifi_RXPacket& pkt = wifiMac.RXPacketQueue.front(); + if (pkt.NotStarted) + { + WIFI_RXPutWord(*(u16*)&pkt.Data[0]); + WIFI_RXPutWord(*(u16*)&pkt.Data[2]); + WIFI_RXPutWord(*(u16*)&pkt.Data[4]); + WIFI_RXPutWord(*(u16*)&pkt.Data[6]); + WIFI_RXPutWord(*(u16*)&pkt.Data[8]); + WIFI_RXPutWord(*(u16*)&pkt.Data[10]); + + WIFI_triggerIRQ(WIFI_IRQ_RXSTART); + pkt.NotStarted = false; + + //wifiMac.rfStatus = 1; + wifiMac.rfPins = 0x00C7; + } + + WIFI_RXPutWord(*(u16*)&pkt.Data[pkt.CurOffset]); + + pkt.CurOffset += 2; + pkt.RemHWords--; + + if (pkt.RemHWords == 0) + { + wifiMac.RXWriteCursor = ((wifiMac.RXWriteCursor + 1) & (~1)); + if (wifiMac.RXWriteCursor >= (wifiMac.RXRangeEnd >> 1)) + wifiMac.RXWriteCursor = (wifiMac.RXRangeBegin >> 1); + WIFI_IOREG(REG_WIFI_RXHWWRITECSR) = wifiMac.RXWriteCursor; + + wifiMac.RXNum++; + WIFI_triggerIRQ(WIFI_IRQ_RXEND); + + WIFI_IncrementRXStat<7>(); + WIFI_DoAutoReply(pkt.Data); + + delete[] pkt.Data; + wifiMac.RXPacketQueue.pop(); + + wifiMac.rfStatus = 9; + wifiMac.rfPins = 0x00C6; + } + } + } + + if ((wifiMac.GlobalUsecTimer & 1023) == 0) + if (wifiCom) + wifiCom->msTrigger(); +} + +/******************************************************************************* + + Ad-hoc communication interface + + *******************************************************************************/ + +#ifdef EXPERIMENTAL_WIFI_COMM +#define ADHOC_MAGIC "NDSWIFI\0" +#define ADHOC_PROTOCOL_VERSION 0x0100 // v1.0 + +typedef struct _Adhoc_FrameHeader +{ + char magic[8]; // "NDSWIFI\0" (null terminated string) + u16 version; // Ad-hoc protocol version (for example 0x0502 = v5.2) + u16 packetLen; // Length of the packet + +} Adhoc_FrameHeader; + + +bool Adhoc_Init() +{ + BOOL opt_true = TRUE; + int res; + + if (!driver->WIFI_SocketsAvailable()) + { + WIFI_LOG(1, "Ad-hoc: failed to initialize sockets.\n"); + wifi_socket = INVALID_SOCKET; + return false; + } + + // Create an UDP socket + wifi_socket = socket(AF_INET, SOCK_DGRAM, 0); + if (wifi_socket < 0) + { + WIFI_LOG(1, "Ad-hoc: Failed to create socket.\n"); + return false; + } + + // Enable the socket to be bound to an address/port that is already in use + // This enables us to communicate with another DeSmuME instance running on the same computer. + res = setsockopt(wifi_socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt_true, sizeof(BOOL)); + + // Bind the socket to any address on port 7000 + sockaddr_t saddr; + saddr.sa_family = AF_INET; + *(u32*)&saddr.sa_data[2] = htonl(INADDR_ANY); + *(u16*)&saddr.sa_data[0] = htons(BASEPORT); + res = bind(wifi_socket, &saddr, sizeof(sockaddr_t)); + if (res < 0) + { + WIFI_LOG(1, "Ad-hoc: failed to bind the socket.\n"); + closesocket(wifi_socket); wifi_socket = INVALID_SOCKET; + return false; + } + + // Enable broadcast mode + // Not doing so results in failure when sendto'ing to broadcast address + res = setsockopt(wifi_socket, SOL_SOCKET, SO_BROADCAST, (const char*)&opt_true, sizeof(BOOL)); + if (res < 0) + { + WIFI_LOG(1, "Ad-hoc: failed to enable broadcast mode.\n"); + closesocket(wifi_socket); wifi_socket = INVALID_SOCKET; + return false; + } + + // Prepare an address structure for sending packets + sendAddr.sa_family = AF_INET; + *(u32*)&sendAddr.sa_data[2] = htonl(INADDR_BROADCAST); + *(u16*)&sendAddr.sa_data[0] = htons(BASEPORT); + + Adhoc_Reset(); + + WIFI_LOG(1, "Ad-hoc: initialization successful.\n"); + + return true; +} + +void Adhoc_DeInit() +{ + if (wifi_socket >= 0) + closesocket(wifi_socket); +} + +void Adhoc_Reset() +{ + driver->WIFI_GetUniqueMAC(FW_Mac); + NDS_PatchFirmwareMAC(); + + printf("WIFI: ADHOC: MAC = %02X:%02X:%02X:%02X:%02X:%02X\n", + FW_Mac[0], FW_Mac[1], FW_Mac[2], FW_Mac[3], FW_Mac[4], FW_Mac[5]); +} + +void Adhoc_SendPacket(u8* packet, u32 len) +{ + if (wifi_socket < 0) + return; + + WIFI_LOG(3, "Ad-hoc: sending a packet of %i bytes, frame control: %04X\n", len, *(u16*)&packet[0]); + + u32 frameLen = sizeof(Adhoc_FrameHeader) + len; + + u8* frame = new u8[frameLen]; + u8* ptr = frame; + + Adhoc_FrameHeader header; + strncpy(header.magic, ADHOC_MAGIC, 8); + header.version = ADHOC_PROTOCOL_VERSION; + header.packetLen = len; + memcpy(ptr, &header, sizeof(Adhoc_FrameHeader)); + ptr += sizeof(Adhoc_FrameHeader); + + memcpy(ptr, packet, len); + + int nbytes = sendto(wifi_socket, (const char*)frame, frameLen, 0, &sendAddr, sizeof(sockaddr_t)); + + WIFI_LOG(4, "Ad-hoc: sent %i/%i bytes of packet.\n", nbytes, frameLen); + + delete[] frame; +} + +void Adhoc_msTrigger() +{ + if (wifi_socket < 0) + return; + + // Check every millisecond if we received a packet + fd_set fd; + struct timeval tv; + + FD_ZERO(&fd); + FD_SET(wifi_socket, &fd); + tv.tv_sec = 0; + tv.tv_usec = 0; + + if (select(1, &fd, 0, 0, &tv)) + { + sockaddr_t fromAddr; + socklen_t fromLen = sizeof(sockaddr_t); + u8 buf[1536]; + u8* ptr; + u16 packetLen; + + int nbytes = recvfrom(wifi_socket, (char*)buf, 1536, 0, &fromAddr, &fromLen); + + // No packet arrived (or there was an error) + if (nbytes <= 0) + return; + + ptr = buf; + Adhoc_FrameHeader header = *(Adhoc_FrameHeader*)ptr; + + // Check the magic string in header + if (strncmp(header.magic, ADHOC_MAGIC, 8)) + return; + + // Check the ad-hoc protocol version + if (header.version != ADHOC_PROTOCOL_VERSION) + return; + + packetLen = header.packetLen - 4; + ptr += sizeof(Adhoc_FrameHeader); + + // If the packet is for us, send it to the wifi core + if (!WIFI_compareMAC(&ptr[10], &wifiMac.mac.bytes[0])) + { + if (WIFI_isBroadcastMAC(&ptr[16]) || + WIFI_compareMAC(&ptr[16], &wifiMac.bss.bytes[0]) || + WIFI_isBroadcastMAC(&wifiMac.bss.bytes[0])) + { + /* WIFI_LOG(3, "Ad-hoc: received a packet of %i bytes from %i.%i.%i.%i (port %i).\n", + nbytes, + (u8)fromAddr.sa_data[2], (u8)fromAddr.sa_data[3], + (u8)fromAddr.sa_data[4], (u8)fromAddr.sa_data[5], + ntohs(*(u16*)&fromAddr.sa_data[0]));*/ + WIFI_LOG(3, "Ad-hoc: received a packet of %i bytes, frame control: %04X\n", packetLen, *(u16*)&ptr[0]); + WIFI_LOG(4, "Storing packet at %08X.\n", 0x04804000 + (wifiMac.RXWriteCursor<<1)); + + u8* packet = new u8[12 + packetLen]; + + WIFI_MakeRXHeader(packet, WIFI_GetRXFlags(ptr), 20, packetLen, 0, 0); + memcpy(&packet[12], ptr, packetLen); + WIFI_RXQueuePacket(packet, 12+packetLen); + } + } + } +} + +/******************************************************************************* + + SoftAP (fake wifi access point) + + *******************************************************************************/ + +// Note on the CRC32 field in received packets: +// The wifi hardware doesn't store the CRC32 in memory when receiving a packet +// so the RX header length field is indeed header+body +// Hence the CRC32 has been removed from those templates. + +// If you wanna change SoftAP's MAC address, change this +// Warning, don't mistake this for an array, it isn't +#define SOFTAP_MACADDR 0x00, 0xF0, 0x1A, 0x2B, 0x3C, 0x4D + +const u8 SoftAP_MACAddr[6] = {SOFTAP_MACADDR}; + +const u8 SoftAP_Beacon[] = { + /* 802.11 header */ + 0x80, 0x00, // Frame control + 0x00, 0x00, // Duration ID + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Receiver + SOFTAP_MACADDR, // Sender + SOFTAP_MACADDR, // BSSID + 0x00, 0x00, // Sequence control + + /* Frame body */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp (modified later) + 0x80, 0x00, // Beacon interval + 0x21, 0x00, // Capablilty information + 0x01, 0x02, 0x82, 0x84, // Supported rates + 0x03, 0x01, 0x06, // Current channel + 0x05, 0x04, 0x02, 0x01, 0x00, 0x00, // TIM (no idea what the hell it is) + 0x00, 0x06, 'S', 'o', 'f', 't', 'A', 'P', // SSID +}; + +const u8 SoftAP_ProbeResponse[] = { + /* 802.11 header */ + 0x50, 0x00, // Frame control + 0x00, 0x00, // Duration ID + 0x00, 0x09, 0xBF, 0x12, 0x34, 0x56, // Receiver + SOFTAP_MACADDR, // Sender + SOFTAP_MACADDR, // BSSID + 0x00, 0x00, // Sequence control + + /* Frame body */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp (modified later) + 0x80, 0x00, // Beacon interval + 0x21, 0x00, // Capablilty information + 0x01, 0x02, 0x82, 0x84, // Supported rates + 0x03, 0x01, 0x06, // Current channel + 0x00, 0x06, 'S', 'o', 'f', 't', 'A', 'P', // SSID +}; + + +const u8 SoftAP_AuthFrame[] = { + /* 802.11 header */ + 0xB0, 0x00, // Frame control + 0x00, 0x00, // Duration ID + 0x00, 0x09, 0xBF, 0x12, 0x34, 0x56, // Receiver + SOFTAP_MACADDR, // Sender + SOFTAP_MACADDR, // BSSID + 0x00, 0x00, // Sequence control + + /* Frame body */ + 0x00, 0x00, // Authentication algorithm + 0x02, 0x00, // Authentication sequence + 0x00, 0x00, // Status +}; + +const u8 SoftAP_AssocResponse[] = { + /* 802.11 header */ + 0x10, 0x00, // Frame control + 0x00, 0x00, // Duration ID + 0x00, 0x09, 0xBF, 0x12, 0x34, 0x56, // Receiver + SOFTAP_MACADDR, // Sender + SOFTAP_MACADDR, // BSSID + 0x00, 0x00, // Sequence control + + /* Frame body */ + 0x21, 0x00, // Capability information + 0x00, 0x00, // Status + 0x01, 0xC0, // Assocation ID + 0x01, 0x02, 0x82, 0x84, // Supported rates +}; + +// Deauthentication frame - sent if the user chose not to connect to WFC +const u8 SoftAP_DeauthFrame[] = { + /* 802.11 header */ + 0xC0, 0x00, // Frame control + 0x00, 0x00, // Duration ID + 0x00, 0x09, 0xBF, 0x12, 0x34, 0x56, // Receiver + SOFTAP_MACADDR, // Sender + SOFTAP_MACADDR, // BSSID + 0x00, 0x00, // Sequence control + + /* Frame body */ + 0x01, 0x00, // Reason code (is "unspecified" ok?) +}; + +//todo - make a class to wrap this +//todo - zeromus - inspect memory leak safety of all this +static pcap_if_t * WIFI_index_device(pcap_if_t *alldevs, int index) +{ + pcap_if_t *curr = alldevs; + + for(int i = 0; i < index; i++) + curr = curr->next; + + WIFI_LOG(2, "SoftAP: using %s as device.\n", curr->PCAP_DEVICE_NAME); + + return curr; +} + +bool SoftAP_Init() +{ + if (!driver->WIFI_PCapAvailable()) + { + WIFI_LOG(1, "SoftAP: PCap library not available on your system.\n"); + wifi_bridge = NULL; + return false; + } + + char errbuf[PCAP_ERRBUF_SIZE]; + pcap_if_t *alldevs; + int ret; + + ret = driver->PCAP_findalldevs(&alldevs, errbuf); + if (ret == -1 || alldevs == NULL) + { + WIFI_LOG(1, "SoftAP: PCap: failed to find any network adapter: %s\n", errbuf); + return false; + } + + pcap_if_t* dev = WIFI_index_device(alldevs,CommonSettings.wifi.infraBridgeAdapter); + wifi_bridge = driver->PCAP_open(dev->name, PACKET_SIZE, PCAP_OPENFLAG_PROMISCUOUS, 1, errbuf); + if(wifi_bridge == NULL) + { + WIFI_LOG(1, "SoftAP: PCap: failed to open %s: %s\n", dev->PCAP_DEVICE_NAME, errbuf); + return false; + } + + driver->PCAP_freealldevs(alldevs); + + // Set non-blocking mode + if (driver->PCAP_setnonblock(wifi_bridge, 1, errbuf) == -1) + { + WIFI_LOG(1, "SoftAP: PCap: failed to set non-blocking mode: %s\n", errbuf); + driver->PCAP_close(wifi_bridge); wifi_bridge = NULL; + return false; + } + + SoftAP_Reset(); + + return true; +} + +void SoftAP_DeInit() +{ + if(wifi_bridge != NULL) + driver->PCAP_close(wifi_bridge); +} + +void SoftAP_Reset() +{ + SoftAP.status = APStatus_Disconnected; + SoftAP.seqNum = 0; +} + +static bool SoftAP_IsDNSRequestToWFC(u16 ethertype, u8* body) +{ + // Check the various headers... + if (ntohs(ethertype) != 0x0800) return false; // EtherType: IP + if (body[0] != 0x45) return false; // Version: 4, header len: 5 + if (body[9] != 0x11) return false; // Protocol: UDP + if (ntohs(*(u16*)&body[22]) != 53) return false; // Dest. port: 53 (DNS) + if (htons(ntohs(*(u16*)&body[28+2])) & 0x8000) return false; // must be a query + + // Analyze each question + u16 numquestions = ntohs(*(u16*)&body[28+4]); + u32 curoffset = 28+12; + for (u16 curquestion = 0; curquestion < numquestions; curquestion++) + { + // Assemble the requested domain name + u8 bitlength = 0; char domainname[256] = ""; + while ((bitlength = body[curoffset++]) != 0) + { + strncat(domainname, (const char*)&body[curoffset], bitlength); + + curoffset += bitlength; + if (body[curoffset] != 0) + strcat(domainname, "."); + } + + // if the domain name contains nintendowifi.net + // it is most likely a WFC server + // (note, conntest.nintendowifi.net just contains a dummy HTML page and + // is used for connection tests, I think we can let this one slide) + if ((strstr(domainname, "nintendowifi.net") != NULL) && + (strcmp(domainname, "conntest.nintendowifi.net") != 0)) + return true; + + // Skip the type and class - we don't care about that + curoffset += 4; + } + + return false; +} + +static void SoftAP_Deauthenticate() +{ + u32 packetLen = sizeof(SoftAP_DeauthFrame); + u8* packet = new u8[12 + packetLen]; + + memcpy(&packet[12], SoftAP_DeauthFrame, packetLen); + + memcpy(&packet[12 + 4], FW_Mac, 6); // Receiver MAC + + *(u16*)&packet[12 + 22] = SoftAP.seqNum << 4; // Sequence number + SoftAP.seqNum++; + + u16 rxflags = 0x0010; + if (WIFI_compareMAC(wifiMac.bss.bytes, &packet[12 + 16])) + rxflags |= 0x8000; + + WIFI_MakeRXHeader(packet, rxflags, 20, packetLen, 0, 0); + WIFI_RXQueuePacket(packet, 12 + packetLen); + + SoftAP.status = APStatus_Disconnected; +} + +void SoftAP_SendPacket(u8 *packet, u32 len) +{ + u16 frameCtl = *(u16*)&packet[0]; + + WIFI_LOG(3, "SoftAP: Received a packet of length %i bytes. Frame control = %04X\n", + len, frameCtl); + + //use this to log wifi messages easily + /*static int ctr=0; + char buf[100]; + sprintf(buf,"wifi%04d.txt",ctr); + FILE* outf = fopen(buf,"wb"); + fwrite(packet,1,len,outf); + fclose(outf); + ctr++;*/ + + switch((frameCtl >> 2) & 0x3) + { + case 0x0: // Management frame + { + u32 packetLen; + u8* rpacket; + + switch((frameCtl >> 4) & 0xF) + { + case 0x4: // Probe request + { + packetLen = sizeof(SoftAP_ProbeResponse); + rpacket = new u8[12 + packetLen]; + memcpy(&rpacket[12], SoftAP_ProbeResponse, packetLen); + + // Add the timestamp + *(u64*)&rpacket[12 + 24] = wifiMac.GlobalUsecTimer; + } + break; + + case 0xB: // Authentication + { + packetLen = sizeof(SoftAP_AuthFrame); + rpacket = new u8[12 + packetLen]; + memcpy(&rpacket[12], SoftAP_AuthFrame, packetLen); + + SoftAP.status = APStatus_Authenticated; + } + break; + + case 0x0: // Association request + { + if (SoftAP.status != APStatus_Authenticated) + return; + + packetLen = sizeof(SoftAP_AssocResponse); + rpacket = new u8[12 + packetLen]; + memcpy(&rpacket[12], SoftAP_AssocResponse, packetLen); + + SoftAP.status = APStatus_Associated; + WIFI_LOG(1, "SoftAP connected!\n"); + } + break; + + case 0xA: // Disassociation + SoftAP.status = APStatus_Authenticated; + return; + + case 0xC: // Deauthentication + SoftAP.status = APStatus_Disconnected; + WIFI_LOG(1, "SoftAP disconnected\n"); + return; + + default: + WIFI_LOG(2, "SoftAP: unknown management frame type %04X\n", (frameCtl >> 4) & 0xF); + return; + } + + memcpy(&rpacket[12 + 4], FW_Mac, 6); // Receiver MAC + + *(u16*)&rpacket[12 + 22] = SoftAP.seqNum << 4; // Sequence number + SoftAP.seqNum++; + + u16 rxflags = 0x0010; + if (WIFI_compareMAC(wifiMac.bss.bytes, &rpacket[12 + 16])) + rxflags |= 0x8000; + + WIFI_MakeRXHeader(rpacket, rxflags, 20, packetLen, 0, 0); // make the RX header + WIFI_RXQueuePacket(rpacket, 12 + packetLen); + } + break; + + case 0x2: // Data frame + { + // If it has a LLC/SLIP header, send it over the Ethernet + if (((*(u16*)&packet[24]) == 0xAAAA) && ((*(u16*)&packet[26]) == 0x0003) && ((*(u16*)&packet[28]) == 0x0000)) + { + if (SoftAP.status != APStatus_Associated) + return; + + if (SoftAP_IsDNSRequestToWFC(*(u16*)&packet[30], &packet[32])) + { + SoftAP_Deauthenticate(); + return; + } + + u32 epacketLen = ((len - 30 - 4) + 14); + u8 epacket[2048]; + + //printf("----- SENDING ETHERNET PACKET: len=%i, ethertype=%04X -----\n", + // len, *(u16*)&packet[30]); + + memcpy(&epacket[0], &packet[16], 6); + memcpy(&epacket[6], &packet[10], 6); + *(u16*)&epacket[12] = *(u16*)&packet[30]; + memcpy(&epacket[14], &packet[32], epacketLen - 14); + + if(wifi_bridge != NULL) + driver->PCAP_sendpacket(wifi_bridge, epacket, epacketLen); + } + else + { + WIFI_LOG(1, "SoftAP: received non-Ethernet data frame. wtf?\n"); + } + } + break; + } +} + +INLINE void SoftAP_SendBeacon() +{ + u32 packetLen = sizeof(SoftAP_Beacon); + u8* packet = new u8[12 + packetLen]; + + memcpy(&packet[12], SoftAP_Beacon, packetLen); // Copy the beacon template + + *(u16*)&packet[12 + 22] = SoftAP.seqNum << 4; // Sequence number + SoftAP.seqNum++; + + *(u64*)&packet[12 + 24] = wifiMac.GlobalUsecTimer; // Timestamp + + u16 rxflags = 0x0011; + if (WIFI_compareMAC(wifiMac.bss.bytes, &packet[12 + 16])) + rxflags |= 0x8000; + + WIFI_MakeRXHeader(packet, rxflags, 20, packetLen, 0, 0); + WIFI_RXQueuePacket(packet, 12 + packetLen); +} + +static void SoftAP_RXHandler(u_char* user, const struct pcap_pkthdr* h, const u_char* _data) +{ + // safety checks + if ((_data == NULL) || (h == NULL)) + return; + + u8* data = (u8*)_data; + + // reject the packet if it wasn't for us + if (!(WIFI_isBroadcastMAC(&data[0]) || WIFI_compareMAC(&data[0], wifiMac.mac.bytes))) + return; + + // reject the packet if we just sent it + if (WIFI_compareMAC(&data[6], wifiMac.mac.bytes)) + return; + + // The packet was for us. Let's process it then. + int wpacketLen = WIFI_alignedLen(26 + 6 + (h->len-14)); + u8* wpacket = new u8[12 + wpacketLen]; + + u16 rxflags = 0x0018; + if (WIFI_compareMAC(wifiMac.bss.bytes, (u8*)SoftAP_MACAddr)) + rxflags |= 0x8000; + + // Make a valid 802.11 frame + WIFI_MakeRXHeader(wpacket, rxflags, 20, wpacketLen, 0, 0); + *(u16*)&wpacket[12+0] = 0x0208; + *(u16*)&wpacket[12+2] = 0x0000; + memcpy(&wpacket[12+4], &data[0], 6); + memcpy(&wpacket[12+10], SoftAP_MACAddr, 6); + memcpy(&wpacket[12+16], &data[6], 6); + *(u16*)&wpacket[12+22] = SoftAP.seqNum << 4; + *(u16*)&wpacket[12+24] = 0xAAAA; + *(u16*)&wpacket[12+26] = 0x0003; + *(u16*)&wpacket[12+28] = 0x0000; + *(u16*)&wpacket[12+30] = *(u16*)&data[12]; + memcpy(&wpacket[12+32], &data[14], h->len-14); + + SoftAP.seqNum++; + + WIFI_RXQueuePacket(wpacket, 12 + wpacketLen); +} + +void SoftAP_msTrigger() +{ + //zero sez: every 1/10 second? does it have to be precise? this is so costly.. + // Okay for 128 ms then + if((wifiMac.GlobalUsecTimer & 131071) == 0) + SoftAP_SendBeacon(); + + // EXTREMELY EXPERIMENTAL packet receiving code + // Can now receive 64 packets per millisecond. Completely arbitrary limit. Todo: tweak if needed. + // But due to using non-blocking mode, this shouldn't be as slow as it used to be. + if (wifi_bridge != NULL) + driver->PCAP_dispatch(wifi_bridge, 64, SoftAP_RXHandler, NULL); +} + +#endif + diff --git a/jni/desmume/src/wifi.h b/jni/desmume/src/wifi.h new file mode 100755 index 0000000..d246d12 --- /dev/null +++ b/jni/desmume/src/wifi.h @@ -0,0 +1,633 @@ +/* + Copyright (C) 2007 Tim Seidel + Copyright (C) 2008-2011 DeSmuME team + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef WIFI_H +#define WIFI_H + +#include <stdio.h> +#include "types.h" + +#include <queue> + +#ifdef EXPERIMENTAL_WIFI_COMM + +#define HAVE_REMOTE +#define WPCAP +#define PACKET_SIZE 65535 +#define _INC_STDIO + +#endif + + +#define REG_WIFI_ID 0x000 +#define REG_WIFI_MODE 0x004 +#define REG_WIFI_WEP 0x006 +#define REG_WIFI_TXSTATCNT 0x008 +#define REG_WIFI_0A 0x00A +#define REG_WIFI_IF 0x010 +#define REG_WIFI_IE 0x012 +#define REG_WIFI_MAC0 0x018 +#define REG_WIFI_MAC1 0x01A +#define REG_WIFI_MAC2 0x01C +#define REG_WIFI_BSS0 0x020 +#define REG_WIFI_BSS1 0x022 +#define REG_WIFI_BSS2 0x024 +#define REG_WIFI_AID_LOW 0x028 +#define REG_WIFI_AID_HIGH 0x02A +#define REG_WIFI_RETRYLIMIT 0x02C +// 02E - internal +#define REG_WIFI_RXCNT 0x030 +#define REG_WIFI_WEPCNT 0x032 +// 034 - internal + +#define REG_WIFI_POWER_US 0x036 +#define REG_WIFI_POWER_TX 0x038 +#define REG_WIFI_POWERSTATE 0x03C +#define REG_WIFI_POWERFORCE 0x040 +#define REG_WIFI_RANDOM 0x044 +#define REG_WIFI_POWER_UNK 0x048 + +#define REG_WIFI_RXRANGEBEGIN 0x050 +#define REG_WIFI_RXRANGEEND 0x052 +#define REG_WIFI_RXHWWRITECSR 0x054 +#define REG_WIFI_WRITECSRLATCH 0x056 +#define REG_WIFI_CIRCBUFRADR 0x058 +#define REG_WIFI_RXREADCSR 0x05A +#define REG_WIFI_RXBUF_COUNT 0x05C +#define REG_WIFI_CIRCBUFREAD 0x060 +#define REG_WIFI_CIRCBUFRD_END 0x062 +#define REG_WIFI_CIRCBUFRD_SKIP 0x064 +#define REG_WIFI_CIRCBUFWADR 0x068 +#define REG_WIFI_TXBUFCOUNT 0x06C +#define REG_WIFI_CIRCBUFWRITE 0x070 +#define REG_WIFI_CIRCBUFWR_END 0x074 +#define REG_WIFI_CIRCBUFWR_SKIP 0x076 + +// 078 - internal +#define REG_WIFI_TXBUF_BEACON 0x080 +#define REG_WIFI_LISTENCOUNT 0x088 +#define REG_WIFI_BEACONPERIOD 0x08C +#define REG_WIFI_LISTENINT 0x08E +#define REG_WIFI_TXBUF_CMD 0x090 +#define REG_WIFI_TXBUF_REPLY1 0x094 +#define REG_WIFI_TXBUF_REPLY2 0x098 +// 09C - internal +#define REG_WIFI_TXBUF_LOC1 0x0A0 +#define REG_WIFI_TXBUF_LOC2 0x0A4 +#define REG_WIFI_TXBUF_LOC3 0x0A8 +#define REG_WIFI_TXREQ_RESET 0x0AC +#define REG_WIFI_TXREQ_SET 0x0AE +#define REG_WIFI_TXREQ_READ 0x0B0 +#define REG_WIFI_TXRESET 0x0B4 +#define REG_WIFI_TXBUSY 0x0B6 +#define REG_WIFI_TXSTAT 0x0B8 +// 0BA - internal +#define REG_WIFI_PREAMBLE 0x0BC +// 0C0 - ? +// 0C4 - ? +// 0C8 - internal +#define REG_WIFI_RXFILTER 0x0D0 +// 0D4 - config +// 0D8 - config +// 0DA - config +#define REG_WIFI_RXFILTER2 0x0E0 + +#define REG_WIFI_USCOUNTERCNT 0x0E8 +#define REG_WIFI_USCOMPARECNT 0x0EA +// 0EC - config +#define REG_WIFI_EXTRACOUNTCNT 0x0EE +#define REG_WIFI_USCOMPARE0 0x0F0 +#define REG_WIFI_USCOMPARE1 0x0F2 +#define REG_WIFI_USCOMPARE2 0x0F4 +#define REG_WIFI_USCOMPARE3 0x0F6 +#define REG_WIFI_USCOUNTER0 0x0F8 +#define REG_WIFI_USCOUNTER1 0x0FA +#define REG_WIFI_USCOUNTER2 0x0FC +#define REG_WIFI_USCOUNTER3 0x0FE +// 100 - internal +// 102 - internal +// 104 - internal +// 106 - internal +#define REG_WIFI_CONTENTFREE 0x10C +#define REG_WIFI_PREBEACONCOUNT 0x110 +#define REG_WIFI_EXTRACOUNT 0x118 +#define REG_WIFI_BEACONCOUNT1 0x11C + +// 120 to 132 - config/internal ports +#define REG_WIFI_BEACONCOUNT2 0x134 +// 140 to 154 - config ports + +#define REG_WIFI_BBCNT 0x158 +#define REG_WIFI_BBWRITE 0x15A +#define REG_WIFI_BBREAD 0x15C +#define REG_WIFI_BBBUSY 0x15E +#define REG_WIFI_BBMODE 0x160 +#define REG_WIFI_BBPOWER 0x168 + +// 16A to 178 - internal + +#define REG_WIFI_RFDATA2 0x17C +#define REG_WIFI_RFDATA1 0x17E +#define REG_WIFI_RFBUSY 0x180 +#define REG_WIFI_RFCNT 0x184 + +// 190 - internal +// 194 - ? +// 198 - internal +#define REG_WIFI_RFPINS 0x19C +// 1A0 - internal +// 1A2 - internal +#define REG_WIFI_MAYBE_RATE 0x1A4 + +#define REG_WIFI_RXSTAT_INC_IF 0x1A8 +#define REG_WIFI_RXSTAT_INC_IE 0x1AA +#define REG_WIFI_RXSTAT_OVF_IF 0x1AC +#define REG_WIFI_RXSTAT_OVF_IE 0x1AE +#define REG_WIFI_TXERR_COUNT 0x1C0 +#define REG_WIFI_RX_COUNT 0x1C4 + +// 1D0 to 1DE - related to multiplayer. argh. + +#define REG_WIFI_RFSTATUS 0x214 +#define REG_WIFI_IF_SET 0x21C +#define REG_WIFI_TXSEQNO 0x210 +#define REG_WIFI_RXTXADDR 0x268 +#define REG_WIFI_POWERACK 0x2D0 + + +#define WIFI_IOREG(reg) wifiMac.IOPorts[(reg) >> 1] + +/* WIFI misc constants */ +#define WIFI_CHIPID 0x1440 /* emulates "old" wifi chip, new is 0xC340 */ + +/* Referenced as RF_ in dswifi: rffilter_t */ +/* based on the documentation for the RF2958 chip of RF Micro Devices */ +/* using the register names as in docs ( http://www.rfmd.com/pdfs/2958.pdf )*/ +/* even tho every register only has 18 bits we are using u32 */ +typedef struct rffilter_t +{ + union CFG1 + { + struct + { +/* 0*/ unsigned IF_VGA_REG_EN:1; +/* 1*/ unsigned IF_VCO_REG_EN:1; +/* 2*/ unsigned RF_VCO_REG_EN:1; +/* 3*/ unsigned HYBERNATE:1; +/* 4*/ unsigned :10; +/*14*/ unsigned REF_SEL:2; +/*16*/ unsigned :2; + } bits; + u32 val; + } CFG1; + union IFPLL1 + { + struct + { +/* 0*/ unsigned DAC:4; +/* 4*/ unsigned :5; +/* 9*/ unsigned P1:1; +/*10*/ unsigned LD_EN1:1; +/*11*/ unsigned AUTOCAL_EN1:1; +/*12*/ unsigned PDP1:1; +/*13*/ unsigned CPL1:1; +/*14*/ unsigned LPF1:1; +/*15*/ unsigned VTC_EN1:1; +/*16*/ unsigned KV_EN1:1; +/*17*/ unsigned PLL_EN1:1; + } bits; + u32 val; + } IFPLL1; + union IFPLL2 + { + struct + { +/* 0*/ unsigned IF_N:16; +/*16*/ unsigned :2; + } bits; + u32 val; + } IFPLL2; + union IFPLL3 + { + struct + { +/* 0*/ unsigned KV_DEF1:4; +/* 4*/ unsigned CT_DEF1:4; +/* 8*/ unsigned DN1:9; +/*17*/ unsigned :1; + } bits; + u32 val; + } IFPLL3; + union RFPLL1 + { + struct + { +/* 0*/ unsigned DAC:4; +/* 4*/ unsigned :5; +/* 9*/ unsigned P:1; +/*10*/ unsigned LD_EN:1; +/*11*/ unsigned AUTOCAL_EN:1; +/*12*/ unsigned PDP:1; +/*13*/ unsigned CPL:1; +/*14*/ unsigned LPF:1; +/*15*/ unsigned VTC_EN:1; +/*16*/ unsigned KV_EN:1; +/*17*/ unsigned PLL_EN:1; + } bits; + u32 val; + } RFPLL1; + union RFPLL2 + { + struct + { +/* 0*/ unsigned NUM2:6; +/* 6*/ unsigned N2:12; + } bits; + u32 val; + } RFPLL2; + union RFPLL3 + { + struct + { +/* 0*/ unsigned NUM2:18; + } bits; + u32 val; + } RFPLL3; + union RFPLL4 + { + struct + { +/* 0*/ unsigned KV_DEF:4; +/* 4*/ unsigned CT_DEF:4; +/* 8*/ unsigned DN:9; +/*17*/ unsigned :1; + } bits; + u32 val; + } RFPLL4; + union CAL1 + { + struct + { +/* 0*/ unsigned LD_WINDOW:3; +/* 3*/ unsigned M_CT_VALUE:5; +/* 8*/ unsigned TLOCK:5; +/*13*/ unsigned TVCO:5; + } bits; + u32 val; + } CAL1; + union TXRX1 + { + struct + { +/* 0*/ unsigned TXBYPASS:1; +/* 1*/ unsigned INTBIASEN:1; +/* 2*/ unsigned TXENMODE:1; +/* 3*/ unsigned TXDIFFMODE:1; +/* 4*/ unsigned TXLPFBW:3; +/* 7*/ unsigned RXLPFBW:3; +/*10*/ unsigned TXVGC:5; +/*15*/ unsigned PCONTROL:2; +/*17*/ unsigned RXDCFBBYPS:1; + } bits; + u32 val; + } TXRX1; + union PCNT1 + { + struct + { +/* 0*/ unsigned TX_DELAY:3; +/* 3*/ unsigned PC_OFFSET:6; +/* 9*/ unsigned P_DESIRED:6; +/*15*/ unsigned MID_BIAS:3; + } bits; + u32 val; + } PCNT1; + union PCNT2 + { + struct + { +/* 0*/ unsigned MIN_POWER:6; +/* 6*/ unsigned MID_POWER:6; +/*12*/ unsigned MAX_POWER:6; + } bits; + u32 val; + } PCNT2; + union VCOT1 + { + struct + { +/* 0*/ unsigned :16; +/*16*/ unsigned AUX1:1; +/*17*/ unsigned AUX:1; + } bits; + u32 val; + } VCOT1; +} rffilter_t; + +/* baseband chip refered as BB_, dataformat is unknown yet */ +/* it has at least 105 bytes of functional data */ +typedef struct +{ + u8 data[105]; +} bb_t; + +/* communication interface between RF,BB and the mac */ +typedef union +{ + struct { +/* 0*/ unsigned wordsize:5; +/* 5*/ unsigned :2; +/* 7*/ unsigned readOperation:1; +/* 8*/ unsigned :8; + } bits; + u16 val; +} rfIOCnt_t; + +typedef union +{ + struct { +/* 0*/ unsigned busy:1; +/* 1*/ unsigned :15; + } bits; + u16 val; +} rfIOStat_t; + +typedef union +{ + struct { +/* 0*/ unsigned content:18; +/*18*/ unsigned address:5; +/*23*/ unsigned :9; + } bits; + struct { +/* 0*/ unsigned low:16; +/*16*/ unsigned high:16; + } val16; + u16 array16[2]; + u32 val; +} rfIOData_t; + +typedef union +{ + struct { +/* 0*/ unsigned address:7; +/* 7*/ unsigned :5; +/*12*/ unsigned mode:2; +/*14*/ unsigned enable:1; +/*15*/ unsigned :1; + } bits; + u16 val; +} bbIOCnt_t; + +#define WIFI_IRQ_RXEND 0 +#define WIFI_IRQ_TXEND 1 +#define WIFI_IRQ_RXINC 2 +#define WIFI_IRQ_TXERROR 3 +#define WIFI_IRQ_RXOVF 4 +#define WIFI_IRQ_TXERROVF 5 +#define WIFI_IRQ_RXSTART 6 +#define WIFI_IRQ_TXSTART 7 +#define WIFI_IRQ_TXCOUNTEXP 8 +#define WIFI_IRQ_RXCOUNTEXP 9 +#define WIFI_IRQ_RFWAKEUP 11 +#define WIFI_IRQ_UNK 12 +#define WIFI_IRQ_TIMEPOSTBEACON 13 +#define WIFI_IRQ_TIMEBEACON 14 +#define WIFI_IRQ_TIMEPREBEACON 15 + +struct Wifi_TXSlot +{ + u16 RegVal; + + u16 CurAddr; + int RemPreamble; // preamble time in ĩs + int RemHWords; + u32 TimeMask; // 3 = 2mbps, 7 = 1mbps + bool NotStarted; +}; + +#define WIFI_TXSLOT_LOC1 0 +#define WIFI_TXSLOT_MPCMD 1 +#define WIFI_TXSLOT_LOC2 2 +#define WIFI_TXSLOT_LOC3 3 +#define WIFI_TXSLOT_BEACON 4 +#define WIFI_TXSLOT_MPREPLY 5 +#define WIFI_TXSLOT_NUM 6 + +struct Wifi_RXPacket +{ + u8* Data; + int CurOffset; + int RemHWords; + bool NotStarted; +}; + +typedef std::queue<Wifi_RXPacket> Wifi_RXPacketQueue; + +enum EAPStatus +{ + APStatus_Disconnected = 0, + APStatus_Authenticated, + APStatus_Associated +}; + +/* wifimac_t: the buildin mac (arm7 addressrange: 0x04800000-0x04FFFFFF )*/ +/* http://www.akkit.org/info/dswifi.htm#WifiIOMap */ + +typedef struct +{ + /* power */ + BOOL powerOn; + BOOL powerOnPending; + + /* status */ + u16 rfStatus; + u16 rfPins; + + /* wifi interrupt handling */ + u16 IE; + u16 IF; + + /* modes */ + u16 macMode; + u16 wepMode; + BOOL WEP_enable; + + /* sending */ + u16 TXStatCnt; + u16 TXPower; + u16 TXCnt; + u16 TXStat; + u16 TXSeqNo; + Wifi_TXSlot TXSlots[WIFI_TXSLOT_NUM]; + int TXCurSlot; + u16 TXBusy; + + /* receiving */ + u16 RXCnt; + u16 RXCheckCounter; + u8 RXNum; + Wifi_RXPacketQueue RXPacketQueue; + + u16 RXStatIncIF, RXStatIncIE; + u16 RXStatOvfIF, RXStatOvfIE; + u8 RXStat[16]; + u16 RXTXAddr; + + /* addressing/handshaking */ + union + { + //TODO - is this endian safe? don't think so + u16 words[3]; + u8 bytes[6]; + } mac; + union + { + u16 words[3]; + u8 bytes[6]; + } bss; + u16 aid; + u16 pid; /* player ID or aid_low */ + u16 retryLimit; + + /* timing */ + u64 GlobalUsecTimer; + BOOL crystalEnabled; + u64 usec; + BOOL usecEnable; + u64 ucmp; + BOOL ucmpEnable; + u32 eCount; + BOOL eCountEnable; + u16 BeaconInterval; + u16 BeaconCount1; + u16 BeaconCount2; + u16 ListenInterval; + u16 ListenCount; + + /* subchips */ + rffilter_t RF; + bb_t BB; + + /* subchip communications */ + rfIOCnt_t rfIOCnt; + rfIOStat_t rfIOStatus; + rfIOData_t rfIOData; + bbIOCnt_t bbIOCnt; + + /* buffers */ + u16 RAM[0x1000]; + u16 RXRangeBegin; + u16 RXRangeEnd; + u16 RXWriteCursor; + u16 RXReadCursor; + u16 RXUnits; + u16 RXBufCount; + u16 CircBufReadAddress; + u16 CircBufWriteAddress; + u16 CircBufRdEnd; + u16 CircBufRdSkip; + u16 CircBufWrEnd; + u16 CircBufWrSkip; + + /* I/O ports */ + u16 IOPorts[0x800]; + + /* others */ + u16 randomSeed; + +} wifimac_t; + + +typedef struct +{ + EAPStatus status; + u16 seqNum; + +} SoftAP_t; + +// desmume host communication +#ifdef EXPERIMENTAL_WIFI_COMM +typedef struct pcap pcap_t; +extern pcap_t *wifi_bridge; +#endif + +extern wifimac_t wifiMac; +extern SoftAP_t SoftAP; + +bool WIFI_Init(); +void WIFI_DeInit(); +void WIFI_Reset(); + +/* subchip communication IO functions */ +void WIFI_setRF_CNT(u16 val); +void WIFI_setRF_DATA(u16 val, u8 part); +u16 WIFI_getRF_DATA(u8 part); +u16 WIFI_getRF_STATUS(); + +void WIFI_setBB_CNT(u16 val); +u8 WIFI_getBB_DATA(); +void WIFI_setBB_DATA(u8 val); + +/* wifimac io */ +void WIFI_write16(u32 address, u16 val); +u16 WIFI_read16(u32 address); + +/* wifimac timing */ +void WIFI_usTrigger(); + + +/* DS WFC profile data documented here : */ +/* http://dsdev.bigredpimp.com/2006/07/31/aoss-wfc-profile-data/ */ +/* Note : we use bytes to avoid endianness issues */ +typedef struct _FW_WFCProfile +{ + char SSID[32]; + char SSID_WEP64[32]; + char WEPKEY_PART1[16]; + char WEPKEY_PART2[16]; + char WEPKEY_PART3[16]; + char WEPKEY_PART4[16]; + u8 IP_ADDRESS[4]; + u8 GATEWAY[4]; + u8 PRIM_DNS[4]; + u8 SEC_DNS[4]; + u8 SUBNET_MASK; + u8 WEP64_KEY_AOSS[20]; + u8 UNK1; + u8 WEP_MODE; + u8 STATUS; + u8 UNK2[7]; + u8 UNK3; + u8 UNK4[14]; + u8 CRC16[2]; + +} FW_WFCProfile; + +/* wifi data to be stored in firmware, when no firmware image was loaded */ +extern u8 FW_Mac[6]; +extern const u8 FW_WIFIInit[32]; +extern const u8 FW_BBInit[105]; +extern const u8 FW_RFInit[36]; +extern const u8 FW_RFChannel[6*14]; +extern const u8 FW_BBChannel[14]; +extern FW_WFCProfile FW_WFCProfile1; +extern FW_WFCProfile FW_WFCProfile2; +extern FW_WFCProfile FW_WFCProfile3; + +#endif diff --git a/jni/desmume/wxwin.m4 b/jni/desmume/wxwin.m4 new file mode 100755 index 0000000..52c55e2 --- /dev/null +++ b/jni/desmume/wxwin.m4 @@ -0,0 +1,366 @@ +dnl --------------------------------------------------------------------------- +dnl Macros for wxWidgets detection. Typically used in configure.in as: +dnl +dnl AC_ARG_ENABLE(...) +dnl AC_ARG_WITH(...) +dnl ... +dnl AM_OPTIONS_WXCONFIG +dnl ... +dnl ... +dnl AM_PATH_WXCONFIG(2.6.0, wxWin=1) +dnl if test "$wxWin" != 1; then +dnl AC_MSG_ERROR([ +dnl wxWidgets must be installed on your system +dnl but wx-config script couldn't be found. +dnl +dnl Please check that wx-config is in path, the directory +dnl where wxWidgets libraries are installed (returned by +dnl 'wx-config --libs' command) is in LD_LIBRARY_PATH or +dnl equivalent variable and wxWidgets version is 2.3.4 or above. +dnl ]) +dnl fi +dnl CPPFLAGS="$CPPFLAGS $WX_CPPFLAGS" +dnl CXXFLAGS="$CXXFLAGS $WX_CXXFLAGS_ONLY" +dnl CFLAGS="$CFLAGS $WX_CFLAGS_ONLY" +dnl +dnl LIBS="$LIBS $WX_LIBS" +dnl --------------------------------------------------------------------------- + +dnl --------------------------------------------------------------------------- +dnl AM_OPTIONS_WXCONFIG +dnl +dnl adds support for --wx-prefix, --wx-exec-prefix, --with-wxdir and +dnl --wx-config command line options +dnl --------------------------------------------------------------------------- + +AC_DEFUN([AM_OPTIONS_WXCONFIG], +[ + AC_ARG_WITH(wxdir, + [ --with-wxdir=PATH Use uninstalled version of wxWidgets in PATH], + [ wx_config_name="$withval/wx-config" + wx_config_args="--inplace"]) + AC_ARG_WITH(wx-config, + [ --with-wx-config=CONFIG wx-config script to use (optional)], + wx_config_name="$withval" ) + AC_ARG_WITH(wx-prefix, + [ --with-wx-prefix=PREFIX Prefix where wxWidgets is installed (optional)], + wx_config_prefix="$withval", wx_config_prefix="") + AC_ARG_WITH(wx-exec-prefix, + [ --with-wx-exec-prefix=PREFIX + Exec prefix where wxWidgets is installed (optional)], + wx_config_exec_prefix="$withval", wx_config_exec_prefix="") +]) + +dnl Helper macro for checking if wx version is at least $1.$2.$3, set's +dnl wx_ver_ok=yes if it is: +AC_DEFUN([_WX_PRIVATE_CHECK_VERSION], +[ + wx_ver_ok="" + if test "x$WX_VERSION" != x ; then + if test $wx_config_major_version -gt $1; then + wx_ver_ok=yes + else + if test $wx_config_major_version -eq $1; then + if test $wx_config_minor_version -gt $2; then + wx_ver_ok=yes + else + if test $wx_config_minor_version -eq $2; then + if test $wx_config_micro_version -ge $3; then + wx_ver_ok=yes + fi + fi + fi + fi + fi + fi +]) + +dnl --------------------------------------------------------------------------- +dnl AM_PATH_WXCONFIG(VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND +dnl [, WX-LIBS [, ADDITIONAL-WX-CONFIG-FLAGS]]]]) +dnl +dnl Test for wxWidgets, and define WX_C*FLAGS, WX_LIBS and WX_LIBS_STATIC +dnl (the latter is for static linking against wxWidgets). Set WX_CONFIG_NAME +dnl environment variable to override the default name of the wx-config script +dnl to use. Set WX_CONFIG_PATH to specify the full path to wx-config - in this +dnl case the macro won't even waste time on tests for its existence. +dnl +dnl Optional WX-LIBS argument contains comma- or space-separated list of +dnl wxWidgets libraries to link against (it may include contrib libraries). If +dnl it is not specified then WX_LIBS and WX_LIBS_STATIC will contain flags to +dnl link with all of the core wxWidgets libraries. +dnl +dnl Optional ADDITIONAL-WX-CONFIG-FLAGS argument is appended to wx-config +dnl invocation command in present. It can be used to fine-tune lookup of +dnl best wxWidgets build available. +dnl +dnl Example use: +dnl AM_PATH_WXCONFIG([2.6.0], [wxWin=1], [wxWin=0], [html,core,net] +dnl [--unicode --debug]) +dnl --------------------------------------------------------------------------- + +dnl +dnl Get the cflags and libraries from the wx-config script +dnl +AC_DEFUN([AM_PATH_WXCONFIG], +[ + dnl do we have wx-config name: it can be wx-config or wxd-config or ... + if test x${WX_CONFIG_NAME+set} != xset ; then + WX_CONFIG_NAME=wx-config + fi + + if test "x$wx_config_name" != x ; then + WX_CONFIG_NAME="$wx_config_name" + fi + + dnl deal with optional prefixes + if test x$wx_config_exec_prefix != x ; then + wx_config_args="$wx_config_args --exec-prefix=$wx_config_exec_prefix" + WX_LOOKUP_PATH="$wx_config_exec_prefix/bin" + fi + if test x$wx_config_prefix != x ; then + wx_config_args="$wx_config_args --prefix=$wx_config_prefix" + WX_LOOKUP_PATH="$WX_LOOKUP_PATH:$wx_config_prefix/bin" + fi + if test "$cross_compiling" = "yes"; then + wx_config_args="$wx_config_args --host=$host_alias" + fi + + dnl don't search the PATH if WX_CONFIG_NAME is absolute filename + if test -x "$WX_CONFIG_NAME" ; then + AC_MSG_CHECKING(for wx-config) + WX_CONFIG_PATH="$WX_CONFIG_NAME" + AC_MSG_RESULT($WX_CONFIG_PATH) + else + AC_PATH_PROG(WX_CONFIG_PATH, $WX_CONFIG_NAME, no, "$WX_LOOKUP_PATH:$PATH") + fi + + if test "$WX_CONFIG_PATH" != "no" ; then + WX_VERSION="" + + min_wx_version=ifelse([$1], ,2.2.1,$1) + if test -z "$5" ; then + AC_MSG_CHECKING([for wxWidgets version >= $min_wx_version]) + else + AC_MSG_CHECKING([for wxWidgets version >= $min_wx_version ($5)]) + fi + + WX_CONFIG_WITH_ARGS="$WX_CONFIG_PATH $wx_config_args $5 $4" + + WX_VERSION=`$WX_CONFIG_WITH_ARGS --version 2>/dev/null` + wx_config_major_version=`echo $WX_VERSION | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + wx_config_minor_version=`echo $WX_VERSION | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + wx_config_micro_version=`echo $WX_VERSION | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + + wx_requested_major_version=`echo $min_wx_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + wx_requested_minor_version=`echo $min_wx_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + wx_requested_micro_version=`echo $min_wx_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + + _WX_PRIVATE_CHECK_VERSION([$wx_requested_major_version], + [$wx_requested_minor_version], + [$wx_requested_micro_version]) + + if test -n "$wx_ver_ok"; then + + AC_MSG_RESULT(yes (version $WX_VERSION)) + WX_LIBS=`$WX_CONFIG_WITH_ARGS --libs` + + dnl is this even still appropriate? --static is a real option now + dnl and WX_CONFIG_WITH_ARGS is likely to contain it if that is + dnl what the user actually wants, making this redundant at best. + dnl For now keep it in case anyone actually used it in the past. + AC_MSG_CHECKING([for wxWidgets static library]) + WX_LIBS_STATIC=`$WX_CONFIG_WITH_ARGS --static --libs 2>/dev/null` + if test "x$WX_LIBS_STATIC" = "x"; then + AC_MSG_RESULT(no) + else + AC_MSG_RESULT(yes) + fi + + dnl starting with version 2.2.6 wx-config has --cppflags argument + wx_has_cppflags="" + if test $wx_config_major_version -gt 2; then + wx_has_cppflags=yes + else + if test $wx_config_major_version -eq 2; then + if test $wx_config_minor_version -gt 2; then + wx_has_cppflags=yes + else + if test $wx_config_minor_version -eq 2; then + if test $wx_config_micro_version -ge 6; then + wx_has_cppflags=yes + fi + fi + fi + fi + fi + + dnl starting with version 2.7.0 wx-config has --rescomp option + wx_has_rescomp="" + if test $wx_config_major_version -gt 2; then + wx_has_rescomp=yes + else + if test $wx_config_major_version -eq 2; then + if test $wx_config_minor_version -ge 7; then + wx_has_rescomp=yes + fi + fi + fi + if test "x$wx_has_rescomp" = x ; then + dnl cannot give any useful info for resource compiler + WX_RESCOMP= + else + WX_RESCOMP=`$WX_CONFIG_WITH_ARGS --rescomp` + fi + + if test "x$wx_has_cppflags" = x ; then + dnl no choice but to define all flags like CFLAGS + WX_CFLAGS=`$WX_CONFIG_WITH_ARGS --cflags` + WX_CPPFLAGS=$WX_CFLAGS + WX_CXXFLAGS=$WX_CFLAGS + + WX_CFLAGS_ONLY=$WX_CFLAGS + WX_CXXFLAGS_ONLY=$WX_CFLAGS + else + dnl we have CPPFLAGS included in CFLAGS included in CXXFLAGS + WX_CPPFLAGS=`$WX_CONFIG_WITH_ARGS --cppflags` + WX_CXXFLAGS=`$WX_CONFIG_WITH_ARGS --cxxflags` + WX_CFLAGS=`$WX_CONFIG_WITH_ARGS --cflags` + + WX_CFLAGS_ONLY=`echo $WX_CFLAGS | sed "s@^$WX_CPPFLAGS *@@"` + WX_CXXFLAGS_ONLY=`echo $WX_CXXFLAGS | sed "s@^$WX_CFLAGS *@@"` + fi + + ifelse([$2], , :, [$2]) + + else + + if test "x$WX_VERSION" = x; then + dnl no wx-config at all + AC_MSG_RESULT(no) + else + AC_MSG_RESULT(no (version $WX_VERSION is not new enough)) + fi + + WX_CFLAGS="" + WX_CPPFLAGS="" + WX_CXXFLAGS="" + WX_LIBS="" + WX_LIBS_STATIC="" + WX_RESCOMP="" + ifelse([$3], , :, [$3]) + + fi + else + + WX_CFLAGS="" + WX_CPPFLAGS="" + WX_CXXFLAGS="" + WX_LIBS="" + WX_LIBS_STATIC="" + WX_RESCOMP="" + + ifelse([$3], , :, [$3]) + + fi + + AC_SUBST(WX_CPPFLAGS) + AC_SUBST(WX_CFLAGS) + AC_SUBST(WX_CXXFLAGS) + AC_SUBST(WX_CFLAGS_ONLY) + AC_SUBST(WX_CXXFLAGS_ONLY) + AC_SUBST(WX_LIBS) + AC_SUBST(WX_LIBS_STATIC) + AC_SUBST(WX_VERSION) + AC_SUBST(WX_RESCOMP) +]) + +dnl --------------------------------------------------------------------------- +dnl Get information on the wxrc program for making C++, Python and xrs +dnl resource files. +dnl +dnl AC_ARG_ENABLE(...) +dnl AC_ARG_WITH(...) +dnl ... +dnl AM_OPTIONS_WXCONFIG +dnl ... +dnl AM_PATH_WXCONFIG(2.6.0, wxWin=1) +dnl if test "$wxWin" != 1; then +dnl AC_MSG_ERROR([ +dnl wxWidgets must be installed on your system +dnl but wx-config script couldn't be found. +dnl +dnl Please check that wx-config is in path, the directory +dnl where wxWidgets libraries are installed (returned by +dnl 'wx-config --libs' command) is in LD_LIBRARY_PATH or +dnl equivalent variable and wxWidgets version is 2.6.0 or above. +dnl ]) +dnl fi +dnl +dnl AM_PATH_WXRC([HAVE_WXRC=1], [HAVE_WXRC=0]) +dnl if test "x$HAVE_WXRC" != x1; then +dnl AC_MSG_ERROR([ +dnl The wxrc program was not installed or not found. +dnl +dnl Please check the wxWidgets installation. +dnl ]) +dnl fi +dnl +dnl CPPFLAGS="$CPPFLAGS $WX_CPPFLAGS" +dnl CXXFLAGS="$CXXFLAGS $WX_CXXFLAGS_ONLY" +dnl CFLAGS="$CFLAGS $WX_CFLAGS_ONLY" +dnl +dnl LDFLAGS="$LDFLAGS $WX_LIBS" +dnl --------------------------------------------------------------------------- + + + +dnl --------------------------------------------------------------------------- +dnl AM_PATH_WXRC([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl +dnl Test for wxWidgets' wxrc program for creating either C++, Python or XRS +dnl resources. The variable WXRC will be set and substituted in the configure +dnl script and Makefiles. +dnl +dnl Example use: +dnl AM_PATH_WXRC([wxrc=1], [wxrc=0]) +dnl --------------------------------------------------------------------------- + +dnl +dnl wxrc program from the wx-config script +dnl +AC_DEFUN([AM_PATH_WXRC], +[ + AC_ARG_VAR([WXRC], [Path to wxWidget's wxrc resource compiler]) + + if test "x$WX_CONFIG_NAME" = x; then + AC_MSG_ERROR([The wxrc tests must run after wxWidgets test.]) + else + + AC_MSG_CHECKING([for wxrc]) + + if test "x$WXRC" = x ; then + dnl wx-config --utility is a new addition to wxWidgets: + _WX_PRIVATE_CHECK_VERSION(2,5,3) + if test -n "$wx_ver_ok"; then + WXRC=`$WX_CONFIG_WITH_ARGS --utility=wxrc` + fi + fi + + if test "x$WXRC" = x ; then + AC_MSG_RESULT([not found]) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT([$WXRC]) + ifelse([$1], , :, [$1]) + fi + + AC_SUBST(WXRC) + fi +]) diff --git a/jni/desmume_compat.mk b/jni/desmume_compat.mk new file mode 100755 index 0000000..5446acf --- /dev/null +++ b/jni/desmume_compat.mk @@ -0,0 +1,106 @@ +# Android ndk makefile for ds4droid + +LOCAL_PATH := $(call my-dir) + +MY_LOCAL_PATH := $(LOCAL_PATH) + +include $(CLEAR_VARS) + + +LOCAL_MODULE := libdesmumecompat +LOCAL_C_INCLUDES := $(LOCAL_PATH)/desmume/src \ + $(LOCAL_PATH)/desmume/src/android/agg/include + +LOCAL_SRC_FILES := desmume/src/aggdraw.cpp \ + desmume/src/addons.cpp \ + desmume/src/slot1.cpp \ + desmume/src/addons/slot1_none.cpp \ + desmume/src/addons/slot1_r4.cpp \ + desmume/src/addons/slot1_retail.cpp \ + desmume/src/addons/slot1_retail_nand.cpp \ + desmume/src/addons/slot2_expMemory.cpp \ + desmume/src/addons/slot2_gbagame.cpp \ + desmume/src/addons/slot2_guitarGrip.cpp \ + desmume/src/addons/slot2_mpcf.cpp \ + desmume/src/addons/slot2_none.cpp \ + desmume/src/addons/slot2_paddle.cpp \ + desmume/src/addons/slot2_piano.cpp \ + desmume/src/addons/slot2_rumblepak.cpp \ + desmume/src/MMU.cpp \ + desmume/src/NDSSystem.cpp \ + desmume/src/utils/vfat.cpp \ + desmume/src/debug.cpp \ + desmume/src/emufile.cpp \ + desmume/src/GPU.cpp \ + desmume/src/gfx3d.cpp \ + desmume/src/SPU.cpp \ + desmume/src/wifi.cpp \ + desmume/src/rtc.cpp \ + desmume/src/armcpu.cpp \ + desmume/src/mc.cpp \ + desmume/src/render3D.cpp \ + desmume/src/FIFO.cpp \ + desmume/src/readwrite.cpp \ + desmume/src/movie.cpp \ + desmume/src/common.cpp \ + desmume/src/cheatSystem.cpp \ + desmume/src/firmware.cpp \ + desmume/src/version.cpp \ + desmume/src/driver.cpp \ + desmume/src/bios.cpp \ + desmume/src/utils/decrypt/decrypt.cpp \ + desmume/src/utils/emufat.cpp \ + desmume/src/utils/libfat/libfat.cpp \ + desmume/src/utils/libfat/libfat_public_api.cpp \ + desmume/src/arm_instructions.cpp \ + desmume/src/thumb_instructions.cpp \ + desmume/src/GPU_osd.cpp \ + desmume/src/utils/dlditool.cpp \ + desmume/src/matrix.cpp \ + desmume/src/metaspu/metaspu.cpp \ + desmume/src/utils/datetime.cpp \ + desmume/src/cp15.cpp \ + desmume/src/utils/tinyxml/tinyxml.cpp \ + desmume/src/utils/tinyxml/tinyxmlparser.cpp \ + desmume/src/utils/tinyxml/tinyxmlerror.cpp \ + desmume/src/utils/tinyxml/tinystr.cpp \ + desmume/src/utils/xstring.cpp \ + desmume/src/utils/guid.cpp \ + desmume/src/utils/ConvertUTF.c \ + desmume/src/utils/decrypt/header.cpp \ + desmume/src/utils/libfat/partition.cpp \ + desmume/src/utils/libfat/fatfile.cpp \ + desmume/src/utils/libfat/cache.cpp \ + desmume/src/utils/libfat/directory.cpp \ + desmume/src/utils/libfat/fatdir.cpp \ + desmume/src/utils/libfat/lock.cpp \ + desmume/src/utils/libfat/file_allocation_table.cpp \ + desmume/src/utils/libfat/filetime.cpp \ + desmume/src/path.cpp \ + desmume/src/fs-linux.cpp \ + desmume/src/saves.cpp \ + desmume/src/ROMReader.cpp \ + desmume/src/OGLRender.cpp \ + desmume/src/texcache.cpp \ + desmume/src/rasterize.cpp \ + desmume/src/utils/task.cpp \ + desmume/src/filter/2xsai.cpp \ + desmume/src/filter/bilinear.cpp \ + desmume/src/filter/epx.cpp \ + desmume/src/filter/hq2x.cpp \ + desmume/src/filter/hq4x.cpp \ + desmume/src/filter/lq2x.cpp \ + desmume/src/filter/scanline.cpp \ + desmume/src/android/mic.cpp \ + desmume/src/android/throttle.cpp \ + desmume/src/android/main.cpp + +LOCAL_ARM_MODE := thumb +LOCAL_ARM_NEON := false +LOCAL_CFLAGS := -DANDROID -DHAVE_LIBAGG -DHAVE_LIBZ -fexceptions +LOCAL_STATIC_LIBRARIES := aggcompat +LOCAL_LDLIBS := -llog -lz -lGLESv1_CM -lEGL -ljnigraphics + +include $(BUILD_SHARED_LIBRARY) + +include $(MY_LOCAL_PATH)/desmume/src/android/agg/agg_compat.mk diff --git a/jni/desmume_neon.mk b/jni/desmume_neon.mk new file mode 100755 index 0000000..325a660 --- /dev/null +++ b/jni/desmume_neon.mk @@ -0,0 +1,108 @@ +# Android ndk makefile for ds4droid + +LOCAL_PATH := $(call my-dir) + +MY_LOCAL_PATH := $(LOCAL_PATH) + +include $(CLEAR_VARS) + + +LOCAL_MODULE := libdesmumeneon +LOCAL_C_INCLUDES := $(LOCAL_PATH)/desmume/src \ + $(LOCAL_PATH)/desmume/src/android/agg/include + +LOCAL_SRC_FILES := desmume/src/aggdraw.cpp \ + desmume/src/addons.cpp \ + desmume/src/slot1.cpp \ + desmume/src/addons/slot1_none.cpp \ + desmume/src/addons/slot1_r4.cpp \ + desmume/src/addons/slot1_retail.cpp \ + desmume/src/addons/slot1_retail_nand.cpp \ + desmume/src/addons/slot2_expMemory.cpp \ + desmume/src/addons/slot2_gbagame.cpp \ + desmume/src/addons/slot2_guitarGrip.cpp \ + desmume/src/addons/slot2_mpcf.cpp \ + desmume/src/addons/slot2_none.cpp \ + desmume/src/addons/slot2_paddle.cpp \ + desmume/src/addons/slot2_piano.cpp \ + desmume/src/addons/slot2_rumblepak.cpp \ + desmume/src/MMU.cpp \ + desmume/src/NDSSystem.cpp \ + desmume/src/utils/vfat.cpp \ + desmume/src/debug.cpp \ + desmume/src/emufile.cpp \ + desmume/src/GPU.cpp \ + desmume/src/gfx3d.cpp \ + desmume/src/SPU.cpp \ + desmume/src/wifi.cpp \ + desmume/src/rtc.cpp \ + desmume/src/armcpu.cpp \ + desmume/src/mc.cpp \ + desmume/src/render3D.cpp \ + desmume/src/FIFO.cpp \ + desmume/src/readwrite.cpp \ + desmume/src/movie.cpp \ + desmume/src/common.cpp \ + desmume/src/cheatSystem.cpp \ + desmume/src/firmware.cpp \ + desmume/src/version.cpp \ + desmume/src/driver.cpp \ + desmume/src/bios.cpp \ + desmume/src/utils/decrypt/decrypt.cpp \ + desmume/src/utils/emufat.cpp \ + desmume/src/utils/libfat/libfat.cpp \ + desmume/src/utils/libfat/libfat_public_api.cpp \ + desmume/src/arm_instructions.cpp \ + desmume/src/thumb_instructions.cpp \ + desmume/src/GPU_osd.cpp \ + desmume/src/utils/dlditool.cpp \ + desmume/src/matrix.cpp \ + desmume/src/metaspu/metaspu.cpp \ + desmume/src/utils/datetime.cpp \ + desmume/src/cp15.cpp \ + desmume/src/utils/tinyxml/tinyxml.cpp \ + desmume/src/utils/tinyxml/tinyxmlparser.cpp \ + desmume/src/utils/tinyxml/tinyxmlerror.cpp \ + desmume/src/utils/tinyxml/tinystr.cpp \ + desmume/src/utils/xstring.cpp \ + desmume/src/utils/guid.cpp \ + desmume/src/utils/ConvertUTF.c \ + desmume/src/utils/decrypt/header.cpp \ + desmume/src/utils/libfat/partition.cpp \ + desmume/src/utils/libfat/fatfile.cpp \ + desmume/src/utils/libfat/cache.cpp \ + desmume/src/utils/libfat/directory.cpp \ + desmume/src/utils/libfat/fatdir.cpp \ + desmume/src/utils/libfat/lock.cpp \ + desmume/src/utils/libfat/file_allocation_table.cpp \ + desmume/src/utils/libfat/filetime.cpp \ + desmume/src/path.cpp \ + desmume/src/fs-linux.cpp \ + desmume/src/saves.cpp \ + desmume/src/ROMReader.cpp \ + desmume/src/OGLRender.cpp \ + desmume/src/texcache.cpp \ + desmume/src/rasterize.cpp \ + desmume/src/utils/task.cpp \ + desmume/src/filter/2xsai.cpp \ + desmume/src/filter/bilinear.cpp \ + desmume/src/filter/epx.cpp \ + desmume/src/filter/hq2x.cpp \ + desmume/src/filter/hq4x.cpp \ + desmume/src/filter/lq2x.cpp \ + desmume/src/filter/scanline.cpp \ + desmume/src/android/mic.cpp \ + desmume/src/android/throttle.cpp \ + desmume/src/android/main.cpp \ + desmume/src/android/neontest.cpp + +LOCAL_ARM_NEON := true +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := -DANDROID -DHAVE_LIBAGG -DHAVE_LIBZ -fexceptions -DHAVE_NEON=1 -march=armv6 -marm -mfloat-abi=softfp -mfpu=neon +LOCAL_STATIC_LIBRARIES := aggneon mathneon +LOCAL_LDLIBS := -llog -lz -lGLESv1_CM -lEGL -ljnigraphics + +include $(BUILD_SHARED_LIBRARY) + +include $(MY_LOCAL_PATH)/desmume/src/android/agg/agg_neon.mk +include $(MY_LOCAL_PATH)/desmume/src/android/math-neon/Android.mk diff --git a/libs/acra-4.2.3.jar b/libs/acra-4.2.3.jar new file mode 100755 index 0000000..c6b57a9 Binary files /dev/null and b/libs/acra-4.2.3.jar differ diff --git a/lint.xml b/lint.xml new file mode 100755 index 0000000..ee0eead --- /dev/null +++ b/lint.xml @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8"?> +<lint> +</lint> \ No newline at end of file diff --git a/proguard-project.txt b/proguard-project.txt new file mode 100755 index 0000000..f2fe155 --- /dev/null +++ b/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/project.properties b/project.properties new file mode 100755 index 0000000..9b84a6b --- /dev/null +++ b/project.properties @@ -0,0 +1,14 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-16 diff --git a/res/drawable-hdpi/ic_action_search.png b/res/drawable-hdpi/ic_action_search.png new file mode 100755 index 0000000..67de12d Binary files /dev/null and b/res/drawable-hdpi/ic_action_search.png differ diff --git a/res/drawable-hdpi/ic_launcher.png b/res/drawable-hdpi/ic_launcher.png new file mode 100755 index 0000000..1f2fd00 Binary files /dev/null and b/res/drawable-hdpi/ic_launcher.png differ diff --git a/res/drawable-ldpi/ic_launcher.png b/res/drawable-ldpi/ic_launcher.png new file mode 100755 index 0000000..45c6c16 Binary files /dev/null and b/res/drawable-ldpi/ic_launcher.png differ diff --git a/res/drawable-mdpi/ic_action_search.png b/res/drawable-mdpi/ic_action_search.png new file mode 100755 index 0000000..134d549 Binary files /dev/null and b/res/drawable-mdpi/ic_action_search.png differ diff --git a/res/drawable-mdpi/ic_launcher.png b/res/drawable-mdpi/ic_launcher.png new file mode 100755 index 0000000..c18df18 Binary files /dev/null and b/res/drawable-mdpi/ic_launcher.png differ diff --git a/res/drawable-nodpi/dscontrols.png b/res/drawable-nodpi/dscontrols.png new file mode 100755 index 0000000..4cc461c Binary files /dev/null and b/res/drawable-nodpi/dscontrols.png differ diff --git a/res/drawable-nodpi/dscontrolstouch.png b/res/drawable-nodpi/dscontrolstouch.png new file mode 100755 index 0000000..75a93fc Binary files /dev/null and b/res/drawable-nodpi/dscontrolstouch.png differ diff --git a/res/drawable-xhdpi/ic_action_search.png b/res/drawable-xhdpi/ic_action_search.png new file mode 100755 index 0000000..d699c6b Binary files /dev/null and b/res/drawable-xhdpi/ic_action_search.png differ diff --git a/res/drawable-xhdpi/ic_launcher.png b/res/drawable-xhdpi/ic_launcher.png new file mode 100755 index 0000000..1f2fd00 Binary files /dev/null and b/res/drawable-xhdpi/ic_launcher.png differ diff --git a/res/drawable/file.png b/res/drawable/file.png new file mode 100755 index 0000000..7c0df1e Binary files /dev/null and b/res/drawable/file.png differ diff --git a/res/drawable/folder.png b/res/drawable/folder.png new file mode 100755 index 0000000..dbb3bb3 Binary files /dev/null and b/res/drawable/folder.png differ diff --git a/res/drawable/updirectory.png b/res/drawable/updirectory.png new file mode 100755 index 0000000..ef841a9 Binary files /dev/null and b/res/drawable/updirectory.png differ diff --git a/res/layout/activity_main.xml b/res/layout/activity_main.xml new file mode 100755 index 0000000..629c75a --- /dev/null +++ b/res/layout/activity_main.xml @@ -0,0 +1,6 @@ +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" > + +</RelativeLayout> diff --git a/res/layout/file_dialog_main.xml b/res/layout/file_dialog_main.xml new file mode 100755 index 0000000..a25241c --- /dev/null +++ b/res/layout/file_dialog_main.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout android:id="@+id/relativeLayout01" + xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" android:layout_width="fill_parent" + android:layout_height="fill_parent"> + + <LinearLayout android:id="@+id/fdLinearLayoutList" + android:orientation="vertical" android:layout_width="fill_parent" + android:layout_height="wrap_content" android:layout_alignParentBottom="true"> + + <LinearLayout android:id="@+id/fdLinearLayoutSelect" + android:orientation="vertical" android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" android:paddingLeft="10dp" + android:paddingRight="10dp" android:paddingBottom="5dp"> + + <LinearLayout android:orientation="horizontal" + android:layout_width="fill_parent" android:layout_height="fill_parent"> + </LinearLayout> + </LinearLayout> + + <LinearLayout android:id="@+id/fdLinearLayoutCreate" + android:orientation="vertical" android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" android:paddingLeft="10dp" + android:paddingRight="10dp" android:paddingBottom="5dp"> + + <LinearLayout android:orientation="horizontal" + android:layout_width="fill_parent" android:layout_height="fill_parent"> + </LinearLayout> + </LinearLayout> + + </LinearLayout> + + <LinearLayout android:orientation="vertical" + android:layout_width="fill_parent" android:layout_height="fill_parent" + android:layout_above="@+id/fdLinearLayoutList"> + <TextView android:id="@+id/path" android:layout_width="fill_parent" + android:layout_height="wrap_content" /> + <ListView android:id="@android:id/list" android:layout_width="fill_parent" + android:layout_height="fill_parent" /> + <TextView android:id="@android:id/empty" + android:layout_width="fill_parent" android:layout_height="fill_parent" + android:text="@string/no_data" /> + </LinearLayout> + + + + +</RelativeLayout> diff --git a/res/layout/file_dialog_row.xml b/res/layout/file_dialog_row.xml new file mode 100755 index 0000000..18c8c62 --- /dev/null +++ b/res/layout/file_dialog_row.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> + +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" android:layout_height="fill_parent"> + + <ImageView android:layout_alignParentLeft="true" android:id="@+id/fdrowimage" + android:layout_height="35dp" android:layout_width="wrap_content" + android:paddingRight="5dp" android:paddingLeft="3dp"></ImageView> + <TextView android:text="@+id/fdrowtext" android:layout_width="wrap_content" + android:id="@+id/fdrowtext" android:layout_toRightOf="@+id/fdrowimage" + android:layout_alignTop="@+id/fdrowimage" android:layout_alignBottom="@+id/fdrowimage" + android:gravity="center_vertical" android:layout_height="35dp" + android:textSize="23dp"></TextView> + +</RelativeLayout> \ No newline at end of file diff --git a/res/menu/activity_main.xml b/res/menu/activity_main.xml new file mode 100755 index 0000000..5963669 --- /dev/null +++ b/res/menu/activity_main.xml @@ -0,0 +1,33 @@ + + <menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/load" android:title="@string/Load"></item> + <item android:id="@+id/quicksave" android:title="@string/QuickSave"></item> + <item android:id="@+id/quickrestore" android:title="@string/QuickRestore"></item> + <item android:id="@+id/savestate" android:title="@string/SaveState"> + <menu> + <item android:id="@+id/save1" android:title="1"/> + <item android:id="@+id/save2" android:title="2"/> + <item android:id="@+id/save3" android:title="3"/> + <item android:id="@+id/save4" android:title="4"/> + <item android:id="@+id/save5" android:title="5"/> + <item android:id="@+id/save6" android:title="6"/> + <item android:id="@+id/save7" android:title="7"/> + <item android:id="@+id/save8" android:title="8"/> + <item android:id="@+id/save9" android:title="9"/> + </menu> + </item> + <item android:id="@+id/restorestate" android:title="@string/RestoreState"> + <menu> + <item android:id="@+id/restore1" android:title="1"/> + <item android:id="@+id/restore2" android:title="2"/> + <item android:id="@+id/restore3" android:title="3"/> + <item android:id="@+id/restore4" android:title="4"/> + <item android:id="@+id/restore5" android:title="5"/> + <item android:id="@+id/restore6" android:title="6"/> + <item android:id="@+id/restore7" android:title="7"/> + <item android:id="@+id/restore8" android:title="8"/> + <item android:id="@+id/restore9" android:title="9"/> + </menu> + </item> + <!-- <item android:id="@+id/settings" android:title="@string/Settings"></item> --> + </menu> diff --git a/res/values-v11/styles.xml b/res/values-v11/styles.xml new file mode 100755 index 0000000..a2ff8dd --- /dev/null +++ b/res/values-v11/styles.xml @@ -0,0 +1,5 @@ +<resources> + + <!-- <style name="AppTheme" parent="android:Theme.Holo.Light" /> --> + +</resources> \ No newline at end of file diff --git a/res/values-v14/styles.xml b/res/values-v14/styles.xml new file mode 100755 index 0000000..2245d62 --- /dev/null +++ b/res/values-v14/styles.xml @@ -0,0 +1,5 @@ +<resources> + + <!-- <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar" /> --> + +</resources> \ No newline at end of file diff --git a/res/values/fileendings.xml b/res/values/fileendings.xml new file mode 100755 index 0000000..0fad9d0 --- /dev/null +++ b/res/values/fileendings.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <array name="fileEndingImage"> + <item>".png"</item> + <item>".gif"</item> + <item>".jpg"</item> + <item>".jpeg"</item> + <item>".bmp"</item> + </array> + <array name="fileEndingAudio"> + <item>".mp3"</item> + <item>".wav"</item> + <item>".ogg"</item> + <item>".midi"</item> + </array> + <array name="fileEndingPackage"> + <item>.jar</item> + <item>.zip</item> + <item>.rar</item> + <item>.gz</item> + </array> + <array name="fileEndingWebText"> + <item>.htm</item> + <item>.html</item> + <item>.php</item> + </array> + <array name="fileEndingText"> + <item>.txt</item> + <item>.log</item> + </array> + <array name="fileEndingVideo"> + <item>.wmv</item> + <item>.avi</item> + <item>.mpg</item> + <item>.mpeg</item> + <item>.mp4</item> + </array> + <array name="fileEndingGeoPosition"> + <item>.loc</item> + <item>.gpx</item> + </array> +</resources> + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml new file mode 100755 index 0000000..7d1b5ff --- /dev/null +++ b/res/values/strings.xml @@ -0,0 +1,32 @@ +<resources> + + <string name="app_name">nds4droid</string> + <string name="hello_world">Hello world!</string> + <string name="menu_settings">Settings</string> + <string name="title_activity_main">nds4droid</string> + <string-array name="file_options"> + <!--item>Rename</item--> + <item>Delete</item> + <!--item>Cut</item--> + <!--item>Copy</item--> + <item>Send To...</item> + </string-array> + <string name="rom_error">There was an error loading this ROM :(</string> + <string name="OK">OK</string> + <string name="location">Location</string> + <string name="cant_read_folder">Folder can\'t be read!</string> + <string name="nnew">New</string> + <string name="select">Select</string> + <string name="file_name">File name:</string> + <string name="cancel">Cancel</string> + <string name="create">Save</string> + <string name="no_data">No Data</string> + <color name="gray">#ffff0000</color> + <string name="err">Error</string> + <string name="Load">Load</string> + <string name="QuickSave">Quick Save</string> + <string name="QuickRestore">Quick Restore</string> + <string name="SaveState">Save State</string> + <string name="RestoreState">Restore State</string> + <string name="Settings">Settings</string> +</resources> \ No newline at end of file diff --git a/res/values/styles.xml b/res/values/styles.xml new file mode 100755 index 0000000..e20c827 --- /dev/null +++ b/res/values/styles.xml @@ -0,0 +1,5 @@ +<resources> + + <style name="AppTheme" parent="android:Theme.Light" /> + +</resources> \ No newline at end of file diff --git a/src/com/opendoorstudios/ds4droid/DeSmuME.java b/src/com/opendoorstudios/ds4droid/DeSmuME.java new file mode 100755 index 0000000..9667bbf --- /dev/null +++ b/src/com/opendoorstudios/ds4droid/DeSmuME.java @@ -0,0 +1,67 @@ +package com.opendoorstudios.ds4droid; + +/* + Copyright (C) 2012 Jeffrey Quesnelle + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +import android.content.Context; +import android.content.SharedPreferences; +import android.graphics.Bitmap; +import android.preference.PreferenceManager; +import android.util.Log; + +class DeSmuME { + + public static Context context; + + static boolean loaded = false; + + static void load() + { + if(loaded) + return; + System.loadLibrary("cpudetect"); + if(useNeon()) { + System.loadLibrary("desmumeneon"); + Log.i(MainActivity.TAG, "Using NEON enhanced native library"); + } + else { + System.loadLibrary("desmumecompat"); + Log.i(MainActivity.TAG, "Using compatibility native library"); + } + } + + static native boolean useNeon(); + static native void init(); + static native int runCore(); + static native void runOther(); + static native void resize(Bitmap bitmap, int width, int height); + static native void draw(Bitmap bitmap); + static native void touchScreenTouch(int x, int y); + static native void touchScreenRelease(); + static native void setButtons(int l, int r, int up, int down, int left, int right, int a, int b, int x, int y, int start, int select); + static native boolean loadRom(String path); + static native void setWorkingDir(String path); + static native void saveState(int slot); + static native void restoreState(int slot); + + public static int getSettingInt(String name, int def) + { + SharedPreferences pm = PreferenceManager.getDefaultSharedPreferences(context); + return pm.getInt(name, def); + } + +} diff --git a/src/com/opendoorstudios/ds4droid/FileDialog.java b/src/com/opendoorstudios/ds4droid/FileDialog.java new file mode 100755 index 0000000..8c5cbe5 --- /dev/null +++ b/src/com/opendoorstudios/ds4droid/FileDialog.java @@ -0,0 +1,262 @@ +package com.opendoorstudios.ds4droid; + +/* + Copyright (C) 2012 Jeffrey Quesnelle + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.TreeMap; + +import android.app.AlertDialog; +import android.app.ListActivity; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.SimpleAdapter; +import android.widget.TextView; + + +//This originally came from http://code.google.com/p/android-file-dialog/ + +public class FileDialog extends ListActivity { + + public static class SelectionMode { + public static final int MODE_CREATE = 0; + + public static final int MODE_OPEN = 1; + } + + + private static final String ITEM_KEY = "key"; + + + private static final String ITEM_IMAGE = "image"; + + + private static final String ROOT = "/"; + + + public static final String START_PATH = "START_PATH"; + + + public static final String FORMAT_FILTER = "FORMAT_FILTER"; + + + public static final String RESULT_PATH = "RESULT_PATH"; + + + public static final String SELECTION_MODE = "SELECTION_MODE"; + + + public static final String CAN_SELECT_DIR = "CAN_SELECT_DIR"; + + private List<String> path = null; + private TextView myPath; + private EditText mFileName; + private ArrayList<HashMap<String, Object>> mList; + + private String parentPath; + private String currentPath = ROOT; + + private int selectionMode = SelectionMode.MODE_CREATE; + + private String[] formatFilter = null; + + private boolean canSelectDir = false; + + private File selectedFile; + private HashMap<String, Integer> lastPositions = new HashMap<String, Integer>(); + + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setResult(RESULT_CANCELED, getIntent()); + + setContentView(R.layout.file_dialog_main); + myPath = (TextView) findViewById(R.id.path); + + + selectionMode = getIntent().getIntExtra(SELECTION_MODE, SelectionMode.MODE_CREATE); + + formatFilter = getIntent().getStringArrayExtra(FORMAT_FILTER); + + canSelectDir = getIntent().getBooleanExtra(CAN_SELECT_DIR, false); + + + String startPath = getIntent().getStringExtra(START_PATH); + startPath = startPath != null ? startPath : ROOT; + if (canSelectDir) { + File file = new File(startPath); + selectedFile = file; + } + getDir(startPath); + } + + private void getDir(String dirPath) { + + boolean useAutoSelection = dirPath.length() < currentPath.length(); + + Integer position = lastPositions.get(parentPath); + + getDirImpl(dirPath); + + if (position != null && useAutoSelection) { + getListView().setSelection(position); + } + + } + + + private void getDirImpl(final String dirPath) { + + currentPath = dirPath; + + final List<String> item = new ArrayList<String>(); + path = new ArrayList<String>(); + mList = new ArrayList<HashMap<String, Object>>(); + + File f = new File(currentPath); + File[] files = f.listFiles(); + if (files == null) { + currentPath = ROOT; + f = new File(currentPath); + files = f.listFiles(); + } + myPath.setText(getText(R.string.location) + ": " + currentPath); + + if (!currentPath.equals(ROOT)) { + + item.add(ROOT); + addItem(ROOT, R.drawable.folder); + path.add(ROOT); + + item.add("../"); + addItem("../", R.drawable.updirectory); + path.add(f.getParent()); + parentPath = f.getParent(); + + } + + TreeMap<String, String> dirsMap = new TreeMap<String, String>(); + TreeMap<String, String> dirsPathMap = new TreeMap<String, String>(); + TreeMap<String, String> filesMap = new TreeMap<String, String>(); + TreeMap<String, String> filesPathMap = new TreeMap<String, String>(); + for (File file : files) { + if (file.isDirectory()) { + String dirName = file.getName(); + dirsMap.put(dirName, dirName); + dirsPathMap.put(dirName, file.getPath()); + } else { + final String fileName = file.getName(); + final String fileNameLwr = fileName.toLowerCase(); + + if (formatFilter != null) { + boolean contains = false; + for (int i = 0; i < formatFilter.length; i++) { + final String formatLwr = formatFilter[i].toLowerCase(); + if (fileNameLwr.endsWith(formatLwr)) { + contains = true; + break; + } + } + if (contains) { + filesMap.put(fileName, fileName); + filesPathMap.put(fileName, file.getPath()); + } + + } else { + filesMap.put(fileName, fileName); + filesPathMap.put(fileName, file.getPath()); + } + } + } + item.addAll(dirsMap.tailMap("").values()); + item.addAll(filesMap.tailMap("").values()); + path.addAll(dirsPathMap.tailMap("").values()); + path.addAll(filesPathMap.tailMap("").values()); + + SimpleAdapter fileList = new SimpleAdapter(this, mList, R.layout.file_dialog_row, new String[] { + ITEM_KEY, ITEM_IMAGE }, new int[] { R.id.fdrowtext, R.id.fdrowimage }); + + for (String dir : dirsMap.tailMap("").values()) { + addItem(dir, R.drawable.folder); + } + + for (String file : filesMap.tailMap("").values()) { + addItem(file, R.drawable.file); + } + + fileList.notifyDataSetChanged(); + + setListAdapter(fileList); + + } + + private void addItem(String fileName, int imageId) { + HashMap<String, Object> item = new HashMap<String, Object>(); + item.put(ITEM_KEY, fileName); + item.put(ITEM_IMAGE, imageId); + mList.add(item); + } + + @Override + protected void onListItemClick(ListView l, View v, int position, long id) { + + File file = new File(path.get(position)); + + + if (file.isDirectory()) { + if (file.canRead()) { + lastPositions.put(currentPath, position); + getDir(path.get(position)); + if (canSelectDir) { + selectedFile = file; + v.setSelected(true); + } + } else { + new AlertDialog.Builder(this).setIcon(R.drawable.ic_launcher) + .setTitle("[" + file.getName() + "] " + getText(R.string.cant_read_folder)) + .setPositiveButton("OK", new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int which) { + + } + }).show(); + } + } else { + selectedFile = file; + v.setSelected(true); + getIntent().putExtra(RESULT_PATH, selectedFile.getPath()); + setResult(RESULT_OK, getIntent()); + finish(); + } + } + + + +} diff --git a/src/com/opendoorstudios/ds4droid/MainActivity.java b/src/com/opendoorstudios/ds4droid/MainActivity.java new file mode 100755 index 0000000..914b2d0 --- /dev/null +++ b/src/com/opendoorstudios/ds4droid/MainActivity.java @@ -0,0 +1,538 @@ +package com.opendoorstudios.ds4droid; + +/* + Copyright (C) 2012 Jeffrey Quesnelle + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +import java.io.File; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.os.Bundle; +import android.os.Environment; +import android.os.Handler; +import android.os.Message; +import android.preference.PreferenceManager; +import android.util.SparseIntArray; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.SurfaceHolder; +import android.view.SurfaceView; + +public class MainActivity extends Activity { + + static EmulatorThread coreThread; + NDSView view; + boolean running = false; + static final String TAG = "nds4droid"; + static boolean touchScreenMode = false; + static boolean inited = false; + static boolean romLoaded = false; + + Handler msgHandler = new Handler() { + + @Override + public + void dispatchMessage(Message msg) { + switch(msg.what) { + case DRAW_SCREEN: + view.invalidate(); + break; + case PICK_ROM: + pickRom(); + break; + } + } + + }; + + static final int DRAW_SCREEN = 1337; + static final int PICK_ROM = 1338; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + view = new NDSView(this); + setContentView(view); + + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + + if(!inited) + pickRom(); + + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } + + void runEmulation() { + boolean created = false; + if(coreThread == null) { + coreThread = new EmulatorThread(); + created = true; + } + coreThread.setPause(!romLoaded); + if(created) + coreThread.start(); + } + + void pauseEmulation() { + if(coreThread != null) { + coreThread.setPause(true); + } + running = false; + } + + void pickRom() { + Intent i = new Intent(this, FileDialog.class); + i.setAction(Intent.ACTION_PICK); + i.putExtra(FileDialog.START_PATH, Environment.getExternalStorageDirectory().getAbsolutePath()); + i.putExtra(FileDialog.FORMAT_FILTER, new String[] {".nds"}); + startActivityForResult(i, PICK_ROM); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if(requestCode != PICK_ROM || resultCode != Activity.RESULT_OK) + return; + String romPath = data.getStringExtra(FileDialog.RESULT_PATH); + if(romPath != null) + coreThread.loadRom(romPath); + } + + @Override + public void onResume() { + super.onResume(); + runEmulation(); + } + + @Override + public void onPause() { + super.onPause(); + pauseEmulation(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.activity_main, menu); + return true; + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + pauseEmulation(); + return true; + } + + @Override + public void onOptionsMenuClosed(Menu menu) { + runEmulation(); + } + + @Override + public boolean onMenuItemSelected (int featureId, MenuItem item) { + switch(item.getItemId()) { + case R.id.load: + pickRom(); + break; + case R.id.quicksave: + saveState(0); + break; + case R.id.quickrestore: + restoreState(0); + break; + case R.id.restore1: case R.id.restore2: case R.id.restore3: case R.id.restore4: case R.id.restore5: + case R.id.restore6: case R.id.restore7: case R.id.restore8: case R.id.restore9: + restoreState(Integer.valueOf(item.getTitle().toString())); + break; + case R.id.save1: case R.id.save2: case R.id.save3: case R.id.save4: case R.id.save5: + case R.id.save6: case R.id.save7: case R.id.save8: case R.id.save9: + saveState(Integer.valueOf(item.getTitle().toString())); + break; + default: + return false; + } + runEmulation(); + return true; + } + + void restoreState(int slot) { + if(romLoaded) { + coreThread.inFrameLock.lock(); + DeSmuME.restoreState(slot); + coreThread.inFrameLock.unlock(); + } + } + + void saveState(int slot) { + if(romLoaded) { + coreThread.inFrameLock.lock(); + DeSmuME.saveState(slot); + coreThread.inFrameLock.unlock(); + } + } + + + class EmulatorThread extends Thread { + + public EmulatorThread() { + super("EmulatorThread"); + } + + long lastDraw = 0; + final AtomicBoolean finished = new AtomicBoolean(false); + final AtomicBoolean paused = new AtomicBoolean(false); + String pendingRomLoad = null; + + public void loadRom(String path) { + pendingRomLoad = path; + synchronized(dormant) { + dormant.notifyAll(); + } + } + + public void setCancel(boolean set) { + finished.set(set); + synchronized(dormant) { + dormant.notifyAll(); + } + } + + public void setPause(boolean set) { + paused.set(set); + synchronized(dormant) { + dormant.notifyAll(); + } + } + + Object dormant = new Object(); + + public Lock inFrameLock = new ReentrantLock(); + int fps = 1; + + @Override + public void run() { + + while(!finished.get()) { + + if(!inited) { + DeSmuME.context = MainActivity.this.getApplicationContext(); + DeSmuME.load(); + + final String defaultWorkingDir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/nds4droid"; + final SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(DeSmuME.context); + final String path = pref.getString("DeSmuMEPath", defaultWorkingDir); + final File workingDir = new File(path); + DeSmuME.setWorkingDir(workingDir.getAbsolutePath()); + workingDir.mkdir(); + new File(path + "/States").mkdir(); + new File(path + "/Battery").mkdir(); + + + DeSmuME.init(); + inited = true; + } + if(pendingRomLoad != null) { + if(!DeSmuME.loadRom(pendingRomLoad)) { + AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); + builder.setMessage(R.string.rom_error).setPositiveButton(R.string.OK, new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface arg0, int arg1) { + arg0.dismiss(); + msgHandler.sendEmptyMessage(PICK_ROM); + } + }); + builder.create().show(); + } + else { + romLoaded = true; + paused.set(false); + } + pendingRomLoad = null; + } + + if(!paused.get()) { + + inFrameLock.lock(); + fps = DeSmuME.runCore(); + inFrameLock.unlock(); + DeSmuME.runOther(); + + running = true; + + if(System.currentTimeMillis() - lastDraw > (1000/fps)) { + msgHandler.sendEmptyMessage(DRAW_SCREEN); + lastDraw = System.currentTimeMillis(); + } + + } + else { + //hacky, but keeps thread alive so we don't lose contexts + try { + synchronized(dormant) { + dormant.wait(); + } + } + catch (InterruptedException e) { + } + } + } + } + } + + static final int BUTTON_RIGHT = 0; + static final int BUTTON_DOWN = 1; + static final int BUTTON_UP = 2; + static final int BUTTON_LEFT = 3; + static final int BUTTON_A = 4; + static final int BUTTON_B = 5; + static final int BUTTON_X = 6; + static final int BUTTON_Y = 7; + static final int BUTTON_L = 8; + static final int BUTTON_R = 9; + static final int BUTTON_START = 10; + static final int BUTTON_SELECT = 11; + static final int BUTTON_TOUCH = 12; + + final int[] buttonStates = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + final SparseIntArray touchMap = new SparseIntArray(); + + + class NDSView extends SurfaceView { + + SurfaceHolder surfaceHolder; + Bitmap emuBitmap; + Bitmap controls; + Bitmap touchControls; + final Paint controlsPaint = new Paint(); + final Paint emuPaint = new Paint(); + + public NDSView(Context context) { + super(context); + surfaceHolder = getHolder(); + + setKeepScreenOn(true); + setWillNotDraw(false); + controlsPaint.setAlpha(200); + } + + @Override + public void onDraw(Canvas canvas) { + + if(!inited) + return; + + if(width != canvas.getWidth() || height != canvas.getHeight()) + resize(canvas.getWidth(), canvas.getHeight()); + + if(emuBitmap == null) + return; + + coreThread.inFrameLock.lock(); + DeSmuME.draw(emuBitmap); + coreThread.inFrameLock.unlock(); + + canvas.drawBitmap(emuBitmap, src, dest, null); + if(touchScreenMode) + canvas.drawBitmap(touchControls, 0, 0, controlsPaint); + else + canvas.drawBitmap(controls, 0, 0, controlsPaint); + } + + + @Override + public boolean onTouchEvent(MotionEvent event) { + if(xscale == 0 || yscale == 0) + return false; + if(touchScreenMode) { + switch(event.getAction()) { + case MotionEvent.ACTION_DOWN: + float x = event.getX(); + float y = event.getY(); + if(touchrect.contains((int)x, (int)y)) { + touchScreenMode = false; + break; + } + x /= xscale; + y /= yscale; + //convert to bottom touch screen coordinates + y -= 192; + if(y >= 0) + DeSmuME.touchScreenTouch((int)x, (int)y); + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + DeSmuME.touchScreenRelease(); + break; + default: + return false; + } + return true; + } + else + { + if(!sized) + return false; + switch(event.getAction()) { + case MotionEvent.ACTION_MOVE: + case MotionEvent.ACTION_DOWN: + + for(int i = 0 ; i < event.getPointerCount() ; ++i) { + int id = event.getPointerId(i); + + int existingTouch = touchMap.get(id, -1); + if(existingTouch != -1) { + //reset touch, it may get re-set below but we need to deal with sliding off a button + buttonStates[existingTouch] = 0; + } + int x = (int) event.getX(i); + int y = (int) event.getY(i); + + if(leftrect.contains(x, y)) + touchMap.put(id, BUTTON_LEFT); + else if(rightrect.contains(x, y)) + touchMap.put(id, BUTTON_RIGHT); + else if(uprect.contains(x, y)) + touchMap.put(id, BUTTON_UP); + else if(downrect.contains(x, y)) + touchMap.put(id, BUTTON_DOWN); + else if(arect.contains(x, y)) + touchMap.put(id, BUTTON_A); + else if(brect.contains(x, y)) + touchMap.put(id, BUTTON_B); + else if(xrect.contains(x, y)) + touchMap.put(id, BUTTON_X); + else if(yrect.contains(x, y)) + touchMap.put(id, BUTTON_Y); + else if(lrect.contains(x, y)) + touchMap.put(id, BUTTON_L); + else if(rrect.contains(x, y)) + touchMap.put(id, BUTTON_R); + else if(startrect.contains(x, y)) + touchMap.put(id, BUTTON_START); + else if(selectrect.contains(x, y)) + touchMap.put(id, BUTTON_SELECT); + else if(touchrect.contains(x, y)) { + touchScreenMode = true; + touchMap.clear(); + break; + } + else + continue; + + buttonStates[touchMap.get(id)] = 1; + } + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + for(int i = 0 ; i < event.getPointerCount() ; ++i) { + int id = event.getPointerId(i); + int button = touchMap.get(id, -1); + if(button == -1) + continue; + buttonStates[button] = 0; + touchMap.delete(id); + } + break; + default: + return false; + } + DeSmuME.setButtons(buttonStates[BUTTON_L], buttonStates[BUTTON_R], buttonStates[BUTTON_UP], buttonStates[BUTTON_DOWN], buttonStates[BUTTON_LEFT], buttonStates[BUTTON_RIGHT], + buttonStates[BUTTON_A], buttonStates[BUTTON_B], buttonStates[BUTTON_X], buttonStates[BUTTON_Y], buttonStates[BUTTON_START], buttonStates[BUTTON_SELECT]); + return true; + } + } + + boolean resized = false; + boolean sized = false; + int sourceWidth; + int sourceHeight; + Rect src, dest; + int width = 0, height = 0; + + float xscale = 0, yscale = 0; + + public Rect lrect, rrect, touchrect, uprect, leftrect, downrect, rightrect, startrect, selectrect, xrect, arect, yrect, brect; + + void resize(int newWidth, int newHeight) { + + //TODO: Use desmume resizing if desired as well as landscape mode + sourceWidth = 256; + sourceHeight = 384; + resized = true; + src = new Rect(0, 0, sourceWidth, sourceHeight); + dest = new Rect(0, 0, newWidth, newHeight); + + xscale = (float)dest.width() / (float)sourceWidth; + yscale = (float)dest.height() / (float)sourceHeight; + + Bitmap originalControls = BitmapFactory.decodeResource(getResources(), R.drawable.dscontrols); + controls = Bitmap.createScaledBitmap(originalControls, dest.width(), dest.height(), true); + + Bitmap originalTouchControls = BitmapFactory.decodeResource(getResources(), R.drawable.dscontrolstouch); + touchControls = Bitmap.createScaledBitmap(originalTouchControls, dest.width(), dest.height(), true); + + float controlxscale = (float)dest.width() / (float)originalControls.getWidth(); + float controlyscale = (float)dest.height() / (float)originalControls.getHeight(); + + lrect = new Rect((int)(0 * controlxscale), (int)(0 * controlyscale), (int)(160 * controlxscale), (int)(90 * controlyscale)); + rrect = new Rect((int)(610 * controlxscale), (int)(0 * controlyscale), (int)(768 * controlxscale), (int)(90 * controlyscale)); + touchrect = new Rect((int)(320 * controlxscale), (int)(0 * controlyscale), (int)(430 * controlxscale), (int)(60 * controlyscale)); + leftrect = new Rect((int)(0 * controlxscale), (int)(915 * controlyscale), (int)(110 * controlxscale), (int)(1015 * controlyscale)); + uprect = new Rect((int)(111 * controlxscale), (int)(810 * controlyscale), (int)(221 * controlxscale), (int)(914 * controlyscale)); + rightrect = new Rect((int)(222 * controlxscale), (int)(915 * controlyscale), (int)(333 * controlxscale), (int)(1015 * controlyscale)); + downrect = new Rect((int)(111 * controlxscale), (int)(1016 * controlyscale), (int)(221 * controlxscale), (int)(1116 * controlyscale)); + arect = new Rect((int)(639 * controlxscale), (int)(895 * controlyscale), (int)(768 * controlxscale), (int)(1026 * controlyscale)); + brect = new Rect((int)(521 * controlxscale), (int)(995 * controlyscale), (int)(639 * controlxscale), (int)(1118 * controlyscale)); + yrect = new Rect((int)(397 * controlxscale), (int)(895 * controlyscale), (int)(517 * controlxscale), (int)(1026 * controlyscale)); + xrect = new Rect((int)(521 * controlxscale), (int)(805 * controlyscale), (int)(639 * controlxscale), (int)(927 * controlyscale)); + startrect = new Rect((int)(270 * controlxscale), (int)(1082 * controlyscale), (int)(364 * controlxscale), (int)(1152 * controlyscale)); + selectrect = new Rect((int)(400 * controlxscale), (int)(1082 * controlyscale), (int)(485 * controlxscale), (int)(1152 * controlyscale)); + + emuBitmap = Bitmap.createBitmap(sourceWidth, sourceHeight, Config.ARGB_8888); + DeSmuME.resize(emuBitmap, sourceWidth, sourceHeight); + width = newWidth; + height = newHeight; + sized = true; + } + + } + +} diff --git a/src/com/opendoorstudios/ds4droid/ds4droidApplication.java b/src/com/opendoorstudios/ds4droid/ds4droidApplication.java new file mode 100755 index 0000000..3e6c091 --- /dev/null +++ b/src/com/opendoorstudios/ds4droid/ds4droidApplication.java @@ -0,0 +1,34 @@ +package com.opendoorstudios.ds4droid; + +/* + Copyright (C) 2012 Jeffrey Quesnelle + + This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>. +*/ + +import org.acra.*; +import org.acra.annotation.*; + +import android.app.Application; + +//@ReportsCrashes(formKey = "") +public class ds4droidApplication extends Application { + + @Override + public void onCreate() { + //ACRA.init(this); + super.onCreate(); + } + +}